Resolve the second-pass review findings — comments undo via .trash recursion, search reach, refuse-don't-degrade paste
Thirteen findings cleared with the user (Redesign board: 3 Contradictions + 3 Gaps + 7 Minors → Resolved): - User template store re-homes to the shared App Group container (09/02) — templates cross editions; App Group implementation card annotated mid-flight. - Comment delete = move into comments/.trash/ (01/05/13) — the materialized-trash pattern one level down; no byte capture returns on any edition; purge at window close, copies strip it; 13's absolutes stay true. - Find & search: card-window ⌘F covers the focused comments pane; board search re-ruled to all meaningful card content — comment bodies via a search-owned transient index when comments ship, attributes as they activate (04/01/05); scope options = WISHLIST #10. - Comments pane visibility = one persisted app-wide bit, à la Show Trash — content-derived auto-show retired (05/11). - Comment attachments author in-window: composer/inline-edit drop carve-outs + paperclip (05). - Item-level copies sever remote/remote-state at every level; whole-board forks exempt (01). - Paste refuses loudly, never degrades — degraded embedded-index.md fallback and its loss row retired; Finder's whole-or-nothing invariant adopted (04/12/02). - Escape: composer moves focus out (never discards a draft); inline comment edit = Cancel (05/11). - Minors: 05 three-pane changes bullet, 01 comments-UI parenthetical, 07 TOFU store naming, WISHLIST item 3 trash wording, README deferred-list now points at the findings board. Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
This commit is contained in:
@@ -67,7 +67,7 @@ The non-modal banner named throughout the read- and write-side rules above is on
|
||||
|
||||
- **Hosted by the window of origin.** Every window hosts a banner strip; a condition surfaces in the window whose action produced it — debounced body save, attachment drop, and raw-source Apply failures in their card window; reload breakage, one-shot write failures, commit failures, and lock states in the board window. A card window that closes while its condition persists re-homes the banner to the board window (the condition is still true; it must stay visible somewhere).
|
||||
- **One-shots dismiss, conditions heal.** One-shot failures ("Couldn't move 'Fix login' — disk full") carry an explicit dismiss control and no timeout — an error never evaporates unread. Persistent conditions (reload breakage, suspended auto-commit, read-only locks) have no dismiss: they describe ongoing state, standing until the next success clears them, per the rules above.
|
||||
- **Concurrent conditions stack.** The strip presents independent rows, precedence-ordered: **in-progress rows (pinned) >** read-only lock > reload breakage > one-shot write failures > **loss rows** > commit and attachment failures **> passive info rows** (the remote-change signpost); newest first within a class. **Loss rows are the warning-tone class for non-failure losses** (settled 2026-07-28): content that didn't arrive though nothing failed — a degraded paste, folders skipped from a Finder drop, their future kin. They take the one-shot's lifecycle (dismissable, untimed — a loss the user didn't notice is the harm, so it never auto-expires), rank below the true failures (an action that didn't happen outranks one that partially did), and above the ambient notices. Each row heals or dismisses independently; beyond three rows the remainder collapse behind a "+N more" disclosure. **In-progress rows are exempt from the collapse and don't count toward its budget** (settled): they are the strip's only explanation for a bracket's write lock and for a close/quit deferring teardown, and the copy rows carry the reachable Cancel — a spinner may never hide behind "+N more". They're safe to pin: few at once, self-clearing, **newest first within the class like every other** (ratified — insertion order; the class rarely holds more than two rows, and one ordering rule beats a special case). Passive info rows rank last and may collapse — calm by design, nothing gated on seeing them instantly.
|
||||
- **Concurrent conditions stack.** The strip presents independent rows, precedence-ordered: **in-progress rows (pinned) >** read-only lock > reload breakage > one-shot write failures > **loss rows** > commit and attachment failures **> passive info rows** (the remote-change signpost); newest first within a class. **Loss rows are the warning-tone class for non-failure losses** (settled 2026-07-28): content that didn't arrive though nothing failed — folders skipped from a Finder drop, a legacy migration's folded notices, their future kin (the degraded paste left the class 2026-07-29 — a snapshot-less paste now refuses outright, a one-shot failure, 04-interactions.md ▸ Clipboard). They take the one-shot's lifecycle (dismissable, untimed — a loss the user didn't notice is the harm, so it never auto-expires), rank below the true failures (an action that didn't happen outranks one that partially did), and above the ambient notices. Each row heals or dismisses independently; beyond three rows the remainder collapse behind a "+N more" disclosure. **In-progress rows are exempt from the collapse and don't count toward its budget** (settled): they are the strip's only explanation for a bracket's write lock and for a close/quit deferring teardown, and the copy rows carry the reachable Cancel — a spinner may never hide behind "+N more". They're safe to pin: few at once, self-clearing, **newest first within the class like every other** (ratified — insertion order; the class rarely holds more than two rows, and one ordering rule beats a special case). Passive info rows rank last and may collapse — calm by design, nothing gated on seeing them instantly.
|
||||
- **Tones, not components.** The banner has kinds — error, warning, info — sharing layout and the accessibility announcement path (10-accessibility.md). The card window's remote-change signpost (07-sync-collab.md) is this same component in the info tone: visually calm, no error color. **Its lifecycle is the one-shot's — dismissable, untimed** (settled): 07's "transient" means non-modal and non-blocking, never auto-expiring; the strip has exactly two lifecycles (one-shots dismiss, conditions heal) and the signpost doesn't add a third.
|
||||
- **In-progress operations are info rows** (settled): bracketed git operations ("Pulling…", "Switching to 'main'…") and long non-git work (big-board Duplicate, template instantiation, large attachment imports, and cross-board transfers — drag copies and moves, staged-clipboard pastes) each show an info-tone row with a spinner — determinate where progress is knowable. Completion clears the row (the VoiceOver completion announcement of 10-accessibility.md rides the same event); failure swaps it for the error row. Sighted and VoiceOver users learn one vocabulary.
|
||||
- **Cancel appears on safe copies only** (settled): copy-shaped work — attachment imports, Duplicate, template instantiation, cross-board copies and pastes — carries Cancel, meaning "remove the partial copy, nothing lost"; a cross-board ⌘-drag *move* cancels the same way during its copy phase — the source deletes only after the copy lands, so Cancel leaves the original untouched. Git brackets get no Cancel: seconds long, and aborting a rebase mid-flight is a repair job, not a cancel.
|
||||
@@ -99,7 +99,7 @@ State that belongs to the app, not the user's files — the recents list, per-bo
|
||||
- **The row's title and icon are registry-cached too — with live write-through** (settled): the record carries the board's `title`, `icon`, and `iconColor` beside the counts, and the welcome row reads only the record — it never opens any board's `index.md` (the same hang-avoidance that motivated the counts rule). Unlike the counts' at-close stamp, these three refresh **whenever an open board's reload changes them**: the store already holds the new snapshot, so an in-app Board rename (03-board-ui.md) lands in the record instantly — never a welcome row showing a name the user just changed away from — and a foreign rename of an *open* board rides the same path for free. The honest residual: renaming a board that isn't open (an agent editing its root `index.md`) stays stale until the next open — accepted, the counts' staleness class. The title falls back to the folder name per 01-storage-format.md, cached at the same moments.
|
||||
- **Files-first stays absolute**: nothing app-private is ever written into the board folder — no frontmatter keys, no sidecar files, no xattrs. Two machines sharing a board via a remote each keep their own record (push-on-commit and window frames are genuinely per-machine choices).
|
||||
- **Graceful orphaning**: a record whose bookmark no longer resolves (board deleted, or moved across volumes where bookmarks can't follow) is orphaned — recents surface it as unavailable with Forget; its settings are conveniences and die with it (accepted).
|
||||
- **App-wide state has the same home.** Not everything app-side is board-scoped: quick-style recents (03-board-ui.md), the SSH host-key assignment table and TOFU fingerprint store (07-sync-collab.md — host-scoped), the last-used card-window size (05-card-window.md), and their peers live beside the registry in the App Group container (or the group's shared `UserDefaults` suite where a scalar fits — 12-editions.md) — no per-board record involved. Secrets are the named exception: Keychain only, never here (07).
|
||||
- **App-wide state has the same home.** Not everything app-side is board-scoped: quick-style recents (03-board-ui.md), the SSH host-key assignment table and TOFU fingerprint store (07-sync-collab.md — host-scoped), the last-used card-window size (05-card-window.md), the user template store (09-templates.md — plain board folders, deliberately edition-crossing), and their peers live beside the registry in the App Group container (or the group's shared `UserDefaults` suite where a scalar fits — 12-editions.md) — no per-board record involved. Secrets are the named exception: Keychain only, never here (07).
|
||||
|
||||
## Caching and search
|
||||
|
||||
|
||||
Reference in New Issue
Block a user