You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Continuation of the block-no-scale effort (#34 / PR #230). ShotSequencer already emits ShotDecision/ShotDecisionReason on its decisions stream (groundwork landed with #34); this design persists the final stop reason onto the ShotRecord.
This clusters with two related items — all three should be designed together:
Stop reason on ShotRecord — persist the final stop reason onto the record
/ws/v1/shotState WebSocket topic — stream ShotSequencer decisions to clients
Mid-shot scale loss → volume fallback — fall back to volume-based stopping when scale drops
Intended shape
A WebSocket that streams ShotSequencer's decision info to clients — why the sequencer advanced the profile to the next step, why it skipped a step, why it stopped the shot (target weight, target volume, scale loss, no-scale block, manual, …), so GHC-/machine-initiated outcomes are explainable to skins the same way REST callers already get a typed error.
The persisted ShotRecord stop reason is the durable tail of that same decision vocabulary.
Current state
ShotDecision / ShotDecisionReason types exist
decisions stream on ShotSequencer currently emits only noScale
Reason vocab intentionally aligns with the REST block_no_scale type
No wire serialization yet
No design/handoff note exists yet (checked 2026-05-26)
Decision vocabulary (proposed)
Reason
Trigger
targetWeight
Stop-at-weight reached
targetVolume
Stop-at-volume reached
scaleLost
Scale disconnected mid-shot
noScaleBlock
Shot blocked by no-scale setting
manual
User-initiated stop (GHC / REST)
profileAdvance
Profile advanced to next step
profileSkip
Step skipped by "move on if"
Open questions
What's the WS wire format? JSON over WebSocket at /ws/v1/shotState?
Should decisions be emitted per-shot-step or only for the final stop?
Volume-fallback: does the existing _accumulatedVolume / targetVolume path work cleanly when scale drops mid-pour?
Should the WS topic be unauthenticated (same trust model as other /ws/v1 endpoints)?
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Context
Continuation of the block-no-scale effort (#34 / PR #230).
ShotSequenceralready emitsShotDecision/ShotDecisionReasonon itsdecisionsstream (groundwork landed with #34); this design persists the final stop reason onto the ShotRecord.This clusters with two related items — all three should be designed together:
/ws/v1/shotStateWebSocket topic — stream ShotSequencer decisions to clientsIntended shape
A WebSocket that streams
ShotSequencer's decision info to clients — why the sequencer advanced the profile to the next step, why it skipped a step, why it stopped the shot (target weight, target volume, scale loss, no-scale block, manual, …), so GHC-/machine-initiated outcomes are explainable to skins the same way REST callers already get a typed error.The persisted
ShotRecordstop reason is the durable tail of that same decision vocabulary.Current state
ShotDecision/ShotDecisionReasontypes existdecisionsstream onShotSequencercurrently emits onlynoScaleblock_no_scaletypeDecision vocabulary (proposed)
targetWeighttargetVolumescaleLostnoScaleBlockmanualprofileAdvanceprofileSkipOpen questions
/ws/v1/shotState?_accumulatedVolume/targetVolumepath work cleanly when scale drops mid-pour?See also
/ws/v1/shotStateTODO itemAll reactions