Found while porting the faces' missing marks (#506). The design's mascot has nine states; RoastyState had eight. The missing one is points — a wink, listed in 03-design-system.md as "wink + points rise, 2150ms" and drawn in prototype/roasty.jsx as face-points: one open eye with its catchlight, one arched-up eye, cheeks at 0.5, and a mouth that rises to the winking side.
Nothing in the app could reach it, so it was absent rather than unused — the whole pose was undrawn.
The part that is settled, and the part that is not
The face is a drawing like the other eight. The points burst beside it is not: roasty.jsx renders +{pointsAmount} PTS, and #16 ruled a hardcoded amount out of the mascot — the guard in companion_no_payout_literal_test.dart keeps it out. So a points state may draw the wink, and the amount has to be passed in by whoever knows it, exactly as the design passes pointsAmount.
Whether the app has a moment that should use it is the open question: nothing today awards points with a mascot beat, and CompanionReaction has no member for one. That is a product call, not a porting one.
Reconciling #212
#212 deleted this pose rather than fix the number baked into it, and rejected parameterizing at triage. Half of that ruling is reversed here and half stands, and #212 now says so:
- Reversed — the pose is drawn, and the amount is the caller's.
Roasty asserts the pairing both ways, so the pose cannot reach a screen without an amount and no other state can be handed one.
- Stands — no v1 moment that already celebrates gets a second celebration wired into it. That is why nothing calls the pose.
Acceptance criteria
Found while porting the faces' missing marks (#506). The design's mascot has nine states;
RoastyStatehad eight. The missing one ispoints— a wink, listed in03-design-system.mdas "wink + points rise, 2150ms" and drawn inprototype/roasty.jsxasface-points: one open eye with its catchlight, one arched-up eye, cheeks at 0.5, and a mouth that rises to the winking side.Nothing in the app could reach it, so it was absent rather than unused — the whole pose was undrawn.
The part that is settled, and the part that is not
The face is a drawing like the other eight. The points burst beside it is not:
roasty.jsxrenders+{pointsAmount} PTS, and #16 ruled a hardcoded amount out of the mascot — the guard incompanion_no_payout_literal_test.dartkeeps it out. So apointsstate may draw the wink, and the amount has to be passed in by whoever knows it, exactly as the design passespointsAmount.Whether the app has a moment that should use it is the open question: nothing today awards points with a mascot beat, and
CompanionReactionhas no member for one. That is a product call, not a porting one.Reconciling #212
#212 deleted this pose rather than fix the number baked into it, and rejected parameterizing at triage. Half of that ruling is reversed here and half stands, and #212 now says so:
Roastyasserts the pairing both ways, so the pose cannot reach a screen without an amount and no other state can be handed one.Acceptance criteria
RoastyStatecarries the design's ninth state, drawingface-pointsasroasty.jsxdraws it —roasty_faces_test.dartreads the design's own markup for the wink's cheek pair, its single eye white and both of its strokesdocs/design/09-deferred-v2.md, so the next reader finds it where the work iscompanion_no_payout_literal_test.dartpasses unchangedflutter analyze, metrics gate, tests clean — 2592 tests