Skip to content

streamdeck: Review dials silently dead for BUGFIX (investigate/fix) and AIR (pr phase) — phase vocabulary hardcoded to SPIR/PIR #1606

Description

@amrmelsayed

Problem

The Review: Files / Headings and Review: Changes / Blocks dials silently no-op for BUGFIX builders during their entire working life (investigate, fix phases) and for AIR builders during the pr phase (until the pr gate is requested). The owner hit this in live use as "the file diff dials sometimes work and sometimes not" — the intermittency is protocol identity, not flakiness.

Diagnosis

phaseArtifactVerb (apps/streamdeck/src/actions.ts:527) resolves dial mode from a hardcoded vocabulary — gates spec-approval | plan-approval | dev-approval | pr | verify-approval, phases specify | plan | implement | review | verify. That list was written against SPIR/PIR's lifecycle. Checked against each bundled protocol's protocol.json phase ids:

  • SPIR (specify/plan/implement/review/verify) and PIR (plan/implement/review): fully covered.
  • AIR (implement/pr): the prphase id is unrecognized, so the dials die between entering the phase and the pr gate being requested (blockedGate === 'pr' revives them).
  • BUGFIX (investigate/fix/pr): investigate and fix are unrecognized — review mode resolves to none for the builder's whole working life; dials only come alive blocked at the pr gate.
  • Porch init phase and no-status (soft/shell/task) builders: also none.

Two compounding effects make it read as intermittent rather than broken:

  1. The Zoom dial's tap falls back to view-diff for unknown phases (zoomInVerb), so a BUGFIX builder's diff opens normally — then the Review dials won't step it.
  2. The none-mode strip label lies: ReviewNav.renderTo has only a canvas/diff branch for line 1, so none renders the diff label (Files · send) while every gesture is a no-op — violating the dial's own "a gesture is never a surprise" contract and the instrument principle (an instrument answering a narrower question than its face implies must say so).

Owner ruling (2026-09-04)

The pr phase should be diffable as well — by that point (BUGFIX and AIR both) the work exists as a diff.

Fix

  1. Map investigate, fix, and phase pr to diff mode. Prefer deriving the mode from the protocol's own protocol.json phase metadata over extending the hardcoded name list, so new/custom protocols never silently fall out of the vocabulary; if metadata can't express it, extend the list and leave a registration note (the same pattern Tower's GATE_LABELS documents).
  2. Make the none-mode strip label honest (e.g. No review target) instead of rendering the diff label.
  3. Keep init/no-status as none (there is genuinely nothing to review), but with the honest label from (2).

Shipping note

apps/streamdeck change → requires a plugin version bump and an Elgato Marketplace resubmission (review lag ~4–10 working days). Consider batching with other queued plugin work rather than shipping alone.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/streamdeckStream Deck plugin — apps/streamdeck, Elgato channel (profiles, Maker Console, packaging)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions