Although as much undo as possible is always a good idea, there are nontrivial, boring technical problems that present significant hurdles for programs like Scrivener allowing undo at every stage. In Scrivener, currently, undo works something like this:
• Each document has its own undo stack for its main text. So, if you make some changes to a document, then go and edit several other documents, then return to it, hitting Undo will undo the changes to that document there in front of you that you edited a little while ago. This makes sense to me, rather than having undo affect text changes you made in documents you can no longer see.
• The binder and the rest of the interface has its own undo stack. This is a bit fragile, though, and gets reset whenever you select a different document in the binder (thus, if you lock the editor and drag things around in the binder, you can undo freely, but not if the document in the editor changes). This is, admittedly.
This last feature of Scrivener is a little odd - undo resetting whenever you switch a document - but it has its roots in the strange way undo works in Cocoa. You might thing that undo is related to the model object - that is, that undo is related to the data. It’s not, though; it’s related to the view. Thus, if you load text into a text view and make changes to it, and then switch to some different text, if you hit undo, the undo manager, which is part of the text view, thinks that text is the text got swapped out, tries to change it, and then you get errors or messed up text. Fortunately, with text views, there is a way of swapping out different undo managers, which is what Scrivener does to avoid this, and which thus allows each main text to have its own undo stack. Even so, the actual process of calling “undo” and “redo” is all handled by the text view itself. So there’s no way for Scrivener to say, "Right, if you hit “undo” now, it should affect the last thing done over here. Instead, whichever view has the focus will grab the undo action if it supports it, and try to call undo on whichever is the active undo stack.
This makes undo very fragile in general when you have a program that has so many different views. If you consider a single document in the binder, it has many different views associated with it: the main text area, the synopsis title field, the synopsis editor, the notes area, the custom meta-data area, the keywords view, the references view and so on. Some of those views support undo off-the-bat and look for the current undo stack, and operate on it; others do not. If they use a single undo stack - as they currently do, sharing the main project undo stack with the binder (except for the main text area, which gets its own undo stack for each document) - then every time you select a different document in the binder, there is suddenly a whole lot of information on the undo stack that is now invalid, because the data associated with it has been swapped out of the associated views (and there is no way to clear only parts of the stack to avoid this). So, calling undo will inevitably thrown an exception. The only solution is to clear the undo stack at these points to avoid errors - which is what currently happens. And it’s not possible for these other views to share the main text view undo stack, either, because having different text areas use the same undo stack without resetting it can cause errors. But giving each of these areas its own undo stack gets very messy. And even if I did that, that doesn’t solve the problem of the binder. Having full undo there could lead to all sorts of problems seeing as it is dealing, behind the scenes, with files on disk. Consider what happens when you create a document in TextEdit and save it into the Finder - you can’t switch to the Finder and undo that action, but have to delete it manually.
So… Full undo gets very tricky with the binder, to say the least. It’s not that I disagree with you that full undo would be lovely, but at the moment these technical considerations make this very difficult. Possibly not insurmountable, but with limited time and resources it becomes a lower priority next to the many other things that need doing, given that things are set up sufficiently so that you generally would have to work quite hard to totally mess up a project in Scrivener and not be able to return it to an earlier state.
Hope that makes sense! (And I hate to sound like a stuck record, blaming everything on technical problems, which admittedly shouldn’t be the user’s concern.)
All the best,