Artifact 7e8ecce19eb50e460aa4ff03fb7128e6216475c7bf51fff2ffbdb1855535f74f:
- File
conformance/rfcs/erratum/repo-state-01-s8.3-ckout-ci-plus.md
— part of check-in
[600861484f]
at
2026-10-13 15:55:30
on branch main
— test(conformance): re-pin the -01 drafts with the 2026-10-13 errata (#430)
* test(conformance): re-pin the -01 drafts with the 2026-10-13 errata
Re-pin the repo-state and sync-protocol drafts to zit check-in 5a1b741b25d8, which applies five more -01 errata: repo-state §5.3, §7.3 and §8.3, sync-protocol §9.4/§9.5 and §10.1. zit now keeps each -01 text under the -00 file name; the copies keep their -01 names and conformance/rfcs/README.md records the zit path and check-in. The new errata are pinned, and the requirement tables are re-read against every changed hunk.
The §7.3 and §8.3 cases that were deviations now pass as written, and new cases cover a date tag's arrival order (§5.3), untagged leaves and a merge parent's recheck (§7.3).
The sync server answers each guard-passing ci-lock with pragma avoid-delta-manifests while forbid-delta-manifests is on, defaulting to on as the draft and fossil 2.29 do (fossil 2.28 defaults it off). The client leaves its transfer unchanged on that pragma. A file or cfile whose content does not match its hash now fails the client's round, in a pull and a clone: the reply rolls back, prefix included, and no further round starts.
The leaf table is still recomputed per crosslink batch, so a parent whose untagged child arrives in a later batch loses the verdict §7.3 keeps; that case is marked as a gap, tracked in #426.
* fix(sync): continue after a uvfile content error; renumber the avoid-delta-manifests row
A uvfile whose content does not match its HASH is a handler-reported content error: warn, commit the prefix and follow ordinary continuation (sync-protocol-01 10.1). The avoid-delta-manifests client row is SP-9.5-7 now that share-links took SP-9.5-5 and SP-9.5-6. Older unreleased changelog entries drop the pending-erratum wording. (user: [email protected], size: 5668) [annotate] [blame] [check-ins using]
Erratum — draft-fossil-repo-state-01 §8.3
| Document | draft-fossil-repo-state-01 |
| Section | 8.3 — Procedure, step 3 (the ckout keyword) |
| Type | Technical (the keyword is recognized for a narrower request type than the draft says) |
| Status | Applied in draft-fossil-repo-state-01 (2026-10-13) |
| Reported | 2026-10-13 |
| Submitter | Dan Mestas |
| Found via | Reading Fossil 2.29's symbolic_name_to_rid() against §8.3 |
1. Summary
§8.3 says ckout resolves to the checkout sentinel "only when the
requested type is "ci" or a checkout-inclusive type". Fossil recognizes it
only for the request type ci+. For ci, for an unconstrained request,
and for any other type, ckout is not a keyword and falls through to the
remaining forms, where it resolves like any other name (for example to a
check-in tagged ckout), or not at all. The draft also leaves "checkout-
inclusive type" undefined, and does not say that the keyword needs an
open checkout. The "ci+" semantics also apply only to the name as given:
Fossil rewrites the type to "ci" before the forms that resolve a
contained name and before the trailing-punctuation retry, so ckout.
under "ci+" names a tag called ckout, not the checkout.
2. Location
§8.3, step 3, the ckout bullet:
* *ckout* (only when the requested type is "ci" or a checkout-
inclusive type) resolves to the sentinel checkout RID rather
than an ordinary artifact RID, and marks that a local checkout
is in use.
3. The reference behavior
Verified against Fossil 2.29 source.
symbolic_name_to_rid()(src/name.c:482-536) setsisCheckin = 1for typeciandisCheckin = 2for typeci+, rewritingci+tocifor the rest of the lookup (:493-499).- The keyword block runs only when the type is unconstrained or a
check-in type and a checkout is open (
0<ridCkout,:519). Within it,current,prev,previousandnextneed no more, butckoutis tested asisCheckin>1 && fossil_strcmp(zTag, "ckout")==0(:529), so onlyci+matches. It returnsRID_CKOUT(RID_MAX+1,:30-34) and setsg.localOpento the checkout's RID (:530-532). - The function's header comment (
:462-468) documents the same: "A value of "ci+" works like "ci" but adds these semantics: if zTag is "ckout" and a checkout is open, "ci+" causes RID_CKOUT to be returned". name_to_uuid()(:834-836) mapsRID_CKOUTback to the checkout's RID before reading its hash.- The rewrite of
ci+toci(:497-498) happens before the forms that resolve a contained name,root:,start:andmerge-in:(:585,:591,:597), and before the trailing-punctuation retry (:730,:739), all of which pass the rewritten type on. The keyword therefore applies only whenckoutis the whole name as given. - No caller in Fossil 2.29's
src/passesci+; the only occurrences of the string are inname.c. Commands that acceptckout(for example the/docpage,src/doc.c:973,:1033) test for it themselves before resolving a name.
4. Impact
Observable only in corner cases. A resolver that follows the draft
returns the sentinel for ckout with type ci, where Fossil resolves
ckout as an ordinary name; a repository with a ckout tag then gives a
different check-in, and one without such a tag gives no check-in in
Fossil and the sentinel in the reader's resolver.
5. Correction
§8.3, step 3:
- * *ckout* (only when the requested type is "ci" or a checkout-
- inclusive type) resolves to the sentinel checkout RID rather
- than an ordinary artifact RID, and marks that a local checkout
- is in use.
+ * *ckout* is a keyword only when the requested type is "ci+"
+ and a local checkout is open. It then resolves to the
+ sentinel checkout RID rather than an ordinary artifact RID,
+ and marks that a local checkout is in use; a caller that
+ needs the check-in itself maps the sentinel to the checkout's
+ RID. The type "ci+" otherwise behaves as "ci". For any other
+ requested type, including "ci" and an unconstrained request,
+ or when no checkout is open, "ckout" is not a keyword and is
+ resolved by the remaining forms of this procedure like any
+ other name. The "ci+" semantics apply only to the name as
+ given: the trailing-punctuation retry below and every form
+ that resolves a contained name (root:, start:, merge-in:)
+ resolve that name under "ci", where "ckout" is an ordinary
+ name.
6. Rationale
Names the one type that enables the keyword, replacing the undefined
"checkout-inclusive type", states the open-checkout condition the other
keywords in the list already carry, and says what happens to the name
when the keyword does not apply, so a resolver gives Fossil's answer for
ckout under ci.
7. Verification
- Source: Fossil 2.29
src/name.c:30-34,:462-468,:482-536,:834-836;src/doc.c:973,:1033. - Run: Fossil 2.28 in an open checkout.
fossil info currentresolves;fossil info ckoutfails withcannot resolve name: ckout; afterfossil tag add ckouton another check-in,fossil info ckoutshows that check-in, not the checkout. - Not run: no Fossil 2.29 command passes
ci+, so the sentinel path is read from the source only. - Run (go-libfossil, Fossil 2.28):
fossil test-name-to-id --type ci+ ckout.with the checkout on c2 and a tag named ckout on c1 answers c1, the tag.