One home, one light controller, three ways in
A home lighting app: the wall panel, the phone app and an evening schedule all send requests (set a light, dim it, run a scene) to one controller, which runs them and keeps Undo and Redo history for the whole home. Each level starts from the previous level’s finished code, so you can begin at any of them.
Users asked for one Undo per turn of the dimmer wheel, not one per notch. A teammate’s pull request gives requests an optional merge key (dimBy’s is “Dim”) and has the controller fold a request into the last step in history when the keys match. QA reports that Undo after a turn stops partway, that turning the kitchen right after the hall loses the hall’s step, and that two turns separated by an Undo sometimes undo together. You are reviewing the pull request.
Undo stops partway through a turn, so people press it again and undo something else. Steps for one light vanish into another light’s, and history no longer matches what anyone did.
Reproduce Turn the hall down one notch, then the kitchen: dimBy("hall", 10), then dimBy("kitchen", 5). History should hold two Dim steps, one per light; today it holds one, and Undo puts back only the kitchen. Then on a fresh home, two notches on the hall and one Undo: the hall should be back at 80. Today it stops at 70.
Acceptance criteria Notches on one light, sent one right after another, are one Dim step: Undo restores the level from before the turn, and Redo replays the whole turn. A notch on another light, a Set, a scene, an Undo or a Redo ends the turn: the next notch starts a new step. A notch that changes nothing (the light is already off) changes nothing, as before. Scenes and single requests still undo and redo as in the earlier levels. Notes Cases print each step’s result, every light, then Past and Future, as in COMMAND-101. Keep the merge key on requests and the controller’s fields; the checker reads its levels and history.