useWorkspace reducer history is incomplete — UNDO/REDO restores only stitchObjects + threadStops; UPDATE_OBJECT, ADD/REMOVE/REORDER_THREAD_STOP don't push history at all #92
Labels
No labels
blocked:commit-ready-failed
blocked:gate-fetch
blocked:gate-lint
blocked:gate-plan
blocked:gate-research
blocked:needs-attention
blocked:needs-decision
blocked:needs-human
blocked:no-changes
blocked:verify-failed
bug
deferred
feature-request
in-progress
needs-decompose
needs-triage
quickfix
security/medium
triage-approved
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Mark/Kimi_Agent_Brother_10_Digitizing_App#92
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Where:
src/components/workspace/useWorkspace.ts(pushHistoryat L129-138,UNDOat L314-323,REDOat L325-334,UPDATE_OBJECTat L304-309,ADD_THREAD_STOPat L336-346,REMOVE_THREAD_STOPat L348-349,REORDER_THREAD_STOPSat L351-356).Bug: Three related gaps in the Workspace reducer's history support.
Bug 1 —
pushHistorysnapshot is incomplete. L130-133:Only
stitchObjectsandthreadStopsare snapshotted.UNDO/REDO(L314-334) restore only those fields. The fields NOT captured/restored:colorRegions— restored to[]on Undo even thoughDELETE_SELECTED(L216-237) explicitly removes from bothstitchObjectsANDcolorRegions(L234-235). So after Delete-then-Undo: regions come back but stitch objects also come back (from snapshot), butcolorRegionsare NOT in the snapshot, so they DON'T come back. The UI shows ghost regions on the canvas with no underlying objects, or vice versa.designSettings— HOOP SIZE / FABRIC / STABILIZER changes viaSET_DESIGN_SETTING(L148-152) don't even push history; they're not snapshot-eligible at all. So changing HOOP from "4x4" to "5x7", then deleting a stitch, then Undo — HOOP stays at "5x7" because (a) the setting change never entered history, (b) even if it had, snapshots don't include it.viewport(zoom/pan) —SET_VIEWPORT(L186-187) doesn't push history. Same gap.selectedIds— not snapshotted. After Undo, selection is stale.appState— not snapshotted. After digitize → Undo, appState stays 'digitized' but stitchObjects are empty.processingStep/processingMessage— usually cleared together with state changes, less critical.Bug 2 — Several mutations don't push history at all:
UPDATE_OBJECT(L304-309):setStitchObjects.map(...), nopushHistorycall. Changing an object's color/density/visibility/name from the UI is un-undoable.ADD_THREAD_STOP(L336-346): nopushHistory. Adding a thread stop is un-undoable.REMOVE_THREAD_STOP(L348-349): nopushHistory. Removing is un-undoable.REORDER_THREAD_STOPS(L351-356): nopushHistory. Drag-reorder of stops is un-undoable.Compare with the existing working flow:
DELETE_SELECTED(L236),DUPLICATE_SELECTED(L257),GROUP_SELECTED(L286),UNGROUP_SELECTED(L301),LOAD_DESIGN(L375) all wrap their return inpushHistory(...). The thread-stop and UPDATE_OBJECT mutations were forgotten.Bug 3 —
commitDigitizedResultsnapshots state that is already on the undo target. L502 callsPUSH_HISTORYafterSET_STITCH_OBJECTS/SET_STATE 'digitized'. So history[n+1] = post-digitize state. User pressing Undo after digitize lands on history[n] = pre-digitize — correct. But history[n+1] is never visited except by Redo, and if Redo is pressed immediately after Undo (without any intermediate mutation), it correctly restores history[n+1]. So this specific flow is fine.However:
LOAD_DESIGN(L369-387) callspushHistoryAFTER replacing stitchObjects/threadStops/designSettings, so history captures the LOADED state. Undo from loaded state goes back to pre-load (the state before LOAD_DESIGN). Correct.Symptom (real, reproducible):
stitchObjectsbut does NOT come back incolorRegions. Canvas may render the region preview without the underlying geometry, or vice versa, depending on which renderer the user is in.colorRegionsis also gone (it was already gone after step2; re-undo doesn't restore).Symptom 2:
Symptom 3:
Fix consistent with existing patterns: Mirror what
useWorkspace.tsitself already does forDELETE_SELECTED/DUPLICATE_SELECTEDetc., and whatEditor.tsx:184-194does for the Editor's history:Expand the snapshot. Replace L130-133 with a broader capture that includes the fields you actually want to roll back. Recommended set:
stitchObjects, threadStops, colorRegions, selectedIds, designSettings.appStateandprocessing*are usually fine to leave alone (a digitize→undo cycle restoring appState is rarely the user's intent; they likely want to keep the design but roll back a delete inside the digitize). Forviewport, either include it (so pan/zoom rolls back) or document that it's intentionally not undoable.Mirror the new fields in UNDO/REDO at L319-322 and L330-332.
Push history for the missed mutations. L308 (UPDATE_OBJECT), L345 (ADD_THREAD_STOP), L349 (REMOVE_THREAD_STOP), L355 (REORDER_THREAD_STOPS): wrap the return in
pushHistory(...)like the four working actions do.Add tests.
useWorkspace.test.tsshould cover:DELETE_SELECTEDthenUNDO→ bothstitchObjectsANDcolorRegionsrestored.UPDATE_OBJECTthenUNDO→ property rolled back.ADD_THREAD_STOPthenUNDO→ stop removed.Severity: medium-high. Users can lose data via the 'Delete → undo' flow (color regions vanish from canvas preview despite objects coming back), and several common UI flows (color change, thread stop add) are un-undoable despite the UI suggesting Ctrl+Z should work. Same family as #89 (Editor undo/redo setPaths missing).
Cross-references: #89 (Editor undo/redo is non-functional — handleUndo/handleRedo never setPaths). #63 (Workspace had no Save Session button — saveCurrentDesign since added). #74 (Gallery has no Open in Workspace action — uses LOAD_DESIGN which DOES push history correctly).