Promote kind to the common schema — written at creation of every object
User addendum to the integrity pass: kind moves from the lane table to the common frontmatter table — board/lane/card at creation, comment reserved; value-trusted where consulted, consequential only inside .trash/ today, carried everywhere for consistency. A missing kind backfills on touch via the integrity service. Guide v6 teaches kind on every object. Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
This commit is contained in:
@@ -52,6 +52,7 @@ MyBoard.kanban/ ← board = the document
|
||||
| `background` | string | no | Palette name or `#RRGGBB[AA]` — see 03-board-ui.md |
|
||||
| `icon` | string | no | SF Symbol name, per-level defaults |
|
||||
| `iconColor` | string | no | Palette name or hex |
|
||||
| `kind` | string | no | The object's kind — `board`, `lane`, `card` (`comment` reserved with the enhanced schema). **Written at creation of every object** (re-ruled 2026-07-29 — consistency across the schema, even where position already answers). The value — never the key's mere presence — names the kind, and consumers that consult it trust the value outright: no stripping, no corroboration machinery. Only consequential inside `.trash/` today, where position can't answer (Deletion below); everywhere else it is redundant with position (level is position) and carried for uniformity. Missing on an older object, it **backfills on touch** — the integrity service's on-touch heal (Validation and healing below), never a scheduled sweep. |
|
||||
|
||||
**`modified`'s scope — content provenance, not file activity (settled).** The stamp updates on every app write that rewrites the item's `index.md`, and only those — it describes the item's *content* (title, body, frontmatter), never its files. Two designed app writes therefore don't bump it, deliberately: **raw-source Apply** writes the validated buffer byte-for-byte (05-card-window.md — the verbatim contract outranks stamping, the same reason it doesn't clear `modified-by` below), and **attachment operations** never touch `index.md` at all — load-bearing, not an oversight: Add Attachment stays enabled during an open raw-source edit precisely because it can't fight the buffer (03-board-ui.md ▸ toolbar). Accepted consequence: the card window's "Modified ⟨date⟩" line (05-card-window.md) can read older than the card's latest attachment activity — attachment history lives where files do (the sidebar shows them; on git boards the Attach/Remove commits are the activity trail — 06-history-undo.md).
|
||||
|
||||
@@ -73,7 +74,6 @@ Body: board description (free Markdown).
|
||||
|---|---|---|---|
|
||||
| `order` | number | yes | Rank among lanes, ascending = left-to-right |
|
||||
| `width` | integer | no | Width multiplier ≥ 1 (default 1); no cap |
|
||||
| `kind` | string | no | Always `lane` (ruled 2026-07-29) — written at lane creation, backfilled on touch when absent (the integrity service's on-touch heal — Validation and healing below), never stripped. Redundant with depth on the live board; load-bearing inside `.trash/` (Deletion below). **Any object may carry `kind`, and the value — never the key's mere presence — names the object's kind** (re-ruled 2026-07-29): consumers that consult the key trust its value outright, with no stripping and no corroboration machinery; the live board never consults it (level is position), the trash consults it first. The app writes it only on lanes — accept liberally, emit conservatively. |
|
||||
|
||||
Body: lane description / WIP policy / notes.
|
||||
|
||||
@@ -115,7 +115,7 @@ Carried over unchanged — gapped fractional ranks:
|
||||
The tombstone model is **retired** — no `deleted:` key, no in-place flags, no ancestor-walked hiding. Deletion is a **move**:
|
||||
|
||||
- **Deleting a card or a lane moves its folder into `<board-root>/.trash/`** (lanes joined 2026-07-29 — retiring the design's sole destructive delete) — a reserved, app-claimed name at board root (joining `CLAUDE.md` and the seeded `.gitignore` on the claimed list; agents and hand-editors should treat it as the app's). `.trash/` holds card and lane folders interleaved directly, no `index.md` of its own. Every arrival lands at the **top** regardless of kind: the move mints an `order` rank above the current topmost, so the trash sorts newest-first by ordinary ranks — no timestamp sort, no tie-break rules. The move **stamps `modified`** (deletion is an edit to the item's story — the deliberate exception to moves-don't-stamp), which is what a future age-based auto-purge will read (deliberate follow-up, not in the initial release). A trashed lane keeps its subtree untouched — its cards ride along and come back with it.
|
||||
- **`kind:` discriminates inside `.trash/`** (ruled 2026-07-29): depth defines meaning *on the live board*, but the trash is flat, and an empty lane folder is shape-identical to a card folder (`<uuid>/index.md` both). Lane `index.md` frontmatter therefore carries **`kind: lane` at all times** — written at lane creation, backfilled on touch when absent (settled 2026-07-29 — the integrity service's on-touch heal, Validation and healing below: any Writer rewrite of that lane's `index.md`, the trash move's rank mint included, stamps the missing key; **on-touch only, never a scheduled backfill sweep**), never stripped (restore stays a pure move; the key is inert on the live board where depth wins). The trash reader's rule **trusts the value** (re-ruled 2026-07-29 — the value-names-the-kind posture, Frontmatter above): `kind: lane` → lane; `kind: card` → card; an unrecognized value or no key falls through to shape — UUID-shaped children with their own `index.md` → lane (the key backfills on the next touch), else card. Trusting the value means an external writer's `kind: lane` on what looks card-shaped is honored, never policed — the app never writes the key on cards, so its presence is a deliberate claim. Honest limit of on-touch-only backfill, accepted: a kind-less trashed lane emptied of its children before any touch becomes indistinguishable from a card.
|
||||
- **`kind:` discriminates inside `.trash/`** (ruled 2026-07-29): depth defines meaning *on the live board*, but the trash is flat, and an empty lane folder is shape-identical to a card folder (`<uuid>/index.md` both). Every object carries `kind` from creation (re-ruled 2026-07-29 — the common-schema row, Frontmatter above); inside `.trash/` it is where the key earns its keep. A lane's `kind: lane` is **backfilled on touch when absent** (the integrity service's on-touch heal, Validation and healing below: any Writer rewrite of that lane's `index.md`, the trash move's rank mint included, stamps the missing key — **on-touch only, never a scheduled backfill sweep**) and never stripped (restore stays a pure move; the key is inert on the live board where position wins). The trash reader's rule **trusts the value** (re-ruled 2026-07-29 — the value-names-the-kind posture): `kind: lane` → lane; `kind: card` → card; an unrecognized value or no key falls through to shape — UUID-shaped children with their own `index.md` → lane (the key backfills on the next touch), else card. Trusting the value means an external writer's `kind: lane` on what looks card-shaped is honored, never policed. Honest limit of on-touch-only backfill, accepted: a kind-less trashed lane emptied of its children before any touch becomes indistinguishable from a card.
|
||||
- **Restore is a move out**: any move of a card folder from `.trash/` into a lane, or of a lane folder to board level — drag, or cut+paste — is an ordinary move; there is no restore-specific machinery and no Put Back. Position (and, for cards, lane) are chosen at restore time.
|
||||
- A folder that disappears entirely (Finder deletion) is also a delete; the app reflects it — such items are gone, they never enter the trash.
|
||||
- Physical removal in-app is the trash's **Delete / Delete Immediately / Empty Trash** (03-board-ui.md).
|
||||
|
||||
Reference in New Issue
Block a user