# zit 0.3.0

zit 0.3.0 is a workflow release. 0.2.0 closed the store and dialect work;
0.3.0 is what happens when a person then sits down and uses the verbs all
day. Its centre is the Fossil-parity programme on everyday verbs:
a Fossil user's fingers now work, the receipts and narration Fossil prints
are printed, and a differential harness runs one scripted session through
both tools and pins every place they differ. Around that sit landings and
strata (a branch proposed for trunk as a reviewable artifact, and stacks of
them), per-request branch protection for a fronted `serve`, Fossil's user
table, and a round of read-path performance work that took the common
verbs from "scales with the store" to "scales with the change".

Nothing in this release changes an artifact, a tag namespace, or a sync
message. A stock `fossil` still clones, pushes, and pulls a 0.3.0 repository
byte-for-byte. Two local records grew an optional field each (the checkout
record and the undo journal); both read older records unchanged.

## Highlights

- **Fossil muscle memory.** Verb prefixes and Fossil's aliases (`ci`, `co`,
  `rm`/`delete`, `changes`, `rename`, …), a suggester for typos, Fossil's
  update and merge receipts, network narration that names the peer, the
  commit editor when `-m` is absent, and checkout-relative names
  (`current`, `prev`, `next`, `trunk~2`). `zig build muscle` runs the same
  27-step session through `fossil` and `zit` and fails on any divergence
  that is not recorded as deliberate.
- **The weekly verbs, filled in.** `branch new|close|reopen|hide|unhide|
  current|info`; `clone URL` derives its directory and opens the tree;
  `mv` takes many operands and directories; `diff` takes paths and grew
  `--numstat`, `--invert`, `--checkin`, `--branch`, `--by`; `merge
  --integrate`, `--baseline`, a bare `merge` onto the one other open leaf;
  `stash snapshot|diff|goto` and `apply --merge`; `revert -r`; `-n` on
  `revert`, `undo`, `redo`, `mv`, `merge`; `settings editor`, `autosync
  pullonly`, `--changed`, `--value`; `grep -i -c -l -v --once`;
  `annotate -n -l`; `timeline -F html`.
- **Landings and strata.** `zit landing` proposes a branch for trunk as a
  forum thread plus a tag on the check-in — a reviewable record any forge
  can display, accept, or reject, from a bare store. Landings stack
  (`strata`): a branch may target another branch with its own open landing.
- **`serve` can protect branches** on a trusted front's say-so: membership
  changes to a named branch are refused per request, including a
  check-in's own singleton claim.
- **Fossil's user table travels.** `import-fossil` and `config pull user`
  carry logins, capabilities, and password hashes; `zit users` reads them.
- **Read paths scale with the change.** `diff`, `status`, `stat`, `settings`,
  `artifact`, and store open no longer derive the whole store per call: a
  stat memo skips re-hashing unchanged files, index v3 carries a sorted
  directory so opening builds no hash map, adopted index entries slice the
  blob instead of copying it, and CRC32 uses the ARMv8 instruction where
  present. `update` and `open` materialize large trees about twice as fast.
- **`import-fossil --submanifest` is usable on real corpora.** Each
  check-in's tree is built from its parent's with the sub-manifest editor,
  SSH-signed manifests are accepted, the whole-history replay gate is gone,
  and the conversion also runs straight from a Fossil URL or as
  `submanifest convert` on a zit store. A 26-hour pkgsrc import became a
  matter of minutes.

## Everyday verbs

The programme's three rules held throughout: no artifact, tag namespace,
or sync message changed; the exit-status contract and silent success on
stdout survived; where Fossil has a spelling it was adopted exactly, with
zit-only forms added beside it, never instead.

### Dispatch and names

- Any unambiguous prefix of a verb dispatches (`zit stat` still means
  `stat`; `zit timel` is `timeline`). Ambiguity is a two-line diagnostic
  naming the candidates.
- Fossil's aliases are accepted: `ci`, `checkin`, `co`, `checkout`, `rm`,
  `delete`, `changes`, `rename`, `ls`/`dir`, and the rest listed under
  `zit help`.
- The typo suggester never proposes a destructive verb for a short token.
- `current`, `ckout`, `prev`/`previous`, `next` resolve relative to the
  checkout; `NAME~N` and `NAME^N` walk parents; `trunk^` alone is the same
  as `trunk` (Fossil's trailing-punctuation rule), no longer silently the
  tip of something else.

### Receipts and narration

- `update` prints Fossil's receipt: a line per changed file, an
  `updated-from`/`updated-to` block with dates, tags, and comment, and the
  `zit undo` hint. `-n`/`--dry-run` and `--latest` are accepted.
- `pull`, `push`, `sync`, and `clone` name the peer (`pull from URL: …`),
  share one no-op phrase (`already in sync`), show per-round progress on a
  terminal, and `clone` prints the project code. A dead peer is named.

### Commit

- With no `-m`, `commit` opens `$VISUAL`/`$EDITOR` (or the new `editor`
  setting) on a template that lists the changes; the comment survives a
  failed commit in `.zit-ci-comment`. `-M FILE`, `--editor PROG`, `-n`,
  `--allow-empty`; `--no-warnings` is `--no-checks`.
- Fossil's warn-by-default on binary and CRLF content was weighed and not
  adopted: zit's content gate — `binary-glob`/`crlf-glob`, honoured
  from versioned `.fossil-settings/` too — stays opt-in, so an unset glob
  is "no opinion", never "refuse everything".

### Reading history

- `timeline -b BRANCH | -c`, `-p PATH`, `-u LOGIN`, `-r`, `--offset N`,
  `-v`, `-F oneline|medium|full|html`, `*CURRENT*` and `*MERGE*` marks,
  `--weekday`.
- `status` classifies (`--added`, `--edited`, `--missing`, `--conflict`,
  `--extra`, `--differ`), detects conflict markers, and prints a header
  with `-v`; `-R` works on `pull`, `push`, `sync`, `remote`.
- Not taken, and why: `--localtime` (no tz database), a global `-U`
  (collides with `commit --user`), `--chdir` (no chdir in std.Io).

### The weekly verbs

- `branch new NAME [BASIS]`, `current`, `close`/`reopen`/`hide`/`unhide`
  (control artifacts, as `tag add --raw` mints them), `info NAME`, list
  `-c -t -r`.
- `clone URL` derives DIR from the URL and opens the working tree in it;
  `--no-open` keeps a bare store; the cone is carried into the open. `open
  URL` delegates to clone.
- `mv OLD... NEW|DIR`: several files into a directory, a tracked directory
  as a unit, `--soft` to record without moving, `-n` to preview. The
  managed set now records one pending rename per moved file, so a commit
  carries every old name.
- `revert -r VERSION` restores another check-in's content without moving
  the checkout; `revert -n`, `undo -n`, `redo -n` name what they would
  touch. `add -f` takes ignored files in a directory expansion; `clean -n`,
  `-f`, `--emptydirs`.
- `diff` takes PATH operands; `--numstat`; `--invert`; `--checkin V`
  (against its parent); `--branch B` (tip against its fork point); `-Z` is
  `-w`; `-N` is accepted; `--by` writes a side-by-side HTML page under
  `$TMPDIR` and opens it from a terminal.
- `merge --integrate` closes the merged leaf when the merge is committed
  (the checkout record carries the leaf's hash as an optional sixth field;
  `commit` mints the same control artifact `branch close` does);
  `--baseline B`; `-n` is `--probe`; a bare `merge` takes the one other
  open leaf and names them when there are several.
- `stash snapshot` saves without touching the tree; `stash diff [ID]`;
  `stash goto [ID]` updates to the entry's check-in and applies; `apply|pop
  --merge` three-way merges into a dirty file, with markers, a conflict
  list, and exit 5.
- Settings: `editor CMD` (executable tier, after `--editor`, before the
  environment; a configured editor makes `commit` editor-capable without a
  terminal), `autosync pullonly`, `--changed`, `--value`. Both new settings
  ride the keyed config block; older stores read unchanged.
- `grep -i -c -l -v --once`; `annotate -n N` (look back N check-ins) and
  `-l` (the check-ins consulted).

### The `fossil ui` answer

- `diff --by` and `timeline -F html` render the two pages people open most.
- `zit ui` launches quarry's single-repository local mode (`quarry ui
  <checkout root> ARGS...`, binary from `ZIT_QUARRY` or `PATH`); when it
  cannot be started the verb says so, points at the two static renders,
  and exits 1. quarry RFC 0010 specifies the mode.

### Acceptance

`zig build muscle` runs 27 steps through `fossil` and `zit`, comparing exit
classes and speech. Every divergence is either `same`, `by_design` with a
reason (the `changes` alias header, `tag list` excluding branches, the dead
peer's exit class, binary content gating), or a failure. It runs in CI.

## Landings and strata

- `landing open` proposes a branch for trunk as a forum thread plus a raw
  tag on the check-in; `landing ls`, `show` (the check-ins being proposed,
  mergeability, and the thread), `comment` (`--reply-to` aims the I-card at
  a post), `accept`, `reject`, `update` (bring the target into the proposed
  branch on the store).
- `accept -R` merges against a bare store in a working area it creates,
  refusing conflicts, so a forge can accept without a checkout. `merge
  --probe` answers mergeability for any pair.
- Strata: a landing may target another branch with its own open landing;
  accepted landings close the landed leaf without propagating; cycles,
  unresolvable targets, already-contained branches, and rejected or
  already-landed bases are refused with the reason.
- The record scan no longer parses every blob to find landings. The
  first line of `-m` is the landing's title; N cards follow Fossil's
  per-type write rule.

## Serve and sync

- Per-request branch protection behind a trusted front: `serve` refuses
  membership changes to protected names, including a check-in's own
  singleton claim, and warms the image only after the refusal check.
- The sync client's holdings are log-backed instead of a whole-store
  snapshot, and `serve` reads push policy from the snapshot rather than
  scanning the log per round — the 20-minute clone stall at ~1.1M
  artifacts is gone.

## Users and configuration

- A `.user` frame kind carries Fossil's user table; `import-fossil` adopts
  it, `config pull user` fetches it from a peer with credentials, `zit
  users` reads it.
- `.fossil-settings/*` is honoured beside `.zit-settings/*`, Fossil's
  spelling winning, so a mirrored Fossil project keeps its ignore globs.
- `settings` and `config` accept `-R` on a bare store.

## Performance

- Store open: index v3 carries a sorted directory (no 255k-key hash map to
  answer one lookup); adopted index entries slice the blob instead of
  copying it; CRC32 uses the ARMv8 instruction where present. Opening the
  302MB tcl store: 47ms → 20ms.
- `diff`, `artifact`, `settings`, and the `diff`/`status` baseline read
  through the image path and the scan index instead of deriving the whole
  view per call; a per-file (mtime, size, hash) memo in
  `.zit-cache` skips re-hashing unchanged files.
- `update`/`open` stage payloads once and rename them into place: about
  2x on large trees. `pack` trusts profitable at-rest deltas and no-ops an
  unchanged log. `ls --long` per-file cost no longer scales with the store.
- The first read after a sync no longer pays a multi-second cache rebuild:
  two quadratic scans inside the image serializer were the cost, not the
  maintenance model. Every verb no longer pays O(store) DWARF stack
  unwinds; the release binary is a third of its former size.
- `timeline --weekday` uses Ben Joffe's branchless day-of-week.

## Sub-manifest import

- Each check-in's tree is built incrementally from its parent's with the
  sub-manifest editor rather than from scratch; baseline manifests are
  read and parsed once; SSH-signed manifests are stripped and verified per
  pair in the mint loop.
- The whole-history replay gate and `--force` are gone: the gate replayed
  every commit through a second converter and disagreed with the store by
  10–20x on cost.
- `import-fossil URL --submanifest` converts straight from a Fossil server;
  `submanifest convert SRC DEST [--k N]` re-mints a flat zit store.
  `fossil_convert` mints FLAT when the names do not partition.

## Indexer feeds

- `frames --structural` emits only what the crosslink links (content blobs
  dominated a full stream: 13.2GB on pkgsrc).
- `crosslink` streams the derived per-check-in records, with the U-card
  user and the changed files, as a CLI contract for indexers.

## Fixes

- A second checkout on a shared store (`open --store`) no longer treats the
  other checkout as "current" for `update` and `merge`.
- `update` carries uncommitted work across the move by three-way merge,
  recording no merge parent; `merge` merges into a dirty tree the same way.
  `undo` restores the uncommitted bytes either way.
- `update` on a never-opened clone no longer uses memory that scales with
  corpus size: the client sits on the same log-backed store `serve` uses.
- `logstore` answers a byte-aligned name prefix from the sorted directory;
  a complete SHA-1 name resolves.
- RFC test vectors are kept inert on disk so Fossil's crosslinker cannot
  mistake one for a real artifact.
- `diff -w` ignores whitespace-only changes in hunks and `--brief`.

## Compatibility

- Artifacts, tags, and the sync protocol are unchanged; Fossil RFC
  revision 00 remains the target.
- The checkout record (`.zit-checkout`) gained an optional sixth field
  (`integrate`), written only when set; a record without it is
  byte-identical to the five-field form. The undo journal's format version
  is 4 (a sixth string); an older journal reads as damaged, which is the
  documented posture for transient working-tree state.
- The repository config block gained two keyed entries (`editor`,
  `autosync_mode`); unknown keys were always skipped, so 0.2.0 reads a
  0.3.0 store.
- `clone URL DIR` now opens the working tree; scripts that ran `zit open`
  afterwards should pass `--no-open` or drop the second step. `mv` with
  three operands moves into a directory instead of failing; `merge` with
  no NAME merges instead of failing; `diff` with a bare word treats it as a
  PATH instead of failing; `clean -f`/`-n` are aliases now.

## Qualification

Every change passed `zig build test`, `e2e` (711 scenarios), `smoke`
(12 Fossil interop scenarios against a real `fossil`), `muscle` (27
differential steps), `git-import-e2e`, `git-export-e2e`, and `dst`, and the
three-runner CI battery (macOS ARM64, Linux x86-64, Linux ARM64). Each
published binary is built from the same checksum-pinned source and
executed under low-feature CPU models before publication, as since 0.1.4.
