Collapse the edition split — one app, Pro as a subscription

2026-07-30 design pass (with the user), superseding the 2026-07-27
two-app split and the 2026-07-29 App Group ruling. Rulings:

- One Mac App Store app (dev.rzen.indie.Kanban, free, 2.0 updates the
  existing record); Lanework Pro = auto-renewable subscription (StoreKit
  2) unlocking the git tier; libgit2 compiles in dormant. The KanbanPro
  target, module-alias tests, verify-editions, UTI/About/Types twins all
  retire. Teams stays deferred — probably a separate app, and never on a
  shared app group.
- No grandfathering: 1.x's free git users get the inert-.git posture;
  unsubscribed and lapsed are one state — histories freeze, resume on
  subscribe via the committer's catch-up commit.
- Entitlement = local read of StoreKit's signed transaction store at
  board-session composition; never a network call on the open path;
  subscribe effective at next open (purchase flow offers reopen); lapse
  never interrupts an open session; expiry-while-offline with auto-renew
  on holds in grace until a real refresh.
- App Group removed wholesale: registry, clipboard staging, template
  store, defaults return to ordinary Application Support; grant slots
  collapse to one bookmark, open-now to one flag; freshness stamp,
  pid-liveness line, group-id provisioning risk all dissolve.
- Quiet signposts carry over; Settings gains the Pro section (subscribe/
  manage/restore) as the third named Pro surface.

12-editions.md rewritten as the tiers doc; edition vocabulary swept to
tiers across 00-13, README, WISHLIST.

Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
This commit is contained in:
2026-07-30 15:04:09 -04:00
parent c741b02016
commit 0bec9a6be5
14 changed files with 62 additions and 53 deletions
+2 -2
View File
@@ -85,11 +85,11 @@ The card-level styling home: the **embedded style editor** — background palett
## The comments column
Designed 2026-07-29 (storage: 01-storage-format.md ▸ Enhanced schema). Ships in **every edition** — only tracker sync is edition-gated (12-editions.md). Feature lands post-2.0.
Designed 2026-07-29 (storage: 01-storage-format.md ▸ Enhanced schema). Ships in **every tier** — only tracker sync is tier-gated (12-editions.md). Feature lands post-2.0.
- **Visibility** (re-ruled 2026-07-29 — the pane obeys the user, not the content): **View ▸ Show Comments** is a checkmark toggle à la Show Trash, and its choice is **app-wide and persisted across restarts** (the group `UserDefaults` suite, beside Comments Beside Body). One bit, no content-derived auto-show: checked, every card window carries the pane (a comment-less card shows the empty thread and the composer — the invitation is the point); unchecked, threads and drafts are out of sight until the user says otherwise, the Show Trash bargain. The checkmark reads the bit — the menu never lies. **File ▸ Add Comment** flips the bit on when it's off (the gesture *is* the user choosing to see comments — same persistence) and focuses the composer in one gesture (11-command-nexus.md). Deleting the last comment never closes the pane — nothing but the toggle does.
- **The thread**: one comment = an author line (self-reported `author`, unattributed when absent; timestamp; "· edited" when `modified` differs from `created`), the rendered Markdown body (the card-body subset), and attachment chips when its `attachments/` is non-empty (Quick Look, the sidebar section's pattern). No avatars — there is no identity system, and initials faked from self-reported strings would be decoration. The section header carries the count ("Comments · 3") and the **sort-direction control**: chronological ascending by default, flippable to newest-first (app-wide, persisted).
- **The composer edits `comments/.draft/`** (ruled 2026-07-29 — the draft is user content in the board, the `.trash` pattern applied to composition): an always-visible text area ("Add a comment…", Edit-mode Markdown highlighting) whose backing file is the card's single draft — a reserved dot-named folder under `comments/` holding ordinary comment schema, `attachments/` included, excluded from the thread listing. Restore-on-reopen falls out for free (the composer just reads its file); drafts ride git and sync across machines and editions like any file; concurrent drafts on two machines are an ordinary file race (local-wins). **The composer sits at the thread's newest end** (bottom ascending, top descending) and the window opens scrolled to it — a thread opens where the conversation is happening. **Comment attachments author here** (ruled 2026-07-29): a file dropped within the composer's bounds imports to the draft's `attachments/` (the hover-target carve-out — Attachments above), a quiet **paperclip affordance** on the composer covers the no-drag path (the section header's add-affordance pattern; File ▸ Add Attachment… stays card-scoped), and the same pair applies within an inline comment edit session, targeting that comment's `attachments/`. Chips on an authoring surface carry remove (to the **system** Trash — the sidebar row's rule); a posted comment's chips are read-only, Quick Look only — Edit the comment to change its files.
- **The composer edits `comments/.draft/`** (ruled 2026-07-29 — the draft is user content in the board, the `.trash` pattern applied to composition): an always-visible text area ("Add a comment…", Edit-mode Markdown highlighting) whose backing file is the card's single draft — a reserved dot-named folder under `comments/` holding ordinary comment schema, `attachments/` included, excluded from the thread listing. Restore-on-reopen falls out for free (the composer just reads its file); drafts ride git and sync across machines like any file; concurrent drafts on two machines are an ordinary file race (local-wins). **The composer sits at the thread's newest end** (bottom ascending, top descending) and the window opens scrolled to it — a thread opens where the conversation is happening. **Comment attachments author here** (ruled 2026-07-29): a file dropped within the composer's bounds imports to the draft's `attachments/` (the hover-target carve-out — Attachments above), a quiet **paperclip affordance** on the composer covers the no-drag path (the section header's add-affordance pattern; File ▸ Add Attachment… stays card-scoped), and the same pair applies within an inline comment edit session, targeting that comment's `attachments/`. Chips on an authoring surface carry remove (to the **system** Trash — the sidebar row's rule); a posted comment's chips are read-only, Quick Look only — Edit the comment to change its files.
- **Draft saves are slow-cadence, never prompted** (flow breakage minimized): the draft writes on composer blur, window close, quit, and a lazy interval (~30 s) — not the body editor's 700 ms, so a Pro user's typing never becomes a commit stream; the saves that do land compose the quiet path-shaped **"Draft comment on '⟨card⟩'"**. Close and quit just proceed — no DirtyBufferGuard, nothing to lose. A draft emptied of text with no attachments deletes its folder — no litter. **Escape moves focus out of the composer, draft untouched** (ruled 2026-07-29 — Escape never discards: the draft is a durable file, so "abandon" has no meaning here; emptying the draft is the discard gesture, and the title field's abandon-Escape stays the transient-bubble exception).
- **⌘↩ posts** (a Comment button twins it): posting renames `.draft` → a fresh lowercase UUID and **restamps `created`/`modified`** in the same write bracket — chronology is when it was posted, not when drafting began — one gesture, one commit ("Comment on '⟨card⟩'" — 06-history-undo.md's verb family per 01).
- **Edit and delete**: every comment is editable and deletable — files-first has no enforced identity. The comment's context menu (the per-item inventory — 10-accessibility.md) carries **Edit / Delete / Reveal in Finder**. Inline Edit is a **body-edit session in miniature** (no second draft mechanism): debounced saves to the comment's own file keep it crash-safe, Save (or ⌘↩) ends the session as its commit point, Cancel — or Escape, its keyboard twin (ruled 2026-07-29; 11's grammar table) — reverts to session-start bytes, window close flushes the session exactly as the body's does. Delete is immediate and undoable, no confirm (01's ruling — undo is the net: the comment moves into `comments/.trash/`, undo is the move back, and the folder purges at window close; 13-native-undo.md ▸ Interaction with the trash).