# Landings

A branch is finished. There is no way to say so.

That is the gap a landing fills. zit can create the branch, commit to it,
merge trunk into it and merge it back — but the act of *proposing* that
it land leaves no trace: nothing to review, nothing to comment on,
nothing to accept or reject, nothing for CI to fire on. The work goes
from "on a branch" to "on trunk" with no event in between.

## This is not a pull request

GitHub's pull request is a **bazaar** mechanism. It exists because a
stranger cannot write to your repository, so they fork it and *request*
that you pull. Every piece of its ceremony descends from that premise:
the fork, the head/base repository pair, the frozen commit range.

Inside a cathedral that premise does not hold. Anyone with the check-in
capability can already push a branch, and the branch is already in the
store. Nothing needs to be transported, filtered or quarantined, because
there is no trust boundary to cross.

So the artifact is not a request to transfer commits. It is a **decision
record about a branch that is already here**, and the name follows the
direction the work actually moves: nobody requests a pull; the branch
**lands**.

## What a landing is made of

**No new artifact type.** This is the constraint the whole feature hangs
from, and zit states it as a rule rather than a habit: *if the
implementation reaches for a new card, the design is wrong.*

A landing is three ordinary fossil artifacts:

| part | artifact |
|---|---|
| the record | a forum thread whose root body opens with a marker |
| every comment and state change | a reply in that thread |
| the outcome | a raw tag on the check-in that landed |

The root body carries the header:

    zit-landing: 1
    branch: <name>
    target: <name>

    <the author's message>

and a transition is a reply whose body opens with `zit-landing-state: X`,
where X is one of `open`, `accepted`, `rejected`.

**Why it matters:** clone a repository carrying landings with stock
fossil and it sees forum threads and tagged check-ins. Fully readable,
merely not actionable. That is the correct failure mode, and it is why
no wire-protocol extension and no compatibility break were needed.

## The lifecycle

### Open

    zit landing open --branch feat/x --to trunk -m "why this should land"

or **New landing** on the forge's landings page, which offers the
branches that exist rather than a text field that accepts a typo, and
defaults the target to the repository's own default branch. `--to`
defaults to trunk on the command line. Either way this mints the thread
root and leaves the branch unmerged; zit refuses a second open landing
on the same branch by name.

On a mirror the control names the upstream instead: a tracking store
takes no local writes, so proposing there would fork it by accident.

### Discuss

Replies in the thread, from the CLI or the record's page. The page
renders them as a discussion; markdown previews through the same
composer the wiki and forum use.

### CI

Opening a landing is an event a pipeline can fire on, as is a new
check-in on a branch with an open landing — the intended workflow keeps
merging the target into the branch and testing there.

### Accept, or reject

    zit landing accept <id>     # merge to the target, settle the record
    zit landing reject <id> -m  # settle it, merge nothing

**The order is the contract.** Accept merges and commits *first*, then
writes the outcome tag and the transition reply. A failure after the
merge leaves merged work under a still-open landing, which one command
settles. The reverse order would leave an accepted record over an
unmerged branch — a lie in a log that cannot retract one.

## What the forge adds

Quarry reads landings out of its own index rather than the store: the
record is a *reading* of forum posts, recomputed whenever any post in a
thread folds, so a reply indexed before its root converges on the same
answer.

**Who may accept.** Accept writes a merge check-in, so it requires
fossil's `i` — Write/check-in. Everything else about a landing is a
forum artifact, so opening, commenting and rejecting require `3`
(WrForum). Rejecting merges nothing and therefore needs nothing more
than the capability to speak.

There is deliberately **no rule against accepting your own landing.**
Inside a cathedral the author already holds the commit bit, and a
required second reviewer is a policy fossil has no capability letter
for; inventing one would be quarry policy wearing fossil's clothes.

**Tickets a record touches.** A landing's message may say what it does
about tickets, in two verbs:

    closes ae12f3      accepting the landing closes that ticket
    addresses ae12f3   the landing works on that ticket, and finishes nothing

`fixes` and `resolves` are spelled differently and mean `closes`. The
reference must follow the verb immediately — "this closes the gap that
ae12f3 describes" declares nothing, because the token is four words
away. Cross-repository references are shown but never acted on: a
landing here has no business settling work in another store.

Both verbs LINK: the ticket page lists every landing and thread that
named it, with the landing's state, so a reader sees "something landed
for this" without opening anything. Only `closes` acts, and only once —
a ticket somebody already resolved keeps their resolution. The chip the
reader sees is produced by the same parser the accept path acts on, so
there is no way to write a reference that acts without appearing, or
appears without acting.

The declaration may sit in the title or the body; the title is where
one-line landings put it.

**A moving branch.** The record references the branch, never a frozen
range, because the intended workflow keeps committing to it after the
record is opened. So the diff is computed at view time, and a landing
page shows a bounded summary with a link to the whole change.

**Conflicts are read, never discovered.** A forge must never learn
whether a branch merges by attempting the merge, because on a server the
attempt is the damage. Quarry asks the store (`zit landing show`), which
answers `merges clean`, `up-to-date`, or `conflict (N)` with the paths.
A conflicted landing renders as blocked, names the files, and disables
accept rather than offering a control that would fail. The answer is
memoised on the pair of check-in tips, so a push invalidates it by
producing a different key.

## What a landing is not

It is not a takedown, and it is not an outside-contribution path. A
landing assumes the branch is already in the store. Accepting one does
not unpublish anything a peer already holds, and no state here reaches
across the trust boundary that bundles and imports exist for.

## Sources

- zit#127 — the ceremony, and the decision to build it from artifacts
  fossil already has
- zit#131 — the mergeability probe and bare-store accept, which is what
  lets a forge with no working tree settle a record
- RFC 0004 §4 — the capability model the accept rule follows
