Realign read-side rules — width range coercion, finite order, symlink pins

The design corpus ratified that ranges are part of a sensible reading:
an exact-integer width below 1 now coerces to 1 read-side (bytes
untouched) instead of reading as malformed — the width division must
never see a zero or negative unit — while a non-finite order (.nan,
.inf) is now the same loud malformed-order rejection as a non-numeric
one, guarded at the single point where the double arrives so loader
and Writer inherit it together. The symlink-never-traversed rule
turned out to be already enforced (the loader has filtered symlinks
ahead of the directory check since the first commit); it and the
copy-preserves-the-link-verbatim behavior are now pinned by tests,
alongside the two hostile shapes the corpus names (width: 0,
order: .nan). Five new tests.

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
2026-07-27 14:21:03 -04:00
parent b4c90838b4
commit bea6d02d1d
6 changed files with 155 additions and 27 deletions
+30 -8
View File
@@ -525,6 +525,16 @@ struct FrontmatterStrictFieldTests {
#expect(try document("order: \"1024\"").order == .malformed(raw: "\"1024\""))
#expect(try document("order: [1]").order == .malformed(raw: "[1]"))
}
/// NaN has no place in the total order the tie-break and midpoint math assume
/// (01-storage-format.md § Frontmatter, settled): a non-finite reading is the same loud
/// malformed-input rejection as a non-numeric one, never a silently `.valid(Double.nan)`.
@Test func nonFiniteOrderIsMalformedNotValid() throws {
#expect(try document("order: .nan").order == .malformed(raw: ".nan"))
#expect(try document("order: .inf").order == .malformed(raw: ".inf"))
#expect(try document("order: +.inf").order == .malformed(raw: "+.inf"))
#expect(try document("order: -.inf").order == .malformed(raw: "-.inf"))
}
}
// MARK: - Lenient fields
@@ -593,27 +603,39 @@ struct FrontmatterLenientFieldTests {
#expect(try document("title: [a, b]").title == .malformed(raw: "[a, b]"))
}
@Test func widthIsLenientForAnythingButAnIntegerAtLeastOne() throws {
#expect(try document("width: 0").width == .malformed(raw: "0"))
#expect(try document("width: -3").width == .malformed(raw: "-3"))
/// Only a fractional or non-numeric reading has no sensible width at all a sequence,
/// mapping, or scalar with no integer reading whatsoever stays malformed and renders as the
/// default 1.
@Test func widthIsMalformedOnlyForFractionalOrNonNumericReadings() throws {
#expect(try document("width: 1.5").width == .malformed(raw: "1.5"))
#expect(try document("width: wide").width == .malformed(raw: "wide"))
#expect(try document("schema: 1").width == .missing)
}
/// A string or double with an exact integer reading 1 coerces; a fractional reading,
/// zero, a negative, or non-numeric text still has none.
/// **Ranges are part of the sensible reading** (01-storage-format.md § Frontmatter, settled):
/// an exact-integer reading below 1 from an int, a double, or a numeric string coerces to
/// 1 rather than falling back to malformed. The table's " 1" is a validity bound on the
/// coerced value, not a gate on which readings count as sensible.
@Test func anIntegerWidthBelowOneCoercesToOne() throws {
#expect(try document("width: 0").width == .valid(1))
#expect(try document("width: -3").width == .valid(1))
#expect(try document("width: \"0\"").width == .valid(1))
#expect(try document("width: \"-3\"").width == .valid(1))
#expect(try document("width: -1.0").width == .valid(1))
}
/// A string or double with an exact integer reading coerces below 1 to 1 (see
/// `anIntegerWidthBelowOneCoercesToOne`), at or above 1 to itself; a fractional reading or
/// non-numeric text still has none.
@Test func widthCoercesStringsAndWholeNumberDoubles() throws {
#expect(try document("width: \"2\"").width == .valid(2))
#expect(try document("width: 2.0").width == .valid(2))
#expect(try document("width: 2.7").width == .malformed(raw: "2.7"))
#expect(try document("width: 0").width == .malformed(raw: "0"))
#expect(try document("width: -1").width == .malformed(raw: "-1"))
#expect(try document("width: banana").width == .malformed(raw: "banana"))
}
@Test func malformedLenientValuesStillRoundTrip() throws {
let text = "---\nschema: 1\nbackground: [red, blue]\nwidth: 0\nicon: {a: 1}\n---\nbody\n"
let text = "---\nschema: 1\nbackground: [red, blue]\nwidth: 1.5\nicon: {a: 1}\n---\nbody\n"
let document = try FrontmatterDocument.parse(text)
#expect(document.serialized() == text)
#expect(document.background.isMalformed)