The card's name renders as part of the card body, so the chrome said it
twice. HostedWindowController gains a titleVisibility slot on the same
retained-slot pattern as the accessory and toolbar (reapplied at attach,
so the macOS 26 provisional-window swap can't lose it); CardWindowHost
opts in beside installToolbar, board windows keep AppKit's default.
window.title itself is untouched — navigationTitle still feeds the
Window menu, Exposé, VoiceOver and restoration.
Known consequence, probed empirically: under .hidden AppKit collapses
title and subtitle into one hidden field, so the "board › lane"
navigationSubtitle disappears with it — and the details sidebar carries
no placement rows, so a card window currently shows its home nowhere.
Filed on the Redesign board to bless or relocate; 05-card-window.md's
subtitle sentence needs reconciling either way.
Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
The modifier flip (⌥ copy / ⌘ move) now reflows the source board once:
a copy re-admits the dragged originals into the resting layout, standing
dimmed in place, and a move lifts them out as before. This retires
DRAG-REORDER.md's operation-blind carve-out and makes 04-interactions.md's
"originals stay" true in flight, not just at echo. The one seam is
DragSession.hiddenMembers reading the observed operation.
Consequences carried honestly: copyCards now takes its index in the
lane's full rendered space (the zones counted the originals, so the
geometry's number is the writer's number — the old neighbour remap is
deleted); resolveOperation freezes under the committed hold exactly as
propose does, fixing a real bug where a settled within-board ⌥-copy drew
the move arrangement until the echo and visibly re-shuffled. Stationary
flips still wait for the next dropUpdated (their own Backlog card).
Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
The full bullet list from Implementation card bf080d9a — both ruling
batches, including the three appended mid-session by 16ef377:
- 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
Repo-nested boards bind native undo in every tier (25d2513): the
no-undo case is gone, makeHistoryProvider answers git or native, and
the native path provably never touches the enclosing repository's
.git. Session undo steps anchor by card identity, never by path
(9119aa1): HistoryAnchor carries the card UUID (plus comment/draft
vocabulary) and apply-time validation resolves the current folder via
the same both-container walk writeCardBody uses — a board-side lane or
trash move no longer stales the coarse close step, while a genuine
field collision still skips it whole.
2448 tests in 423 suites green.
Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
Phase C of the two-level undo card: the committer stages around the
whole open card folder — comments included — so gestures in an open
window never land in interim commits; window close flushes the session
as one semantically-named commit ("Edit card 'X'" with the thread as
body bullets, "Mixed update — N changes to card 'X'" when events mix),
with the two-commit foreign/user split preserved and the
comments/.trash purge riding the same bracket. Comment gestures lose
their per-gesture commits structurally (they write inside the held
folder). Branch-switch settle releases every window's staging before
checkout and re-arms on resume.
Fixes two latent pro-m1 defects: the committer was composed without
the store's EchoLedger, so every production commit classified foreign
and was authored Lanework External; and interim flushes dropped
harvest receipts they had not spent, unvouching the session's own
writes at close. Also lands 06's mixed-subject re-ruling (the retired
"Update board" fallback) and phase B's two files missed by the
previous commit's pathspec.
2444 tests in 422 suites green.
Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
Phase B of the two-level undo card: every card-window gesture — comment
post/delete/edit, body Edit sessions, style and details changes —
registers fine-grained on the window's own stack (window.undoManager
answers with it; board ⌘Z never sees mid-session card steps; an empty
window stack beeps, never falls through). Window close folds the stack
into one coarse values-based board step ("Edit card 'X'") — per-target
per-field later-wins merge, so foreign mid-session writes stay out by
construction, a no-net-change session registers nothing, and any stale
component skips the whole step. The comments/.trash purge defers with
the coarse step via a step-retirement seam on the providers: it runs
when the step leaves the board stack or the board session ends; the git
provider retires dropped steps on register, which keeps Pro's
purge-at-close-flush structural with no tier check. Interim on git
boards: gestures still auto-commit per debounce until phase C's
close-flush commit.
2432 tests in 418 suites green.
Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
The 2026-07-31 re-ruling: gitless boards bind the native stack in every
tier — a Pro upgrade no longer removes undo from mode-none boards — and
Pro git boards bind the git provider; repo-nested stays the no-undo
case under Pro, while the free tier (which never runs detection) binds
native there too, per 12's inert posture. Add-git now swaps a live
native substrate mid-session: the in-flight stack is cleared with the
discarded provider, the git trail seeds from the root commit, and the
same BoardUndoManager instance keeps nil-target menu validation fresh.
2405 tests in 413 suites green.
Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
The trash sorts by modified descending — the arrival rank mint retires
(Ranks.isOrderedForTrash one comparator, loader + merged order agree;
the legacy deleted: migration stamps modified from the tombstone
timestamp where parseable; delete undo steps validate existence-only;
agent guide v8). Trash selection goes kind-blind — ranges, marquee,
Select All, and the successor walk sweep both kinds; the guard moves to
the exits (mixed-payload drop refusal, copy/cut validation). The copy
stamping preflight widens back to comment depth (load-scoped posture —
the board always loads, the gesture refuses whole). Fixes a latent
no-op: trashed-lane drag restore never fired (DragSession.beginLanes
hard-coded the board container).
2403 tests in 413 suites green.
Claude-Session: https://claude.ai/code/session_01CqjXB7ASoWtbyoGod68k97
Settled from the Redesign Minor card: SHA-256 repos are unsupported,
safely — unopenable ones take the corrupt-repo loud-failure path,
never a silent fall to mode-none; opened ones get hygiene's abstention
by construction (SHA-1 shape filter, empty work list). Recorded in 06.
No code change.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
Settled from the Redesign Minor card: the hygiene pass never
consolidates, rewrites, or deletes existing packs — one pack per
threshold's worth of objects accrues forever, the never-rewrite
posture's price. Terminal git gc remains the consolidation path.
Recorded in 06. No code change.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
Settled from the Redesign Minor card: loose-object pack at the 6,700
threshold (git's gc.auto default), 8 s after session activation,
background priority, skipped under contention, at most once per
session, all injectable. Recorded in 06's repo-growth bullet.
No code change.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
Settled from the Redesign Minor card: identity writes append a plain
[user] section, never editing existing sections or tool-specific
subsections; reads take the last plain-section value, git's own
semantics — so the append always wins without reformatting anything.
Recorded in 06's identity bullet. No code change.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
Two Redesign Minor settlements in 06: the popover's name/email fields
re-read repo config at 2 s only while visible (the watcher never
delivers .git, so the resync courtesy needs its own signal; focused
fields keep keystrokes); and the wholesale-bracket failure sentence
now defers to 02's hosted-by-window-of-origin rule — the card window
hosts its own strip, a ⌘Z pressed there fails there.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
Settled from the Redesign Minor card: popover-asked operations fail
inline at the form; board-wholesale brackets — branch switch and undo
restore named explicitly — fail as banner rows, red one-shot failures
per the same-day banner ruling. A switch's bounded lock wait can
expire long after the popover dismissed. Recorded in 06.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
Settled from the Redesign Minor card: the stamp clears on successful
abort only. A failed abort keeps it — the stamp is the sole evidence
the leftover is the app's own, and clearing on failure would orphan it
as somebody-else's forever. Recovery retries at next open or the 15 s
paused-state re-read. Recorded in 06. No code change.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
Settled from the Redesign Minor card: the waiting posture stays calm,
but the wait ends — 30 s (injectable), then the clean-failure path,
tree untouched, lock path named. Only a stale lock ever reaches the
bound; an eternal spinner holding the wholesale bracket is worse.
Recorded in 06's index.lock bullet. No code change.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
Settled from the Redesign Minor card: no at-HEAD fast path — the
"can't change the tree" proof fails under concurrent writers, and
pending work flushes onto the branch it was made on. One sequence,
no special case; recorded in 06's Branch switching intro. No code
change.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
Settled from the parked Redesign Minor card, with the user: 02's
hang-avoidance doctrine and 06's ordering guarantee genuinely conflict
at noteWillWrite, and the guarantee wins — rare, bounded, load-bearing,
reentrancy-safe only in the synchronous shape. Full semantic
composition stays on the path: the commit preserving somebody else's
version keeps its real subject. Carve-out recorded in 06.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
Settled from the Redesign board's Gap card: the failure class gains a
message-carrying GitOperationFailure shape beside the BoardWriteError
one — error tone, failure rank, BannerCenter phrasing. A failed undo
restore, branch switch, or pull/push presents as the failure it is,
never as a warning-tone loss row; recovery notices stay warning-tone.
Code realign pending (both reportFailure wirings post loss rows today).
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
Settled from the Redesign board's Gap card: crossing a restore commit
post-relaunch emits the inverse prefix ("Undo: S" crossed -> "Redo: S")
rather than stacking "Undo: Undo: S". Semantically exact and caps
prefixes at one; cosmetic-only mislabel accepted for foreign commits
whose subjects happen to open with a prefix. Code realign pending in
the restore-subject composer.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
Settled from the Redesign board's Gap card: crossing the parentless root
commit could only restore the empty tree, and the root is a baseline,
not a change-set. Undo bottoms out at the initial board state; the
reseed walk stops in the same place. The shipped GitHistoryProvider
already conforms.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
Add-git seeds a minimal .gitignore (.DS_Store) before the initial
stage — the seed rides "Initial board state" and .DS_Store never
enters history; an existing .gitignore (or a directory wearing the
name) is left alone forever, adoption and repo-nested seed nothing.
GitHousekeeping is the periodic loose-object repack: filesystem
enumeration of objects/<2hex>/<38hex> (never git_odb_foreach, which
would rewrite the whole database into a fresh pack each pass),
git_packbuilder_insert one oid at a time, additive pack write — and
deletion only after each oid is re-verified against the written
pack opened as a standalone one-pack odb with no loose backend. Any
failure returns before deleting; the worst case is a stray pack.
Nothing prunes, expires, or consolidates — existing packs
accumulate, recorded as the accepted cost of never rewriting
storage the app didn't write. GitHousekeeper schedules it: git's
own 6700 threshold, 8s after session activation (outlasting the
launch catch-up), background priority, skipped under pause states,
held locks, or an in-flight commit, never retried — the next open
tries again. Free tier composes none of it.
20 new tests: full-odb equality, per-oid survival, identical walks,
byte+mtime-identical refs/HEAD/working tree, whole-.git identity on
every declined pass, and deleting-never-forgets. 2394 tests / 412
suites green; InertGitTests untouched. Closes pro-m1-git-undo.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
GitBranchSwitcher holds 06's sequence as one object: settle editors
explicitly (SessionSettleGate — Save All applies raw buffers with
validation and a refused buffer cancels the whole switch; Discard
reverts buffers AND reconciles the session folders against HEAD;
never silent), flush the pending auto-commit, stamp intent in the
per-board registry, bracketed safe checkout (git_checkout_tree
GIT_CHECKOUT_SAFE + set_head — no path passes FORCE, abort
included), one reload via the async wholesale bracket (failed final
reload engages the existing read-only lock), reseed undo/redo from
the new HEAD with redo empty, clear the stamp. Create-and-switch
keeps the full sequence — the tree-cannot-change proof fails under
concurrent writers. Lock contention shows the 02 in-progress row's
waiting state ("waiting for another writer's git lock"), bounded at
30s then failing cleanly naming the lock path.
GitOperationStamp + GitOperationRecovery: the own-leftovers rule as
a pure conjunction — pause state AND matching stamp = the app's own
interrupted operation, aborted to the pre-operation state with a
banner, stamp cleared on success only; either alone defers to the
pause-and-defer stance. Checked where the committer starts.
BoardGitControls replaces the read-only branch line: branch picker,
inline create-and-switch, the abnormal-state pause note in 06's own
words with controls dimmed, and commit-identity fields that read and
write repo-local .git/config (derived default as placeholder, never
value; unfocused resync, focused keystrokes kept; 2s poll while
visible — .git is watcher-filtered by design).
Also fixes a shipped bug from the undo card: plan(reconciling:)
matched card ids as path prefixes, so the reconcile branch was inert
on every board (<lane>/<card> never matches a bare id) — a session
file the restore diff couldn't name (attachment, comment, draft)
survived Discard and landed in the next flush's commit. One shared
component-exact folder-name resolver now serves both Discard paths;
noteDiscarded takes cardFolderName; regression test verified failing
against the pre-fix code.
41 branch tests + the regression; 2374 tests / 409 suites green;
InertGitTests untouched.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
GitHistoryProvider is the second HistoryProviding implementation:
its stack IS HEAD's first-parent ancestry, reseeded on load (redo
empty), re-synced to HEAD before every crossing so agents'
self-commits become the top and ⌘Z steps back exactly one commit;
any arriving commit clears redo (a heal-only window deliberately
does not). Restores are forward commits through the ordinary
signature path — GitRestoreOperation materializes only the
current-vs-target diff as working-tree writes and resolves no
reset/checkout symbol at all; heal commits are transparent
in-session (pointer passes over, restores exclude heal-owned paths,
identity carried on landed windows via PlannedCommit.kind →
GitLandedCommit). Subjects "Undo:/Redo: <crossed subject>"; menu
labels never nest in-session; the root commit is not a step
(crossing it would restore the empty tree).
Provider binding flips: makeHistoryProvider(store, tier, git) —
free binds native everywhere, Pro binds the git provider on git
boards and NOTHING on mode-none/repo-nested (the pair disables
through existing validation); add-git mid-session live-binds via
HistoryStore.didAddGit → bindHistoryProvider (the flip only ever
adds).
SessionSettleGate is the reusable Save All / Discard / Cancel step:
restores whose diff touches an open Edit session or raw-source
buffer gate on it (Save All applies with validation — a refused
buffer cancels the whole restore focused on the offender; Discard
reverts via CardBodyEditSession.discardBuffer and reconciles against
the working tree, deliberately skipping the second flush); untouched
sessions ride through undisturbed. Built for the branch-switch card
to reuse. BoardStore gains the async performWholesale sibling.
CardHistorySection fills the m6 EmptyView slot: read-only, newest
first, follows the card across lane moves by folder-component match
(the UUID is the identity — no rename detection), absent off git
mode and off Pro.
2332 tests / 403 suites green; InertGitTests untouched.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
CommitMessageEngine replaces the interim composer as the wired
default: a pure total function from two snapshots + changed paths to
a message. Full vocabulary — Add / Delete / Move / Rename / Edit /
Restyle / Resize / Reorder over cards, lanes, board; Attach / Remove;
Repair for the duplicate remint (detected as a heal-classed
rename-paired arrival whose id the previous snapshot never held —
the loader withholds duplicates, so the shape is a bare arrival);
the trash triple by diff shape alone (into .trash = Delete, out =
Restore, leaving the tree = Permanently delete); Relabel / Assign /
Set due date plus the named generic for custom keys. Plural folding
with shared destinations, implied events as body bullets never
subjects, ~40-char subject truncation, "(untitled)". Bookkeeping
(sequence-preserving renumbers, stamps, backfilled kind) composes
nothing. Non-snapshot paths compose path-shaped events — CLAUDE.md
reads "Update agent guide (vN)" via the marker line (the m10 card's
deferred bullet lands here), everything else "Update '<path>'".
The comment verb family per 01's ruling (comments shipped, so 06
gains the verbs): Comment on / Edit comment on / Delete comment on /
Draft comment on / Permanently delete comment on '<card>', grouped
one event per comment folder, classified ahead of the model-silence
rules, card title resolved from either snapshot. GIT_DELTA_ADDED is
surfaced as GitChangedPath.isArrival — post vs edit is unanswerable
from snapshots that exclude comments by ruling. A card moving with
its thread swallows the comment events (implied-events one level
down).
The previous snapshot is HEAD's tree, materialized per flush into a
temp dir (index.md blobs in full, other blobs zero-byte — the model
reads attachment names, never bytes) and re-parsed through the one
BoardLoader; never a value carried forward. changedPaths is a hard
filter per split commit, which also earns the stage-around and kills
phantom events. Launch catch-up and foreign windows compose through
the same engine.
48 new tests (35 pure + comment family + engine-level); 2293 tests /
394 suites green; InertGitTests untouched.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
Every settled change on a git-mode board commits, debounced 2s past
drag/typing churn, staged whole-root with .gitignore respected.
GitCommitOperation reaches the vendored libgit2 directly (same 1.9.2
pin SwiftGitX resolves — importable, not duplicated) for
signature-capable commits; add-git's config materialization is gone,
identity resolves at commit time (repo-local config, else derived
default) per the 2026-07-31 ruling in 06. CommitAttribution
classifies per file off EchoLedger receipts: user identity on
app-mediated windows, Lanework External <[email protected]>
on foreign, the modified-by refinement (<slug>@agents.lanework
.invalid) when every foreign file agrees, heal-marked receipts split
into their own commit — window split foreign → heal → user.
Edit-session granularity: ~700ms saves stay uncommitted, staging
excludes open session folders (closure-resolved so mid-session moves
stage around the new location), session end nudges the debounce so
each session lands exactly one body commit. Flush-before-overwrite
gates on known-foreign windows and commits synchronously ahead of
the write; close/quit flush the pipeline via CloseFlushCoordinator's
committerFlush. index.lock backs off briefly then re-debounces
silently; clean tree no-ops; genuine failures ride the standing
history-suspension banner and retry next debounce. Abnormal repo
states (detached HEAD, merge/rebase/cherry-pick in progress) hold
the engine with a 15s re-check; unborn HEAD commits "Initial board
state" whole-tree; dirty tree at open catches up through the same
engine. Message seam (CommitMessageComposing) ships interim — the
semantic composer is the next card.
Discovery diffs HEAD against an in-memory index with rename
detection (git status alone never pairs a bare mv), and a failed
survey reads as "could not look", never "nothing changed".
46 new tests / 8 suites, all real repositories via bundled libgit2.
2240 tests / 383 suites green; InertGitTests untouched.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
The pro-m1 foundation card. SwiftGitX 0.4.0 (bundled libgit2, the
pathfinder's pin) joins the one target; new Kanban/Git/ holds
BoardGitMode (pure nearest-.git-wins detection, .git-as-file counts,
NSString ancestor walk), HistoryStore (@MainActor @Observable;
compose() is the tier gate — free tier gets no object, no detection,
no stat), GitRepository (scope-confined SwiftGitX handles: create =
init + HEAD forced to main + whole-tree "Initial board state" commit;
branch reads incl. unborn/detached; path-history ranks), GitIdentity
(derived default as a pure function + repo-local config reader — not
libgit2's merged ladder), and GitPathHistory (Mutex-guarded lazy
ranker). beginSession composes the git state beside the tier and
feeds BoardStore.makeIdentityHistoryRanker; git-mode loads pass the
git-backed IdentityHistoryRanker to BoardLoader. The popover's git
slot resolves a pure five-way matrix: free tier unchanged (absent /
BoardGitNote), Pro mode-aware — Add Git on mode none, honest prose on
repo-nested, read-only branch line on git. Provider binding
unchanged: both tiers still bind native until the undo/redo card.
42 new tests across 8 suites, all repositories built through bundled
libgit2; InertGitTests untouched and green. 2194 tests / 375 suites.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
DESIGN/14-git-operations.md distills the settled conclusions from the
pathfinder's AI-ANALYSIS-git-operations.md so pro-m1 has a citable
in-repo source: the forward-restore model (C3/C9 — restores are new
forward commits, never reset, never force; pull's rebase of unpushed
local commits is the one deliberate rewrite), C8 as later design
settled it (no sidecar state, reseed from HEAD's first-parent
ancestry, history browser out of scope with the per-card History
section as the one carve-in), and honest call-outs of the three
leanings 06/07 settled differently (C1 substrate, A1 iCloud dual
mode, B6 cadence-as-divergence-budget). Resolves the corpus's
outstanding git-operations-doc tbd.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
Replaces the pathfinder-inherited round-robin deal (child i -> column i % C)
with contiguous column segments: base = n/C, the first n%C columns take one
more, and logical order runs down each column before crossing to the next.
Only the geometric mapping changes -- ranks, selection flatten, and VoiceOver
order are untouched, and MasonryPlacement stays the single placement function
both the Layout and the drop model replay.
Why: an insertion under round-robin shifted every later card across columns;
under the column-major deal later cards slide within their column and at most
one card crosses each boundary, so the drag reflow is far calmer. Drop-slot
math gets simpler too -- a column's cards are one contiguous range, a
non-final column's tail is now a genuine mid-list position, and only the last
column's tail means append.
DropSlotMathTests recomputed and extended (46 -> 50): the uneven-fill deal,
boundary positions, the shared tail/head boundary index, and a placement/
drop-model shadow-agreement check. DRAG-REORDER.md and DESIGN/10 amendments
are listed for ratification, deliberately not edited here.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
The per-element .accessibilitySortPriority read slots.count from inside the
ForEach closure, re-running the whole slots -> renderedCards chain (an O(n)
card filter plus the session's hidden-member resolution) once per element --
O(n^2) per lane body. A drag pickup runs a synchronous whole-board layout
inside the drag-start nested run loop, which multiplied this into a stack-
sampled ~700ms-1s stall between mouse-down and the visible lift. Hoisting
the evaluation into a local makes pickup effectively immediate.
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY