Skip to content
quarry Artifact [61f4d0d058]
Login

Artifact [61f4d0d058]

Artifact 61f4d0d05864023326337ea1c037059107f43a5a38f062123184b6621002bd3d:


- Feature Name: `strata` (stacked landings, rendered as a chain)
- Start Date: 2026-08-24
- Status: Draft for review
- Depends on: RFC 0001 §4 (event bus), §6 (CI); `docs/landings.md` (the record
  and its lifecycle); RFC 0004 §4 (capability model)
- Upstream: zit#144 — the CLI half. This RFC covers only what the forge adds.
- Findings, with the experiments that produced them:
  https://claude.ai/code/artifact/69ab2f7e-c60f-4cb3-ae8e-7da871a399cb

## Summary
[summary]: #summary

A **stack** is a chain of dependent landings: each segment targets the branch
below it, and they land bottom-up. quarry renders the chain, refuses accept on
anything that is not the bottom, and flags a segment whose base was abandoned.

The name is **strata** — layers deposited in order, each resting on the one
below, which is what the data already is.

**No new index and no new artifact.** quarry computes landings as a reading of
forum posts (`docs/landings.md`); a stack is a reading of those same landings.
The edge is already there: a landing whose `target` equals another open
landing's `branch` *is* a stack edge. Nothing needs a `depends:` field.

## Why this is small here
[why]: #why

Every stacked-PR tool in git automates a rebase. GitHub's native stacked PRs
(public preview 2026-07-30) rebase and retarget the whole stack server-side when
the bottom merges. That is the product and also the cost: force-pushes,
comments stranded as "outdated", cascading conflicts, CI churn.

zit cannot rebase, and does not need to. When a segment lands as a *merge*, the
segment above it still has the lower tip as an ancestor, so a later three-way
sees only its own delta. Measured against zit trunk `944ee007`, including the
case that forces a restack in git — two segments editing the same file:

    === after A landed, trunk shared.txt ===
    A-EDIT / line2 / line3 / line4 / line5
    === featB -> trunk probe (post-land, same file) ===
    merges   clean

So the forge's "restack" is **not a history operation**. It is one metadata
write per child, and zit#144 puts it behind `landing accept`. quarry's job is
to show the chain and to refuse the out-of-order action.

This also means the comment problem never arises. A landing names a *branch*,
not a frozen range, and comments are replies in its thread — so there is nothing
commit-anchored for a restack to detach. That is a property worth stating
because it is the single loudest complaint about stacked PRs elsewhere.

## What quarry adds
[what]: #what

### The chain, on the landings page and the record page

A landing that is part of a stack renders its position: what it sits on, what
sits on it, and how deep the stack is. The list view groups a stack under its
base rather than interleaving segments with unrelated landings.

Derived, not stored: follow `target` → `branch` across open landings. A cycle is
possible to express and must be handled as a rendering fault, not a crash —
report the chain as broken and name the segments involved.

### Accept is disabled above the bottom

Only the bottom of a stack is acceptable. quarry disables the control and states
the reason, in exactly the posture it already uses for a conflicted landing:
**a control that would fail is not offered.**

The refusal is zit's too (zit#144), so the rule holds for a CLI accept as well.
quarry disabling the button is the courtesy; the guard is upstream.

### An abandoned base is flagged

Reject the bottom and every segment above it is stacked on work nobody will
land. Those segments still report `merges clean` against their target, which is
true and useless. The record page says the base was rejected and names it.

### Events

Per RFC 0005's noun-and-action vocabulary, the stack needs no new nouns. A
retarget is a change to an existing landing, so it rides `landing.updated`;
opening and settling already have events. A pipeline that wants "the stack
advanced" subscribes to `landing.accepted` on the base and reads the chain.

Adding `landing.retargeted` is tempting and probably wrong: it describes a
mechanism, not a thing that happened to a repository, and RFC 0005's test for a
noun is that a person would recognise it.

### Capabilities

Unchanged. Accept still requires fossil's `i` (Write/check-in), because it
writes a merge check-in. Retarget writes a forum reply, so it requires `3`
(WrForum) like every other landing transition. No new capability letter, which
matters — RFC 0004 §4 is explicit that inventing one is quarry policy wearing
fossil's clothes.

## What this is not
[not]: #not

- **Not a merge queue.** The ordering guard plus the existing mergeability probe
  covers sequencing at cathedral scale. A queue answers contention that does not
  exist here.
- **Not a rebase engine.** Nothing in quarry rewrites history, and the whole
  advantage of this model is that it does not have to.
- **Not a new index.** Landings are already a reading of forum posts; a stack is
  a reading of landings.
- **Not speculative mergeability.** "Would this merge into trunk once its base
  lands?" is not exactly answerable before the base lands, and once zit
  auto-retargets it becomes the ordinary question the existing probe answers
  exactly. Rendering an approximation would be a confident wrong answer.

## Open questions
[open]: #open

- **Concurrent accepts.** Two people accepting adjacent segments at once, on a
  bare store. The upstream ordering guard reads state and then acts; the race
  window between them is unexamined, and quarry is where it would be observed.
- **Depth.** Everything above was measured on a three-deep stack. The merge
  property is structural rather than empirical, but nothing beyond three has
  been run.
- **Fold cost.** The chain is derived per view. On a store with many open
  landings this is a walk over all of them; whether it needs memoising on the
  same tip-pair key the mergeability answer already uses is unmeasured.
- **A stack spanning repositories.** Out of scope here, and probably meaningless
  — a landing assumes the branch is already in the store.

## The cost worth stating
[cost]: #cost

fossil never squashes and never rebases, so a deep stack leaves every
intermediate merge in permanent history — landing merges plus a restack merge
per revision of each base. Trunk stays correct and becomes visibly braided.

That is the trade this model makes: noisier history in exchange for never
rewriting, never force-pushing, and never stranding a review comment. It is the
right side of it, but the cost grows with depth in a way git's does not, and
history legibility — not correctness — is where a complaint would surface first.