Realign code with the 2026-07-31 findings-resolution rulings
The full bullet list from Implementation card bf080d9a — both ruling batches, including the three appended mid-session by16ef377: - Restore subjects compose the inverse, never nest: crossing "Undo: S" emits "Redo: S" and vice versa; parity, not stack depth, reads a legacy double prefix (GitHistoryProvider.restoreSubject). - Git-operation failures join the one-shot failure banner tier: BannerCenter.GitFailureBanner (undo/redo/branchSwitch/addGit), error tone at failure rank merged with write one-shots by recency; the postLoss compromise is retired at both AppModel wirings. - order/schema optional below the board root: append-at-end reading (ordered siblings first, folder-name tie-break among the order-less), schema reads 1, both coerce-tier logged; the root keeps its requirements. Ranks.resolvedOrders materializes finite ranks so models and placement math stay untouched; first Writer rewrite stamps a real rank on touch, placement against an order-less sibling stamps that sibling inline in the same bracket. Agent guide v10 teaches optional keys and zero-read filing. Hostile-YAML order shapes become coercion tests; Fixtures/Valid/optional-keys.kanban replaces the four retired Malformed boards. - .gitignore is the relocation-heal noise gate: GitignoreRules pure matcher (standard semantics, board-root file only), loader consults it once per walk so matched loose files keep the stray posture; seeded (.DS_Store + .*.lanework-*) at board creation and template instantiation, healed in when missing at open — repo-nested included; empty file honored, existing files never edited; the committer's obedience via libgit2 status is pinned by test. - Comments crash-residue sweep gates on step ownership: HistoryStep derives backing from its own undo expectations, backedContent unions both stacks, the sweep purges per-entry only what no live step owns. - Skip-purge decoupled (16ef377): a stale-skipped coarse step strands whole in NativeHistoryProvider.strandedSteps — still backing, retired only at session end; clean exits purge as before. - Coarse close step named "Changes to '<card>'"; the fine body-edit wording never leaks onto the board menu. - Branch-switch settle clears every open card window's fine stack on Save All and Discard alike; the empty fold registers no coarse step. - Close flush awaits its covering snapshot (quiesce + one generation bump, 1s bound), and an explicit flush now queues behind an in-flight one instead of skipping — the audit-caught interleaving could lose a close flush permanently when the debounce fired inside the close sequence; regression tests force both races. - Commit comment bullets sort chronologically by created, not UUID. - The production-unwired CardBodyEditSession.editSessionDidChange seam is deleted with its seam-only tests. - Composition-root pins: beginSession composes the committer with the store's own EchoLedger and binds the announcer (the miswire class). - Deliberate 06 conformance pass over every 2026-07-31-tagged sentence: fixed Change-custom-key subjects (the retired named generic was the only producer), the unbuilt Replace attachment vocabulary, heal commits now authored Lanework Integrity, the config reader scopes identity to plain [user] sections, add-git re-runs detection at create (a stale mode-none could initialize inside the user's repo), and add-git failures answer at the form or the banner. Structural residue filed on the Redesign board. 2554 tests / 439 suites green. Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
This commit is contained in:
@@ -76,8 +76,15 @@ enum AgentGuide {
|
||||
/// defect was a missing second line, and the parser's complaint pointed at the *last* key it
|
||||
/// swallowed rather than the title. The guide now teaches long values as one long line, says
|
||||
/// why the wrapped shape is the dangerous one to copy, and names the unterminated quote beside
|
||||
/// the unquoted colon in Hard rules.
|
||||
static let version = 9
|
||||
/// the unquoted colon in Hard rules. **v10 makes `order` and `schema` optional below the board
|
||||
/// root** (01-storage-format.md § Frontmatter and § Ordering, re-ruled 2026-07-31): the guide's
|
||||
/// whole point is that filing a card must need nothing but the schema
|
||||
/// (08-agent-integration.md's masterplan requirement), and until now that was untrue — a card
|
||||
/// needed a rank, and a rank needed a scan of every sibling in the lane. The guide now teaches
|
||||
/// the zero-read minimum (`mkdir` plus one `index.md`, no `order`, no `schema`; it lands at the
|
||||
/// lane's bottom and the app stamps a real rank on its first touch) while still teaching
|
||||
/// *writing* `order` as the way to control position, which is the only way to control it.
|
||||
static let version = 10
|
||||
|
||||
// MARK: - The version marker
|
||||
|
||||
@@ -367,7 +374,8 @@ enum AgentGuide {
|
||||
## Reading the board
|
||||
|
||||
- Lanes run left→right by ascending `order`; cards top→bottom by ascending
|
||||
`order` within their lane. Ties break by folder name.
|
||||
`order` within their lane. Ties break by folder name. An item with no
|
||||
`order` sorts after every item that has one — see Creating a card.
|
||||
- Lane titles carry the workflow semantics (e.g. To Do → In Progress →
|
||||
Done). Read the board's and lanes' index.md bodies for descriptions and
|
||||
per-lane policy before deciding where a card belongs.
|
||||
@@ -376,13 +384,15 @@ enum AgentGuide {
|
||||
|
||||
## Frontmatter
|
||||
|
||||
All levels: `schema` (required, always `1`), `title` (optional — an item
|
||||
without one renders as untitled, so give cards real titles), `created` and
|
||||
`modified` (ISO-8601 with timezone, e.g. `2026-07-24T18:00:00Z`),
|
||||
`background` (color), `icon` (SF Symbol name), `iconColor` (color, tints
|
||||
`icon`). Lanes and cards additionally require `order` (a number; floats are
|
||||
fine). Lanes may set `width` (integer ≥ 1, multiplier of the standard lane
|
||||
width).
|
||||
All levels: `schema` (always `1`; **required at the board's own `index.md`**,
|
||||
optional below it — a lane or card without one is read as schema 1), `title`
|
||||
(optional — an item without one renders as untitled, so give cards real
|
||||
titles), `created` and `modified` (ISO-8601 with timezone, e.g.
|
||||
`2026-07-24T18:00:00Z`), `background` (color), `icon` (SF Symbol name),
|
||||
`iconColor` (color, tints `icon`). Lanes and cards may set `order` (a number;
|
||||
floats are fine) — **optional, and the way to control position**: an item
|
||||
without one goes last. Lanes may set `width` (integer ≥ 1, multiplier of the
|
||||
standard lane width).
|
||||
|
||||
**Quote any `title` containing a colon** — `title: Fix: the thing` is
|
||||
invalid YAML; write `title: "Fix: the thing"`. The same goes for any value
|
||||
@@ -418,9 +428,7 @@ enum AgentGuide {
|
||||
|
||||
## Creating a card
|
||||
|
||||
1. Pick the lane folder. Compute `order`: bottom of the lane = max existing
|
||||
card `order` + 1024; top = min − 1024; between two cards = their
|
||||
midpoint. (Empty lane: any number, conventionally 1024.)
|
||||
1. Pick the lane folder.
|
||||
2. Create a folder named a fresh lowercase UUID:
|
||||
`id=$(uuidgen | tr 'A-Z' 'a-z')`.
|
||||
3. Write `<lane>/$id/index.md` (timestamp: `date -u +%FT%TZ`):
|
||||
@@ -438,8 +446,31 @@ enum AgentGuide {
|
||||
The card's content — any Markdown.
|
||||
```
|
||||
|
||||
**`order` is what places the card, and computing it means reading the
|
||||
lane**: bottom of the lane = max existing card `order` + 1024; top =
|
||||
min − 1024; between two cards = their midpoint. (Empty lane: any number,
|
||||
conventionally 1024.) Write it whenever the position matters.
|
||||
|
||||
**You can also file a card without reading the lane at all.** The minimum
|
||||
legal card is a `mkdir` and one `index.md` containing nothing but a title —
|
||||
no `order`, no `schema`:
|
||||
|
||||
```markdown
|
||||
---
|
||||
title: Short imperative card title
|
||||
---
|
||||
The card's content.
|
||||
```
|
||||
|
||||
It lands at the bottom of the lane (an item with no `order` sorts after
|
||||
every item that has one; two such items sort by folder name), and the app
|
||||
writes a real `order` into it the next time it rewrites that file. Prefer
|
||||
the full frontmatter above — `kind`, the timestamps and `modified-by` are
|
||||
all worth having — but when you are filing into a 200-card lane and the
|
||||
position doesn't matter, the short form costs one write and no reads.
|
||||
|
||||
Creating a lane is the same one level up (body optional; `kind: lane`;
|
||||
`order` ranks lanes left→right).
|
||||
`order` ranks lanes left→right, and is optional in the same way).
|
||||
|
||||
**Always write `kind`** at creation — `kind: card`, `kind: lane`,
|
||||
`kind: board` at board root. Depth already says what an item is on the
|
||||
@@ -508,10 +539,11 @@ enum AgentGuide {
|
||||
|
||||
## Hard rules (the app fails loudly on violations)
|
||||
|
||||
- Frontmatter must parse as YAML; `schema` (plus `order` on lanes and
|
||||
cards) is required. Keep `schema: 1`. The classic violations are an
|
||||
unquoted colon in a title and a quoted value left unclosed across a
|
||||
line break (see Frontmatter above).
|
||||
- Frontmatter must parse as YAML. The board's own `index.md` must carry
|
||||
`schema: 1`; everywhere else `schema` and `order` are optional and a
|
||||
missing one is read, never refused. Never write a `schema` other than
|
||||
`1`. The classic violations are an unquoted colon in a title and a
|
||||
quoted value left unclosed across a line break (see Frontmatter above).
|
||||
- Files must be UTF-8 without BOM.
|
||||
- Never create a card folder without an `index.md`.
|
||||
- Never rename UUID folders.
|
||||
|
||||
Reference in New Issue
Block a user