The paper agrees with the code — guide v11, README, DESIGN re-rulings, and the adjudicated sweep

Step 7 of strategy/01-git-excision.md, the companions. The agent guide bumps to v11: the Git section teaches repo-resident etiquette alone (stage only your own paths, commit your own changes, leave app-maintained files to the app) — existing boards heal to the new text on next open. README re-anchors: the four git feature bullets out, tiers say the complete Mac experience is free, and one bullet states the format's git-friendliness promise. The changelog drops the never-shipped git entries. DESIGN re-rules: 06 retired with Undo routing migrated to 13 (now the sole substrate's doc, seam kept open), 07 retired as written pending the ops-service workstream, 14 retired as superseded record, 12 carries the second pivot note, the index reflects all of it; the charter gets a pointer note (the anchors' full re-ruling stays with the user). InertGitTests renames to GitAgnosticStorageTests — the excision restores its original claim app-wide. And the sweep: ~70 comment sites across 36 files adjudicated against the keeper list, every present-tense description of the excised machinery made past tense or repointed, keepers untouched. 2,707 tests green.

Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
This commit is contained in:
2026-08-08 12:31:27 -04:00
parent 8cf1457814
commit 445d035a83
50 changed files with 397 additions and 313 deletions
+2 -1
View File
@@ -15,7 +15,8 @@ import os
/// touched and what they said before. It also keeps the one rule every step must obey in a single
/// place **an inverse is performed as an ordinary app-mediated write**, through `performWrite`,
/// so an undo brackets the watcher, echoes back through the reload like any other change, refreshes
/// every window on the board, and (on git boards, pro-m1) commits. Undone changes are real writes,
/// every window on the board once it also committed on git boards, pro-m1, before app-managed
/// git was excised (`strategy/01-git-excision.md`, 2026-08-08). Undone changes are real writes,
/// never in-memory reverts.
///
/// ### Values, never live references
+25 -21
View File
@@ -13,13 +13,15 @@ import AppKit
/// exactly how the system's Edit Undo row and the toolbar's nil-target pair (`BoardToolbar`) light
/// up, disable and retitle with no code of the app's own.
///
/// The seam, though, must not be an `NSUndoManager`: a gitless board's stack is one, a Pro git
/// board's is git (12-editions.md The provider seam), and a protocol that vended one could only
/// ever have had a single implementation. So the substrate stays behind `HistoryProviding` and
/// The seam, though, must not be an `NSUndoManager`: a protocol that vended one could only ever have
/// had a single implementation, and the substrate stays behind `HistoryProviding` so a future
/// provider can bind without touching this class (`strategy/01-git-excision.md` Reversibility). So
/// *this* object is the translation one per board session, over whichever provider that session
/// was composed with. A git board inherits the whole command surface (enablement, dynamic titles,
/// Z, the toolbar pair) by binding its provider and changing nothing here, which is what "a user
/// subscribing (or lapsing) relearns nothing" (12) has to mean in code.
/// was composed with. (Once two providers shared the seam this way a gitless board's native stack,
/// a Pro git board's git history, 12-editions.md The provider seam with whichever bound
/// inheriting the whole command surface, enablement, dynamic titles, Z, the toolbar pair, by
/// binding and changing nothing here. App-managed git is gone now, 2026-08-08, and native is the
/// only one left.)
///
/// **And one per open card window**, over that window's own stack (13 Rules two levels, re-ruled
/// 2026-07-31 `CardWindowUndo.manager`): the second level needs precisely the same translation, so
@@ -52,8 +54,8 @@ import AppKit
/// responder chain validates through this object, so answering `false` here disables all of them
/// at once, exactly as the lock's other victims disable through menu validation (02-architecture.md
/// § "The lock's scope"). Putting it in the *provider* would have been the same answer in the wrong
/// place: the stack is not the thing that is locked, the board is, and a Pro session binding the git
/// provider must inherit the rule without reimplementing it.
/// place: the stack is not the thing that is locked, the board is, and whatever provider a session
/// binds a future one included must inherit the rule without reimplementing it.
public final class BoardUndoManager: UndoManager {
/// The substrate this manager is a face for. Strong: the session owns both, and the manager is
@@ -65,7 +67,10 @@ public final class BoardUndoManager: UndoManager {
/// only under locks and on empty stacks the provider follows the board, so boards without
/// app-managed git repo-nested included bind 13-native-undo.md's native stack in **every**
/// tier" (03-board-ui.md Toolbar Catalog). The repo-nested board was the last holder of this
/// state and no longer is: that rule was about *git*, and this stack never touches git.
/// state and no longer is: that rule was about *git*, and this stack never touches git. (The
/// distinction the quote draws collapsed entirely with the 2026-08-08 excision,
/// `strategy/01-git-excision.md`: every board is "without app-managed git" now, not just
/// repo-nested ones.)
///
/// The state stays modelled because the seam still admits it a test binds a substrate-less
/// session through `AppModel.makeHistoryProvider` and because an absent substrate is the honest
@@ -73,20 +78,19 @@ public final class BoardUndoManager: UndoManager {
/// toolbar pair, and Z itself go quiet together through the same validation path a lock uses,
/// and nothing can accidentally accumulate in a stack that is not there.
///
/// ### Settable, for exactly one event
/// ### Settable, once for exactly one event now for none
///
/// **Add-git** (06 Rules Detection) is the design's one sanctioned mid-session mode flip:
/// "clicking it flips the open board into git mode immediately". 13's header says what that means
/// here the flip **swaps the substrate**: the mode-none board's native stack is discarded and
/// the git trail seeded from the root commit, the branch-switch discard-and-reseed precedent. The
/// composition root writes the new provider into this property rather than rebuilding this
/// object, so AppKit keeps the identical manager it has already been handed by
/// `windowWillReturnUndoManager` and simply revalidates over a different stack.
/// **Add-git** (06-history-undo.md Rules Detection, retired) was the design's one sanctioned
/// mid-session mode flip: "clicking it flips the open board into git mode immediately", swapping
/// the substrate the mode-none board's native stack discarded for the git trail seeded from the
/// root commit. The composition root wrote the new provider into this property rather than
/// rebuilding this object, so AppKit kept the identical manager it had already been handed by
/// `windowWillReturnUndoManager` and simply revalidated over a different stack.
///
/// (This is *not* a tier flip. 12-editions.md's "an open board finishes with the provider it
/// composed" is about a subscription lapsing, which cannot change a running session's tier at
/// all `BoardSession.tier` is a `let` with no setter. Mode can change, by explicit command,
/// and only in this one direction.)
/// App-managed git left the app entirely on 2026-08-08 (`strategy/01-git-excision.md`), and
/// add-git went with it: nothing left in the app ever assigns this property after composition. It
/// stays a `var` rather than a `let` for the same reason `HistoryProviding` stays a protocol a
/// future substrate swap, mid-session or not, re-binds without re-plumbing this class.
var history: (any HistoryProviding)?
/// Whether the board is refusing writes `BoardStore.isReadOnly`, read through a closure rather
+4 -4
View File
@@ -15,10 +15,10 @@ import Foundation
///
/// **The fine stack**: an ordinary `NativeHistoryProvider`, on *every* board. The steps a card window
/// registers are values-based inverses at the Writer boundary the same shape whatever substrate the
/// board's own history has so a git board's card window still walks its own gestures with the
/// native grammar, and only the *coarse* close unit splits by substrate ("one native board step, or
/// one commit" 06-history-undo.md Undo routing). The split was written as a tier split and is a
/// board split since 12-editions.md PIVOT 2026-08-07; nothing in this type ever read either.
/// board's own history has. (Once only the *coarse* close unit split by substrate "one native board
/// step, or one commit" 13-native-undo.md Undo routing; the split was written as a tier split and
/// became a board split with the 2026-08-07 pivot before the 2026-08-08 excision removed the git half
/// of it outright, `strategy/01-git-excision.md`. Nothing in this type ever read either axis.)
///
/// **The fold**: window close registers "one coarse step ... whose undo restores the card subtree to
/// its session-start state ... and whose redo reapplies the net effect". That net effect is exactly
+23 -18
View File
@@ -80,9 +80,10 @@ public enum HistoryStepOutcome: Equatable, Sendable {
/// holds: move move back ...; rename restore title" and both halves of that write are already
/// in the caller's hands: the before-value *is* the inverse, and the after-value is what the write
/// set (which is also what the staleness predicate compares). A step is therefore that pair, in the
/// design's own terms, and deliberately says nothing about how a stack stores it: a gitless board's
/// stack is `NSUndoManager`-backed and a Pro git board's is git (12-editions.md The provider
/// seam), and neither substrate appears here.
/// design's own terms, and deliberately says nothing about how a stack stores it: the board's stack
/// is `NSUndoManager`-backed, and no substrate appears here. (Once two substrates shared this seam
/// a gitless board's native stack, a Pro git board's git history, 12-editions.md The provider
/// seam before app-managed git left the app entirely, 2026-08-08, `strategy/01-git-excision.md`.)
///
/// ### `name` is the 06 vocabulary, unprefixed
///
@@ -262,27 +263,30 @@ public struct HistoryStep {
/// seam from a window is the one coarse step its close registers.
///
/// `AppModel.BoardSession` is where the board half's ownership lives, and the composition root binds
/// which implementation it gets **following the board, and since the 2026-08-07 pivot the board
/// alone** (re-ruled 2026-07-31; 12-editions.md PIVOT 2026-08-07): a board without app-managed git
/// repo-nested included (re-ruled 2026-07-31) binds `NativeHistoryProvider` (two step stacks over
/// the inverses registered at the Writer boundary), and a git-mode board binds the git provider (undo
/// as forward restore commits over HEAD's first-parent ancestry 06-history-undo.md). Both answers
/// are the same in every tier; the tier used to decide whether git was on the table at all, and no
/// longer does.
/// which implementation it gets **always `NativeHistoryProvider`** now (two step stacks over the
/// inverses registered at the Writer boundary), on every board, in every tier
/// (`AppModel.makeHistoryProvider`). A git-mode board once bound a git provider instead undo as
/// forward restore commits over HEAD's first-parent ancestry, 06-history-undo.md between the
/// 2026-08-07 pivot (12-editions.md PIVOT 2026-08-07, when the tier stopped deciding whether git
/// was on the table at all) and the 2026-08-08 excision that removed the git provider outright
/// (`strategy/01-git-excision.md`).
///
/// ### What this protocol deliberately does not say
///
/// - **No `NSUndoManager`, anywhere in the signature.** It is the native provider's implementation
/// detail, and a seam that vended one would be a seam only one provider could ever satisfy the
/// opposite of the reason the seam exists at all ("the free tier's native undo is the first proof
/// the seam is real", 12 written when native undo was the free tier's; the proof it names is
/// two working substrates, which the pivot leaves standing). AppKit still needs an `UndoManager`
/// to hand the responder chain; that adapter is `BoardUndoManager`, which sits *over* this
/// protocol rather than inside it.
/// - **No persistence promise.** The native stack dies with the session (13); the git provider's
/// survives relaunch because git does (06). Both are honest implementations of these seven members.
/// the seam is real", 12 written when native undo was the free tier's; the proof it named was
/// two working substrates, which the pivot left standing and the 2026-08-08 excision then narrowed
/// back to one, `strategy/01-git-excision.md` the seam itself is what stays proved either way).
/// AppKit still needs an `UndoManager` to hand the responder chain; that adapter is
/// `BoardUndoManager`, which sits *over* this protocol rather than inside it.
/// - **No persistence promise.** The native stack dies with the session (13); a git provider's once
/// survived relaunch because git does, before app-managed git was excised entirely (2026-08-08,
/// `strategy/01-git-excision.md`). Both were honest implementations of these seven members; only
/// native's promise is live to keep now.
/// - **No routing.** Which surface Z reaches is focus's answer, not the substrate's
/// (06 Undo routing, tier-independent) `BoardUndoRouting`.
/// (13-native-undo.md Undo routing, tier-independent) `BoardUndoRouting`.
///
/// ### One obligation every implementation shares: retire what you let go of
///
@@ -298,7 +302,8 @@ public struct HistoryStep {
/// nonetheless stands to the session's end, because "the skip banner says nothing was applied, and an
/// irreversible purge riding that gesture would be surprise loss". A substrate that pops stale steps
/// therefore has a place to put them (`NativeHistoryProvider.strandedSteps`); one that never keeps a
/// step is untouched by the distinction, which is why the git provider needed no change.
/// step is untouched by the distinction which is why the git provider, while it existed, needed no
/// change for this rule at all.
///
/// ### And its mirror: say what you are still holding
///
+6 -5
View File
@@ -2,10 +2,10 @@ import Foundation
// MARK: - NativeHistoryProvider
/// The undo substrate of every board without app-managed git: one stack per board session
/// (13-native-undo.md, whose header lost its tier axis with the 2026-08-07 pivot the substrate is
/// the board's mode alone, and git is opt-in per board, so a board nobody opted in keeps this stack
/// for good) **and the substrate of every open card window's stack, on any board** (re-ruled 2026-07-31, the
/// The undo substrate of every board: one stack per board session (13-native-undo.md, whose header
/// lost its tier axis with the 2026-08-07 pivot and then its mode axis with the 2026-08-08 git
/// excision, `strategy/01-git-excision.md` there is no other substrate left to be the board's
/// alternative to) **and the substrate of every open card window's stack, on any board** (re-ruled 2026-07-31, the
/// session-coarsening model): a window's fine-grained gestures are values-based inverses whatever the
/// board's own substrate is, so `CardWindowUndo` holds one of these too. Nothing below knows which of
/// the two it is; both need the same four-line grammar.
@@ -147,7 +147,8 @@ public final class NativeHistoryProvider: HistoryProviding {
public func redo() { cross(.redo) }
/// Session teardown, the add-git substrate swap, a branch reseed every step goes, so every step
/// Session teardown once the add-git substrate swap and a branch reseed too, both gone with
/// app-managed git (`strategy/01-git-excision.md`, 2026-08-08) every step goes, so every step
/// retires: "the purge runs when the coarse step leaves the board stack ... or the board session
/// ends" (13 Interaction with the trash).
///