---
title: "Plan repositories"
description: "Plans, specs, decisions, milestones and every engineering document as records in Fir, stored in the code repository's tree or in a plan repository, read through one index, linked to every commit and pull request without anyone typing, and answering why any line of code exists."
url: https://frazer.ai/docs/source/plans
index: https://frazer.ai/docs/source/plans/llms.txt
tokens: 8502
---

> For agents: this page is indexed at https://frazer.ai/docs/source/plans/llms.txt, and every page at https://frazer.ai/llms.txt. Copy commands from this file exactly.

# Plan repositories

A plan repository holds a project’s engineering records: plans, specs, decisions, milestones, runbooks and the other documents a change needs. Each record is a Markdown file with front matter, and Fir keeps it as an object: a number, versions made when it merges, typed blocks with stable anchors, and links stored in both directions to the commits, pull requests, checks and releases that touch it.

People meet records as **Plans**: Engineering › Source › Plans in the console, and the Plans tab of every repository. Agents use `fir record`, `fir plan` and `fir why`, and the records tools of Fir’s MCP server.

> **Two meanings of plan:** On this page a plan is the document a change is written against, such as `acme/storefront#469`. It is not the preview that `--dry-run` prints, and not a write that waits for approval.

## Two homes, one index

A record’s file is stored in exactly one **home**: the code repository’s own tree, or the project’s plan repository, such as `acme/plans`. There are never two copies. Everything people and agents use reads one **project index** of records, versions, numbers and links, never the storage location, so a record has the same type, checks, links, Why, place on Today, approvals and delivery to agents in either home.

| What differs | In the code repository (`records.home: repository`) | In the plan repository (`records.home: plans`) |
| --- | --- | --- |
| Where the file is | `docs/plans/…` in the repository’s tree and history | `acme/plans`, in its type’s folder |
| What a workspace shows | The files, as in any tree | The same path under `docs/plans/`, mounted: lazy, sparse, readable and writable |
| A pull request that edits it | Plan changes in the same repository, atomic with the code | Plan changes as a companion change to the plan repository: atomic in one cell, in order otherwise |
| Readers | The repository’s readers; a read grant on `docs/plans/` lets product or support read records without the code | The plan repository’s readers |
| Export to git | In the tree, always | With the plan repository; `export: materialize` also writes it into each code repository’s export |
| Number | By scope: a record about one repository takes that repository’s number (`acme/infra#88`) | The same rule: `acme/storefront#469` is stored in `acme/plans`; a project record takes the plan repository’s number (`acme/plans#50`) |

**The records folder.** `docs/plans/` in a code repository’s workspace shows every record about that repository, whatever its home: records stored in its tree are files of the tree, and records stored in the plan repository that are scoped to the repository or to the whole project are mounted beside them. It is one namespace: Fir refuses a create, a move or an enrollment that would put two records at one path. A new file goes to the default home for its type and scope, and Fir says where it went: `fir status` prints “stored in acme/plans”, and the console’s tree shows one entry, `docs/plans · 20 records · 14 stored here · 6 mounted from acme/plans`. Project-wide records are read-only in the mount unless your grant covers them.

### The setting

Settings › Plans › Records home, `.fir/records.yaml`, a Terraform resource and the API hold the same setting. It is layered organization → project → repository → type, and the more specific level wins unless a level above locked it:

```yaml
records:
  home: repository                 # repository | plans: where records about this repository alone are stored
  home_by_type: {}                 # optional overrides, such as {decision: plans} or {spec: repository}
  mount: {"on": true, path: docs/plans/}   # the plan repository's records about this repository, in its workspaces
  paths: [docs/adr/]               # extra record roots kept in this tree (an import keeps its folders)
  lock: false                      # an organization may lock the home for every repository
```

`fir record new --home plans` chooses the home for one record. Records that span repositories, and project records (goals, programs, milestones, risks, and the SLOs, incidents, lessons and reviews of the project), are stored in the plan repository whenever the project has one, so cross-repository work always has one place.

| Shape of the project | Default home |
| --- | --- |
| One repository, or a monorepo | The repository. No plan repository until a record spans repositories |
| Several repositories | Records about one repository in that repository; records that span repositories and project records in the plan repository, created with the first such record |
| A public repository | The private plan repository; public records, such as an open-source project’s RFCs, in the tree by choice |
| An imported repository | Where its records already are: `docs/adr/` or `specs/` become record roots, and moving them is one command later |
| An organization that wants no records in code repositories | The plan repository for every record, locked at the organization; the mount keeps the files in every workspace |

### Moving between homes

```sh
fir record move acme/infra#88 --to plans
fir record move --repository acme/infra --to plans --dry-run
```

A move opens one reviewed pull request: the file leaves one home and arrives in the other, atomic in one cell, in order otherwise. It is a `mechanical` version, so approvals carry. The record keeps its number, ID, key, versions, links, comments and approvals; the path under `docs/plans/` does not change, so agents and links in text see nothing move; the old storage path stays an alias. A move is also a permission change, and its pull request shows the readers it adds and removes before it merges.

Acme’s two choices (demo data): `acme/storefront` stores its records in `acme/plans` (`records.home: plans`), so product and support read plans without reading code, and its workspaces mount 37 records at `docs/plans/`. `acme/infra` keeps the default: plan `acme/infra#88` “Gateway egress through a fixed allowlist” is a file of its tree at `docs/plans/88-gateway-egress-allowlist.md`, beside runbook `RB-0012` and decision `ADR-0029`, because its runbooks travel with the Terraform tree into every workspace and every git export. Milestone `acme/plans#50` counts `#469` (stored in `acme/plans`) and `#88` (stored in `acme/infra`) the same way.

```text
# acme/plans, the plan repository
README.md                 # the project plan; appears as docs/plans/PROJECT.md in mounts
goals/  plans/  milestones/  risks/  briefs/  rfcs/  research/
specs/  decisions/  contracts/  architecture/  security/  glossary.md
runbooks/  slos/  incidents/  test-plans/  reviews/  docs/  standards/  lessons/
.fir/types/*.yaml  .fir/templates/*.md  .fir/views/*.yaml
.fir/records.yaml         # enrolled repositories, homes, mounts, record rules, key prefixes

# acme/infra, a code repository with records.home: repository
docs/plans/README.md                              # the repository plan (stored here)
docs/plans/88-gateway-egress-allowlist.md         # acme/infra#88 (stored here)
docs/plans/runbooks/RB-0012-rotate-egress-allowlist.md
docs/plans/PROJECT.md  docs/plans/milestones/50-peak-ready-checkout.md   # mounted from acme/plans
```

Record types follow a record’s **scope, never its home**: the project’s types apply to every record of the project wherever it is stored, and a code repository’s `.fir/types/` adds to the records scoped to it ([Record types](https://frazer.ai/docs/source/record-types)).

## What a record is

-   **A number** in its scope’s one sequence, shared with issues and pull requests, given when its first version merges, so an abandoned draft takes none.
-   **An ID** that never changes, wherever the file moves, and links point at it.
-   **A key** for types that carry one, such as `ADR-0031`, `RB-0007` or `RISK-003`, from the type’s own sequence on the server. Keys are never reused.
-   **Versions.** Each merge that changes a record makes a version, and Fir computes its **change kind** from the structured diff: `mechanical`, `tightening` or `material`. An approval carries across mechanical and tightening versions and is void on a material one ([The planning flow](https://frazer.ai/docs/source/planning-flow#what-carries-and-what-voids)).
-   **Blocks with anchors.** Headings with an ID (`## Retry a capture that times out {#CAP-4}`), typed rows (`AC1`, `D2`, item `1.2`), front matter fields, and prose anchored by quote. Comments, approvals and links attach to a block at a version and follow it through later edits.
-   **IDs reserved by the server.** The editor and the `reserve_ids` tool reserve block IDs, so two open pull requests never add the same `CAP-10`.
-   **States Fir owns.** States that come from events (`merged`, `done`, proof states, a decision in force) are written by Fir; nobody types them.

## Types, programs and milestones

Every file in either home is a record. A Markdown file with no type is a `doc`, any other file is an attachment, and a type is structure a team opts into: twenty-two built-in types in six groups, packs for regulated and other industries, and types of your own with no ceiling on what they can say. [Record types](https://frazer.ai/docs/source/record-types) has the catalog, the type language and the three ways to make a type.

| Group | Types |
| --- | --- |
| Direction | goal, brief, project plan, RFC, research |
| Work | plan (tiers fix, task, program, inquiry, incident, migration), milestone, risk |
| Truth | spec, decision, contract, architecture, glossary, threat model |
| Operations | runbook, SLO; a postmortem is a plan of tier incident |
| Quality | test plan (kinds tests, eval and experiment), review |
| Knowledge | doc, standard, instructions, lesson |

A plan that outgrows one file is part of a **program**: a tree of nodes with no fixed depth (program, plan, phase, section, item by default), run by many squads and models, with milestones whose progress counts only merges with passing proofs. A plan repository opens on **Today** for the person signed in. [Programs](https://frazer.ai/docs/source/programs) has the tree, Today, the views, the insights and milestones.

## Every commit and pull request linked

Fir writes every link from what it already knows, so nobody types one. A person is asked for one key at most.

| Where the link comes from | Who writes it | Trust |
| --- | --- | --- |
| The session’s **binding**: plan version, items, pull request, workspace | Fir, into the intent of every commit the session makes | attested |
| The **stack layer** made from plan items | Fir, from the layer’s items | attested |
| The workspace’s active plan (`fir plan use 469`) | Fir, from the person’s choice | declared |
| A **suggestion** accepted with one key: the active plan, the branch’s earlier pull requests, the issue the change fixes, plans whose paths cover the changed files | The person | declared |
| The **merge** | The merge queue, in the merge’s transaction | as the intent |
| A **check** at a merged version | Frazer CI | attested |
| A **release** | Frazer Releases | attested |
| An **import** | The importer | recovered |
| A model’s **inference** for history older than Fir, when asked | Fir | inferred until a person confirms |
| An **outside tool** (OSLC, a pasted URL) | The person or the tool | declared, never counted by a rule |

Every commit’s intent carries a link block, hashed into the commit’s ID:

```yaml
plan: {ref: acme/storefront#469, written_against: 4, digest: "b3:9f2c41…", trust: attested}
items: [1.2, 1.3]
implements: [payments/capture#CAP-4]
follows: [ADR-0031]
fixes: [acme/storefront#479]
session: s-81f2
receipt: {id: cr-9b3e, digest: "sha256:…"}
in_force_digest: "sha256:…"
epoch: 3
```

**A push is never refused for a missing link**: you can push any code you like. The record rules decide at the merge queue: `requires_plan: suggest` shows a red Plan row with the suggestion, `require` holds the pull request until it links a plan or a verified exemption. A commit made outside any workspace, from a laptop or a script, gets the suggestion at `fir pr create` and in the console’s pull request form.

| Link | From → to | Written by |
| --- | --- | --- |
| `written_against` | A commit, pull request or stack → a record version | The pull request’s intent, at merge |
| `implements` | A pull request or layer → a plan item or a requirement | The intent |
| `proves` | A check result at a version → a criterion or requirement | Frazer CI, when the result arrives |
| `covers` | A requirement, runbook, contract or threat → paths, services | Front matter, checked at merge |
| `governs` | A decision or a standard’s rule → paths | Front matter |
| `follows` | A pull request or plan → a decision | The intent; front matter |
| `in_milestone` | A plan or issue → a milestone | Front matter; the issue’s field |
| `depends_on` | A plan → a plan; a milestone → a milestone | Front matter |
| `derived_from` | A plan → an RFC, brief or research record | Front matter |
| `contributes_to` | A program, milestone or plan → a goal | Front matter |
| `mitigates` | A plan or requirement → a risk, threat or hazard | The risk’s mitigation rows |
| `learned_from` | A lesson → a postmortem, plan or incident | The lesson’s evidence rows |
| `planned_in` | An issue → a plan item | The plan’s items; the triage agent |
| `supersedes` | A record → the record it replaces | Front matter |
| `references` | A record → paths, symbols, commands, configuration keys | Parsed from the text |

A type adds link kinds of its own and says which links its records must have ([Record types](https://frazer.ai/docs/source/record-types#links-a-type-allows-and-requires)).

### Links survive every rewrite

Links point at the pull request’s stable `change_id` and the record’s ID, never at a commit hash or a key typed into text, so no rewrite breaks them:

| Rewrite | What happens to the links |
| --- | --- |
| A new version of a pull request (rebase, amend, push) | Nothing moves: the intent belongs to the change; “written against v3, the plan is at v4” shows when the plan advanced |
| A restack | Copied to the new version by restack kind; a `conflicted` restack carries them with the items’ proofs unproven at that version |
| A conflict resolved by a person or a model | A new version of the same change; links carry, and the version records how it was resolved |
| A fold, a split, a dropped layer | A fold unions the items; a split sends each item with the layer whose files match its paths and never leaves one in neither; a dropped layer’s items reopen |
| A squash merge, a rebase merge | One link row per merged commit, with the layer’s intent |
| A cherry-pick or a backport | `backport_of` plus the original’s links, at the plan version the original was written against |
| A revert | `reverts`; the lines get their earlier origins back; the items reopen |
| A record moved between homes, renamed or retyped; a repository renamed | Nothing changes; old paths, numbers and names become aliases |
| An export to git, and its import back | `Plan:` and `Plan-Digest:` trailers and `.fir/links.jsonl`; Fir’s own signed export comes back attested |

### Link coverage

“Everything is accounted for” is a number per repository and per project, over a window (30 days by default), on the repository’s Plans tab, in Settings › Plans › Rules, in Provenance and as the insight `link_coverage`. Counts are written at merge, so reading them scans nothing.

| Measure | Counted as | Target |
| --- | --- | --- |
| Merged pull requests | Linked (attested or declared), exempt by a verified class, or none | 100 % accounted for under `require`; 99 % or more under `suggest` when agents do most of the work |
| Merged commits | The same, per commit | The same |
| Lines at `main@verified` | Origin linked, exempt (generated, dependency, format), or older than Fir | Every line written on Fir has an accounted origin |
| Records | Records with no inbound link, requirements with no implementing merge, suspect links | Findings, never a held merge unless a rule says so |

```sh
fir links coverage --repo acme/storefront --since 30d
```

Before work starts, the plan check `plan/links` fails a plan when a link its type requires is missing or does not resolve ([The planning flow](https://frazer.ai/docs/source/planning-flow#plan-checks)).

### Suspect links, consistency and baselines

Links pin versions: when either end changes, the link turns `suspect`, and a passing proof clears it. Fir also checks **consistency**, not only links: a requirement and the test that proves it name the same values, and a decision in force and a requirement on the same path do not contradict. A **baseline** names a set of record versions and the commit of every enrolled repository; `fir trace` and `fir impact` accept `--baseline`. Traceability exports as CSV, JSON and ReqIF 1.2, and an OSLC RM 2.1 provider per plan repository lets requirement tools link to records live.

## Why for any line

Ask why any line, range, symbol, file, commit, test or configuration key exists, and one call answers with everything behind it:

1.  **Origin.** The change that wrote the line, read from the stored origin index. Format-only, move, rename and revert changes are skipped by their class, moves are followed across files, a generated line points to its generator and its source, and a vendored line to its dependency bump.
2.  **Change.** The pull request, its version and `main@N`, the layer and its stack.
3.  **Plan.** The plan version the change was written against, the plan now with its summary card, the item it delivered and the approval of that version.
4.  **Spec.** The requirements the change implements and the ones that cover the line, each with its proof state.
5.  **Decisions, then and now.** The decisions in force for the path when the change merged and today, each with how it evolved.
6.  **Session.** The session and its receipt: what it was given, for readers allowed to see it.
7.  **Evidence, shipped, after.** Proofs at the merged version, the release, and the reverts, incidents and issues that followed.
8.  **History.** Up to three earlier meaningful changes on these lines, each with its plan item.
9.  **Withheld.** What you may not read, as **Request access** where a readable record names it, and nothing otherwise.

```text
$ fir why services/checkout-api/payments/client.go:88
services/checkout-api/payments/client.go:88 at main@48213
  req.IdempotencyKey = o.CaptureKey()
Origin   #473 "Add idempotency keys to the payments client" · merged as main@48190 · coder for lena
         skipped: main@48198 (format only)
Plan     #469 "Payment capture retry" · written against v1, merge made v2 · now v3, in progress
         item 1.1 "Every capture call carries the order's key" · v1 approved by tomasz, Oct 13
Spec     payments/capture#CAP-7 "never capture one order twice" · proof NoDoubleCapture passed at main@48207
Decision ADR-0031 in force since Sep 24 · supersedes ADR-0019 ("keys from the cart ID"): a cart split into two orders
         and the gateway rejected the second capture as a duplicate · followed 4 times
Session  s-41a7 · receipt cr-5d2a · 6 sources, In force 7 rows
Shipped  checkout-api 2.14.0 · canary 25 %
History  #455 "Add the payments gateway client" (Sep 12) · plan #450 v3
```

-   **Stored, not recomputed.** The origin index is written at every merge from the parent’s line runs and the change’s hunks. Nobody keeps an ignore list: Fir knows each change’s class.
-   **Hard cases.** A line many layers changed answers with the newest meaningful change and lists the ones it replaced. A line in your workspace or an open pull request says “this pull request, not merged”. A line a conflict resolution wrote says how it was resolved and against what. Lines older than Fir show the import record, the recovered links and, on request, an inferred plan a person must confirm, labeled “before Fir”.
-   **Built for agents.** Sections fill in order until the budget is spent, each with its token count; a section that does not fit returns a handle; the stable prefix carries no timestamps, so prompt caches stay warm. `--concise` answers in about 250 tokens, one line per section; the full answer has a 1,500-token default budget. `--as-of main@48190` answers as of an earlier commit.
-   **Fast.** Designed to answer in under 3 ms at the median and 15 ms at p99 warm, end to end, and 60 ms at p99 cold.

```sh
fir why services/checkout-api/payments/client.go:88 --concise
fir origin services/checkout-api/payments/errors.go:10-24
```

`fir origin` shows a range’s origins with the moves and skipped changes.

## Provenance: what a change used and how it linked

Every pull request, layer, plan, decision and release has a **Provenance** tab, and agents get the same rows with `get_provenance`:

| Section | What it lists | Trust |
| --- | --- | --- |
| **Given** | Each receipt: the In force rows, the task, the sources with versions and anchors, and what was left out and why | attested |
| **Read** | Records and files the sessions opened, with version, time and how | attested; declared when a harness’s hook reported the read |
| **Cited** | Anchors cited in the plan, assertions, notes, handoffs, As built and the intent, and whether each resolves | attested |
| **Changed** | Files, records, symbols and contracts | attested |
| **Linked** | Every link row the change made or received, with kind, how, trust, by whom, when and who confirmed it | as each row |
| **Proved** | Criteria and requirements with their proofs at the merged version | attested |
| **Approved** | Approvals with signer, time and meaning, and what carried from earlier versions | attested |

The tab is a W3C PROV graph, exported as PROV-JSON and as an in-toto statement bound to the merged commit by its digest. It reads stored rows only, designed to open in under 5 ms at the median.

```sh
fir provenance '#482' --format prov-json
```

## Outside systems

-   **Move in.** The importers bring issues, pull requests, milestones, projects, wikis, documents, decision and RFC folders and requirement tools’ requirements into Fir as records and issues, reviewed once as pull requests.
-   **Keep identity.** Every imported object keeps its outside identity as an **alias**, such as `jira:PAY-88`, `linear:ENG-42` or `git:3f9c2e1`, with URL patterns, so a pasted outside URL turns into the record (the console’s search box and the `resolve` tool) and text in imported records keeps working.
-   **Link only as declared.** A live link to a system that stays outside is a `references` row of trust `declared`, shown with its fetch time and “outside Fir”. It never satisfies a record rule, never counts toward coverage and never enters In force, because In force needs a version Fir holds and can re-check. To make it bind, choose **Move into Fir**: the import opens as a pull request and keeps the outside identity as an alias.

## Record rules: Requires a plan, and more

A record rule asks for a record before a merge. Each rule has three modes: `off`, `suggest` (a red row with the fix; the merge is not held) and `require` (the merge queue holds). A rule is scoped by branch, path, change class, record type and risk class, has exemptions checked against the change’s class, and shows a 30-day backtest of what it would have held before you choose `require`.

| Rule | Asks | New repositories |
| --- | --- | --- |
| `requires_plan` | An approved plan, or a fix’s plan inline in the intent | `suggest` |
| `requires_spec_change` | A change to code a requirement covers names the requirement, or edits the spec | `suggest` once a spec exists |
| `requires_decision` | A new dependency, a new service, or an architectural path links a decision | `off` |
| `requires_contract_check` | A contract’s source passes its compatibility check; a breaking change needs its owners | `suggest` once a contract exists |
| `requires_runbook_review` | A change to alerting or a covered service updates the runbook, or records that it holds | `suggest` once a runbook exists |
| `requires_threat_review` | A change on security paths links the current threat model and one of its owners | `off` |
| `requires_review` | A plan of a risk class links a passed review of a kind, such as production readiness | `off` |

A type can bring its own rule. Every rule is a row of **Settings › Plans › Rules** on a repository, a plan repository, a project or an organization, where the stricter level wins; the same rows are `.fir/records.yaml`, a Terraform resource and the API. Agents read the rules that apply to their change with `get_record_rules` before they open a pull request.

## Editing

-   **People** open a record in the console: rendered, with its outline, typed blocks as widgets and the type’s form for front matter. Edit opens a draft in a server-side workspace that several people and agents can co-edit live; comments attach to a block or a quote, and text an agent wrote is marked. **Publish** opens the record’s pull request, or adds a version to it.
-   **Agents** write the Markdown file in their workspace and get typed errors with anchors on push (`sections.Outcome: AC3 has no proof`), or call `update_record` with block operations and `expected_version`, so two agents never overwrite each other.
-   **Merges** go by block and row ID, so pull requests that append As built entries or add requirements with reserved IDs merge cleanly; two edits to the same block conflict, as code does.

## Nothing set in rock

Every part of this page changes by a reviewed, versioned act that agents can read:

| What | How it changes | What people and agents see |
| --- | --- | --- |
| A project’s or repository’s home | Change the setting; `fir record move` moves what exists, in one pull request | The record shows “moved from acme/infra on Oct 20 by #512” |
| Link kinds | New kinds in a versioned catalog; types add their own; a renamed kind keeps its old name as an alias | `list_link_kinds` with versions; each row keeps the kind it was written with |
| A link’s trust | Rows are append-only: a person confirms or retires a row, with a reason, never edits it | The row’s history in Provenance |
| How origins are computed | A new version of the origin index, backfilled newest first; the old one serves until the backfill ends | Why names the origin version that answered |
| Why’s answer | Additive fields; a new section never reorders the stable prefix | The answer’s `format_version` |
| Coverage targets and record rules | Settings with history and owners | The rules page’s history; `get_record_rules` |

## Commands

```sh
fir record new milestone --title "Peak-ready checkout"
fir record new plan --home plans
fir record view acme/plans#50 --json
fir record list --type spec --path services/checkout-api/
fir record diff payments/capture v5 v6
fir record links acme/plans#50
fir record check docs/plans/specs/payments/capture.md
fir record move acme/infra#88 --to plans
fir record move --repository acme/infra --to plans --dry-run
fir record settings --repo acme/infra
fir plan new --from-issue 479 --tier task
fir plan use 469
fir plan view 469 --at main@48190
fir why services/checkout-api/payments/client.go:88 --as-of main@48190
fir origin services/checkout-api/payments/errors.go:10-24
fir provenance '#482' --format in-toto
fir links coverage --repo acme/storefront --since 30d
fir trace payments/capture --baseline storefront-2026.11
fir impact payments/capture#CAP-4
```

`fir spec view` and `fir decision view` are shortcuts for `fir record view` on that type. `fir plan versions`, `fir plan as-built --draft` and `fir record evidence --framework soc2 --period 2026-Q3` complete the set; the [Fir CLI reference](https://frazer.ai/docs/source/reference/cli#plans-and-records) lists every command.

## MCP tools

Every tool is also a `fir` command and an API method (`frazer.records.v1`). Tools in the default toolset load with Fir’s MCP server; the rest are in the `records` toolset.

| Tool | Does | Toolset |
| --- | --- | --- |
| `get_record` | Any record by number, key, slug or reference, at a version or now, whole, by block or concise | Default |
| `why` | Why a line, range, symbol, file, commit, test or key exists; `origin`, `as_of`, a workspace snapshot, `concise` | Default |
| `resolve` | A number, key, alias, outside URL or path to its record | Default |
| `get_plan`, `get_commit_plan`, `get_record_rules` | A plan; the plan version a commit was written against; the record rules for your change | Default |
| `lookup`, `get_summary` | Find any plan by key, item, path, symbol, milestone or text, with its card; a plan’s summary | Default |
| `assemble_context` | The record sections a task needs, each with its reason ([Agents and plans](https://frazer.ai/docs/for-agents/plans)) | Default |
| `get_origin`, `get_provenance`, `get_link_coverage` | A range’s origins with moves and skipped changes; the Provenance tab; coverage for a scope | `records` |
| `move_record`, `get_records_settings` | A move between homes, as a pull request; the layered records setting of a repository | `records` |
| `list_records`, `search_records` | Records by type, state, owner, path, milestone, program or link; full-text search | `records` |
| `create_record`, `update_record`, `reserve_ids` | Create from a template; block operations with `expected_version`; reserve IDs | `records` |
| `diff_record_versions`, `list_record_links`, `impact`, `trace` | Structured diffs; links both ways; what a change touches; the traceability matrix | `records` |
| `check_record` | The type’s rules and the readiness inputs, as the record check runs them | `records` |
| `get_mount` | A code repository’s records folder: stored and mounted records | `records` |

Types, programs, decisions and the planning flow have their own tools on their pages. Every record and version is also an MCP resource, such as `fir://acme/plans/records/50` and `fir://acme/plans/records/50/v2`; a session subscribes to the records it works from and is told when one changes.

## Moving in, and leaving

**Import** reads docs folders in common layouts (spec and plan folders, decision record folders, RFC repositories), issues, milestones and project boards, the pages, documents and projects of Notion, Confluence, Google Docs, Linear and Jira, and ReqIF 1.2 from requirement tools. A mapping preview shows what each source object becomes and what will not carry over before anything is written, and the import opens pull requests, so every imported record is reviewed once. Numbers and keys are kept. A repository’s own record folders stay where they are and become record roots; moving them is `fir record move`, later, with every version kept.

**Export** writes the files as they are, `.fir/types/`, a log of every version with its approvals (signer, time and meaning), every stored link with how it was made and its trust (`.fir/links.jsonl`), every alias (`.fir/aliases.jsonl`), and ReqIF for specs. Records stored in a code repository’s tree are in that repository’s export as they are, and each export writes a `.git-blame-ignore-revs` from Fir’s change classes, so plain `git blame` comes close to Fir’s origin. Import reads all of it back.

## Who sees what

A record stored in a code repository is readable by that repository’s readers, and a read grant with a path condition on `docs/plans/` lets people who do not read the code read its records. A record stored in the plan repository is readable by the plan repository’s readers. Path rules and sealed paths narrow both, so a restricted record lives on a restricted path such as `security/`. A link to a record you cannot read shows **Request access** when a record you can read names it, and nothing otherwise; counts count only what you can read. Approvals carry the signer, the time and their meaning, and are attested with the merge, so they cannot be copied to another record.

## Pricing

Records, types, versions, links, the index, Why with origins, provenance, link coverage, aliases, moves between homes, milestones with progress and forecasts, record rules, traceability, impact and context assembly are part of Fir; records are stored as Fir data. Work a model does (a cold review, a panel’s opinions on a decision, a drafted milestone update or summary, an inferred link for old history) bills as tokens through the LLM gateway.

## Related

-   [Record types](https://frazer.ai/docs/source/record-types): the catalog, the type language, versions and packs
-   [Programs](https://frazer.ai/docs/source/programs): the tree, Today, views, insights, milestones and squads
-   [Decisions](https://frazer.ai/docs/source/decisions) and [The planning flow](https://frazer.ai/docs/source/planning-flow)
-   [Stacks and conflicts](https://frazer.ai/docs/source/stacks): stacked pull requests, the merge queue and conflicts
-   [Agents and plans](https://frazer.ai/docs/for-agents/plans): what a session receives and how it reports progress
-   [Fir](https://frazer.ai/docs/source) and the [Fir CLI](https://frazer.ai/docs/source/reference/cli)

## Pages in Fir

- [Overview](https://frazer.ai/docs/source.md)
- [Plan repositories](https://frazer.ai/docs/source/plans.md) (this page)
- [Record types](https://frazer.ai/docs/source/record-types.md)
- [Programs](https://frazer.ai/docs/source/programs.md)
- [Person tasks](https://frazer.ai/docs/source/person-tasks.md)
- [Decisions](https://frazer.ai/docs/source/decisions.md)
- [Decide by conversation](https://frazer.ai/docs/source/decisions/conversation.md)
- [The planning flow](https://frazer.ai/docs/source/planning-flow.md)
- [Loops and learned checks](https://frazer.ai/docs/source/planning-flow/loops.md)
- [Stacks and conflicts](https://frazer.ai/docs/source/stacks.md)
- [Auto-merge and the merge queue](https://frazer.ai/docs/source/merge-queue.md)
- [Sessions](https://frazer.ai/docs/sessions.md)
- [Issues](https://frazer.ai/docs/source/issues.md)
