4.4 KiB
undo_redo_lifecycle_fix_20260605 — Design
Date: 2026-06-05 Status: Draft Track: undo_redo_lifecycle_fix_20260605 (sub-project of v2)
Problem Statement
tests/test_undo_redo_sim.py::test_undo_redo_lifecycle failed in the 2026-06-05 second batched test run (after the first run had it passing). The test:
- Sets
temperature=0.5andai_input="Initial Input". - Modifies to
temperature=1.5andai_input="Modified Input". - Asserts current state — passes.
- Clicks
btn_undo. - Asserts
ai_input == "Initial Input"andtemperature == 0.5. - Fails on the
ai_inputassertion: gets''(empty string).
The undo restores temperature correctly but not ai_input. The other 2 tests in the same file (test_undo_redo_discussion_mutation, test_undo_redo_context_mutation) pass — they don't exercise ai_input.
Possible causes
-
App/Controller state sync bug for
ai_input. The snapshot atsrc/gui_2.py:551readsself.ui_ai_input(App), butset_valuewrites tocontroller.ui_ai_input. The snapshot captures the App's (stale) value. This should be fixed by thelive_gui_state_sync_20260605track (which adds anui_ai_inputproperty on the App that delegates to the Controller). -
Snapshot doesn't include
ai_inputfield at all. Checksrc/history.py:UISnapshot— ifai_inputisn't a field, the snapshot stores nothing, and the apply can't restore. -
Test flake. The test was passing in the first run, failing in the second. The
live_guifixture is session-scoped, and different test orders can produce different state. The test'stime.sleep(2.0)afterbtn_undomay not be enough if the GUI is under load. -
Recent user commit
873edf42regression. The user's cleanup commit touched 53 files includingsrc/gui_2.py:261lines. If the cleanup accidentally changed the snapshot mechanism, this could break the test.
Design
Approach: Two-phase investigation
Phase 1: Re-run the test after the live_gui_state_sync_20260605 track lands.
If the state-sync property fix for ui_ai_input unblocks the test, the issue is resolved. No further work needed.
Phase 2: If the test still fails, deep-dive into the snapshot mechanism.
Investigate in this order:
- Check
src/history.py:UISnapshotto see ifai_inputis a field. If not, add it. - Check
src/gui_2.py:_apply_snapshotto see if it restoresai_input. If not, add the restore line. - Check if there's a per-tick snapshot filter that excludes certain fields.
- Add a regression test that explicitly verifies the snapshot/undo round-trip for
ai_input.
Phase 3: If still failing, test-ordering / flake investigation.
The test uses time.sleep(2.0) after btn_undo. Convert to polling (wait_for_load_completion from the wait_for_ready_test_pattern_20260605 track). If the test passes with polling, it was a flake.
Why this approach
- Sequential investigation: cheapest fixes first. State-sync is the most likely cause (it just landed as a property fix). Snapshot mechanism is the second most likely. Flake is the third.
- No speculative changes: don't add
ai_inputto the snapshot if it's already there. Don't change the undo mechanism if the state-sync fix is sufficient.
File Changes
Phase 1: None (state-sync fix is in a different track)
Phase 2 (if needed):
- Modify:
src/history.py(addai_inputfield to UISnapshot if missing) - Modify:
src/gui_2.py:_apply_snapshot(addai_inputrestore line if missing) - Add:
tests/test_undo_redo_ai_input_snapshot.py(regression test for the round-trip)
Phase 3 (if needed):
- Modify:
tests/test_undo_redo_sim.py(replacetime.sleep(2.0)withwait_for_load_completion)
Risk Assessment
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Phase 1 fixes the issue | High | None | Done |
| Phase 2 needed: snapshot already has ai_input but apply doesn't restore | Medium | Low | Check first, then add the restore line |
| Phase 2 needed: snapshot doesn't have ai_input | Low | Low | Add the field + apply line |
| Phase 3 needed: it's a flake | Low | None | Replace sleeps with polling |
Out of Scope
- State sync fix — separate track (
live_gui_state_sync_20260605). - prior_session test — separate track (
prior_session_test_harden_20260605). - wait_for_ready pattern — separate track (
wait_for_ready_test_pattern_20260605). - General undo/redo system improvements — out of scope.