Stream Deck: phase-aware review dials (canvas navigation reuses the diff dials) - #1419
Merged
Conversation
…e commented-block nav)
…HANGES) + regression tests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PIR Review: Stream Deck phase-aware review dials
Fixes #1400
Summary
The Stream Deck's two diff dials (Files / Changes) sat idle whenever the selected builder was
writing a spec or plan — exactly when the artifact canvas is the thing under review. This change
makes those two dials phase-aware: the selected builder's phase picks the dial mode, so the
same physical gestures review whichever artifact form applies. Diff-phase builders drive the diff
(unchanged); spec/plan-phase builders drive the artifact canvas (headings / blocks, composer, comment
walk) over #1401's
sendCanvasCommand. No bridge, sdk, Tower, or vscode change — only the deck.Files Changed
apps/streamdeck/src/actions.ts(+164 / -21) —reviewMode()resolver +DiffNav→ phase-awareReviewNavapps/streamdeck/src/__tests__/actions.test.ts(+118 / -8) — canvas-mode, legibility,reviewMode, per-code feedback testsapps/streamdeck/com.cluesmith.codev.sdPlugin/manifest.json(+11 / -11) — dial Name/Tooltip/TriggerDescription reflect the dual role (UUIDs unchanged)apps/streamdeck/README.md(+13 / -6) — Actions list updated for the renamed, phase-aware dialsCommits
9aa1a29d9[PIR Stream Deck: phase-aware review dials — canvas navigation reuses the diff dials (deck half; bridge is #1401) #1400] Phase-aware review dials: canvas mode reuses the diff dials1abc02025[PIR Stream Deck: phase-aware review dials — canvas navigation reuses the diff dials (deck half; bridge is #1401) #1400] Rename review dials in manifest to reflect phase-aware behavior[PIR #1400]thread + plan commits; README rename folded into the review commit)Test Results
npm run build: ✓ pass (esbuild bundle)npx tsc --noEmit: ✓ passnpm test: ✓ pass (82 tests, 11 new)npx streamdeck validate: ✓ passswitch, the live touchstrip re-title, and that diff-phase behavior is unchanged.
Architecture Updates
No hot-tier (
arch-critical.md) change: this is a self-contained controller-side feature, not a newinvariant or module boundary. No cold-tier (
arch.md) change needed either — the existingapps/streamdeckentry already describes the deck as an "outside-in controller: … command-relayverbs via the sdk's
controller/nodesubpaths," andsendCanvasCommandlives on that samecontrollersubpath, so the description stays accurate.Lessons Learned Updates
No new hot-tier lesson. Two existing hot lessons already governed the key decisions and were followed
rather than added to: "Single source of truth beats distributed state" (the dial mode is derived
from the shared
phaseArtifactVerbresolver, not a re-derived phase-string table) and "After anyrename … grep the whole repo" (the manifest rename drove the README + tooltip + trigger-description
sweep). The MRU-vs-file-qualified targeting call is spec-narrow and already captured in the plan (§5)
and issue thread, so it does not warrant a cold-tier entry.
Things to Look At During PR Review
reviewMode()reuse (actions.ts): it is intentionally a thin derivation ofphaseArtifactVerb(
open-spec/open-plan→ canvas,view-diff→ diff, elsenone) so the wire source stays single(
blockedGatebeatsprotocolPhase; never guessed). If the phase→artifact mapping ever changes,both the Builder Action key (Stream Deck: merge Fleet Slot into Builder Action (phase-aware press) #1404) and these dials move together — that coupling is the point.
file) (runCanvas): every canvas gesture targets{ workspace }only. Thiswas the deliberate v1 decision (plan §5, co-signed by main as the types stakeholder) because
OverviewBuildercarries no artifact path; Stream Deck: merge Fleet Slot into Builder Action (phase-aware press) #1404's press converges the MRU onto the selectedbuilder's artifact. File-qualified targeting is the documented additive upgrade, not a gap.
count = |ticks|(onDialRotate): onesendCanvasCommandper rotate event carrying thetick count, never a burst of single-tick sends. Diff-mode rotate is unchanged (one verb per event).
statusfield +canvasErrorLine): a failed canvas command shows itsper-code reason (
no-canvas→ "Open artifact",unreachable→ "Tower offline") on the touchstripuntil the next overview tick clears it — the
render()onChange handler clears it, gesture handlersset it. Worth a look that the clear/set ordering can't strand a stale error.
CanvasCommand(re-exported from@cluesmith/codev-sdk/controller), notTraversalCommand— the latter isn't re-exported there andthe import-boundary test forbids importing
@cluesmith/codev-typesdirectly. No sdk change;countisn't type-restricted to traversal by the sdk signature anyway.
How to Test Locally
pnpm --filter @cluesmith/codev-sdk buildthenpnpm --filter @cluesmith/codev-streamdeck build), thenstreamdeck link apps/streamdeck/com.cluesmith.codev.sdPlugin+streamdeck restart com.cluesmith.codev(unlink any existing build first)Files/Changes; rotate/press/tap drive the diffexactly as before (no regression)
Headings/Blocks; press the builder key (Stream Deck: merge Fleet Slot into Builder Action (phase-aware press) #1404)to open its artifact; rotate steps headings/blocks, press opens the composer, coarse tap jumps to
the top, fine tap walks forward through commented blocks
Open artifact; Tower stopped →Tower offlinewithin one overview tick