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
+30 -17
View File
@@ -84,7 +84,15 @@ enum AgentGuide {
/// 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
/// **v11 rewrites Git for the excision** (strategy/01-git-excision.md, ruled 2026-08-08):
/// app-managed git is gone the app never runs git, and the auto-commit the old section
/// promised no longer exists, so shipping v10's text would document machinery to agents that
/// isn't there. The section now teaches repo-resident etiquette alone the format stays
/// deliberately git-friendly, a board may live in a repository of the user's own, and there an
/// agent stages only its own paths, commits its own changes with clear messages, and leaves the
/// app-maintained files to the app. The stamping section drops its auto-commit clause the same
/// way.
static let version = 11
// MARK: - The version marker
@@ -235,9 +243,8 @@ enum AgentGuide {
/// when the decision called for it.
///
/// **Called inside `BoardStore.performWrite`**, so both halves ride one watcher bracket: the
/// rescue and the guide land as a single app-mediated reload, and (under Pro) as a
/// single honestly-attributed commit rather than a foreign-looking rename followed by an
/// app write (06-history-undo.md Commit messages, "Update agent guide (vN)").
/// rescue and the guide land as a single app-mediated reload rather than as two foreign-looking
/// events.
///
/// The move is `FileManager.moveItem` and nothing else: it preserves the bytes exactly the
/// displaced file may not even be UTF-8 and it **fails rather than overwrite** if
@@ -298,8 +305,8 @@ enum AgentGuide {
}
try BoardWriter.atomicReplace(text: content, at: guideURL, operation: .agentGuide)
// Heal-marked: the guide's refresh is app-initiated work, and its commit is its own
// ("Update agent guide (vN)" already commits alone 06-history-undo.md Commit messages).
// Heal-marked: the guide's refresh is app-initiated work, and the ledger records it as the
// heal it is rather than as anyone's edit.
EchoLedger.current?.markHeal(at: guideURL)
return displaced
}
@@ -420,11 +427,11 @@ enum AgentGuide {
Add `modified-by: <your-name>` (e.g. `modified-by: claude`) to the
frontmatter of every `index.md` you write — it attributes the change in the
app and, on git boards, in the auto-commit. The app clears the stamp on its
own writes, so **re-stamp on every write, and after every move**: a bare
folder move rewrites no file, so the moved card arrives unstamped unless you
touch its `index.md` again. When you need exact authorship, commit your
changes yourself instead (see Git below).
app. The app clears the stamp on its own writes, so **re-stamp on every
write, and after every move**: a bare folder move rewrites no file, so the
moved card arrives unstamped unless you touch its `index.md` again. On a
board that lives in a git repository of the user's own, committing your
changes yourself (see Git below) records exact authorship as well.
## Creating a card
@@ -567,14 +574,20 @@ enum AgentGuide {
## Git
Some boards are git repositories — because the board lives inside a repo of
yours, or because Lanework Pro manages its history. Two rules when one is:
Lanework itself never runs git: the app manages no repository, makes no
commits, and never reads `.git`. But the format is deliberately
git-friendly — one file per card, stable UUID folder names, byte-faithful
rewrites — and a board may live inside a repository of the user's own.
When it does:
- **Stage only your own paths** — never `git add -A` or `git add .`: a
sweep would commit the user's not-yet-committed changes under your name.
- Committing your changes yourself is fine and gives you exact authorship;
the app follows along. If you don't commit, Lanework Pro auto-commits
your changes as external edits (attributed via `modified-by` when you
stamped it).
- **Commit your own changes, with clear messages** — nothing else will
commit them for you, and a semantic message ("Move card 'Fix login' to
Doing") is the history the user will actually read.
- **Leave the app-maintained files to the app** — this guide and the
seeded `.gitignore` are rewritten by Lanework when they need to be;
don't edit or delete them, and don't commit changes to the user's other
files that you didn't make.
"""
}
+12 -9
View File
@@ -1060,19 +1060,22 @@ public enum BoardLoader: Sendable {
// MARK: - The earlier-occurrence-wins history seam
/// **Where git path history plugs into the duplicate-id winner rule** (01-storage-format.md
/// **Where git path history once plugged into the duplicate-id winner rule** (01-storage-format.md
/// § Fractal layout Rules: "on git boards, the path history already tracks outranks the
/// newcomer (both tracked: the path that entered history first)").
/// newcomer (both tracked: the path that entered history first)") kept as a seam, unfilled,
/// since app-managed git was excised entirely (`strategy/01-git-excision.md`, 2026-08-08).
///
/// A seam rather than an implementation because the first rung of that ladder is unreachable
/// without git: the free tier runs no git machinery at all (12-editions.md The inert posture),
/// so the loader consults an injected ranker and falls through to birth date and traversal order
/// when there is none which is every free-tier board, and every Pro board without a repo.
/// A seam rather than an implementation because the first rung of that ladder was unreachable
/// without git even before the excision: the free tier ran no git machinery at all
/// (12-editions.md The inert posture), so the loader consults an injected ranker and falls
/// through to birth date and traversal order when there is none which is every board today, no
/// exceptions.
///
/// Deliberately one closure and no protocol: the loader asks one question "how early did this
/// path enter history" and pro-m1's implementation answers it from `git log --diff-filter=A
/// --follow`-shaped plumbing behind the provider seam. `nil` means "untracked, or no history
/// here", which the rule reads as *outranked by anything tracked*.
/// path enter history" and pro-m1's implementation once answered it from `git log
/// --diff-filter=A --follow`-shaped plumbing behind the provider seam, before that plumbing left
/// with the excision. `nil` means "untracked, or no history here", which the rule reads as
/// *outranked by anything tracked*; nothing installs a ranker today, so every path reads `nil`.
///
/// - Parameter rank: keyed by the occurrence's **board-root-relative path**, which is what a
/// repo's path history knows; lower is earlier.
+12 -8
View File
@@ -585,9 +585,9 @@ public enum BoardWriter: Sendable {
///
/// - **`.DS_Store`** the Finder writes one into every folder a user looks at, and on a board
/// that means one per lane and one per card, each churning as icons and window positions move.
/// On a git board it would be committed by the whole-tree stage, forever, under the user's own
/// name; on every board it is now also the plainest thing the loose-file heal must not treat as
/// a card's attachment.
/// Once committed by the whole-tree stage on a git board, forever, under the user's own name;
/// app-managed git is gone now (`strategy/01-git-excision.md`), and on every board it is the
/// plainest thing the loose-file heal must not treat as a card's attachment.
/// - **`.*.lanework-*`** this file's own temp pattern, and the one entry the app is entitled to
/// have an opinion about: `atomicReplace` writes `.<name>.lanework-<uuid>` beside its target,
/// so a crashed write's residue is the app's litter rather than the user's file. The two must
@@ -1890,7 +1890,8 @@ public enum BoardWriter: Sendable {
/// `updateIndex`'s closure cannot. Everything else is identical and deliberately so read
/// fresh from disk, refuse an uneditable frontmatter shape, edit, stamp `modified` and clear
/// `modified-by`, replace atomically. A toggle is "an ordinary user edit the standard atomic
/// write, auto-committed and undoable on git boards" (05), not a special case of anything.
/// write" (05) once "auto-committed and undoable on git boards" too, before app-managed git was
/// excised (`strategy/01-git-excision.md`, 2026-08-08) not a special case of anything.
///
/// ### The offset, and why it is re-checked
///
@@ -2085,7 +2086,7 @@ public enum BoardWriter: Sendable {
///
/// Text identical to what is already on disk writes nothing and returns `false` `writeBody`'s
/// untouched gate, applied to the whole file instead of the body span. Apply on a buffer the user
/// only read must not churn `mtime`, wake every watcher, and (on git boards) mint an empty commit.
/// only read must not churn `mtime` or wake every watcher.
///
/// - Returns: `true` when bytes were written, `false` when the file already read exactly like
/// `text`.
@@ -2591,9 +2592,11 @@ public enum BoardWriter: Sendable {
/// reminting it would change an identity for no reason at all the vanished-duplicate race,
/// read from the surviving side.
///
/// **Heal-marked**, because the app started it on its own: the receipt is what splits the remint
/// **Heal-marked**, because the app started it on its own: once the receipt that split the remint
/// into its own commit on git boards, named for the Repair verb (06-history-undo.md Commit
/// messages). Undo never sees it heals are not gestures (13-native-undo.md).
/// messages, retired with app-managed git, `strategy/01-git-excision.md`) the receipt still
/// exists for whatever consumes it next. Undo never sees it heals are not gestures
/// (13-native-undo.md).
///
/// - Parameter duplicate: the withheld occurrence, `path` relative to `boardRoot` so the write
/// lands wherever the board lives *now*.
@@ -3020,7 +3023,8 @@ public enum WriteOperation: Sendable, Equatable, CustomStringConvertible {
/// The board-root `.gitignore` being seeded at creation, at instantiation, and by the
/// scheduled heal that gives a board born before the ruling the file it now needs
/// (06-history-undo.md Repository hygiene, re-ruled 2026-07-31; `seedGitignoreIfAbsent`).
/// (06-history-undo.md Repository hygiene, retired with app-managed git,
/// `strategy/01-git-excision.md`; `seedGitignoreIfAbsent`).
///
/// **No payload**, for `.agentGuide`'s reason: there is one such file per board, its name is
/// fixed, and it is not an item with a title. Its own case beside `.agentGuide` rather than a
+11 -7
View File
@@ -4,15 +4,19 @@ import Foundation
/// one, and asked one question: is this board-relative path ignored?
///
/// The file outgrew git on 2026-07-31 (01-storage-format.md § Fractal layout Rules, "`.gitignore`
/// is the noise gate"; 06-history-undo.md Repository hygiene): it is now the one definition of
/// is the noise gate"; 06-history-undo.md Repository hygiene, retired with app-managed git,
/// `strategy/01-git-excision.md`): it is now the one definition of
/// noise the **loose-file relocation heal** obeys, on every board, git or not. A file matching it
/// keeps the ordinary stray posture "skipped, preserved verbatim, logged, never relocated, never
/// announced" and "the exclusion list is exactly that file, nothing hardcoded". On a Pro board the
/// same file governs the committer through libgit2, so ignored noise neither relocates nor commits:
/// one definition, two consumers. This type is the app's half of that, because the load path cannot
/// reach for libgit2 the free tier opens a board without so much as a `fileExists` under `.git`
/// (12-editions.md The free tier and `.git`), and the heal runs on boards that have no repository
/// at all.
/// announced" and "the exclusion list is exactly that file, nothing hardcoded". (On a Pro board the
/// same file once governed the committer through libgit2 too, so ignored noise neither relocated nor
/// committed one definition, two consumers; app-managed git is gone now, so the heal is the only
/// consumer left.) This type is the app's half of that once split from libgit2 because the load
/// path couldn't reach for it while the committer did; libgit2 left the project entirely with the
/// git excision (`strategy/01-git-excision.md`, step 6), so today there is no other implementation to
/// duplicate at all. The free tier always opened a board without so much as a `fileExists` under
/// `.git` (12-editions.md The free tier and `.git`), and the heal runs on boards that have no
/// repository at all.
///
/// **Pure: no I/O, no filesystem, no `URL`.** It parses text and answers about paths. Reading the
/// bytes is `BoardLoader.ignoreRules(atBoardRoot:)`' job, once per walk the loader stays a pure
+8 -4
View File
@@ -878,8 +878,10 @@ public enum IntegrityRules: Sendable {
/// The filesystem birth date (`.creationDateKey`), `nil` when it cannot be read the
/// **second** rung of the earlier-occurrence-wins ladder.
public let birth: Date?
/// Where the git path history places this path, `nil` when the board has no history or the
/// path is untracked the **first** rung, injected through `BoardLoader.IdentityHistoryRanker`.
/// Where a history ranker once placed this path `nil` unconditionally today, since
/// app-managed git was excised entirely (`strategy/01-git-excision.md`, 2026-08-08) and
/// nothing installs `BoardLoader.IdentityHistoryRanker` any more. The **first** rung when
/// populated; nil-safe by design, so the ladder falls straight through to birth date now.
public let historyRank: Int?
public init(
@@ -958,8 +960,10 @@ public enum IntegrityRules: Sendable {
/// folder and often the tracked one, so every other rung would withhold the very card the user
/// just restored and render its ghost instead. The heal remints the trashed occurrence. The same
/// preference governs a trashed lane sharing a live lane's UUID.
/// 1. **Git path history** (`historyRank`): both tracked, the path that entered history first
/// wins; one tracked, it outranks the newcomer outright.
/// 1. **History rank** (`historyRank`): once git path history both tracked, the path that
/// entered history first wins; one tracked, it outranks the newcomer outright. Always `nil`
/// today, no ranker installed since the git excision (`strategy/01-git-excision.md`,
/// 2026-08-08); the ladder falls through to rung 2.
/// 2. **Filesystem birth date** (`birth`): the older folder wins. Only consulted when *both*
/// dates are readable and they differ one unreadable date is no comparison at all.
/// 3. **Deterministic traversal order**, which is `occurrences`' own order and therefore the