Undo Redo Blueprint
Linear history stack with debounced recording, forward-branch destruction, and keyboard shortcut navigation
| Feature | undo-redo |
| Category | Data |
| Version | 1.0.0 |
| Tags | undo, redo, history, state-management, editor |
| YAML Source | View on GitHub |
| JSON API | undo-redo.json |
Actors
| ID | Name | Type | Description |
|---|---|---|---|
user | Editor User | human | Person performing actions in the editor that are recorded in history |
history_manager | History Manager | system | System that records, navigates, and prunes the history stack |
Fields
| Name | Type | Required | Label | Description |
|---|---|---|---|---|
histories | json | Yes | History Stack | |
history_index | number | Yes | Current Index | Validations: required |
has_past | boolean | Yes | Has Past (undo available) | |
has_future | boolean | Yes | Has Future (redo available) |
Rules
- recording:
- debounce_ms: 250
- excluded_actions: register_zone, unregister_zone, set_data, set_ui
- snapshot_full_state: true
- navigation:
- forward_branch_destruction: true
- tidy_on_navigate: true
- stack:
- no_max_size: true
- unique_ids: true
- hotkeys:
- undo: Cmd+Z or Ctrl+Z
- redo: Cmd+Shift+Z or Ctrl+Shift+Z or Cmd+Y or Ctrl+Y
Outcomes
Record_action (Priority: 1)
Given:
- a state-changing action occurs (insert, move, delete, edit, etc.)
- the action is not in the excluded list
- debounce window of 250ms has elapsed since last recording
Then:
- create_record target:
history_entry— Snapshot current state with unique ID and append to history stack - set_field target:
history_index— Move index to point to the new entry (end of stack) - emit_event event:
history.recorded
Result: New state saved to history, undo becomes available
Record_after_undo (Priority: 2)
Given:
- user has undone to a past state (index < stack length - 1)
- a new state-changing action occurs
Then:
- set_field target:
histories— Discard all entries after current index, append new entry - set_field target:
history_index— Move index to the new end of stack - emit_event event:
history.branch_destroyed
Result: Future history discarded, new timeline established
Undo (Priority: 3)
Given:
- user triggers undo (hotkey or UI button)
- has_past is true (index > 0)
Then:
- set_field target:
history_index— Decrement index by 1 - set_field target:
application_state— Restore state from history entry at new index, clearing field focus - emit_event event:
history.undo
Result: Application reverts to previous state, redo becomes available
Redo (Priority: 4)
Given:
- user triggers redo (hotkey or UI button)
- has_future is true (index < stack length - 1)
Then:
- set_field target:
history_index— Increment index by 1 - set_field target:
application_state— Restore state from history entry at new index, clearing field focus - emit_event event:
history.redo
Result: Application advances to next state in history
Undo_at_beginning (Priority: 5) — Error: UNDO_UNAVAILABLE
Given:
- user triggers undo
- has_past is false (index is 0)
Result: No action taken, undo button remains disabled
Redo_at_end (Priority: 6) — Error: REDO_UNAVAILABLE
Given:
- user triggers redo
- has_future is false (index is at end of stack)
Result: No action taken, redo button remains disabled
Load_history (Priority: 7)
Given:
- external system provides a saved history stack
Then:
- set_field target:
histories— Replace entire history stack with provided entries - set_field target:
history_index— Set index to last entry - set_field target:
application_state— Restore state from the latest history entry - emit_event event:
history.loaded
Result: History restored from external source, full undo/redo available
Errors
| Code | Status | Message | Retry |
|---|---|---|---|
UNDO_UNAVAILABLE | 400 | Nothing to undo | No |
REDO_UNAVAILABLE | 400 | Nothing to redo | No |
Events
| Event | Description | Payload |
|---|---|---|
history.recorded | A new state snapshot was added to the history stack | history_id, index, stack_size |
history.undo | User navigated backward in history | from_index, to_index |
history.redo | User navigated forward in history | from_index, to_index |
history.branch_destroyed | Future history was discarded after a new action during undo state | discarded_count, new_stack_size |
history.loaded | History stack was loaded from an external source | stack_size, index |
Related Blueprints
| Feature | Relationship | Reason |
|---|---|---|
| editor-state | required | History records and restores the centralized editor state |
| drag-drop-editor | recommended | Drag operations should be recorded in history for undo support |
| component-registry | recommended | Component insert/edit/delete operations create history entries |
AGI Readiness
Goals
Reliable Undo Redo
Linear history stack with debounced recording, forward-branch destruction, and keyboard shortcut navigation
Success Metrics:
| Metric | Target | Measurement |
|---|---|---|
| data_accuracy | 100% | Records matching source of truth |
| duplicate_rate | 0% | Duplicate records detected post-creation |
Constraints:
- performance (non-negotiable): Data consistency must be maintained across concurrent operations
Autonomy
Level: supervised
Human Checkpoints:
- before making irreversible changes
Escalation Triggers:
error_rate > 5
Tradeoffs
| Prefer | Over | Reason |
|---|---|---|
| data_integrity | performance | data consistency must be maintained across all operations |
Coordination
Protocol: orchestrated
Consumes:
| Capability | From | Fallback |
|---|---|---|
editor_state | editor-state | degrade |
Safety
| Action | Permission | Cooldown | Max Auto |
|---|---|---|---|
| record_action | autonomous | - | - |
| record_after_undo | autonomous | - | - |
| undo | autonomous | - | - |
| redo | autonomous | - | - |
| undo_at_beginning | autonomous | - | - |
| redo_at_end | autonomous | - | - |
| load_history | autonomous | - | - |