Artifact 61f4d0d05864023326337ea1c037059107f43a5a38f062123184b6621002bd3d:
- File
docs/rfcs/0006-strata.md
— part of check-in
[041ca46258]
at
2026-08-24 16:37:44
on branch strata-rfc
— RFC 0006: strata — stacked landings, rendered as a chain
The forge half of zit#144. A stack is a chain of dependent landings that land bottom-up; quarry renders the chain, refuses accept above the bottom, and flags a segment whose base was rejected.
No new index and no new artifact: the edge is already implied by a landing's target, so a stack is a reading of landings the way a landing is a reading of forum posts. (user: dmestas, size: 6667) [annotate] [blame] [check-ins using] [more...]
- 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.