Artifact 303d8965faf556e30a2456f1d9ab65e9ec0e72926b220a9672bce913e7108d58:
- File
conformance/requirements/submanifest.tsv
— part of check-in
[b77d8b119e]
at
2026-10-18 16:44:21
on branch feat/submanifest-reader
— test(conformance): cover the sub-manifest writer, with zit as oracle
The submanifest table gains the writer's requirements: the §6.1 predicate, §6.2's construction, limits, merge, stops, canonical encoding and storage order, §6.3's pinning, out-of-range fallback and selection, §6.4's manual and automatic re-tune, §8.1's enable rules and disabling, and the writer vectors of A.5. The writer reproduces every Appendix A tree, the A.5 three-level vector at k = 2 and the height-0 merge and encoding vectors at k = 3. 71 requirements: 66 covered, 3 partial, 2 deviations, 0 failing.
TestZitWriterInterop, with zit present, has zit commit ten scenarios (the A.1 set; 40 files at k = 1, 2 and 12; 3,000 files at k = 1, 3 and 5; deep paths; names with spaces, tabs, newlines and non-ASCII, executables and a rename) and requires go-libfossil's check-ins byte-identical. zit then clones, verifies and lists go-libfossil's trees, and verifies a tree go-libfossil commits on top of zit's; the §6.3 selection matches zit's analysis on five file sets. TestZitWriterBundle replays the recorded zit manifests in CI. zitRun now returns stdout only and sets FOSSIL_HOME, and zitListing reads names holding spaces, tabs or newlines. (user: [email protected], size: 12325) [annotate] [blame] [check-ins using]
# Requirements of draft-fossil-submanifests-00, written from the draft text, # reader and writer. Skipped, with reasons, in the suite's report: 5.6 and # 6.5 (informative), 8.2 (an operator rule for provisional repositories, not # observable in a library) and 11 (IANA). Not implemented: the 7.4 SHOULD # (memoized sub-manifest enumeration). The writer's construction is checked # byte for byte against the Appendix A artifacts and against check-ins zit # wrote (testdata/zit-writer, replayed without zit in CI). # The reference for behaviour the draft leaves open is zit, the other # implementation: its 2.29.0 version threshold (7.2), its avoid-submanifests # placement, and its configuration request (6.3, SM-6.3-3; the draft text is # tracked in danmestas/zit#240). Fossil has no plans to read trees, yet 2.29 # and every later release announce at least that threshold, so SM-7.2-1 # records a deviation until zit and the draft move to a version no fossil # announces (tracked in danmestas/zit#239). # Format: <id>\t<section>\t<requirement>[\t<scope note>] # draft draft-fossil-submanifests-00.txt b6cb37690b9273c92568222abe65c450c5a103c149225f94604420bc5127ad52 SM-3.1-1 3.1 A card letter outside A-Z is rejected, and the in-range undefined letters O, V, X and Y are rejected; S is defined. SM-3.2-1 3.2 An S card carries exactly a filename and a hash; a third token, or a missing hash, is rejected. SM-3.3-1 3.3 The S card filename is escape-decoded; the S card hash is never decoded. SM-3.4-1 3.4 S cards repeat, and an S run ascends strictly by decoded filename under the canonical comparator; an equal or descending neighbour is rejected. SM-3.4-2 3.4 S falls between R and T in the card order, so a manifest's S run follows its R card and precedes its T cards. SM-3.5-1 3.5 The S card hash is exactly 40 or 64 case-insensitive hexadecimal characters. SM-3.6-1 3.6 The decoded S card filename passes the pathname predicate; one that does not is rejected. SM-4.2-1 4.2 A manifest may carry an S card alongside B C D F N P Q R T U Z, and requires D and Z. SM-4.2-2 4.2 A sub-manifest may carry only F, S and Z cards, and requires a Z card. SM-4.3-1 4.3 S is a manifest-setting letter, and a manifest with no D card is reclassified as SUBMANIFEST once its type is final and before legality is checked; no card assigns SUBMANIFEST directly. SM-4.3-2 4.3 No artifact valid under the base artifact format changes classification. SM-4.4-1 4.4 A manifest carrying both a B card and an S card is rejected. SM-4.4-2 4.4 A manifest carrying both F cards and S cards is rejected. SM-4.4-3 4.4 A sub-manifest carrying both F cards and S cards, or neither, is rejected. SM-4.4-4 4.4 Every F card of a sub-manifest carries a hash; a delete marker in a sub-manifest is rejected. SM-4.4-5 4.4 The tree walk delivers each emitted F card's hash, permission and old-name tokens to consumers unaltered. SM-4.5-1 4.5 An interior sub-manifest, whose first card is S, is not rejected by a pre-filter on its first card letter. SM-5-1 5 A manifest is a tree manifest if and only if it carries an S card, and a consumer that needs its file set derives it by the tree walk. SM-5.1-1 5.1 The walk enumerates a tree depth first and in order, emitting each leaf's F cards in order, through interior sub-manifests as well as leaves. SM-5.1-2 5.1 Each S card's decoded filename, and each emitted filename, compares strictly greater than the last filename emitted; an enumeration that does not ascend across sibling slices fails. SM-5.1-3 5.1 The enumeration fails when a referenced sub-manifest is absent. SM-5.1-4 5.1 The enumeration fails when a referenced artifact is not of type SUBMANIFEST. SM-5.1-5 5.1 The enumeration fails when a referenced artifact is the artifact of a frame already on the walk's stack. a cycle cannot be built from content-addressed artifacts: the case shows the depth bound ending a path, and internal/manifest's TestTreeWalkRefusesRepeatedArtifact the check itself SM-5.1-6 5.1 The enumeration fails when a sub-manifest lies deeper than 16 sub-manifests, counting the leaf; a depth of 16 is accepted. SM-5.1-7 5.1 A leaf's first emitted filename is byte-identical to the filename of the S card that reached it. SM-5.1-8 5.1 An interior sub-manifest's first S card filename is byte-identical to the filename of the S card that reached it. SM-5.1-9 5.1 Downstream consumers do not distinguish a walked enumeration from a flat one: a tree check-in's file-change records are those of a flat check-in of the same files. SM-5.2-1 5.2 The enumeration entry points, the full walk and single-name lookup, treat an unresolvable sub-manifest as a fatal error, and no partially resolved tree is presented as a complete file set. SM-5.2-2 5.2 A consumer that defers records the gap, keyed by the dependent and the missing hash and inserted idempotently, and retries when the sub-manifest arrives. SM-5.3-1 5.3 Single-name lookup binary-searches each S run for the last card at or before the name, descending one sub-manifest per level to a leaf; a name before the first S card is absent. SM-5.3-2 5.3 A lookup that would resolve a sub-manifest deeper than 16 fails, and a sub-manifest it cannot resolve fails it hard. SM-5.4-1 5.4 A delta manifest may name a tree manifest as its baseline: the merge walk takes the tree walk as its baseline cursor, and single-name lookup takes the tree lookup as its baseline step. SM-5.4-2 5.4 A writer with the enable-submanifests setting off does not create a delta manifest against a tree baseline. SM-5.5-1 5.5 A tree manifest's R card is computed over the walked enumeration, and a delta over a tree baseline's over the composed enumeration. SM-6.1-1 6.1 The partition predicate is the count of leading zero bits of the SHA3-256 digest of the decoded filename, tested against k for leaves and (h+1)*k at height h; content, permission and old name never influence the partition. SM-6.2-1 6.2 The construction is deterministic: leaves carry their group's F cards and a Z card, interiors one S card per member and a Z card, each S card names its child under the repository hash policy, and two writers produce byte-identical artifacts for the same check-in and k. SM-6.2-2 6.2 A scan yielding fewer than two groups emits a flat manifest and no sub-manifest: N = 0, N = 1, at most MAX names with no qualifying boundary, and a boundary suppressed by MIN. SM-6.2-3 6.2 A group holding MAX members forces a boundary whatever the predicate says. SM-6.2-4 6.2 A final group shorter than MIN merges into its predecessor when the two fit in MAX, at height 0 and at every interior height. SM-6.2-5 6.2 A scan yielding one group, or as many groups as nodes, ends the construction with the manifest carrying that height's nodes; otherwise interior sub-manifests form the next height, never a node of height 16. SM-6.2-6 6.2 S card filenames and a leaf's filename and old-name tokens take the canonical encoding: exactly space, newline and backslash escaped, every other byte raw. SM-6.2-7 6.2 Sub-manifests are stored before the manifest that references them, and an unchanged subtree is shared by content addressing. SM-6.3-1 6.3 A supporting server recognizes submanifest-k, enable-submanifests and submanifest-auto-retune as members of the /project configuration group. SM-6.3-2 6.3 A receiver stages the three settings through the end of the containing reply, validates them, and applies all or none; card order does not affect the result, and an invalid value, or enable-submanifests on without a submanifest-k from 1 to 12, rejects all three. SM-6.3-3 6.3 A client supporting this specification and holding Read permission requests reqconfig /project during pull and after clone authorization succeeds. SM-6.3-4 6.3 A newly cloned repository that could not retrieve the group leaves enable-submanifests false. SM-6.3-5 6.3 The writer takes k from the stored pin, never derives it per commit, and supports every value from 1 to 12. SM-6.3-6 6.3 A stored k outside 1 to 12 makes the writer fall back to flat manifests rather than substitute a value, and report it. SM-6.3-7 6.3 Automatic selection costs every k from 1 to 12 over the current check-in's entries under the sha3 policy, C(k) = S + sum(L*L)/sum(L), choosing the least cost and the lowest k on a tie; with no candidate it has no result. SM-6.4-1 6.4 A re-tune is forward-only and operator-initiated: the next commit is built under the new value, sharing exactly the byte-identical sub-manifests, and no history is rewritten. SM-6.4-2 6.4 A writer re-tunes automatically only while submanifest-auto-retune is true (default false), and only when a distinct candidate costs less than (1 - m) times the pin's cost; m is 15%, as zit's. SM-7.1-1 7.1 Storing a structural artifact whose S references are absent creates a phantom for each, with the referencing artifact's privacy. SM-7.1-2 7.1 Dephantomizing a sub-manifest retries the deferred processing of every recorded dependent. SM-7.2-1 7.2 A sender refuses to transmit a SUBMANIFEST artifact, or a manifest carrying an S card, to a peer whose announced version predates sub-manifest support, with an explicit error and never by converting, downgrading or silently omitting it. SM-7.2-2 7.2 A server whose enable-submanifests setting is false sends pragma avoid-submanifests in the reply positions of avoid-delta-manifests. SM-7.2-3 7.2 A client that received avoid-submanifests emits no S card in commits created during the session. the root package makes no commit within a sync session: the internal session reports the pragma (SyncResult.AvoidSubmanifests) and manifest.Checkin honours it (CheckinOpts.AvoidSubmanifests) SM-7.3-1 7.3 Crosslinking a tree manifest uses its full enumeration wherever a flat manifest's F cards are used, and an absent sub-manifest defers it as an absent baseline defers a delta. SM-7.3-2 7.3 A SUBMANIFEST artifact has no crosslink effect of its own, and a derived view over an incomplete tree closure is not presented as complete. SM-8.1-1 8.1 A writer emits no S card unless the enable-submanifests setting is true, which is false by default. SM-8.1-2 8.1 When the first S-bearing artifact is stored, a seen-submanifest indicator is recorded. SM-8.1-3 8.1 A local request to enable emission keeps a valid pin and refuses a different explicit k; with no valid pin it pins an explicit k from 1 to 12, refuses one outside, or selects one automatically; a request that cannot be met changes neither setting. SM-8.1-4 8.1 Disabling the setting stops new tree manifests and leaves existing ones in place. SM-9.1-1 9.1 SUBMANIFEST is determined by the post-pass reassignment, not while cards are read, and required-card logic treats it as an exception to the D card. SM-9.2-1 9.2 A sweep that discovers crosslink work by the absence of derived rows excludes SUBMANIFEST artifacts or records a completion marker for them, so it never reselects them. SM-9.3-1 9.3 Every consumer of a check-in's file set (checkout, diff, crosslink, rebuild, annotate, commit) obtains it through one shared enumeration interface. SM-9.4-1 9.4 When a tree manifest's processing is deferred, enough is recorded to rediscover it when the missing sub-manifest arrives, and the dephantomization path traverses that record. SM-10-1 10 The tree walk enforces the depth bound and the repeated-artifact check, and bounds the total sub-manifests visited per enumeration. the visit bound (2^20) is asserted by construction, not by a case that reaches it SM-A-1 A.2, A.3 The Appendix A.2 and A.3 artifacts parse, determine their types, recompute their names, walk to the four-file enumeration, and the R card verifies over it. SM-A-2 A.4 The Appendix A.4 artifacts parse, recompute their names, walk to the nine-file enumeration, and the R card verifies over it. SM-A-3 A.5 The authored Appendix A.5 acceptance vectors (three-level tree, height-0 merge, canonical encoding, delta over a tree) parse, walk, and verify their R cards; the reader accepts them at any partition parameter. SM-A-4 A.5 The writer vectors of A.5: the A.4 set reproduced at k = 3, the height-0 merge and three-level vectors reproduced, flat output for N = 1 and a MIN-suppressed boundary, no selection over one name with a first enable failing atomically, and an injected persistence failure leaving no setting applied.