You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[3b] Add apply with inverse capture and per-session undo #441
The repository's apply with inverse capture and a linear per-session undo stack; settles how a ChangeSet carries boundary changes.
Done when: conformance tests cover undo and redo, boundary changes included, and a payload linked from two books, edited through one, saves and reloads with the edit.
Undo restores an old tokenRef after a reanchor pass or a Scripture edit
An undo or redo re-anchors what it restores to the current text, as on main; a whole-scope change clears the history
Decisions
Question
Decision
From
Undo
Inverse ChangeSets captured in the repository's apply; one linear stack per session; undo and redo re-anchor what they restore to the current text, as on main; a whole-scope change (New, Open or opening a session, but not a wipe) clears the history
D, A, J
Contract rules
A ChangeSet is a list of whole-record puts and deletes, keyed by record type and id. It and its inverse also carry boundary changes, so replies and undo cover boundary edits as they do today; 3b settles how.
The repository's apply is all-or-nothing, records each record's prior value for undo, and keeps the derived indexes current.
Derived indexes are rebuilt from the records on load and never trusted over them.
Every repository call is async, index lookups included, and lookups take keys in batches.
Index lookups are part of the repository interface, and the conformance suite tests them. The in-memory implementation backs them with maps; a later backend answers them its own way.
Index lookups promise no order. Where a command must pick one record, the domain layer picks by a rule (1a).
The domain layer enforces the approval rule before it calls apply.
A command reply is its ChangeSet plus, beside it, the pool buckets it touched; a wipe's reply also carries hasFreeTranslations.
No read returns a whole document.
The conformance suite defines the seam. Any later backend passes it to replace the in-memory implementation.
From #432: the done-when's shared-payload case is in the suite via replaceAll; port it to apply. The unreadable-book and failed-cleanup cases port to apply as well. Undo and redo tests go in the suite too.
#475 settles the WebView path for a draft book whose stored analysis can't be read: a write leaves that book's analysis out and saves the rest (see its "Unreadable draft books" section). That's a partial write, so it can't carry over under apply's all-or-nothing rule. Decide whether an edit touching such a book is refused, and what the undo stack records for it.
Activity
myieye commentedon Oct 16, 2026
See the
ChangeSetproposal on #431 (#431 (comment)): one typed list per record kind, and boundary changes carried as the scope record'ssegmentation.imnasnainaec commentedon Oct 21, 2026
From #432: the done-when's shared-payload case is in the suite via
replaceAll; port it toapply. The unreadable-book and failed-cleanup cases port toapplyas well. Undo and redo tests go in the suite too.imnasnainaec commentedon Oct 21, 2026
#475 settles the WebView path for a draft book whose stored analysis can't be read: a write leaves that book's analysis out and saves the rest (see its "Unreadable draft books" section). That's a partial write, so it can't carry over under
apply's all-or-nothing rule. Decide whether an edit touching such a book is refused, and what the undo stack records for it.Add apply with inverse capture and per-session undo (#441)
Add apply with inverse capture and per-session undo (#486)
[claude] Add morpheme commands with parity tests (#497)