Files
lanework/Kanban/App
rzen 57542177c1 The undo rows stop hearing their own echo — a text manager answers canRedo by posting the checkpoint that re-invalidated the row, forever
Diagnosed by sampling a live frozen instance: with a text surface focused,
RedoMenuRow's body reads the routed manager's title, NSUndoManager.canRedo
posts NSUndoManagerCheckpoint synchronously, UndoCommandTicker bumps its
observed revision mid-body, and SwiftUI schedules the re-evaluation whose
own read posts the next checkpoint — the main thread never returns to the
event loop (~99% CPU, app frozen). Board-routed reads never echo, because
BoardUndoManager's overrides answer from the provider without posting —
which is why the board-only live probe (21/21) never met the loop.

The rows now derive title and enablement inside
UndoCommandTicker.silencingReadEchoes, a synchronous main-actor window in
which bump() drops what arrives: a read cannot change the state it reads,
so the echo carries no information and dropping it loses nothing. Genuine
checkpoints — registration closing a group, a crossing — still land.

Three regression tests pin the mechanism, including the asymmetry that
made the redo side the fuel: canUndo answers silently, canRedo posts.

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
2026-08-08 22:50:00 -04:00
..