Context
RotationDirection.counterclockwise is implemented in the reducer and plumbed through the presentation model, but no button, menu item or context-menu entry ever requests it. An operator correcting a 90° error in the wrong direction has to press Rotate three times on every affected side.
grep -rn 'counterclockwise' Sources/ Tests/ returns exactly three lines — the enum case, its delta = 3 branch, and one producer reachable only by passing clockwise: false. Zero hits in Tests/, so the (rawValue + 3) % 4 wraparound has never been executed by the suite.
What to change
Sources/ScanDeckApp/ScanDeckPresentationModel.swift — rotateSelectedCardSide(_:) drops the flag. Give it a direction, or add a counterclockwise sibling.
Sources/ScanDeckApp/ScanDeckApp.swift — add menu commands beside the existing "Rotate Front/Back Clockwise" (⌘] / ⌘[). Pick shortcuts that do not collide with the eight already registered; ⇧⌘] / ⇧⌘[ is the obvious pair.
Sources/ScanDeckApp/BatchWorkspaceView.swift — the card context menu has "Rotate Front"/"Rotate Back" on rotate.right; add the counterclockwise entries with rotate.left.
Tests/ScanDeckCoreTests/BatchSessionTests.swift — cover the reducer arithmetic. The interesting case is .none rotating counterclockwise to .clockwise270, i.e. the % 4 wraparound.
Go through the existing rotate(cardID:side:clockwise:); do not add a second path. Mutations reach the reducer through dispatch(_:) and nothing in the presentation model decides rotation policy.
How to verify
swift test --filter BatchSession
swift test -c release
bash Scripts/bundle-app.sh --synthetic
In the synthetic app: scan a card, rotate a side counterclockwise from both the menu and the context menu, and confirm four presses in either direction returns it to where it started.
Use the bundle rather than swift run ScanDeck — a bare SwiftPM executable receives no keyboard events, which would make the shortcuts look broken when they are not.
See CONTRIBUTING.md. No scanner needed.
Context
RotationDirection.counterclockwiseis implemented in the reducer and plumbed through the presentation model, but no button, menu item or context-menu entry ever requests it. An operator correcting a 90° error in the wrong direction has to press Rotate three times on every affected side.grep -rn 'counterclockwise' Sources/ Tests/returns exactly three lines — the enum case, itsdelta = 3branch, and one producer reachable only by passingclockwise: false. Zero hits inTests/, so the(rawValue + 3) % 4wraparound has never been executed by the suite.What to change
Sources/ScanDeckApp/ScanDeckPresentationModel.swift—rotateSelectedCardSide(_:)drops the flag. Give it a direction, or add a counterclockwise sibling.Sources/ScanDeckApp/ScanDeckApp.swift— add menu commands beside the existing "Rotate Front/Back Clockwise" (⌘] / ⌘[). Pick shortcuts that do not collide with the eight already registered; ⇧⌘] / ⇧⌘[ is the obvious pair.Sources/ScanDeckApp/BatchWorkspaceView.swift— the card context menu has "Rotate Front"/"Rotate Back" onrotate.right; add the counterclockwise entries withrotate.left.Tests/ScanDeckCoreTests/BatchSessionTests.swift— cover the reducer arithmetic. The interesting case is.nonerotating counterclockwise to.clockwise270, i.e. the% 4wraparound.Go through the existing
rotate(cardID:side:clockwise:); do not add a second path. Mutations reach the reducer throughdispatch(_:)and nothing in the presentation model decides rotation policy.How to verify
In the synthetic app: scan a card, rotate a side counterclockwise from both the menu and the context menu, and confirm four presses in either direction returns it to where it started.
Use the bundle rather than
swift run ScanDeck— a bare SwiftPM executable receives no keyboard events, which would make the shortcuts look broken when they are not.See CONTRIBUTING.md. No scanner needed.