# zit

[Fossil](https://fossil-scm.org)'s formats and sync protocol, reimplemented in
[Zig](https://ziglang.org) from their specifications.

zit is a library first — a Zig analog of libfossil: the delta encoding, the
artifact formats, derived repository state, and the HTTP sync protocol as a
clean, embeddable API. The `zit` binary is a thin CLI over that library.

The implementation is a direct port of five companion Internet-Drafts (frozen
reference copies in [`docs/rfcs/`](docs/rfcs/); errata the code implements
ahead of the published text sit beside them in
[`docs/rfcs/erratum/`](docs/rfcs/erratum/)):

| Module | RFC | What it specifies |
|--------|-----|-------------------|
| `delta` | `draft-fossil-delta-format-00` | byte-level delta encoding |
| `artifact` | `draft-fossil-artifact-format-00` | manifest / control-artifact card format, naming, checksums |
| `repostate` | `draft-fossil-repo-state-00` | derived branch / tag / leaf / current-trunk views |
| `submanifest` | `draft-fossil-submanifests-00` | S-card tree manifests: bounded per-commit manifest size for wide repositories |
| `sync` | `draft-fossil-sync-protocol-00` | HTTP sync / clone protocol |

Implementation follows the RFC dependency layering:

```
delta  ->  artifact  ->  repostate  ->  sync
                \-> submanifest -/
```

## Design

The drafts are the authority, not Fossil's source. Test expectations come from
the spec text and its worked examples — every normative clause a module
implements gets a test citing its section. Fossil itself appears only in an
on-demand interop smoke check, which may confirm a spec-derived expectation but
never author one; a disagreement there means either zit misread the spec or the
spec is wrong, and the spec gets an erratum rather than the code a workaround.

No module touches ambient time, randomness, filesystem, or network; effects
arrive through injected interfaces. The sync client in particular is a pure
state machine — bytes in, bytes out — with transport supplied by the caller.
This keeps the library embeddable and makes the whole stack testable under
seeded deterministic simulation, where any failure replays exactly from its
seed.

## Scope

zit targets the **version-control substrate**: the check-in (manifest),
cluster, and tag/control artifact types. The collaboration types (wiki,
ticket, forum, attachment, technote) are carried opaquely — stored and
transported by hash, but not interpreted.

Beyond the substrate, the CLI carries Git interop in both directions
(`import-git`, `export-git`), sub-manifest adoption tooling with
replay-measured k selection (`submanifest analyze`/`enable`), a local rebuild
checkpoint that collapses cache-cold opens from minutes to seconds
(`checkpoint`), store reclamation (`shun`, `pack`), and an fsck (`verify`).

## What Fossil has that zit doesn't

Deliberate scope, not defects — zit is a substrate, not a Fossil replacement.

- **The collaboration layer.** Wiki, tickets, forum, technotes, and
  attachments (and their `W` cards) are carried opaquely — stored and synced
  by hash, never interpreted. The web UI (`fossil ui`) goes with them, as do
  `grep` and `settings`. (`stash` exists: save/list/show/apply/pop/drop over
  a local `.zit-stash` sidecar, with a fail-closed apply instead of merging.)
- **Delta manifest authoring on fresh repositories.** A repository whose
  history carries delta manifests keeps its dialect — commits there emit
  deltas against the proper baseline. A purely flat repository stays flat;
  zit never introduces the delta dialect on its own.
- **Manifest signing.** Signature wrappers are recognized and stripped on
  read (§4.1.1); zit never signs what it commits.
- **SHA-1 repository creation.** SHA-1 history clones and reads fine; `zit
  init` writes the sha3-256 naming policy only.
- **Unversioned-file management.** No `uv` verb; the uvfile sync vocabulary
  is understood on the wire.

## What zit has that Fossil doesn't — and where compatibility breaks

- **Sub-manifests** (`draft-fossil-submanifests-00`): S-card tree manifests
  bound per-commit manifest size on wide repositories, with adoption tooling
  that replays the repository's own history to measure whether enabling pays
  (`submanifest analyze` / `enable`, `import-git`'s k selection).

  **This is the one compatibility break.** A repository that emits S-bearing
  artifacts is permanently unreadable by stock Fossil (§8.1: disabling stops
  new trees but cannot retire existing ones), and sync's peer-version gate
  refuses to send trees to a pre-S peer rather than hand it artifacts it
  would misread. Emission is off by default; enabling it — and `import-git`,
  whose default imports as trees — states the spend.
- **The rebuild checkpoint** (`zit checkpoint`): a local, disposable sidecar
  witness that collapses cache-cold opens from minutes to seconds on large
  histories. Never stored, never synced; no wire or format impact.
- **A library-first, sans-IO architecture**: every module is embeddable and
  runs under seeded deterministic simulation; the sync client is a pure
  state machine.

Everything else round-trips with real Fossil in both directions — clone,
push, pull, and serve are exercised against a stock `fossil` binary in the
smoke suite, R checksums included. Where the code deliberately follows
Fossil's implemented behavior against the published draft text, the
divergence is documented in [`docs/rfcs/erratum/`](docs/rfcs/erratum/).

## Build

Requires Zig 0.16+.

```sh
zig build            # build the `zit` binary into zig-out/bin/
zig build run -- version
zig build test       # run unit tests
```

Further named steps: `zig build dst` (deterministic simulation, `--seed N` to
replay), `zig build fuzz -- <target> --seed N` (seeded fuzz targets),
`zig build bench` (benchmarks), `zig build cov` (kcov coverage report over the
test suite), and `zig build smoke` (interop check against a `fossil` binary on
PATH; run manually at milestones, never part of `test`).

## Source control

This project is itself under Fossil. The repository lives in `.zit.fossil`
(ignored); open a checkout with `fossil open --keep .zit.fossil`.
