Skip to content
zit Timeline
Login

Timeline

50 descendants and 50 ancestors of 4c24d037b7dc7ed2

2026-08-17
19:28
-R: say which mistake was made, not 'no checkout here' (#97)

The discovery message tells the operator to name the repository with -R. For a -R failure that advises supplying the flag already supplied, and it reads the same whether the path was mistyped or simply holds no repository -- so a stale path in a script looked like a bug in the verb. Reported against tarball; every -R verb had it. One reporter, routed through all nine resolveRoot call sites; the no-flag discovery message is unchanged. check-in: 10a1236a7a user: dmestas tags: trunk

19:28
archive differential: unpack zips without an unzip binary (#95)

The runners have no unzip, so the harness exited 2 for a missing tool and the step failed on its own coverage guard instead. Adding a third tool to the battery for one step is the worse trade: python3 is already required here, and ZipFile.extractall drops modes and symlinks -- the exact defect this differential exists to catch -- so the external attributes are applied explicitly rather than trusted to an extractor. check-in: 2420f6fb88 user: dmestas tags: trunk

19:16
ci: the archive differential asserts on output it never captured

archive-fossil-diff.sh writes the per-format comparison to stderr, but the step piped only stdout into diff.log, so the 'kinds compared' line the coverage guard greps for was never in the file -- it counted 0 on every platform and the step could not pass.

pipefail with it: the pipeline was taking tee's status, so the differential's own failure, including its exit 2 for a missing tool, was swallowed and only the guard could ever fail this step. check-in: 98243aad6a user: dmestas tags: trunk

19:00
zit purge: recoverable removal of leaf check-ins (#87)

Removes a check-in and the blobs only it introduced, into a local graveyard that purge undo restores and purge obliterate empties.

The drop set is (seed + reachable(seed)) minus reachable(everything retained), so a blob a surviving check-in still names is never freed -- dropping it would create a phantom rather than reclaim anything. Only leaves go, judged over the whole named set: purging a parent alongside its child is accepted, purging it alone is refused.

Reuses shun's rewriteAndSwap and records no tombstone: a purge is local, so content that already synced comes back from a peer. The help says so and points at shun. check-in: 8536f59fba user: dmestas tags: trunk

18:41
ls: size from the frame header, full names through the index (#96)

A blob's plaintext length is already in every frame kind -- a zlib container states it outright, a delta carries it in its own header -- so --size reports one without resolving a chain. The binary verdict cannot be had that way (a NUL may be the last byte), so --long still reads every blob and keeps its exact columns.

The larger cost was neither: resolveHexPrefix scanned the whole store per file to resolve a full-width name the digest index answers outright, which slowed plain ls too. On tcl's tip --long drops 167s to 93s and --size costs what plain ls costs. check-in: 3b7e8c7569 user: dmestas tags: trunk

17:10
smoke S11: a stock fossil push refused by the content policy (#88)

Unlike S10, which its own comment notes survives deleting the server's admission check, this one genuinely exercises the decision: the violating file is ordinary new content fossil pushes because it is new.

Records the limitation in the header: fossil exits 0 after printing the refusal, so the assertions are on the store and on fossil's output rather than its exit status. zit push exits 1. check-in: abc41cae82 user: dmestas tags: trunk

16:41
serve refuses a push that violates its content policy (#88)

#81's predicates bind a checkout; nothing stopped a push from a clone that never adopted them, or from stock fossil. Fossil cannot close this at all -- its hooks are before-commit (client-side) and after-receive.

The policy is the SERVER's, resolved per round from its own settings, never from the artifacts arriving: a push carrying its own policy would otherwise arrive bearing permission to land. Only inspecting rules cross the wire; before-commit has no server-side counterpart.

A push sends artifacts by hash and only a manifest names paths, so the walk is manifest-first -- the policy gates what becomes REACHABLE, not what bytes transit. Decided before ingest, so a refusal stores nothing, and the whole round is refused rather than half of it.

Verified against fossil 2.28: it prints the refusal text verbatim and lands nothing. Note it exits 0 while doing so, where zit push exits 1. closed check-in: e091f2ac80 user: dmestas tags: push-policy

16:41
grep: search a file's history for a literal (#92)

zit had no content search at all -- not git's pickaxe, not fossil grep's file-scoped walk. This is the latter: each named file's stored versions newest-first, every version whose content contains PATTERN reported with line numbers. A run of check-ins that never touched the file shares one blob and reports once.

PATTERN is literal; zit carries no regex engine and git log -S is literal for the same reason. Working-tree search stays ripgrep's job -- what only zit can do is read content that is not on disk.

A version the store cannot produce is counted and reported on stderr, not skipped: a search that quietly examined less looks like one that found nothing. Exit 0 found, 1 not found. check-in: a0ab591180 user: dmestas tags: trunk

16:20
zip: the same archive in the format Windows reads (#95)

Selection, top-level directory, reproducibility, and the refusal to write a partial archive are shared with tarball whole; only the container differs. Zip's header carries the size and CRC, so a member is compressed before its header is written, and deflate is used only when it makes the member smaller. Modes live in the central directory's external attributes, which is where a reader looks and where an executable silently becomes 0644 if you get it wrong -- so the fossil differential compares both formats now. check-in: c454de8df9 user: dmestas tags: trunk

15:32
tarball: check zit's archives against fossil's, modes included (#95)

Comparing zit to itself cannot catch a wrong permission bit -- writer and reader agree in the same direction. Fossil is an independent witness that already gets it right, so the harness unpacks both archives and compares member set, modes, and contents. It found one: -R was dropped at dispatch, which every test missed by running inside a checkout. Fossil versions symlinks where zit add still refuses them, so an imported corpus is also what finally exercises the l-perm path. check-in: 96a6d46d19 user: dmestas tags: trunk

14:41
tarball: write a check-in's files as a reproducible gzip tar (#95)

The effective-set walk already resolves sub-manifests and delta chains in canonical order, so this is that walk with an archive writer. Members carry the F card's permission, so an executable stays executable. Two runs of one version are byte-identical: history supplies the order and the timestamps, and no uid, gid, or build host is recorded. A file the store does not hold is refused by name -- a partial archive looks exactly like success. check-in: 580d0691c7 user: dmestas tags: trunk

14:29
Merge tag-list release filtering to trunk

Plain tag listing now reflects only singleton symbolic release names, while raw listing preserves complete repository tag state.

Refs ticket a679b1197b61127930f7e2a6478145c561dd54cc. check-in: 24356ebb90 user: dmestas tags: trunk

14:28
Fix tag list release-name filtering

Plain tag list now shows only singleton symbolic names globally and on a check-in, excluding branch machinery, raw properties, and propagating tags. Raw listing preserves every active tag, stored prefix, and value.

Add a tag-type-filtered repository-state query and end-to-end coverage for mixed singleton, propagating, raw, and branch tags.

Refs ticket a679b1197b61127930f7e2a6478145c561dd54cc. closed check-in: 41852f0a9e user: dmestas tags: fix-tag-list-release-filter

13:58
Create new branch named "fix-tag-list-release-filter" check-in: cf62ee5ea1 user: dmestas tags: fix-tag-list-release-filter
13:33
merge quarry-support: ls --long and log --long (#96, #93) check-in: 15fa309b01 user: dmestas tags: trunk
13:27
ls --long and log --long: one invocation answers a page (#96, #93)

ls --long adds size, the F card's permission token, and text/binary. The permission is the fact no other verb can supply -- it lives in the manifest, and the blob it names does not know it is executable -- so a listing could not mark executables and mis-rendered symlinks. --under bounds the listing to one directory, which is also what makes --long's per-file content read affordable.

log --long adds each check-in's timestamp, user and comment. log CHECKIN PATH already selected the check-ins touching PATH; emitting only hashes meant a file-history page cost a subprocess per row.

Both are opt-in; the default outputs are byte-identical. A blob the store cannot produce reports 'absent' rather than a zero-byte text file. closed check-in: f01eb5b6a0 user: dmestas tags: quarry-support

11:06
merge sparse-cone: classify paths against the cone and name the deciding member (#79) check-in: 187ad81e8c user: dmestas tags: trunk
01:05
cone test: classify paths against the cone and name the deciding member (#79)

Longest match across both polarities decides coverage, so the verdict alone cannot say why a file is missing. The member prints bare so it pastes into zit cone remove. Exits 0 when every path is covered, 1 when any is elided. closed check-in: 3cb62134a3 user: dmestas tags: sparse-cone

00:14
Create new branch named "sparse-cone" check-in: a620c24254 user: dmestas tags: sparse-cone
2026-08-16
21:47
binary-glob and crlf-glob: declarative content policy (#81)

Both are opt-in: an unset glob is no opinion, not refuse-everything, so a repository that never set one commits exactly as before. Set binary-glob to *.png and PNGs are the binaries the project expects, so a stray .o is refused. Neither runs code, so unlike before-commit they bind a fresh clone with no consent step -- that asymmetry is why they exist.

The check gates what a commit INTRODUCES: an all-files commit re-captures every managed path, so classifying unchanged content would make declaring a glob block every later commit until the whole tree already conformed. Comparing against the parent's blob grandfathers inherited files, per content rather than per path, so editing one re-checks it.

--no-checks waives it, the same flag that waives before-commit. check-in: 2711adbb03 user: dmestas tags: trunk

21:28
merge project-code: read a repository's identity without a checkout (#85) check-in: 1fc9e67f22 user: dmestas tags: trunk
21:18
stat: read a repository's identity without a checkout (#85)

project-code and hash-policy join stat's fields, and stat joins the -R family it was refused for a plumbing reason rather than a policy one. A consumer needing the project code had to find a free port, spawn zit serve, poll for readiness, POST a clone container and scrape the push card -- a subprocess and a listening socket per repository -- because the value was reachable only by speaking the sync protocol to a server you started yourself.

The no-checkout diagnostic said 'no .zit found' in directories where .zit was sitting right there; discovery looks for .zit-checkout, so it now says that and names -R as the way in. closed check-in: cd748a57c2 user: dmestas tags: project-code

19:28
Create new branch named "project-code" check-in: e77f1e196a user: dmestas tags: project-code
18:57
settings: keep-glob, manifest, before-commit consent, config pull (#82, #83)

keep-glob protects files clean must never delete while extras still lists them; manifest becomes a project setting driving build stamps. Both resolve across the tier chain, so a tracked .zit-settings file clones with the code.

before-commit splits declaration from consent (#82): the project ships the check as a tracked file, zit trust records the SHA-256 this checkout agreed to run. Cloning executes nothing, and an edit revokes consent by itself because the record pins content, not a flag. Non-zero exit aborts before anything is minted.

zit config pull shun is fossil's explicit request side; carriage stays clone-time otherwise so no peer can suppress content here on its own say-so.

Storage gains one keyed-string block: unknown keys are skipped by length, so the next string setting needs a key rather than another shape tag. Existing frames are unchanged.

clean-glob is deliberately absent: it means never-prompt and no-undo, which zit clean already is. check-in: 998dbf9d43 user: dmestas tags: trunk

18:45
merge empty-trailing-token: C and J accept an empty trailing token (#86) check-in: b4893b3fee user: dmestas tags: trunk
18:30
C and J accept an empty trailing token (#86)

Fossil distinguishes an absent token from an empty one positionally: `C` LF has none and is rejected, `C` SP LF has one empty token and is a present, empty comment. zit implemented §4.2's `token = 1*tchar` literally and rejected the empty form on C and J, which drops the whole artifact — every ticket change with an empty field, every check-in with an empty comment. T and U were already right.

Two tests asserted the old behaviour and now assert the corrected one; a third pins the writer, since --submanifest re-mints every manifest. The RFC text is unchanged; docs/rfcs/erratum/ carries the correction. closed check-in: 5ccb138e6d user: dmestas tags: empty-trailing-token

18:04
settings: hazard-tiered model with a global tier and provenance (#83) check-in: 6677853a3d user: dmestas tags: trunk
17:44
smoke S9: require the carried shun row, not a phantom (#73)

Carrying the /shun config group means a fossil clone records the artifact as suppressed instead of holding a phantom for it. That is the better end state: a phantom is something fossil goes looking for, so the next sync with any third party would undo the takedown.

S9 asked for the phantom specifically and so went red. It now asks fossil's own shun table and REQUIRES the row — tolerating the phantom would leave the scenario unable to notice the carriage regressing. The phantom probe stays as a diagnostic that tells a lost row apart from a served artifact. check-in: 7c656e4718 user: dmestas tags: trunk

17:33
merge frames-parallel: verify a batch across workers (#84) check-in: c36e9952c2 user: dmestas tags: trunk
17:28
frames verifies a batch across workers (#84)

Profiling the post-memo stream put 59% in artifact.verify and 38% in reconstruction, so the parallel target is verification, not reconstruction: reconstruction is what the plaintext memo made sequential-friendly, and fanning it out would contend on that cache.

Reconstruction stays single-threaded; a bounded batch is hashed by workers walking disjoint strides, then emitted in order. Workers touch no store, no cache and no allocator, so there is no queue, lock or atomic — join supplies the ordering. libfossil 2.35s -> 1.37s wall, byte-identical output. closed check-in: 4b2fceeacd user: dmestas tags: frames-parallel

16:30
local signing settings, and the shun table over the /shun config group (#72, #73, #83)

clearsign and pgp-command join zit settings as repo-local values fossil never propagates: pgp-command is a command line this machine executes, which fossil classifies sensitive for that reason. Config frame gains shape v4 for the command string; clearsign rides the existing flags byte. Precedence is ZIT_PGP_COMMAND, then the setting, then fossil's default.

zit serve now answers reqconfig for a named group, and clone requests and adopts /shun. A clone that dropped the table would re-accept content its origin was ordered to remove on the next sync with any peer; the #73 scale run also traced 12 spurious phantoms to the same loss. Verified both directions against stock fossil 2.28.

scripts/roundtrip-fossil.sh is the fossil -> zit -> fossil differential, run in CI on a built corpus: zig build e2e can only spawn zit, so nothing in the Zig suite can assert a stock fossil accepts what zit served. check-in: 57a9e0fc6b user: dmestas tags: trunk

16:00
merge frames-memo: stream through the plaintext memo (#84) check-in: 6759506ea8 user: dmestas tags: trunk
16:00
frames streams through the plaintext memo (#84)

frames was the one bulk reader still calling the uncached content(), so a delta base was reconstructed once per referencing delta rather than once per run — superlinear work against a linear stream, on corpora that are ~90% deltas after a fossil import.

libfossil (17,449 artifacts): 12.4s -> 2.34s real, 12.0s -> 2.25s user. Output byte-identical, peak RSS down 362MB -> 314MB. memoize_undeltaed stays off: the sweep reads each artifact once, and bases are memoized regardless of their own frame kind, which is the win. closed check-in: 2e3bb0b9db user: dmestas tags: frames-memo

15:04
merge record-cards: technote C/T cards and forum N card (#77) check-in: 5bea261864 user: dmestas tags: trunk
14:46
technote and forum verbs write the cards the format allows (#77)

technote add gains --comment (the C card a timeline renders as the note's title, unattachable by any later verb) and repeatable --tag, minting T +sym-NAME * sorted ascending as fossil writes it. forum post and reply gain --mimetype, matching wiki commit's spelling. Empty titles, repeated tags, and whitespace tag names are refused.

First CLI-level coverage for either verb: #76 shipped them tested only at the artifact layer. closed check-in: 21f6efdd1c user: dmestas tags: record-cards

13:52
merge tag-cards: raw-namespace tags, values, and cancel (#80) check-in: 6b4ac926e6 user: dmestas tags: trunk
13:26
tag: raw-namespace tags, values, and cancel (#80)

tag add could mint only T +sym-NAME, so a verdict like ci-pass became a symbolic check-in name and the second check-in carrying it made that name ambiguous. add and cancel now take fossil's --raw namespace choice, an optional VALUE, and --propagate; list --raw reads raw tags back, since they are deliberately outside the name space. Names under wiki-, tkt-, or event- are refused, as fossil refuses them.

The composer's arguments moved into a TagCardSpec, which hides its two precondition asserts from the release-assert scanner (a struct field is not slice-shaped), so its baseline entry goes; the asserts stay. closed check-in: 3fa532af3a user: dmestas tags: tag-cards

12:49
commit --sign: clearsigned manifests, fossil's contract (#72)

The signed text is the stored artifact, so readers strip the wrapper to reach the cards and the signature travels wherever the check-in syncs. Signer invocation matches fossil's clearsign.c: COMMAND OUTFILE INFILE, default 'gpg --clearsign -o ', ssh* basenames take the detached path with assembled armor, 'off' disables. A signer that fails or alters the manifest refuses the commit rather than storing it unsigned. artifact reports signature presence; carry is pinned through pack, verify, and the sync wire. check-in: eb2f1adeda user: dmestas tags: trunk

05:35
wiki and ticket leave the top-level command list: the four authoring verbs are machine verbs by the #76 posture (another process is their audience), each still fully documented by its own help check-in: d18a3b5589 user: dmestas tags: trunk
05:17
merge worktree-registry: the store-side worktree list and the worktrees verb (#70); verb-set union with forum/technote (#76) check-in: d88bdc5e67 user: dmestas tags: trunk
05:01
worktree registry (#70): every open and update stamps the tree's absolute path into the store's .zit-cache/worktrees (advisory tier, best-effort, self-healing — the store-cone discipline); 'zit worktrees' lists the registered trees with branch and check-in, verifies membership by the store file's inode, lazily prunes dead or re-pointed entries, and answers bare via -R closed check-in: 9d079f3009 user: dmestas tags: worktree-registry
05:01
forum and technote authoring verbs (#76)

zit forum post/reply and zit technote add record forum-thread and event artifacts under the #71 machine-verb contract: bare store via -R, hash-only stdout, exact exit codes, unlisted in the human help. A reply resolves its thread root transitively; a technote edit reuses its event id. check-in: 4317c47ed5 user: dmestas tags: trunk

04:27
D cards carry milliseconds (#75)

Every artifact-minting path writes the .SSS writer form fossil itself emits, so same-second writes keep a real-time order for latest-wins consumers. SOURCE_DATE_EPOCH pins .000; display surfaces unchanged. check-in: 0ff8e58ce8 user: dmestas tags: trunk

04:05
e2e: the import-fossil residue scans iterate a dedicated .iterate handle scoped to the scan — Linux dirRead re-seeks the fd per batch, so iterating a handle owned elsewhere is BADF there (macOS tolerates it) check-in: 68506d0e3e user: dmestas tags: trunk
02:37
sync: per-round credentials over the cookie channel (#74)

An authenticated exchange now carries a fresh credential on every round: body login until the peer's gate is known, then an x-f-l-c cookie whose nonce covers that round's own body. The transport attaches it; serve now verifies it (and refuses tampered, replayed, and duplicate logins) instead of ignoring the header its own announced version solicits. check-in: 1fd84b4327 user: dmestas tags: trunk

02:21
zig fmt check-in: f7b57a5869 user: dmestas tags: trunk
01:51
merge import-fossil: fossil history import with the compatibility consequence chosen at import time (#61) — --compatible preserves the corpus byte-exact in the origin's sync world; --submanifest re-mints history as sub-manifest trees under a new project code, gated by whole-history replay, proven file-set-equivalent pair by pair, published atomically, with the old->new provenance map shipped as a technote. Merge resolution unions the verb set with wiki/ticket (#71) and completes their top-help listing check-in: 3f1f2a257d user: dmestas tags: trunk
2026-08-15
23:20
conversion under the staged-publication discipline plus the provenance technote (#61): the bundle's atomic rename is the only commit point (a failed run leaves a sweepable .zit-tmp-*, never a half-repo), and the old->new map ships as a deterministic event artifact inside the converted repository — sorted pairs, source-tip timestamp, project-code-derived id — so external hash citations resolve by lookup closed check-in: cbbc910841 user: dmestas tags: import-fossil
22:49
import-fossil --submanifest converts (#61): topo-ordered re-mint of every check-in as an S-tree (text-level card rewrite — F run out, S run in sorted position, B dropped, P/Q/T chased through the old->new map, PGP stripped and counted, Z resealed), control artifacts remapped, blobs and non-referencing chains verbatim, clusters dropped; every (old,new) pair proven file-set-equivalent through the destination flattener before anything survives, counts reconciled against the census, failed runs roll back to nothing. --compatible byte-exactness is a pinned invariant: the frames census of an imported corpus equals the origin's stream, and the import still pulls from it (#73's prerequisite) check-in: 5d61c0da47 user: dmestas tags: import-fossil
20:52
fossil_convert: the corpus census and the re-mint cascade rule (#61) — classify every artifact, count the remap surface (check-ins re-mint; wiki/forum/ticket/attachment chains carry verbatim under kept content names), state the casualties (PGP signatures strip, clusters drop), and refuse an incomplete corpus; --submanifest prints the census as the conversion's reconciliation baseline check-in: ce57c94b6d user: dmestas tags: import-fossil
18:46
import-fossil verb (#61): the compatibility consequence is chosen at import time — --compatible preserves the corpus verbatim through the clone machinery and stays in the origin's sync world; --submanifest runs the whole-history replay gate (static k sweep at the tip, winner±1 replayed, refuse-if-worse without --force) ahead of the conversion pass, which lands next; fossil support lives in src/fossil/ beside src/git/ check-in: 4c24d037b7 user: dmestas tags: import-fossil
17:39
the submanifest -R pin follows the analyze-mode grant check-in: dab7ec41f3 user: dmestas tags: import-fossil
17:19
submanifest analyze: -R over a bare store (tip file set, no checkout) and --replay-all for whole-history replay (#61 step 2) — the conversion gate's evidence pass and before/after table in one read-only command; settings actions refuse -R in-verb check-in: 70b7e2f06e user: dmestas tags: import-fossil
16:37
extract the staged-publication pipeline into src/publication.zig (#61 step 1): PublicationBundle's one-way stage transaction, PublicationHooks, generation names, and the atomic-rename extern move verbatim; git_import_cli re-exports the same names, so import-git behavior, tests, and callers are unchanged — history converters share one publication discipline check-in: 7eff935454 user: dmestas tags: import-fossil
16:16
zig fmt check-in: 54cdfbbfaa user: dmestas tags: trunk
16:08
mirror-export: prune closed-branch refs on every export check-in: b0fde46c32 user: dmestas tags: trunk
15:58
merge worktrees: detached checkouts, store lock, open --store re-point (#59) check-in: bcbf29d017 user: dmestas tags: trunk
15:30
merge diff-repo-override: bare-store diff --from/--to via -R (#69) check-in: 8066a7c21d user: dmestas tags: trunk
15:16
diff --from/--to honors -R (#69): the check-in pair touches no working tree, so a bare store serves it; the worktree comparison refuses -R in-verb with the works-in-a-checkout diagnostic closed check-in: 4002513eeb user: dmestas tags: diff-repo-override
15:06
open --store re-points an already-open tree (#59)

A moved store strands its satellites, and a stranded tree can hold uncommitted work. Re-open repairs the pointer in place, gated on the new store containing the tree's current check-in. closed check-in: 7ac1ec2255 user: dmestas tags: worktrees

13:39
worktrees: detached checkouts of one store (#59)

Every store writer serializes on an exclusive flock held open-to-commit (released before autosync and the drift advisory). A checkout's store_location section is resolved in one place; open --store PATH creates a detached working tree, and probeRoot accepts a checkout whose pointer resolves. Store-scoped verbs (pack, shun, serve) follow the pointer end to end. check-in: 94d4659a53 user: dmestas tags: worktrees

13:04
merge help-topics: help topics, single-source option fragments, exit-status blocks everywhere, mechanical usage-line audit (#68) check-in: 9a5ae9774b user: dmestas tags: trunk
12:50
help topics (#68): 'zit help names/sparse/repo/exit-codes'; verbs point at the names topic instead of restating the resolution litany (timestamp forms were documented in one help of six); unknown help topics refuse with exit 2; the -R/--no-cache prose and the conventional exit-status block become single spliced consts (28 helps gain the block); a unit test asserts every options-table flag reaches its usage line — it caught commit --no-sync, merge --no-sync, and the cone flags on open/update/clone closed check-in: 21fa16cc4b user: dmestas tags: help-topics
12:10
import-git: O(changes) per-commit cost and live progress (#65)

Tree edits adopt untouched sibling leaves, the tree witness digest is structural over the root S-run (flat digests unchanged), and log reads go through a primed plaintext cache. Ingest reports strided progress with pack/verify phase markers. check-in: db4b2573e7 user: dmestas tags: trunk

04:01
merge read-verbs: frames incremental artifact stream and annotate VERSION/--full (#66, #67) check-in: b41272c88c user: dmestas tags: trunk
02:52
read verbs for external consumers (#66, #67): frames streams whole raw artifacts since an opaque cursor in persisted order, with LogKey prefix validation (appends keep a cursor alive, a pack/shun rewrite fails it with exit 4; exit 3 = current) and per-artifact hash verification; annotate gains a VERSION operand resolved like cat's (bare-repo -R works) and --full for full artifact IDs closed check-in: 68eba6cd49 user: dmestas tags: read-verbs
01:03
merge sparse-cone: sparse checkouts and sparse stores per draft-fossil-sparse-cone-00 — worktree cones with exclusions, cone-scoped clone/open/update, cone/cone-not wire pragmas with graceful degradation, demand fetch, pack --drop-elided, cross-cone record merges, and the sparse-origin clone refusal check-in: 2ad75a9bea user: dmestas tags: trunk
00:39
sparse origin refuses clones it does not cover (spec 5.3): dense and uncovered-cone clone requests answer one error card and no content; the client treats a progress-free error round-0 reply as fatal (spec amended — the sync 11.1 discard tolerance is for cosmetic cards on progressing replies) and quotes the peer's refusal closed check-in: 6e064b7301 user: dmestas tags: sparse-cone
2026-08-14
23:23
cone exclusions (spec 3.2): --cone-not/'!' cone-file lines subtract a subtree, longest-match decides coverage (spec reworded from ordered last-match — order-independent, keeps canonical serialization and digests), dead rules and contradictions refused; serialized cone v2 (0x00 lead-in + flag byte, v1 bytes unchanged without exclusions); cone-not wire pragma with over-send degradation check-in: 60274756a0 user: dmestas tags: sparse-cone
22:48
import: sub-manifest memo progress line every 25k commits, and an adaptive trim target tracking each walk's touched bytes (#63 investigation — preventive; the pkgsrc slowdown reframed, see issue) check-in: aa54d6f651 user: dmestas tags: trunk
21:37
clone/open/update: --cone-file=FILE reads cone members from a file (one per line, # comments); clone help gains the missing --cone entry check-in: 9191baea4b user: dmestas tags: sparse-cone
21:16
cross-cone merge applies to the record (spec 4.4): out-of-cone paths resolve at hash level with no blob reads, theirs-only changes ride a merge_overlay container section (v4) in the pending-merge splice, commit composes and clears it one-shot, and only both-changed conflicts refuse — naming the path and the widen remedy check-in: de5e6d9dc0 user: dmestas tags: sparse-cone
20:17
merge trunk check-in: 8b3d577ec1 user: dmestas tags: sparse-cone
20:02
zit cone verb: show/add/remove drive the update --cone path, so add fetches and remove dematerializes; member cap to 255 (the count byte's range, spec 3.2 bounds sentence added); spec gains exclusions (cone-not pragma, last-match-wins) and the patterns-deliberately-absent rationale check-in: 2cd32f8a38 user: dmestas tags: sparse-cone
19:39
sync: unversioned cards tolerate-and-report (#58) — validated, counted, never an abort; sessions report N not transferred; NotImplemented retired; uv-only replies are the clean §3.7 terminal check-in: 3cf76b982e user: dmestas tags: trunk
19:07
cone lifecycle completes: update --cone/--dense demand-fetch through the saved remote with one bounded retry; store policy follows the worktree cone only on already-sparse stores (a dense store's --cone can never arm reclaim); pack --drop-elided reclaims the elide set composed with the shun filter (spec 5.4, the only deletion) check-in: f79b3e469a user: dmestas tags: sparse-cone
18:42
pull scoping on the wire: pull/sync clients carry the store cone as pragmas, and the server filters its igot advertisement so out-of-cone holdings never mint requester phantoms — the transfer narrows at its source check-in: 9abd665d70 user: dmestas tags: sparse-cone
18:27
open on a sparse store demand-fetches (spec 6.4 policy form): the requested materialization becomes the store cone, an ordinary pull aligns to it, and one bounded re-attempt resolves fresh; without a remote the refusal names the class and remedies check-in: 658ae6bf26 user: dmestas tags: sparse-cone
18:27
import-git: refuse git older than 2.45 by name before any work — first preflight query, without --no-lazy-fetch; CI verifies the minimum beside fossil (#62) check-in: 43efce758a user: dmestas tags: trunk
18:03
add sparse.zig: the shared cone classification the previous check-in imports check-in: f031a5283c user: dmestas tags: sparse-cone
18:02
cone pragma on the wire (spec 6.1/6.2): client requests scoping via fossil's silently-ignored pragma contract; the server filters clone batches from a digest-keyed classification memo dropped with its snapshot; a cone-aware pair transfers spine + in-cone content only check-in: a52eb95fc0 user: dmestas tags: sparse-cone
17:34
sparse-cone spec: the cone request rides pragma cards — fossil answers unknown bare cards with a protocol error (xfer.c) but specifies unknown pragmas as silently ignored, so degradation becomes a documented property rather than assumed tolerance check-in: f7b3d64db8 user: dmestas tags: sparse-cone
17:33
merge trunk: autosync + commit fork guard; update grows --no-sync beside --cone/--dense check-in: c50dcc978a user: dmestas tags: sparse-cone
17:18
sparse store round trip: verify summarizes elision distinctly from damage (streamed off the existing plaintext pass); commit omits R only when an elided carried blob makes the aggregate uncomputable, and the minted check-in converges to dense peers check-in: 6eecca3136 user: dmestas tags: sparse-cone
16:57
commit: fork guard — parent must still be its branch's leaf (--allow-fork to fork); autosync — settings verb, pull before commit/update/merge, push after commit, warn-and-continue (#57) check-in: 7a4dff5d5f user: dmestas tags: trunk
16:34
sync on a sparse store: elided phantoms are never gimme'd (Eligibility.elided, distinct from shun) and volunteered content filters at every receive persist via post-run reclassification, so new in-cone commits arrive while declined content stays declined check-in: 4fb1a29e3e user: dmestas tags: sparse-cone
16:10
clone --cone: local filtering at persist (spec 6.3) — structural artifacts and in-cone blobs keep, exclusively-out-of-cone blobs elide, count reported; open's preflight classifies absence three ways (foreign / elided / transit) instead of reading a sparse store as foreign check-in: 5a74b96333 user: dmestas tags: sparse-cone
15:55
store cone: .zit-cache/store-cone member with loss-heals-to-dense semantics; derived caches proven cone-independent (spec 7 corrected: no cone term in cache keys) check-in: 7c734e7763 user: dmestas tags: sparse-cone
15:40
merge trunk: import-git drops std.c (Ambient environ, Io dir fsync); export-git DEST preflight names its own git dir check-in: 7c1fb6e58d user: dmestas tags: sparse-cone
15:37
linux: iterate/fsync need real fds — reopen O_PATH dir handles with iterate rights (7 sites + test helpers); runScripted captures into caller-owned storage, ending a use-after-return the Linux stack exposed check-in: a60df1f752 user: dmestas tags: trunk
15:17
sparse cone: tree-dialect keystone on an S-card repo, narrowing dematerializes cleanly; README RFC row; open help teaches --cone check-in: 18ad2eea27 user: dmestas tags: sparse-cone
14:42
sparse commit synthesis: snapshot inside the cone, parent cards carried verbatim outside; R stays log-sourced; keystone e2e pins reader-indistinguishability check-in: e7c880ac83 user: dmestas tags: sparse-cone
14:37
import-git: drop std.c — child environ threads from Init via Ambient, dir fsync goes through Io; Linux builds no longer demand libc check-in: 951b654c5b user: dmestas tags: trunk
14:33
sparse worktree verbs: open/update --cone and --dense; add/mv refuse outside the cone; extras/clean/addremove/status cone-scoped; R verified over a dense probe (spec 4.3 verification clause added) check-in: c59a64678f user: dmestas tags: sparse-cone
14:12
sparse cone at the seam: MergeWalk filter, cone-aware requireClean, SparseOpt on applyCheckin (record+cone one splice), cross-cone merge refuses fail-closed check-in: 259219f90e user: dmestas tags: sparse-cone
13:50
container v3: cone + store_location tags; v2 folds forward, version negative space pinned check-in: 49815f9ac6 user: dmestas tags: sparse-cone
13:43
export-git: DEST preflight must name DEST's own git dir — upward discovery adopted the enclosing repo and aimed fast-import at its refs check-in: f451567485 user: dmestas tags: trunk
13:09
sparse-cone: RFC draft + cone module (spec 3): sorted-minimal members, covers/coversRange, canonical serialize with fail-closed parse, SHA3 digest check-in: 0fade1c499 user: dmestas tags: sparse-cone
12:21
merge sub-manifest: delta-manifest dialect, R cards, diff hunks, server identity, stash, open/log resolution, clone remote+progress, timestamp names; e2e expectations updated check-in: 8a45a021f9 user: dmestas tags: trunk
10:11
clone: save the URL as the remote (canonical, password-free, --once opts out); live per-round progress on a TTY stderr (#55 #56) closed check-in: 69c14cd747 user: dmestas tags: sub-manifest
10:11
resolve: §8.3 portable T/Z timestamp form and the NAME:TIMESTAMP compound (#60) check-in: f2691f0a23 user: dmestas tags: sub-manifest