Artifact 6eeae7f178f5937bd6d685dd9327a9160c1a59b3ecf750117ceb9032953ae987:
- File docs/HANDOFF.md — part of check-in [a82aedc9df] at 2026-07-08 22:45:07 on branch trunk — Say the RFCs, not fossil, are the source of expected test values (user: dmestas, size: 5304) [annotate] [blame] [check-ins using]
zit — Handoff
Start-here document for anyone continuing the implementation. The scaffold is in place, builds clean, and tests pass. Nothing of the actual VCS is implemented yet beyond two foundational primitives.
What this is
zit is a Fossil version-control system written in Zig — a direct port from
the specifications, not from Fossil's C source. The authority is the four
Internet-Drafts frozen in docs/rfcs/ (.txt). Fossil's C source is
used only as an oracle for byte-exact verification, never copied.
Current status
| Area | State |
|---|---|
| Project scaffold, build, CLI | done — zig build, zig build test, zig build run -- version |
src/delta.zig |
base-64 int codec (MSB-first) + checksum (mod 2³²), with RFC-derived tests. apply/create stubbed. |
src/artifact.zig |
artifact naming (SHA-1/SHA3-256, lowercase hex) + Z-card MD5, with RFC example vectors. Card/type enums. parse stubbed. |
src/repostate.zig |
skeleton: Rid, resolveName, currentTrunk stubs with the governing rules in doc comments. |
src/sync.zig |
skeleton: ClientState (the §3.8 state machine), Client.step stub. |
Everything marked "stub" returns error.NotImplemented and cites the RFC
section that governs it.
Layout
build.zig, build.zig.zon Zig 0.16 build (module "zit" + exe "zit")
src/root.zig library root; re-exports the four modules + aggregates tests
src/main.zig CLI entry
src/{delta,artifact,repostate,sync}.zig one module per RFC
docs/rfcs/*.txt the four frozen RFC finals (reference)
docs/HANDOFF.md this file
.zit.fossil the Fossil repository (ignored; not tracked)
Build & test
Requires Zig 0.16+.
zig build # -> zig-out/bin/zit
zig build test # unit tests
zig build run -- version
Implementation approach
- Test-first, one RFC rule at a time. Each rule becomes a test that cites its section, then the code to make it pass.
- Expected values come from the specifications. Every test's expected bytes
are taken from the RFC text and its worked examples — e.g. the SHA3-256
artifact name and the empty-tree MD5 both appear verbatim in
draft-fossil-artifact-format-00(the R-card / naming example and the Z-card section). Fossil is never consulted to derive an expected value; it is used only, and only at layer milestones, as an interoperability check that the artifacts zit produces are well-formed enough for it to read back. - Layer order:
delta -> artifact -> repostate -> sync. Don't start a layer before the one it depends on is real.
Suggested next steps (in order)
- delta.apply (RFC §4) — the decoder: parse header, copy/literal segments, trailer; enforce the enumerated rejection conditions; verify the checksum. This is the smallest self-contained deliverable and fully testable.
- delta.create (RFC §3, §5) — the encoder.
- artifact.parse (RFC §4, §5) — card tokenizer, ordering rules, per-type validity, Z/R verification, delta-manifest reconstruction (RFC §"Delta Manifest Reconstruction").
- repostate (RFC §3–§9) — DAG build, crosslink, tag propagation, leaves,
symbolic-name resolution (pure max-
mtime). - sync (RFC §3–§11) — the client state machine, round dispatch, phantom resolution, clone, auth, config.
Scope
Version-control substrate only: check-in (manifest), cluster, tag/control
artifact types; cards B C D F M N P Q R T U Z. The collaboration types
(wiki, ticket, forum, attachment, technote — cards A E G H I J K L W) are
carried opaquely (stored/transported by hash, not interpreted). This is a
deliberate scope decision; the RFCs still describe the full set.
Fossil workflow
The repo lives in .zit.fossil inside the tree (ignored via
.fossil-settings/ignore-glob). To work with a fresh clone of the directory:
fossil open --keep .zit.fossil # establish a checkout without touching files
fossil status
fossil commit -m "..." # commits land on trunk
Standard fossil: fossil timeline, fossil diff, fossil branch new, etc.
Zig 0.16 notes (things that changed and cost time)
main's signature ispub fn main(init: std.process.Init) !void.- Command-line args:
try init.minimal.args.toSlice(arena)(there is nostd.process.argsAlloc/argsWithAllocator). - stdout is via the new I/O interface:
var w: std.Io.File.Writer = .init(.stdout(), init.io, &buf);thenw.interface.writeAll(...)andw.interface.flush(). - Test aggregation:
std.testing.refAllDeclsRecursiveis gone; instead atest { _ = @import("delta.zig"); ... }block inroot.zigpulls each module's tests into the library test binary. build.zig.zonrequires a.fingerprint;zig buildprints the value to add if it is missing.
References
docs/rfcs/draft-fossil-delta-format-00.txtdocs/rfcs/draft-fossil-artifact-format-00.txtdocs/rfcs/draft-fossil-repo-state-00.txtdocs/rfcs/draft-fossil-sync-protocol-00.txt- fossil 2.28 (
fossil version) — used only as an end-to-end interoperability check, never as a source of expected values.