The toast hid every status after six seconds, so a refusal the user was
still fixing vanished with its prompt open: su4u's bug on a timer. The
browser now asks the TUI's question. EditorSession moves into
improvise-protocol, ClientState records which editor a status was
written in, and RenderModel::status_stands tells the toast to hold it
until that editor closes.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
#257 restored a stale message whenever the mode after a key equalled the
mode before it. Editing and RecordsEditing commit with CommitAndAdvance,
which re-opens an equal AppMode on the next cell. So the message followed
the editor from cell to cell until Esc. The reviewer's repro was R, o, 5,
Tab: "Added new record row", or o's "That record row is already here"
refusal, survived the Tab.
press now compares an EditorSession, made of the things an opening sets:
- the whole AppMode, not its variant;
- the cursor cell, which is a cell editor's target;
- the editor's seed, which EnterEditAtCursor re-seeds from the cell, so a
commit that re-opens on the same cell (Tab in the last column) is new.
A generation counter was rejected: editors are opened by more than one
effect, and a counter in each is a hand-kept list. The view was left out:
no minibuffer key can switch it and stay.
Tests:
- four press scenarios: the two records repros, Enter in a plain grid,
and Tab in the last column;
- a direct check that ItemAdd on another category is another editor.
Rivals: mode-only (#257 as pushed), no cell, no seed and discriminant
each fail a distinct step.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
#233 clears the status message at the start of every TUI keypress. In a
text-entry mode the message sits beside the prompt, and a formula that
does not parse keeps the editor open with the error. So the error
vanished on the first correcting key.
press now remembers the mode and the message. It clears the message as
before and dispatches the key. It puts the stale message back only if
the key left the user in the same text-entry mode and wrote no message
of its own. Editing keys keep the refusal on screen, a key's own message
still wins, and leaving the minibuffer (a successful commit or Esc)
drops it.
The mode check is observed, not predicted: which keys commit is the
keymap's knowledge, and the TUI loop does not copy it.
Rivals, each injected into press and restored: never restoring (#233),
restoring over a key's own message, and restoring whatever the mode each
fail a distinct step of the test.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
tt22 removed the formula crate's serde dependency with the legacy JSON loader,
keeping serde only where a type crosses the wire. FormulaId crosses the wire, so
it is the third such type. No derive goes back on the formula AST.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
socket.rs: EditTarget takes the union (document_generation, cell, version,
opened); typed_target_frame keeps #205's untouched early return, then claims
as read at the captured generation. Evidence appended after gh/main's.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
The reviewer's probe_fold_hidden_measure, over its three rows (hidden,
bogus, no measure). The b114 group rule refuses all three; removing it
fails this test and the b114 test and nothing else.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
App::group_refusal asks the document, not the layout, whether any
coordinate names a group rather than an item, and runs first in
unwritable: a measure-half fold hides from both the stored arm and the
projection. Rival (rule removed) fails the new test and nothing else.
command.md and the ciw8 fold evidence now say the aggregate arm guards
only the None-axis case.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze