| Comment: | fix(deck): re-encode present-but-empty values and keep timestamp precision (#272) (#338)
Marshal dropped a present-but-empty C comment, N mimetype or T value, a bare P card and an empty W body, and wrote D to the millisecond and E to the second, so an artifact carrying any of those did not round-trip through Parse and Marshal. Carry the presence of a C, N or P card, and of a T value, in unexported Deck/TagCard fields that Parse sets and Marshal reads, and re-emit the W card whenever its body is non-nil (a parsed empty body is a non-nil empty slice). The public API is unchanged: a caller that sets a non-empty value still has it marshalled. Write the D and E timestamps at their writer precision -- millisecond and second -- extended to keep whatever finer fraction the parser read, so a sub-second timestamp survives the round trip. Remove the three FuzzArtifactRoundTrip knownLosses these fixes retire. |
|---|---|
| Timelines: | family | ancestors | descendants | both | main | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
0902561005f7ef80a3ee6630df2e6754 |
| User & Date: | [email protected] on 2026-10-12 17:44:22.000 |
| Other Links: | branch diff | manifest | tags |
|
2026-10-12
| ||
| 17:52 |
fix(deck): enforce card legality, required cards and per-type semantics (#273) (#339)
deck.Parse determined an artifact's type but then checked nothing against it, so a card a type disallows, a required card left out, or a tag that breaks a per-type semantic rule all parsed. Add deck/legality.go with fossil's manifestCardTypes table (allowed and required cards per type) and the §5.4 semantic checks: a control artifact's tags may not target itself, a technote's tags are all self-referential singletons, and a forum post carries at most one of an H or I card and at most one parent. Parse now determines the type (inferType gains the B, J and Q type-setters it was missing and falls back to a control artifact, not an empty check-in, when nothing sets a type and there is no comment or parent), then applies legality and the semantic checks. A missing Z card is now caught by the universal required-card rule. Several internal/manifest and internal/deck tests built incomplete artifacts fossil also rejects -- a cluster with a D card, a forum post with both an H and an I card, control-shaped D/U/Z artifacts with no T card, and single-card fixtures missing their type's required cards. Frame each as a valid artifact of its type; the behavior each test pins is unchanged. This also makes two repostate conformance cases conform: the technote with a non-self tag is now rejected at parse (not by a later isArtifact gate), and the opaque-control rebuild case. Their marks are removed in conformance/repostate_gaps_test.go. check-in: 7b8f655da6 user: [email protected] tags: main, trunk | |
| 17:44 |
fix(deck): re-encode present-but-empty values and keep timestamp precision (#272) (#338)
Marshal dropped a present-but-empty C comment, N mimetype or T value, a bare P card and an empty W body, and wrote D to the millisecond and E to the second, so an artifact carrying any of those did not round-trip through Parse and Marshal. Carry the presence of a C, N or P card, and of a T value, in unexported Deck/TagCard fields that Parse sets and Marshal reads, and re-emit the W card whenever its body is non-nil (a parsed empty body is a non-nil empty slice). The public API is unchanged: a caller that sets a non-empty value still has it marshalled. Write the D and E timestamps at their writer precision -- millisecond and second -- extended to keep whatever finer fraction the parser read, so a sub-second timestamp survives the round trip. Remove the three FuzzArtifactRoundTrip knownLosses these fixes retire. check-in: 0902561005 user: [email protected] tags: main, trunk | |
| 17:39 |
fix(deck): parse D and E timestamps with the full 4.6.4 grammar (#271) (#337)
The parser tried only two time.Parse layouts and rewrote a lowercase t to T, so it rejected the HH:MM, timezone, hour-24, Feb-31 and negative-year forms fossil accepts via SQLite's julianday(), and it silently accepted a lowercase t separator the draft rejects. Add deck/timestamp.go: a byte cursor that parses the date-time form (optional leading minus, YYYY-MM-DD, one or more whitespace-or-T separators, HH:MM with optional seconds and fraction, an optional Z/z or +HH:MM/-HH:MM zone), the date-only form, and a bare Julian-day number, with the exact-digit field ranges the 4.6.4 erratum scopes to those forms and the "strictly after -4713-11-24" lower bound. A lowercase t separator is rejected. time.Date normalizes the hour-24 and unchecked-day forms the way julianday() does. check-in: 127685f0f5 user: [email protected] tags: main, trunk | |