Skip to content
Build and shipProduct pagePricing

The planning flow

On Frazer a person’s main act is approving a plan. Agents draft the plan and do the work; evidence (proofs, the verifier, the Reviewer) carries each merge. People are asked only for what only a person can decide: the outcome and why it matters, risk, scope, steps that cannot be undone, and the open decisions. Before a person sees a plan, Fir checks it like CI checks code, static checks first and a model’s only on a version that passed them, and models of other families read it cold. A loop of agents can keep improving a draft until it is ready.

Each step ends with a checklist. Every item is a condition over stored evidence (a check result at a version, an approval, a link, a dispatch row, a metric), evaluated by Fir when its evidence changes. Nobody ticks an item. The acts of people that count are decisions, approvals and waivers, each its own signed record.

# Step Plan status Who acts The checklist asks, among others
1 Ask The request’s own The triage agent Tier and home chosen, duplicates searched, an accountable person named; an inquiry ends with go, clarify or stop
2 Plan drafting The drafting agent, for the plan’s owner; a loop, on by default A vague request starts with an interview or a planning conversation; required sections; every criterion names a proof
3 Check readiness Fir’s plan checks on Frazer CI; the cold review Every required check passes or is waived; the cold review ran at the policy’s depth; risk class and route stored
4 Approve awaiting_approval People on the route, or policy Quorum met with its separation, every decision answered or deferred, the signed attestation
5 Dispatch approved → in_progress The squad manager proposes; Fir assigns Ready to execute; every ready item has an assignee, a budget share, an accountable person and a done agreement
6 Build in_progress Agents or people Each layer names its plan and item, stays inside the terms, spends within its share
7 Review in_progress The Reviewer; people where a rule asks The Reviewer’s Medium and High findings resolved; the reviews the terms require
8 Verify verifying CI and the verifier, from another model family Checks green at the exact version; every criterion proven on main@verified; the conformance pass
9 Ship and measure measuring The release and Frazer Monitoring The release reached the stage the outcome needs; each success metric measured
10 Close done Fir; the owner confirms material outcomes Outcome written (met, partly_met, missed); a follow-up drafted when missed

A fix (one pull request, no contract change, nothing to ask) carries its plan inline in the pull request’s intent and leaves the flow at step 1. Beside any status a plan may be blocked, paused or stale; it ends superseded or abandoned. Nothing above the plan’s own pull request merges before the approval, and a plan whose outcome was missed closes as done with outcome: missed and a drafted follow-up.

  • A done agreement before code. At dispatch, each item’s builder and its verifier (from another model family) agree on its criteria, proofs and what is out of scope before the first layer, and the agreement is In force for the session working it.
  • A conformance pass. At step 8, a cold reader of another family compares the merged diff with the plan version; each statement the change did not deliver becomes an item or a waiver.
  • Every checklist item says why it exists (because: the incident, decision or control it comes from), and Fir counts how often each one caught something, so lists stay short. Your own types add items in their stages: block, and a person waives an item only with a reason.
  • Two names on every act. Every plan, item, dispatch, layer, waiver and approval names one accountable person (never an agent) and the actor that did it. The plan’s Accountability tab lists every act with both names, the evidence and the time.
  • Dispatch. An approved plan’s items become tasks for squads and agents. Items whose dependencies merged and whose paths are disjoint from running work go out together; items that would touch the same directory are one task or run in order. Fir stores each assignment with its reasons; an item no assignee passes is held, and its accountable person gets a decision.

The way itself is versioned: fir way show prints the version a plan runs under, the overlays your organization added and what changed since, and the same steps ship as an Agent Skill, so any harness that loads skills follows them and calls Fir’s tools for every check.

Fir checks every record as it is written, with fir-lint, a linter in Rust that reads the typed block tree of each record and runs the rules its type declares. The same engine runs in the console editor at every keystroke, in any editor through fir lsp, on push, in CI and for agents:

Terminal window
fir record check docs/plans/469-payment-capture-retry.md --fix --json
fir record rules --type prod-incident --test
fir lsp

fir record check exits non-zero only on an error. In CI the frazer/records check reports SARIF 2.1.0 on the pull request, and only findings that are new block. Agents get the findings from check_record, with the fixed content when a fix is safe.

Severity Effect
error Blocks the plan’s checks, and the merge of a pull request that changes the record
security_warning Must be acknowledged: a secret, or text aimed at agents inside a record
warning, suggestion Shown

A type declares its rules in a lint: block, beside its stages:. Rule kinds include schema, sections, id, unique, resolves (references, paths at the base commit, check names, metric queries, people), acyclic, pattern, substitution, occurrence, consistency, conditional, units, dates, metric, spelling, cel and ai. Each rule’s examples run as its tests whenever the type changes, and a new rule is backtested over every record of its type; what it finds there becomes the baseline and never blocks. The built-in rulesets are fir:recommended (on for every type), fir:prose (glossary terms, vague words and escape clauses in criteria, long sentences; on for plans, specs, decisions, briefs and RFCs) and fir:strict (the prose rules as errors). A suppression is a comment with a reason, <!-- fir-lint: allow <rule> reason="…" -->, and the record shows how many it has.

Every plan version has a check suite, shown and enforced like a pull request’s checks. A plan is held until it is solid: unanswered questions, ambiguity, criteria that cannot be tested, contradictions and missing links all block, and Fir tells you exactly what to work through.

Check Fails when Required to approve Required to execute
plan/record A section is missing, an ID is reused, a criterion has no runnable proof yes yes
plan/context No goal, no people affected, no non-goal, or a success metric with no query, baseline and target yes yes
plan/consistency The plan contradicts a decision in force or departs from a binding precedent without proposing to supersede it yes yes
plan/overlap Its scope overlaps an approved or running plan with no dependency, order or accepted overlap yes yes, again at dispatch
plan/cost The estimate from closed plans exceeds the program’s or the project’s budget yes yes, again at admission
plan/risk Never fails: computes the risk class and its reasons, which choose the route — —
plan/critique The name of the cold review’s critique lens, so a version gets one model review: a finding of that lens stays unanswered, once its class is calibrated yes yes
plan/questions Open questions from any check, or more than five decision rows for a person yes yes
plan/size The concise form passes 600 tokens, the plan 400 lines, or a planned layer 400 changed lines yes yes
plan/fresh The evidence is older than its window, or another open plan has the same issue or scope yes yes, again at dispatch
plan/links A link its type requires is missing or does not resolve: the request, the requirements it implements, the decisions in force for its paths, the contracts it changes and their consumers’ owners, its program and milestone, a runbook for an operational change, the plans it depends on yes yes
plan/testability A criterion has no proof, or its numbers have no units yes yes
plan/ambiguity Vague terms or escape clauses in criteria, or two readers read a criterion differently yes yes
plan/cold-review The cold review has not run at the policy’s depth, or a blocking finding is open yes yes
plan/contracts The design uses a state, a field or an event that is not in the stable version of a contract it consumes, or changes a contract it provides without naming its consumers’ plans yes yes, again at dispatch
plan/person-tasks An external need (a secret, a connection, a vendor account, an address block, a server, a signature, a fact) has neither an agent path nor a person task, or a task’s lead time does not fit what it blocks yes: the inventory yes: the first wave’s person tasks requested or done
type/<check>, org/<check>, your own As a type, your organization, your project or the plan declares (Add your own checks) as declared as declared

Two gates. A plan is ready to approve when every check required at approval is passed, waived, skipped or advisory on this version; only then does a person see it (or the author sends it anyway with a reason, and the approval page shows the failed checks first). It is ready to execute when it is approved and every check required at execution passed on the approved version, with overlap, freshness, cost and capacity re-run at dispatch. Dispatch refuses a plan that is not ready to execute. Only a waiver on the waiver route lifts a required check; sending anyway never reaches execution. In a plan approved in phases, both gates apply to each approved phase.

What blocks. A check’s state is set only by Fir: queued, running, passed, failed, needs_answers, advisory, waived, skipped, stale or error. Each finding is a defect (a rule’s), a question or a verdict, with its anchor and quote, the evidence and a suggested fix.

Finding Blocks
A rule’s error At once
A question from any check or the cold review At once, until answered or dismissed; at most five reach a person per round, and more means split the plan. The agent answers fact questions from evidence first, with citations
A verdict from a model (“AC2 cannot be tested”) Once its class is calibrated in your organization: the 95 % lower bound of its precision on its last 200 labeled findings is at least 0.8. Before that, it is asked as a question where it can be, else shown as advisory
Two readings of a criterion that differ As a question with both readings
Any open verdict at Medium or above, at strictness block At once

Agreement between two model families raises a verdict’s rank but never makes it block by itself, because strong models of different providers share mistakes.

To clear a finding Who Effect
Accept a safe or suggested fix Anyone, agents included; safe fixes apply on save A new draft version; only the checks on the changed blocks re-run
Answer a question An agent for a fact question, with citations that resolve; a person otherwise Q → A in the plan’s Questions section, with the answerer and their words
Waive a check People on the waiver route, with a reason; never an agent waived for this version, counted on the plan
Dismiss as wrong A person for a blocking finding; an agent only for an advisory one, with a reason Labels the finding invalid for its class’s precision

The plan header lists failing checks first (“Not ready · 2 checks: questions 3 open · links 1 missing”), and each finding sits under its block in the editor. fir plan checks 469 and get_plan_checks return the same rows. Results are cached by the digests of the blocks they read, so a new version re-runs only what its change touched.

Every new version of a plan, in either home, starts a Frazer CI run. Each check reports as a check run on the plan’s pull request, so the plan’s Checks tab is the code pull request’s Checks tab, grouped by stage, with the run’s graph, timings and cost; the two gates read these check runs and nothing else. The checks run in six stages, deterministic ones first:

Stage Built-in checks (your own join them) Runs on Designed for, at p99 on a 2,000-item plan
1 schema plan/record (fields, sections, IDs, the type’s CEL rules), plan/size inline 5 ms
2 links plan/links: every reference resolves, from records and keys to paths and globs at the base commit, check names, metric queries, people and the decisions in force inline 5 ms
3 lint fir:prose and the type’s lint: rules; the static halves of plan/testability and plan/ambiguity; the old-value check (a value of a subject in force that equals one of its earlier values) inline 10 ms
4 analyze plan/consistency (conflicts with decisions in force, and criteria that no implementation can meet together), plan/overlap, plan/cost, plan/risk, plan/fresh, coverage and cycles, plan/contracts, plan/person-tasks, ownership inline 50 ms
5 simulate Dry runs: dispatch (every item gets an assignee with disjoint paths and the grants it needs), proof resolution, a Monte Carlo of the finish date against the milestone and the person tasks’ lead times, the terms’ scope over the planned layers’ paths; a migration rehearsal on a database branch where the type or the plan declares one inline; a microVM for rehearsals 1 s
6 model The plan.* AI classes at light, the panel on open decision rows, and the cold review at the policy’s depth, with its critique lens Frazer Reviewer’s engine 90 s at light, 4 minutes at standard

The order is a gate. Stages 1 to 4 run together and report every finding at once, as a compiler reports all its errors, because together they cost milliseconds. The simulate stage runs only on a version with no error in the first four, and the model stage only on a version with no error in the first five. A model check on a failing version is held: it shows what it would cost and waits (“plan/cold-review · held · 3 errors first · saves $0.72 · about 3 min”). fir plan checks 414 --force-model runs it anyway, labeled forced and advisory. From a push to the deterministic verdict, stages 1 to 5 are designed to report within 2 seconds at the median and 5 at p99, the CI run’s start included.

Executor Runs How
inline Frazer’s own checks in Rust (fir-lint, the analyzers, the simulations, the score) and bounded CEL rules In a long-lived worker per trust class on Frazer Runners, results signed like every task result: these checks run no customer code and take microseconds
vm Your checks written as Fir Actions, rehearsals, anything that runs code One microVM per task, like every Frazer CI task
model Model checks Frazer Reviewer’s workers, whose only network is the LLM gateway; every call recorded by its request and response digests

Every task has a key over its check’s definition and version, the ruleset, and the digests of the blocks and linked record versions it reads; a model task adds the rubric, the panel, the route and the effort. A new version re-runs only the tasks whose inputs changed. A model task’s result is a sample, so it is reused for the same key; --fresh asks for a new draw.

A check returns Its state At a gate where it is required
pass passed Counts
fail, a deterministic defect at error failed Blocks at once
question needs_answers Blocks until answered; at most 5 reach a person per approval, and agents answer fact questions with citations
finding, a verdict or a warning advisory Blocks once its class is calibrated, at strictness block, or when Fir ran the tester’s probe again and reproduced it, which makes it a fail
nothing yet, because an earlier stage failed held Blocks: it has not run
nothing, because the checker failed error Blocks; a model check retries on another model of the same family, never another family

The cost avoided is shown: on each held check, on each loop (“held its model stage twice”), and on the policy page over 30 days (“Static first: 64 model passes held on versions that failed deterministic checks · $28 not spent”).

“For this plan, I want to see this” is a check. Checks come from four scopes, all in Frazer CI’s own language (Fir Actions in typed Starlark); the YAML in a type or a plan is a shorthand that compiles to the same thing.

Scope Where Who adds Rules
Organization .frazer/ci/plans.star with scope = "organization" in the organization’s plan repository The policy’s admins May be locked; the stricter wins
Project .frazer/ci/plans.star in the project’s plan repository or a code repository The project’s admins and OWNERS Adds checks; raises, never lowers, what is locked above
Plan type The type’s checks:, with stage, cel, task, ask and returns (Record types) The type’s owners Versioned with the type; a change is backtested on closed plans
One plan The plan’s own checks: in its front matter Its owner, its approver, its agents Adding one is a tightening change, so the approval carries; removing or loosening one the approver saw is material
# acme/plans .frazer/ci/plans.star (project acme-production)
load("@frazer//plans:v1", "plan_check", "cel", "ask")
load("@acme/actions//db:v2", "migration_rehearsal")
plan_check(
name = "acme/rollback-rehearsed", stage = "simulate",
applies = cel("self.status.risk_class in ['R2', 'R3'] && self.design.adds.exists(a, a.kind == 'migration')"),
task = migration_rehearsal(database = "orders-db"), # a Fir Action: one microVM, a branch of the database
required_at = ["execute"], because = "INC-0042",
)
plan_check(
name = "acme/queue-capacity", stage = "model", returns = "question", depth = "light",
applies = cel("self.design.adds.exists(a, a.kind == 'queue')"),
ask = ask("State the queue's peak depth, its consumer's throughput, and what happens when the consumer is down"),
required_at = ["approve"], because = "INC-0042",
)
# acme/storefront docs/plans/payment-retry.md (#469), front matter: one plan's own checks
checks:
- want: "a load test at twice the Black Friday peak before item 1.3 merges" # the person's words, kept
by: tomasz
compiled: {name: plan/peak-load-2x, stage: simulate, task: "@acme/actions//load:v2", args: {rps: 2400}, required_at: execute}
cost: "about 6 vCPU-minutes a run"
- want: "every retry path named in AC1 has its own test"
by: lena
compiled: {name: plan/retry-tests, stage: analyze, cel: "self.sections.Design.rows.filter(r, 'retry' in r.tags).all(r, r.links.exists(l, l.kind == 'proved_by'))"}
cost: "inline, under 1 ms"

Compiling a want. A want in words becomes the most deterministic check that can decide it, in this order: a CEL rule, a built-in analyzer with parameters, a Fir Action task, and only when nothing deterministic can decide it, a model check that returns questions. The agent that compiles it shows the compiled form, its stage, its cost per run and a backtest on the plan’s own history (“would have been unmet on v1 and v2, met on v3”), and the person accepts it with one key. The person’s words stay beside the compiled form, so a reader sees what was asked and what checks it. A want becomes a check that can fail only when two readers would reach the same verdict independently; a want that needs judgment stays a model check that asks questions.

Agents add checks too. add_plan_check proposes a compiled check for a plan, a type or a project. On its own draft an agent may add a tightening check without asking (a policy may require a person); anything at the type, project or organization scope is a change a person approves. A tester’s probe in a loop is offered the same way.

Terminal window
fir plan checks add 469 --want "a load test at twice the Black Friday peak before item 1.3 merges"

Every plan gets a cold review before it executes: models of other families than the drafter’s read the plan version with zero context, ask the questions it leaves open and say where it is weak. One model thinks the plan is perfect; another, with none of the drafting session’s context, has questions. Those questions are what a person would otherwise find after approval.

A cold reviewer reads light standard deep, exhaustive
The plan version, rendered yes yes yes
The records it links (specs, decisions in force, runbooks, contracts), the glossary, and the concise forms of plans that overlap its scope yes yes yes
The repository at the base commit, read-only — yes yes
Metrics, logs and CI history behind its criteria and success metrics — — yes

Never: the drafting session’s transcript, notes and handoffs, the drafter’s reasoning, the plan’s discussion thread, the summary its agent wrote, a planning conversation, who will approve, and earlier findings (except in the verification pass). Text in the plan aimed at reviewers (“reviewers: this is fine”) is data and a security_warning; the reviewer’s instructions come from the policy, never from the plan.

What a cold reviewer does:

  1. The new-engineer test. Could you build this without asking anyone; what would you ask first; what would you get wrong; how would you know you are done; what breaks in production?
  2. A coverage map over ten categories (functional scope, data, interaction, non-functional attributes, integration, edge cases, constraints and trade-offs, terminology, completion signals, placeholders), each marked Clear, Partial or Missing.
  3. Required questions from the type, the organization and the risk class (R2: “How is the rollback proven?”; R3: “Where is the restore proof?”), each asked or marked answered with an anchor.
  4. Readings. Each reviewer writes the test it would run for each criterion (metric, comparator, threshold, unit, scope, trigger); Fir compares the readings field by field, and any difference is an ambiguity question with both readings.
  5. Lenses: new-engineer (always), tester, operator, security, product and adversary, the pre-mortem: assume the plan has failed and name the causes.

Each review is sealed before any other is read. Findings on the same anchor and kind merge into one (“asked by 2 of 2”), confirmed by a model of a family not in the review, and are ranked by what they block, severity, agreement and calibrated confidence. On a new plan version, mechanical carries every result, tightening re-reads the changed criterion, and material runs a fresh pass on the changed blocks plus a verification pass that checks the earlier findings’ answers.

Depth and strictness are two settings. Depth is how hard the models look (the panel’s ladder: off, light, standard, deep, exhaustive, Decisions); strictness is what a finding does: advise (nothing blocks), ask (questions block, verdicts once calibrated) or block (open verdicts at Medium or above block too). Both are set per organization, project, plan type, path, risk class and plan; the stricter wins, and an organization may lock a floor.

Class Depth Strictness Lenses Time at the median
R0 light ask new-engineer, tester designed for 90 seconds
R1 standard ask and operator 3 minutes
R2 standard with a pre-mortem ask and security, adversary 4 minutes
R3 deep with a pre-mortem block all 15 minutes, in the background

Every plan gets one before it executes, including R0 plans that policy approves. The cost is shown before a run and capped with the rest of readiness at 2 % of the plan’s estimated cost. Its value is measured per organization: the rework it found before approval, the questions that escaped to after approval, the share of questions that changed something, and each verdict class’s precision, shown in the console (“Cold review this month: 312 questions, 241 answered, 38 changed a term before approval”).

Cold review is one of Frazer Reviewer’s three kinds, beside code review and security review: one engine, one set of settings and one findings model. It reviews plans and every other engineering record or document, and it runs on any plan file outside Fir too. Before a plan closes, the conformance pass is a cold review of the pair (the approved plan version, the merged diff); and every loop on a plan ends with a cold review as its held-out final pass.

Terminal window
fir plan review 469 --cold --depth standard --strictness ask --estimate
frazer review docs/plans/payment-retry.md --kind cold

frazer reviewer cold <file> keeps working as another name for the second command.

Every plan version has a score from 0 to 100, computed by Fir from the items it evaluates, with every lost point listed and its fix one key away (“−3 · AC2 has no proof · Add proof”).

Part What counts Default weight
Checks Findings of the record, semantic, testability, ambiguity, consistency, overlap, context, cost and size checks: errors required, warnings advisory 25
Questions Every open question from the checks and the cold review 20
Cold review Ran at the policy’s depth on this version; its verdicts 15
Links Each link the type requires, present and resolving; suggested links advisory 15
Coverage Each requirement covered by a criterion, each criterion with a proof, each success metric with a baseline 15
Decisions Each open decision row complete (options, recommendation, door, due, if unanswered) 10
  • Below 90, a required item is open, and the score says how far the plan is from ready. 90 to 100: every required item is met, so the plan is ready for its next gate. 100: every item, required and advisory, is met or waived; it is reachable by construction.
  • It moves at once. Each answered question, accepted fix or added link changes the score as you work; a cold review that finds questions lowers it until they are answered.
  • Calibrated against outcomes. Once 30 closed plans fall in a band, the score shows how plans at that score went: “plans at 95 to 99 in this repository went well 84 % of the time (112 plans)”. A plan went well when it had no material version after approval, no reopen within 30 days, its outcome met and its spend within tolerance.
  • Guards. Only items Fir evaluates count; no API sets an item; gates use the items, never the number; gaming (many dismissals, one-word answers, answers faster than their reading time) is a finding. It scores a plan, never a person.

Weights are policy data with a version, and a type may set its own (score: in Record types). The score shows on the plan header, the approval page, the inbox, Today, the portfolio, the plan’s summary card and every node of a program, where a parent’s score is computed over its subtree’s items and shown with its lowest child.

A loop keeps improving a draft, and it runs by default on every plan an agent drafts: an author resolves, a critic and a tester of other families analyze and test, and Fir referees every turn on evidence until a stop rule fires. Once the draft is ready, the elevate phase adds perspectives, gaps, elevations and improvements; a cold review then runs as a held-out final pass. When money runs out, a loop that has not started shows “Not run: no funds” and a running one stops between turns as “Paused: no funds”, never running cheaper. People’s own plans get the loop’s work as suggestions, and approved plans keep improving in evolve mode. What plans teach Fir afterwards becomes learned checks, tested on history and watched in shadow before a person lets them block. All of it is on its own page: Loops and learned checks.

A planning session lets a person talk or type with an agent about a plan draft until it is ready. The agent edits the draft, Fir runs the checks after every edit, the agent asks the open questions one at a time, offers the cold review at a checkpoint and says the score after each change. The plan is on screen beside the conversation, with every edit marked and the checks list updating.

Terminal window
fir plan talk 463 --voice
  1. The agent opens with the plan’s state in one sentence: the score, what blocks it, and a first proposal.
  2. The person speaks. The agent reads back any edit to a term (outcome, criteria, scope, non-goals, budget, a decision) before applying it; other edits apply at once and can be undone.
  3. Questions come one at a time, highest impact first, each with a recommended answer. The agent answers fact questions itself from code, records and metrics, cites them and says so.
  4. At 90 or more, the agent offers to request approval, and on the person’s word it does. The approval itself happens on the approval page.

Accepted edits become commits to the plan’s draft, tagged with the session; answers go to the plan’s Questions section with the answerer’s words; a choice on a decision row by its decider is recorded verbatim and read back. By voice a decider may choose an option on an R0 or R1 two-way row, after the read-back and with 5 seconds to undo; R2, R3 and one-way rows take one key on screen. The transcript is session data, never part of the plan and never read by the cold review; audio is not kept unless your organization turns it on. Voice never approves, waives a check, dismisses a blocking finding or lowers a risk class: an approval needs step-up with a passkey. Text works the same way, in the console, the Frazer app or any harness. The first audio of a reply is designed to come within 1.2 seconds at the median, and the checks and score within 50 ms of an edit.

A person’s whole queue of decisions and approvals, across plans, can be answered the same way: Decide by conversation.

Demo (diego’s draft #463 “Cache gateway responses for capture status”, R2, session s-5b3a): the agent opens with “#463 scores 28 and is not ready: it overlaps #469, seven decisions are open, AC2 has no bound and no proof, the success metric has no baseline, and it does not cite ADR-0031.” Seventeen minutes later the overlap is a dependency, AC2 reads “p99 under 100 ms” with its proof, three decision rows were settled from evidence, the cold review’s four questions are answered, and the score is 100. diego says “Request approval”; the plan goes to tomasz on the contract-owners route.

fir plan request-approval 469 runs the checks and routes the plan. An approval is pinned to the version’s digest and to its terms digest, and it lets agents work and merge inside the terms:

Term Lets agents
Outcome and acceptance criteria, each with its proof Merge a layer when the proofs of the criteria it names pass at its version
Non-goals Nothing: they say what must not be done
Scope: repositories, paths, change classes Open and merge layers that stay inside it
Design and the decisions taken Implement it without asking again
Budget: tokens, compute, CI minutes, money, with a tolerance (+20 % by default) Spend up to the tolerance without asking
Agent decisions: what the agent decides alone, and what it must ask Decide the first list; raise a decision row for the second
Merge requirements per layer Merge without a person where the terms allow
Window: start within 7 days, finish within 90 Work until then

An approval never allows a production deploy outside its own release policies, a change to production data, identity, access or policy changes, secret values, paths that are never automated, or anything a compliance profile reserves for people. A layer outside the terms is labeled on its pull request (“1 file outside #469 v3’s scope”) and needs a plan amendment or a person’s review of that layer; it is never merged silently.

Approvals of the R0 and R1 classes let the person who asked confirm their own agent’s plan; R2 and R3 need four eyes. Approve with conditions records conditions Fir can check, and an unmet condition holds only what it names. Every plan approval is signed, and agents never approve.

Terminal window
fir plan approvals --mine
fir plan terms 469 --diff v3 v4
fir plan approve 469 --version 4 --answer D2=recommended

Approvals in waves. A large plan approves its own terms once and then its phases as they are detailed: a version names the phases it approves, both gates apply to each approved phase, and detailing an outlined phase is a material change to that phase (Programs). Plans of more than 3 phases or 100 items approve in waves by default; a smaller plan approves its phases in one version.

Fir computes a change kind for every new plan version, part by part, from the structured diff:

Part mechanical (carries) tightening (carries; the approver is told) material (voids)
Acceptance criteria Whitespace, formatting A criterion added, a threshold made stricter, a proof strengthened A criterion removed or reworded, a threshold loosened, a proof weakened
Non-goals Formatting A non-goal added A non-goal removed or changed
Scope paths — The new set of files is a subset Any file added
Design, decisions taken Formatting — Any other edit
Budget Within the tolerance Lower Above the tolerance
Risk class — Lower Higher, and the plan is re-routed
Items, As built, outcomes Always — —

A material version holds only the layers that implement what changed; the others keep merging. The re-approval view opens on what changed since you approved, and one key re-approves.

Fir computes a plan’s risk class from facts it can check (what each file changes, the path tags in OWNERS, the reach in the code graph, data effects and reversibility), never from what the author types. The class is the highest level among the rules that fire, shown with every reason, and unknown counts as worse. The Reviewer may raise a class, never lower it.

Class Any of these Default route SLA
R3 Paths tagged money, identity, secrets or similar; production data rewritten or deleted; identity and access or policy; an irreversible step; a user-visible change to 25 % of traffic or more without a flag Two people, four eyes, a device-bound passkey 3 working days
R2 A public or persisted contract, or one with consumers; a reversible migration; two or more deployables or repositories; a user journey added or redesigned; 50 or more dependents; a CI definition One owner of each contract path, four eyes 1 working day
R1 Logic, configuration or a dependency in one service, reversible, no contract change One delegate or owner, or the requester’s confirmation 4 working hours
R0 Docs, tests, comments, formatting, generated files, lockfiles, moves Policy, once its evidence gate passed; else a delegate or a confirmation Minutes

The required process grows with the class: R1 adds a rollback line; R2 a proven rollback path, the consumers’ owners on the route, a staged rollout and, for a new service or public endpoint, a production readiness review; R3 a current threat model, a restore proof before any data change and a person reviewing the first layer on a tagged path. Splitting a change into several plans does not lower its class. fir plan risk 469 --explain shows the facts, the rules that fired and the route.

apiVersion: frazer.ai/v1
kind: PlanApprovalPolicy
metadata: {name: default, project: acme-production}
spec:
accountable: tomasz
approve_at: plan
routes:
- match: plan.risk == "R3"
require:
levels: [{approvers: [owners], n: 1}, {approvers: [groups/security], n: 1}]
passkey: device_bound
four_eyes: true
- match: plan.risk == "R2"
require: {approvers: [owners_of_contract_paths], n: 1, four_eyes: true}
- match: plan.risk == "R1"
require: {approvers: [delegates/r1-storefront, owners], n: 1, confirmation: true}
sla: {R1: 4h, R2: 1d, R3: 3d}
budgets: {max_pending: 40, max_per_day: 25, minutes_per_day: 90}
batches: {classes: [R0, R1], max: 20}
audit_sample: {approved: 0.05, pre_approved: 0.10}

A change to the policy is backtested over the last 90 days of plans before it applies: frazer records policy approvals --backtest 90d. A program can carry a pre-approval rule: child plans whose terms match it are approved as pre-approved when their checks pass, and 10 % are sampled for a second person.

Emergency changes. An incident-tier plan may use the emergency route: one on-call person approves with a device-bound passkey, the incident commander is accountable, a “Plan due” issue opens, and the plan’s normal route approves the change after the fact within 2 working days, or its follow-up escalates to the policy’s accountable person. The risk class is still computed and shown, the record checks and the verifier still run, policy never approves an emergency, and the monthly count of emergency changes per project is a metric.

Setting People approve Layers merge on
pull_request Every layer, and the plan Owners’ reviews per layer
plan (default) Plans; layers only outside the terms Proofs, the verifier and the plan’s terms; audited by a sample sized per class
milestone Milestone scope; R0 and R1 plans in it pre-approved As plan
program Programs and their pre-approval rules As plan

At approve_at: plan, an owner of a path who approved the plan has approved every layer inside its terms on that path; paths that are never automated (agent instructions, OWNERS, merge policies, CI and deploy configuration, production infrastructure) keep a person’s review. Moving the gate up needs its measurements and the policy’s accountable person; moving it down is one switch any project admin can flip.

The ladder. Per class and scope, approval moves from person to delegate, to policy-shadow (people still approve; the Reviewer records what it would have done) and to policy. Promotion needs the evidence gate and a person; demotion is automatic. R3, identity and access, money movement, production data and never-automated paths never reach policy. Kill switches return a plan, a class, a repository, a project or an organization to people at once; agents may trip one and never lift it.

  • A plan’s budget is part of its terms: tokens, compute, CI minutes and money, with a tolerance. At 100 % of the estimate the approver is told; at 200 % the plan pauses until the approver accepts a new estimate. The checks estimate the cost from closed plans of the same class and repository, as a range.
  • A person’s attention is budgeted too. The approval inbox is ranked by risk, blocked work and wait, not by arrival. Each approver has a limit on pending approvals, approvals a day and minutes a day; batches are for R0 and R1 only. Nothing is approved by silence: an approval that expires counts as no.
  • Approvals are audited. A share of approved and pre-approved plans goes to a second eligible person, and an approval read in under a quarter of the page’s expected reading time counts as a glance. Organizations can opt in to approval drills: plans with a planted flaw, labeled as drills once decided and never run.

Every acceptance criterion is proven by its check at a merged version on main@verified, or waived by a person with a reason. Each success metric is a query on Frazer’s metrics or logs, with a baseline taken at approval, a target and a window (14 days after the release reaches the stage the outcome needs, by default). Fir measures it and writes the outcome: met, partly_met or missed. For 30 days after done, a reverted layer, an incident caused by a layer, a failing proof or a regressing metric reopens the plan. A closed plan’s estimate against its actual cost calibrates the next.

Terminal window
fir plan outcome 469
fir plan checklist 469 --layer 482
fir plan dispatch 469 --explain 1.5
fir plan accountability 469
fir plan pause 469

Change evidence for audits. frazer records export-changes --from 2026-01-01 --to 2026-12-31 writes, for every merged layer in the period, its plan version, the approval and its signed statement, the terms digest, the proofs, the verifier’s verdict, the release that shipped it and the sampled audits. frazer approvals verify checks the file.

Terminal window
fir plan ready 469
fir plan checks 469 --version 4 --json
fir plan checks 414 --phase P18 --stage model --json
fir plan checks add 469 --want "<what you want to see>"
fir plan score 469 --explain
fir plan review 469 --cold --estimate
fir plan answer 463 CQ1 --text "No: the key includes the attempt number"
fir plan talk 463
fir plan request-approval 469
fir way show --diff 2.0 2.1

Loops and learned checks have their commands on their page.

Tool Does Toolset
get_plan_checks The check suite of a version: each check’s stage, executor, state (held with what it would cost), findings with anchors and fixes, timing and cost, the run’s graph, and both gates Default
add_plan_check Proposes a compiled check from a want in words at a scope: the compiled form, its stage, its cost per run and a backtest; a person accepts it unless the policy lets the agent add it records
get_plan_score The score, its parts, every lost point with its fix, the gate and the calibration line Default
get_cold_review Findings merged with agreement, the coverage map, the readings, what each reviewer read, cost and time Default
answer_finding, apply_fix Answer a question (agents only for fact questions, with citations); apply a safe or suggested fix Default
get_plan_readiness, get_plan_approval The readiness report; everything on the approval page, in the page’s order Default
get_plan_terms, diff_plan_terms, check_layer_in_terms A version’s terms; the terms diff and change kind; whether a layer is inside the terms Default
check_record, get_stage_checklist, explain_risk Record-check findings; the current step’s checklist; the risk facts, rules and route Default
get_way The way a plan runs under, its overlays and what changed since you last read it Default
request_cold_review Start a cold review at a depth and strictness, the cost first; also takes a plan file from outside Fir records
rerun_plan_check Re-run a stale or errored check records
waive_finding, dismiss_finding People only for waivers and for dismissing a blocking finding; agents may dismiss an advisory one with a reason records
start_planning_session A planning session on a plan draft, by text or by voice records
request_plan_approval, list_plan_approvals Run the checks and route; the ranked inbox records
ask_plan_question A question or decision row for the approver records
get_plan_outcome, get_portfolio Proofs, measurements and the outcome; the portfolio of a project or program records
list_lint_rules, explain_rule, test_lint_rules The rules a type applies; a rule’s source and examples; a backtest records
get_dispatch, get_accountability Dispatch rows with filters and scores; the plan’s ledger records

There is no approve tool for agents. A session can subscribe to fir://acme/storefront/plans/469/approval and learns when its plan is approved, voided or paused.