# Fixture boards Golden fixture boards for the storage-contract test suite — real on-disk folder trees, not inline strings, so the same fixtures can later drive XCUITests via the `--open-board` launch hook. Bundled into the unit-test target as a folder reference (see `project.yml`). Valid boards live under `Valid/`, fail-fast cases under `Malformed/`. Tests live in `KanbanTests/FixtureBoardTests.swift`. Lane/card folder names are fixed literal lowercase-UUIDv4-shaped strings (never generated at test time), chosen so their lexicographic order matches the expected tie-break order — usually a leading digit (`10000000-...`, `20000000-...`, …) so folder order reads the same as array-index order in the tests. That is a fixture-authoring convention, not the loader's gate: the identity predicate is shape-only (`8-4-4-4-12` hex, **any case, any version** — 01-storage-format.md § Fractal layout ▸ Rules), and the case/version coverage lives in `KanbanTests/BoardLoaderTests.swift` rather than here. ## Valid/ — one board per tolerated/valid case | Board | Case | |---|---| | `rich-board.kanban` | A full-breadth well-formed board: 2 lanes, 3 cards, bodies, styling (background/icon/iconColor/width), unknown + reserved frontmatter keys, `attachments/` and `comments/` with real content. Also the board every `index.md` in the tree is round-tripped against. | | `interrupted-create.kanban` | The motivating skip-not-error case: a UUID-shaped lane folder and a UUID-shaped card folder, each with no `index.md` yet (folder created, write not yet landed). | | `non-uuid-strays.kanban` | Non-UUID-shaped folders at both lane and card depth, with and without `index.md` — name shape gates candidacy before the file is ever read. | | `stray-files.kanban` | Stray (non-directory) files at board, lane, and card level — never level candidates, never warned about. | | `tombstones.kanban` | A tombstoned lane and a tombstoned card, both still on disk and still in the snapshot, flagged (`isDeleted`) rather than removed. Also proves a tombstoned lane doesn't recursively flag its own un-deleted children. | | `duplicate-order-tie-break.kanban` | Three cards sharing one `order` in one lane, and two lanes sharing one `order` — both broken by folder name, ascending. | | `unknown-key-order.kanban` | Unknown/reserved frontmatter keys interleaved with schema-owned ones at board, lane, and card level — `document.unknownFields` must preserve exactly the order they were written in. | | `coercion.kanban` | Lenient-field coercion and fallback: wrong-type scalars that coerce (`title: 2048`, `iconColor: 42`, `background: 12345`, `width: "3"`) versus ones with no sensible reading that fall back to the default (`title: [a, b]`, `background: {x: 1}`, `width: 1.5`), plus a `deleted` with an unusable timestamp that still tombstones. | | `duplicate-top-level-keys.kanban` | A top-level key written twice — at board, lane (the strict `order` field), and card level. Last occurrence wins; **not** a fail-fast case (settled, newer than the original card text). Round-tripped to prove the earlier occurrence survives on disk, invisible only to reads. | | `board-level-deleted.kanban` | A board-level `deleted:` key — legal per the frontmatter table but meaningless; ignored + warned, rest of the board loads normally. | ## Malformed/ — one board per fail-fast case Each board is minimal: one broken thing. | Board | Case | |---|---| | `unparseable-yaml.kanban` | An unterminated flow sequence in the board's frontmatter. | | `missing-schema.kanban` | Board root `index.md` has no `schema` key. | | `schema-newer-than-app.kanban` | Board root `schema: 2`, newer than `BoardLoader.supportedSchema`. | | `missing-order-lane.kanban` | A UUID-shaped lane `index.md` with no `order` key. | | `missing-order-card.kanban` | A UUID-shaped card `index.md` with no `order` key. | | `explicit-null-order.kanban` | A lane's `order:` key present with no value — reads as missing, not malformed. | | `non-numeric-order.kanban` | A card's `order: banana` — present but not a number. | | `board-root-missing-index.kanban` | The board root folder itself has no `index.md`. |