Artifact 0b464491b3880ce883d29e4d68baf41f80c4a828925c081e9e701762a005a00d:
- File docs/RELEASE-NOTES-0.3.3.md — part of check-in [441d99370f] at 2026-09-02 02:57:23 on branch trunk — 0.3.3: version bump and release notes (user: dmestas, size: 4220) [annotate] [blame] [check-ins using]
zit 0.3.3
zit 0.3.3 finishes what 0.3.2 started: no read verb walks the store for what
the derived state already knows. A full zit timeline of SQLite's history
went from 66.5 seconds to 0.37; zit annotate, which did not finish at all
on that history, answers in about a second for most files. Around the fixes
sits the thing that keeps them fixed: every manifest read is now counted,
and a regression test requires the count to stay flat as history grows.
No artifact, tag namespace, or sync message changed.
timeline (zit#172)
The default-format timeline read and parsed a manifest per row. The fetch
condition still said "unless the format is oneline" from when oneline was
the default; 0.3.0 made medium the default for Fossil parity, and from
that day every row inflated a manifest for two strings — comment and login —
that the state carries. Nothing failed; the verb just grew with the store.
Full timeline of SQLite (131,558 artifacts, 44,581 lines, 4.7MB): 66.5s to
0.37s, byte-identical output, level with fossil timeline's 0.34s.
A manifest is read only where its file cards are needed: full, -v, and
a path filter.
annotate (zit#172)
Worse still: annotate materialized PATH's content for every ancestor of the tip — a manifest read and a blob read each, then a full-file line diff per ancestor — ~36,000 of everything on SQLite where ~400 check-ins touched a typical file. Killed after four minutes without an answer.
Three changes, each preserving the one house line-diff core:
- The cache's records already say which check-ins changed PATH (each record's file list is the diff against its primary parent, so "not listed" means byte-equal there). One sequential scan builds the set; untouched ancestors inherit the parent's content pointer outright.
- A node whose content IS its parent's slice resolves to the parent's origins without a diff.
- The LCS matches the common prefix and suffix directly and runs its O(n×m) table on what remains — two adjacent 15k-line versions were 225 million cells for a three-line change.
annotate, full SQLite history |
0.3.2 | 0.3.3 | fossil |
|---|---|---|---|
| VERSION | killed, >4min | 1.2s | 0.04s |
| README.md | — | 0.5s | 0.03s |
| src/shell.c.in (15k lines, heavily edited) | — | 57s | 2.3s |
The honest residue: a version that edits lines near both ends of a large file still pays a quadratic middle, which is the whole remaining gap on shell.c.in. The remedy is a real diff core (Myers or anchor-recursion), which touches merge conflict resolution and gets its own careful change rather than a ride-along. One visible delta now: when a repeated line (usually a blank one) could equally have come from two origins, the attribution may pick the other equally-valid one than 0.3.2 did — the inherent tiebreak of any line diff.
The regression net (zit#172)
Every manifest read through the repository facade is counted, and any
invocation reports it on exit under ZIT_MANIFEST_READS=1. An e2e runs
eleven listings — timeline in four formats, leaves, branch -v,
tag list, status, info, ls, and annotate of a file committed
once — over two histories of different lengths and requires the counts to
be IDENTICAL. A verb that reads per row fails by construction: no timing,
no tolerances, no constants to maintain. Wall clock was measured at ±29%
on a shared machine in the course of this work; an integer does not vary.
Compatibility
- Artifacts, tags, and the sync protocol are unchanged; Fossil RFC
revision 00 remains the target. A stock
fossilclones, pushes, and pulls a 0.3.3 repository byte-for-byte. - No on-disk format changed (the image schema stays at 0.3.2's version 6).
- No command or flag changed. Output is byte-identical except the annotate tiebreak noted above.
Qualification
zig build test, e2e, smoke (Fossil interop against a real fossil),
muscle (41 differential steps), git-import-e2e, git-export-e2e, and
dst, plus the three-runner CI battery (macOS ARM64, Linux x86-64, Linux
ARM64). The invariance test is mutation-verified: reintroducing the
timeline defect turns it red with the read counts in the message.