---
title: "Stacks and conflicts"
description: "Stacked pull requests in Fir as the default unit of merging: a stack object with planned layers from plan items, typed edits, server-side restacks that never fail, approvals that follow each layer's own patch, one stack review for the approver, one queue entry per stack, and conflicts that are prevented, predicted and resolved without people at 10,000 pull requests a day."
url: https://frazer.ai/docs/source/stacks
index: https://frazer.ai/docs/source/llms.txt
tokens: 7843
---

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

# Stacks and conflicts

Most changes on Fir arrive as stacks: five or seven pull requests, each one concern a reviewer can read in one sitting, built on the one below. Fir makes the stack a first-class object, so restacking, review, CI, merging and conflicts all work per layer, and people approve the plan a stack implements instead of approving each layer.

## The model

**Every pull request is in a stack.** A single pull request is a stack of one layer, so there is one merge path, one review path and one API, and no feature works only for unstacked pull requests.

-   A **stack** is a server object: a name (`delivery-dates`), a stable ID, a base branch (`main`), its layers and their dependencies, and immutable **stack versions** (`s6`). It is never derived from branch names.
-   A **layer** is a pull request, with its number, versions, reviews, checks and intent. A reviewer of a layer reads only its own change, from its parent’s head to its own.
-   A **planned layer** is a slot made from a plan item before any code exists. `fir stack create --plan` turns a plan’s items into planned layers, so the whole shape is visible on the first day; opening a pull request for an item fills its slot.
-   **Shapes.** A line in the common case; a **graph** when a layer depends on several layers or siblings share one. A layer may also wait on a pull request outside the stack, or in another repository (“waits for #466”).
-   **States.** A stack is `draft`, `open`, `queued`, `merging`, `merged`, `partially_merged` or `closed`, with the flags `conflicted`, `blocked` and `behind_plan`. A restack in progress is never visible: readers see the old stack version or the new one.

```json
{
  "name": "delivery-dates", "base": "main", "stack_version": 6, "state": "partially_merged",
  "shape": "line", "merge_mode": "as_ready",
  "plan": {"ref": "acme/storefront#531", "written_against": 1},
  "progress": {"items_total": 6, "items_merged": 4, "items_done": 4},
  "layers": [
    {"pull_request": "#530", "kind": "plan", "state": "merged", "made": "#531 v1"},
    {"pull_request": "#535", "state": "merged", "items": ["1.5"], "restack_kind": "resolved"},
    {"pull_request": "#536", "state": "open", "items": ["1.5"], "restack_kind": "none"}
  ],
  "blockers": [{"layer": "#536", "kind": "outside_terms", "detail": "web/i18n/** is outside #531 v1's scope"}]
}
```

`get_stack` returns this (abridged here); agents ask for only the fields they need, such as `layers.state,blockers`.

## Edits

Every edit is one call with a list of typed operations, applied in one transaction that restacks what it must and makes one new stack version. `--dry-run` returns the new versions, their restack kinds and the conflicts it expects, without writing. A stale `--expect-version` fails with the current version, so two agents editing one stack never lose a write, and `fir undo` restores the previous structure.

| Operation | What it does |
| --- | --- |
| `add`, `insert` | A new layer on top, or between a layer and the layers above it |
| `split` | One layer into two or more, by paths, hunks, commits or symbols; approvals carry per file to the part that holds the file |
| `fold` | A layer into the layer below it |
| `move`, `reorder` | A layer onto other dependencies; a new order for a line |
| `drop`, `detach` | A layer out of the stack; a layer and what depends on it into a new stack |
| `absorb` | Edits in a workspace go to the layers that last touched those lines |
| `link`, `unlink` | Adopt existing pull requests into a stack, or release them |

An edit is refused, with a typed error naming the layer, when it would merge a layer before its dependency, form a cycle, touch a merged layer, or change a layer the caller may not write.

## Restacking

The server restacks, automatically, in **one transaction for the whole stack**, and a restack **never fails**:

-   When a layer gets a new version, every layer above it is rebuilt at once; when a layer merges, the layers on it move onto its merged commit before the merge is announced. When `main` advances under an open stack, nothing is written: the stack is shown rebased, and Fir rebases for real at merge, or on `fir stack restack`.
-   A layer whose files did not overlap what changed below it reuses its own change unchanged, so a clean 50-layer restack is 50 reuses and one transaction. Squash merges cause no phantom conflicts: the layer above simply takes the merged commit as its new parent.
-   A layer that cannot be merged cleanly gets a new version that holds the **conflict as data**, state `conflicted`. The layers above keep working on it, only merging waits, and the fix, once written, restacks everything above again.
-   Workspaces follow their layer: an agent’s workspace moves onto its lower layer’s new version at the next tool-call boundary (never in the middle of an edit), and its next tool result says `base_changed` with the kind and any conflicts. People’s workspaces show “#482 changed: Update to v3” instead.
-   When a lower layer changes a symbol that a higher layer uses (a signature, an error contract), the higher layer’s new version carries a **semantic hint** naming the symbol, and the Reviewer re-checks that layer.

Every restacked version records its **restack kind**, from comparing the layer’s own patch before and after:

| Kind | Means | People’s approvals |
| --- | --- | --- |
| `clean` | The layer’s patch is unchanged, three lines of context included | **Carry**, every file |
| `context` | Every hunk is the same, but lines near a hunk changed underneath | **Carry**; the Reviewer re-checks the touched hunks |
| `resolved` | The restack needed a resolution; everything else is identical | Carry, except on the resolved files, whose owners approve the resolution only |
| `conflicted` | The new version holds conflict terms | Kept but cannot count until resolved |
| `none` | Not a restack: an author’s push or an applied suggestion | Carry for files whose content did not change |

So stale-approval protection stays on: a restack that changes nothing a reviewer approved keeps the approval, and one that changes something does not. Approvals belong to a layer, never to the stack, and rules are evaluated against the stack’s base branch for every layer.

## Review and the stack review

-   **One layer.** A reviewer reads the layer’s own diff, with lines a higher layer changes again marked (“changed in #483”), code moved from a lower layer’s additions shown as a move with only its edits highlighted, the restack note (“v3 · restacked from v2, clean”) and the plan items the layer delivers with their proofs.
-   **The whole stack.** The stack page shows the map, the plan and its progress, the blockers and one primary action, and a whole-stack diff where every hunk is labeled with the layer that introduced it. “Changes since your last review” compares each layer’s patch with the version you last reviewed, so a layer whose newer versions are all `clean` reads “No changes since your review (restacked twice)”.
-   **Who reviews what.** `OWNERS` rules apply to each layer’s own files; the lowest unmerged layer comes first in its reviewers’ turn; the Frazer Reviewer reviews each layer with the layers below as context, then the whole stack once for issues between layers. Layers over 400 changed lines or 25 files get a suggestion to split, never a block.

**Approving a stack.** The person approves the plan’s terms once ([The planning flow](https://frazer.ai/docs/source/planning-flow#the-approval-binds-the-terms)). Every layer inside the terms merges on its proofs and the verifier’s PASS. The **stack review** is the one page that shows what is left for that person, and nothing else asks them per layer:

| Block | What it shows |
| --- | --- |
| Header | The plan version and its approval, the risk class and route, the merge mode, one count line (“7 layers · 4 merged on proofs · 1 needs you”) |
| **Needs you** | Each decision this person owes, ranked by what it blocks, one key each: a layer outside the terms, a layer on a never-automated path, a decision raised during the build, a conflict repair that left its hunks, a condition |
| Layers, bottom to top | Each layer’s items and criteria with proof states, whether it matches its item, the restack kind since your last look, how it merged |
| Since you last looked | The layers’ patch changes since your last visit, `clean` restacks folded |
| Merged without you | Each layer that merged on proofs, with its evidence; one marked as the day’s sample for your digest |

`A` approves the selected row, `J` and `K` move between rows, Enter opens the layer. At `approve_at: pull_request`, the page signs one review per layer you opened, at its exact version, in one act (“Approve layers 2 to 7”).

Demo (acme/storefront, Oct 16): plan `#531` “Show delivery dates at checkout” is R2, so kenji, an owner of `@acme/checkout`, approved it at 15:05. Agent `coder` for diego built the stack `delivery-dates`: `#530` the plan, then `#532` the API field, `#533` the estimates, `#534` a cache, `#535` the cart and checkout line, `#536` translations and `#537` an alert. The plan layer and four code layers merged, the code layers on their proofs; `#535`’s restack conflicted with another stack’s change to `web/cart/drawer.tsx` and structured merge resolved it. At 16:45 kenji’s stack review shows **Needs you (2)**: `#536`, because `web/i18n/**` is outside the plan’s scope (approve the layer, or add the path to the plan as an amendment), and decision `D3`, raised during the build. Two keys, and kenji’s day spent on the whole stack is the plan approval plus those two rows.

## Above the stack: the plan’s levels

A stack groups the layers of one concern. Above it, Fir groups by **intent**, not by size: every stack carries its plan **node**, the lowest common ancestor of the items its layers deliver in the [program tree](https://frazer.ai/docs/source/programs), and you see that node’s level name: a **phase** in Frazer’s built-in plan type, or a section, a plan or a program, at whatever depth fits the screen. The levels are your team’s: a type that calls a level “block” shows blocks. Campaign shards group by their campaign’s **wave**, dependency updates by their update group, and work outside any plan by repository. A level changes nothing about merging: its stacks stay the merge queue’s entries and merge in parallel across partitions, and what must land together is one stack, merged `together`.

**What a level gives you:** counts that add up at every level (open, in the merge queue, merged in 24 hours, merged with no person, merged with a person, reverted, exceptions open, closed); a **node review**; controls at the level (pause, throttle, freeze); and a release set when the level says `ship: together`.

**The node review** is the stack review raised to any level (`fir node review <ref>`, MCP `get_node_review`):

| Part, in order | What it shows |
| --- | --- |
| Header | The level, its plan version and approval, its risk class, and one count line in stacks and layers |
| **Needs you** | The decisions you owe across the level’s stacks, one key each, ranked by what they block |
| Stacks | One Standard row a stack, with its squares and its Next cell; a stack opens to its own review |
| Interfaces | One pass over what crosses the level’s stacks only (a type one stack adds and another uses, a migration and its readers); the stacks’ own verdicts are rolled up, never re-read in one large context, because one review over many changes catches far less than reviews of each |
| Merged without you | The merge receipts in Compact rows, folded past five, with the day’s sample to read |

Demo (priya at Pellwyn, Tue Nov 17 at 15:00, product UI, demo data): `pellwyn/plans#405` P9 “Dual-write parity for 7 days” · 10 stacks · 47 layers in 24 h · 44 merged on their receipts · 2 merged ahead of a blocked layer · 1 needs priya (a decision above the value line: whether a parity gap of one minor unit for 7 days blocks the cutover); the interface pass found nothing new.

**Stacks at scale.** The Stacks view opens with one count line in stacks, groups by plan level by default with each level one rollup line, and opens the groups that hold something for you first. A stack is one Standard row of 36 px: one square a layer up to eight, then a number (“▪▪▪▪▪▫ +24”), its name and version, its plan, its counts and the Next cell; stacks of one stay in the [pull request views](https://frazer.ai/docs/source#pull-requests-at-10000-to-50000-a-day). On the stack page and the review, merged layers fold into one line once there are more than five (“24 merged on their receipts · proofs 61 of 61 · verifier pass 24 · Reviewer 0 blocking”). In the merge queue each partition is one rollup line (entries waiting and testing, merged in 24 hours, time in the queue at p50 and p99, the window and the test batch size); see [Auto-merge and the merge queue](https://frazer.ai/docs/source/merge-queue). The count line and level rollups are designed to read within 5 ms at p99 on the server, a node review within 120 ms at p99 for a level of 500 stacks, and 2,000 stack rows to paint within 200 ms.

## CI for every layer

Every layer is tested, at about the cost of its own patch: task keys come from trees, so tasks a layer does not change are cache hits from the layer below, and a failure is bisected by layer. A whole stack is designed to cost at most 1.3 times one squashed run. A plan’s checks run on the plan layer like any other check.

## Merging

`fir stack merge delivery-dates --up-to 535` makes **one queue entry** for a set of layers closed under their dependencies. The queue rebases the set onto the running tip in memory, layer by layer, and merges every layer as its own squashed commit, with contiguous positions (`main@48231..48235`) in one compare-and-swap, so history, blame and revert stay per layer.

| Mode | What merges | Right for |
| --- | --- | --- |
| **`as_ready`** (the default) | Each layer as soon as it and every layer it depends on are ready; a failure at one layer still merges the green layers below it in the same test batch, and the failing layer leaves with its dependents and the culprit named | Almost everything: progress never waits on the slowest layer |
| **`together`** | The requested set merges in one test batch or not at all; positions inside the group are marked `interior`, never a target of `main@verified` or a release | Changes whose intermediate states must never be deployed |

A layer can also carry `merge_with_next: true` to glue it to the layer above. `--auto` admits each layer as it becomes ready.

**An independent layer merges ahead.** When a lower layer waits, a ready layer above it merges first, automatically, once Fir proves the two independent: it shares no path with the waiting layers, it uses nothing they add or change (no reference to, override of or test of their changed symbols in the code graph), their plan items have no declared dependency, the stack is `as_ready` with no `merge_with_next` between them, and its required checks pass at the reordered tree (the tip without the waiting layers; only the tasks whose keys change run). The merge record notes `merged_ahead_of: [#536]`, and the stack map shows the order (“#537 merged ahead of #536: independent”). `merge_ahead: auto` is the default for `as_ready` stacks; `suggest` asks for one key and `off` turns it off, per stack or per repository.

-   **Each layer is tested under its own path policy**: a layer on a `queue` path is tested on the tip first, and leaf-code layers above it merge in the same test batch when their own checks passed.
-   **Before every compare-and-swap** the server proves that each merged commit holds exactly its layer’s patch, that a layer tested as a cumulative tree merges the tree its checks ran on, and that the test batch’s final tree is the tip with every layer applied in order. A failed check aborts the test batch and keeps every entry queued: no merge is better than a wrong one.
-   **Every merge is an operation** with an ID and a state; an entry with no progress for 30 minutes reports `stalled` with its last step, so nothing sits on a spinner.
-   **After the merge**, a confirmed culprit layer is reverted together with the merged layers of its stack that depend on it, as one revert stack; `fir stack revert` opens the same by hand.

## Plans and stacks

-   **The plan is the bottom layer.** `fir stack create --plan new --from-issue 479` opens the plan’s pull request as layer 1 and turns its items into planned layers. Until the plan merges, the layers above are written against the draft’s digest, so the plan and the first code are reviewed at once, and nothing above layer 1 merges before the approval.
-   **Either home.** A plan scoped to one repository is an ordinary layer of that repository, whether its file is stored in the repository’s tree or in the plan repository as a companion change merged atomically with it; a plan that spans repositories is a layer in the plan repository, and the stack is cross-repository.
-   **Items tick as layers merge.** Each layer names the items it delivers; an item is `merged` when every layer that names it merged and `done` when its proofs pass at a merged version. The stack and the plan show “#469 v3 · 1 of 4 items merged, 1 done”. Nobody ticks an item by hand.
-   **Behind the plan.** When the plan moves past the version a stack was written against, the stack shows `behind_plan` with the item differences; `fir stack plan-sync` moves its open layers to the newest version, and every approval carries.
-   **Stack shapes.** A record type may declare `stack_shapes:`: an ordered list of layer templates with the items each delivers and how it merges. Built in: `expand-contract` (add the new form, write both, backfill, switch reads after `main@verified`, remove the old form), `flagged-ui`, `dependency-bump` and `api-change`. `fir-lint` flags a plan whose items break its shape, such as a reader switched before the backfill merged.

Across repositories, a stack lives at the project: layers in several repositories merge `together` atomically in one cell, or in order with holds such as `after: verified`, so a web layer never merges before the API it calls is deployable. In a monorepo, a stack’s layers often fall in different partitions of the merge queue and merge in parallel.

## Conflicts: few, found early, resolved without people

An **overlap** (two open units of work touch one path, symbol or contract) is not a **conflict**. A conflict is **textual** (hunks touch and cannot be reconciled), **structural** (add/add, modify/delete, rename/rename, or a plan node moved under two parents), **semantic** (each side passes alone and the combination fails) or **plan** (two plans’ terms contradict). Every conflict is data, never a stop.

### Prevent

-   **Approve plans, not layers.** Conflicts grow with the time work stays open, and a layer inside its plan’s terms merges in minutes on its proofs.
-   **Small layers, stacked.** Layers of one stack never conflict with each other, because each is built on the one below.
-   **Built-in rules for the cheap cases:** whitespace-only differences merge through the repository’s formatter, and set-like blocks (import lists, dependency tables) merge as sets. Each rule is a repository setting, on by default.
-   **Claims inform dispatch, never merge order.** Items of one plan whose paths overlap go to one stack, in order, so they never conflict; plans that overlap are caught when they are checked. Claims never lock a path and never hold a merge.
-   **Hot paths.** A file that many concurrent layers change is listed in the Conflicts insight with a remedy, cheapest first: a union merge driver, regeneration in CI, fragments (one file per entry instead of one shared file) or the `queue` policy. A remedy is a proposal to the path’s owners, never applied by itself.

### Predict

Fir holds every workspace’s snapshots on the server, so every snapshot is checked against every open workspace: a path index finds the candidates, sorted hunks are compared, an in-memory merge runs only where hunks touch, and the code graph flags semantic risk. Planned layers are checked too, so an overlap is known before code exists. The check is designed for 50 µs at p99 per snapshot with 10,000 open workspaces, and a warning reaches both sessions within a second.

| Result | Both sessions get | The later session does by default |
| --- | --- | --- |
| Textual conflict | `overlap.warning` with both hunks | Continues; when either side merges, the other restacks at once and resolves while its session is alive |
| Add/add (the same new path) | `kind: add_add` | Renames its file or reuses the other’s, at once |
| Modify/delete | `kind: modify_delete` | A decision row to both authors if the deletion is intended |
| Semantic risk | `semantic_hint` with the symbol and the change | Adapts its use, or asks |
| Plan conflict | A decision row to both plans’ owners | — |

**Following is a choice.** A warned layer may build on the other one (`fir stack follow 494`): it becomes an outside dependency and the layer restacks onto it now. Fir never does this by itself, because a follower waits and stays open longer; by default both proceed and the second to merge resolves.

### Resolve

Conflicts never stop work: the conflicted layer keeps its version, the layers above keep working, and only merging waits. Resolutions climb a **ladder**, cheapest first:

1.  **Built-in rules** for whitespace and sets.
2.  **Merge drivers** for hot files: union, regenerate.
3.  **Structured merge**: different entities changed in one file (functions, methods, keys, props) merge by syntax tree.
4.  **Resolution memory**: a conflict fixed before is fixed the same way.
5.  **Model repair** by the layer’s own session if it is alive, otherwise the repository’s repair agent, with the base, both sides, both intents and the tests.
6.  **A verifier** of another model family for a repair that left the conflicted hunks.
7.  **A person** last: both layers’ authors and the path’s owners get one decision row with the three sides, the failed repairs and a recommendation.

**Nothing merges unless the resolution invariant holds**, deterministically, whatever wrote the resolution: it parses, and the formatter changes nothing; it keeps both sides’ edits outside the conflict exactly once, none dropped and none applied twice; it changes only the conflicted hunks and adjacent lines, or it is marked `semantic` and goes to the verifier; and the layer’s required checks and the plan criteria it names pass at the resolved version. A resolver that fails the invariant is discarded and the next step runs. At `approve_at: plan`, a resolution inside the plan’s terms merges on its proofs; R3 and never-automated paths always need a person. Every resolution is recorded on the layer’s version, so `fir why` on a resolved line says how it was resolved and against what.

Each resolver and each structured-merge pattern is turned on per repository only after a replay of that repository’s last 500 merges shows it correct, and it is re-measured every month; the numbers are in the Conflicts insight.

### Merge at 40,000 a day

-   **Hybrid policy.** `direct` for leaf code, `queue` for paths that must stay serial, `hybrid` by default. Before a `direct` layer merges, the **target re-check** runs its affected tasks again if an interface it uses or changes moved since its checks, so a semantic break becomes a conflict before merge, never a revert after it.
-   **Partitions by affected targets.** Each protected branch’s queue splits into partitions by the build targets its entries affect, so entries with disjoint targets merge independently. An entry joins every partition it affects.
-   **Test batches sized by the measured failure rate**, a stack always whole; windows shrink only on CI failures, never on conflicts found before CI ran; an entry enters the queue only when each of its dependencies is merged or ahead of it in a partition they share; a failing layer leaves with its dependents.
-   **Speed is prevention.** Proofs and the second opinion take about 6 minutes at the median and CI runs on cached task keys, so a layer is open for minutes, not hours.
-   **Repair, then regenerate.** Three repair attempts behind the resolution invariant and the proofs; when they fail, an agent’s layer is written again from its plan item on the new base by another model family, behind the same proofs and a full second opinion. When funds are out it does not run, and the conflict waits for a person.
-   **Intent clashes are settled once, at the plans.** A plan that deletes or moves paths another open plan’s items change is flagged when the plans are checked, so their owners decide once per pair, before code exists.
-   **Flakes** are retried within their test’s flake budget, or confirmed by a later green tree that contains the layer.
-   **Contract breaks between squads** are held outside the partitions with the consumers named, so they never block unrelated work ([Programs](https://frazer.ai/docs/source/programs#many-squads-many-models)).

| Target | 23,000 pull requests a day | 40,000 a day | 100,000 a day |
| --- | --- | --- | --- |
| Layers that conflict | 10 % or fewer | 15 % or fewer | 25 % or fewer |
| Conflicts that reach a person, per 1,000 merged layers | 6 or fewer | 9 or fewer | 20 or fewer |
| Conflicts resolved without a person | 93 % or more | 93 % or more | 93 % or more |
| Conflict to green | 12 minutes at the median, an hour at p90 | The same | The same |
| Post-merge reverts per 1,000 | 0.1 or fewer | The same | The same |
| Merged resolutions that fail the invariant | 0 | 0 | 0 |

These are the targets Fir is designed and tested for, measured on replays of real histories before they are claimed.

## Limits that stop runaway stacks

| Limit | Default | Hard cap |
| --- | --- | --- |
| Layers per stack | 30 (more asks for a reason) | 100 |
| Open layers per stack | 20 | 50 |
| Open stacks per agent session | 5 | 20 |
| Structural edits per stack an hour | 120 | — |
| Versions of one layer in an hour | 20, then CI pauses and the person is asked | — |
| Idle stacks | A reminder at 14 days; closed as abandoned at 30, undoable for 90 | — |

Every limit is a repository setting within the caps, every refusal is a typed error with the limit’s name and value, and no limit ever blocks a server restack, a repair or a revert.

## For agents

1.  **Build layer by layer.** `fir stack create --plan 469` makes the stack with its planned layers; push layer 1 from your workspace, then `fir stack add --ws` gives you a workspace for layer 2 on layer 1’s head. Or work in one workspace and split at submit: `fir stack submit --split-by plan` builds each layer and checks that no layer uses a symbol only a higher layer adds.
2.  **Never rebase by hand and never force anything.** Read `base_changed` and act only on `conflicted` or a semantic hint.
3.  **Read a warning and keep working.** Rename at once on add/add; adapt on a semantic hint; follow another layer only when it is truly a prerequisite.
4.  **When your layer is conflicted,** call `get_conflicts`, write a resolution that stays in the conflicted hunks, and push it as the next version. Never merge a resolution the invariant refuses.
5.  **One stack, one story.** A layer that cannot be described in one sentence is usually two layers. Layers authored by others are read-only to you unless their author grants you push.

```sh
fir stack create --plan 469
fir stack add --ws
fir stack view delivery-dates --json
fir stack merge delivery-dates --up-to 535 --auto
fir overlaps --json
fir conflicts 535
fir resolve 535 --tool structured
fir hot --by conflicts
```

| Command | What it does |
| --- | --- |
| `fir stack create`, `fir stack submit` | A new stack, from a plan or from the current workspace |
| `fir stack view`, `fir stack list`, `fir stack log` | The map, states and blockers; stacks; stack versions with operations and actors |
| `fir stack add`, `insert`, `split`, `fold`, `move`, `reorder`, `drop`, `detach`, `absorb`, `link`, `unlink` | The typed edits; each takes `--dry-run` and `--expect-version` |
| `fir stack restack`, `fir stack plan-sync` | Rebase onto the newest `main` now; move to the plan’s newest version |
| `fir stack merge`, `fir stack revert` | Merge a set of layers; revert a layer with what depends on it |
| `fir stack up`, `down`, `top`, `bottom` | Move your workspace to another layer’s workspace |
| `fir stack follow` | Build on another stack’s layer |
| `fir stack close`, `reopen` | Close or reopen a stack, undoably |
| `fir overlaps`, `fir conflicts`, `fir resolve`, `fir hot --by conflicts` | Open overlaps; a layer’s conflicts; resolve one with a resolver; the hot paths |

| MCP tool | Does |
| --- | --- |
| `get_stack`, `list_stacks`, `get_stack_blockers`, `get_stack_review` | A stack, its blockers as data, and the stack review’s rows |
| `create_stack`, `submit_stack`, `edit_stack`, `merge_stack`, `revert_stack` | Writes, with `expected_stack_version` and a request ID |
| `get_overlaps`, `follow_layer` | Every open overlap with its kind, hunks and suggested action; building on another layer |
| `get_conflicts`, `resolve_conflict`, `get_hot_paths` | Base, sides, intents and tests; a resolution as a new version through the invariant; hot paths with remedies |

The tools are in the `stacks` toolset, loaded on demand. Events: `stack.restacked`, `stack.layer_conflicted`, `stack.layer_merged`, `stack.stalled`, `overlap.warning`, `conflict.resolved` and `conflict.escalated`, among others; for people they are digested per stack, never one message per layer.

> **Settings, all per repository:** `conflicts.rules`, `conflicts.drivers`, `conflicts.structured`, `conflicts.memory`, `conflicts.repair`, `conflicts.follow` and `conflicts.warnings` each have a default, and changing one is a reviewed change to `.fir/` that replays the repository’s last 500 merges first.

## Related

-   [Fir](https://frazer.ai/docs/source): workspaces, pull requests and merge policies
-   [The planning flow](https://frazer.ai/docs/source/planning-flow): approving the plan a stack implements
-   [Plan repositories](https://frazer.ai/docs/source/plans): how links survive restacks, folds and splits
-   [Fir CLI reference](https://frazer.ai/docs/source/reference/cli#stacks-and-the-merge-queue)

## Pages in Fir

- [Overview](https://frazer.ai/docs/source.md)
- [Plan repositories](https://frazer.ai/docs/source/plans.md)
- [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) (this page)
- [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)
