Workspace's history stack has no MAX_HISTORY — undo can grow unbounded across many edits; Editor caps at 50 but the larger surface does not #172

Closed
opened 2026-10-03 17:33:47 +00:00 by Mark · 1 comment
Owner

Finding

src/components/workspace/useWorkspace.ts:412-428 (the UNDO and REDO reducer cases) doesn't bound the state.history array. Each edit pushes a new entry; nothing trims old ones.

src/pages/Editor.tsx:215-262 has const HISTORY_LIMIT = 50; and trims next when the array exceeds that length (line 258: const shiftCount = next.length - HISTORY_LIMIT;).

The Editor's bound at 50 is reasonable (50 deep undo is more than most users need). The Workspace's missing bound means a user who makes 500 edits has 500 history entries — each a snapshot of the design state. Memory grows linearly. Browser becomes sluggish. Save to Gallery produces a Design row with a snapshot of the current state, but localStorage doesn't store history (the history is in-memory only), so the only consequence is runtime memory.

Where

src/components/workspace/useWorkspace.ts:412-428 (UNDO/REDO reducer cases — no bound)

Suggested fix shape

Mirror the Editor's pattern. In the UNDO/REDO case and in the PUSH_HISTORY helper (if it exists), cap the history length:

const MAX_HISTORY = 50;
if (newHistory.length > MAX_HISTORY) {
  newHistory = newHistory.slice(newHistory.length - MAX_HISTORY);
}

The slice preserves the most recent entries. The user can still undo the last 50 changes; older history is lost. Same UX as the Editor.

Severity

Low. The unbounded growth is a memory issue, not a correctness issue. Users making 500+ edits in one session is uncommon.

Discovered by

Gap analysis (2026-10-02) of workspace resilience.

  • The Editor's HISTORY_LIMIT = 50 is the model. Apply the same to the Workspace's reducer.
## Finding `src/components/workspace/useWorkspace.ts:412-428` (the `UNDO` and `REDO` reducer cases) doesn't bound the `state.history` array. Each edit pushes a new entry; nothing trims old ones. `src/pages/Editor.tsx:215-262` has `const HISTORY_LIMIT = 50;` and trims `next` when the array exceeds that length (line 258: `const shiftCount = next.length - HISTORY_LIMIT;`). The Editor's bound at 50 is reasonable (50 deep undo is more than most users need). The Workspace's missing bound means a user who makes 500 edits has 500 history entries — each a snapshot of the design state. Memory grows linearly. Browser becomes sluggish. Save to Gallery produces a Design row with a snapshot of the current state, but localStorage doesn't store history (the history is in-memory only), so the only consequence is runtime memory. ## Where `src/components/workspace/useWorkspace.ts:412-428` (UNDO/REDO reducer cases — no bound) ## Suggested fix shape Mirror the Editor's pattern. In the `UNDO`/`REDO` case and in the `PUSH_HISTORY` helper (if it exists), cap the history length: ```ts const MAX_HISTORY = 50; if (newHistory.length > MAX_HISTORY) { newHistory = newHistory.slice(newHistory.length - MAX_HISTORY); } ``` The slice preserves the most recent entries. The user can still undo the last 50 changes; older history is lost. Same UX as the Editor. ## Severity Low. The unbounded growth is a memory issue, not a correctness issue. Users making 500+ edits in one session is uncommon. ## Discovered by Gap analysis (2026-10-02) of workspace resilience. ## Related - The Editor's `HISTORY_LIMIT = 50` is the model. Apply the same to the Workspace's reducer.
Author
Owner

Closed by Mark/Kimi_Agent_Brother_10_Digitizing_App@7cdf4b8

Note: the workspace reducer's pushHistory() helper at src/components/workspace/useWorkspace.ts:183 already had an inline cap (if (newHistory.length > 50) newHistory.shift()) — the magic 50 was hiding in the body rather than being a named constant. The fix landed in 7cdf4b8 extracts it to MAX_HISTORY = 50 to mirror the Editor's HISTORY_LIMIT = 50 and adds a comment citing this issue. No behavior change; the bound held since init.

Closed by https://forgejo.tail018ac4.ts.net/Mark/Kimi_Agent_Brother_10_Digitizing_App/commit/7cdf4b8 Note: the workspace reducer's pushHistory() helper at src/components/workspace/useWorkspace.ts:183 already had an inline cap (`if (newHistory.length > 50) newHistory.shift()`) — the magic 50 was hiding in the body rather than being a named constant. The fix landed in 7cdf4b8 extracts it to MAX_HISTORY = 50 to mirror the Editor's HISTORY_LIMIT = 50 and adds a comment citing this issue. No behavior change; the bound held since init.
Mark closed this issue 2026-10-03 19:14:19 +00:00
Sign in to join this conversation.
No description provided.