fix(members): show the roster patrol badge only while a loop is active - #9422
fix(members): show the roster patrol badge only while a loop is active#9422CrysisDeu wants to merge 1 commit into
Conversation
Since #8936 a member's avatar carried a badge whenever an auto-patrol record existed for its thread: accent while active, warn-yellow with a pause glyph once the loop had stopped. Stopped is the resting state of most members (every cycle-capped or hand-stopped loop leaves a record), so most idle avatars wore a permanent yellow mark that read as "this member is broken" rather than "nothing is scheduled". The roster badge is now two-state: the accent goal glyph with its "On patrol · 3 of 24" tooltip while the loop is ACTIVE, and no badge at all otherwise — a stopped loop and a never-armed member look the same at the roster, the way the presence dot (#6859) and unread dot already work: appearance is the signal. The drawer's Auto patrol block keeps its full three verdicts (active / stopped with reason and last wake / none); the stop reason lives there. Fade-out on stop stays through AnimatePresence (no hard vanish, #8718); `useReducedMotion` cuts the tween under prefers-reduced-motion. The `patrol_badge_stopped` key is removed from all 13 catalogs and en-XA is regenerated. Tests pin one badge on a mixed active/stopped/never roster and no intermediate "stopped" badge when a loop stops in place. The capture harness asserts exactly one badge per active loop. Closes #9420
Design Review (Fable 5) — 🟡 CONCERNSDesign-level review of Design-Verdict: CONCERNS Removing the stopped badge for ALL stop reasons quietly reverses the #8931/#8936 incident-visibility decision for stalled patrols, not just the noisy resting-state cases. Watch
Suggestions
[DESIGN-REVIEWED] b9950c2 |
Opus 4.8 Review — ✅ no blocking findingsReviewed Verdict parsed from the review's SHA-scoped output markers for commit False positive or not applicable? A repository writer can comment: |
First Principles Review (Fable 5) — ✅ PASSPremise-level review of All the counts I need are run: the removed i18n key has zero remaining references anywhere in the repo; First-Principles-Verdict: PASS Verify #9420 knowingly trades away the roster-level dead-patrol signal #8936 shipped for incident #8931 — drawer-only is now the sole surface for a stopped loop. Not justified as shipped
What this change shipsIntent: stop marking every idle member with a permanent yellow "patrol stopped" badge that read as broken — a FIX (closes #9420, PM review of the shipped page).
The deleted pin ("a dead patrol must show at the roster, not only after the drawer opens") is overturned with checkable evidence — linked issue #9420 and the PM's review of that shipped decision — so the framing is honest, not "a gap". Subtractions
[FIRST-PRINCIPLES-REVIEWED] b9950c2 |
GPT 5.6 Review — ✅ no blocking findingsGPT 5.6 completed its review of This comment is updated in place on each push. Review detailsNo findings. False positive or not applicable? A repository writer can comment: |
UX Review (Fable 5) — 🟡 CONCERNSUX-level review of All evidence checks out: eight screenshots cover every state (active dark/light, unlimited, both stop reasons, none, loading, error), two committed recordings show the arm/disarm fade and the drawer crossfade, the exit tween plus reduced-motion handling are in the diff, and the blind reader correctly read the screens. The one residual risk is that the removal flattens an actionable stop (approval stalled) into the same no-signal as a benign one (cap reached). UX-Verdict: CONCERNS Dropping the warn badge also silences the one stop that needs the user: an approval-stalled patrol now dies invisibly at the roster. Watch
[UX-REVIEWED] b9950c2 |
|
|
Closes #9420. Follow-up to #8936 (which added the badge for the #8931 incident).
Why
Since #8936 the roster put a badge on a member's avatar whenever an auto-patrol record existed: accent goal glyph while active, warn-yellow pause glyph once stopped. Stopped is the resting state of most members — every cycle-capped, budget-expired or hand-stopped loop leaves a record — so most idle avatars wore a permanent yellow mark that read as "this member is broken". PM review of the shipped page: 做成如果有自动巡检才加一个标,不然有一个这个标很 confusing ("only add a mark when there IS an auto patrol; otherwise the mark is confusing").
Stopped is not an incident, and the roster already has the idiom for this: the presence dot (#6859) and the unread dot render only while there is something to say. The stop reason has a home — the drawer's Auto patrol block — and it stays there.
What
website/src/pages/members/MembersPage.tsx— roster badge is two-state.patrolBadgeOf(three-way verdict) becomesactivePatrolOf, returning the loop record only whileactive; the render drops thestoppedbranch, thebg-warnfill, thePauseglyph and the colour-flip transition. Tooltip /aria-labelkeep the drawer's spelling ("On patrol · 3 of 24" / "61 · no limit").data-state="active"is kept on the element so the harness and tests still address the badge by state.AnimatePresence— when a loop stops the badge fades out rather than vanishing, and no intermediate yellow state appears. NewuseReducedMotion()read: underprefers-reduced-motionthe tween is skipped (initial: false,duration: 0) and the badge cuts straight to its new state.needs_youpill (feat(members): chat-profile projection and escalation cards in the DM thread #8614), presence dot and unread dot keep their positions; the badge's corner is unchanged.pages.membersPage.patrol_badge_stoppedremoved from all 13 catalogs (line-anchored delete, no re-sort) anden-XAregenerated (i18n:pseudo, 13016 keys). Zero remaining references.lint:i18nandi18n:checkgreen.docs/feature-map/README.md— Crew Members row now says the badge shows only while a loop is active.origin/main.Tests
MembersPage.test.tsx:data-state="active", aria-label3 of 24, beside the single presence dot, and no element titled "Patrol stopped".activeto false, what the websocket hook triggers) drops the badge after the exit tween with no "stopped" badge in between.Local:
tsc -b, eslint on both files,lint:i18n,i18n:checkgreen. vitest left to CI per the lane rules.Screenshot Evidence
Capture harness
website/scripts/capture-members-patrol.mjs(real built SPA overstubDashboardApi, no gateway), updated to assert exactly one badge per active loop and none otherwise before every frame — a frame can only be written from the state it claims. Five-member roster: radar (active 3/24, running) and ledger (active, unlimited) beside scout (stopped at wake limit), scribe (stopped, approval stalled) and fixer (never armed).Active and stopped members side by side, dark — radar and ledger carry the accent badge; scout / scribe / fixer show nothing. radar's drawer open:
Same roster, light:
scout's drawer: the stop reason ("Patrol stopped. Reached its wake limit. Last wake 4h ago") lives here — and scout's avatar in the roster has no badge:
scribe stopped on a stalled approval — same: reason in the drawer, no roster mark:
fixer, nothing scheduled:
Unlimited cap tooltip spelling preserved on ledger:
Registry read in flight / failed (unchanged behaviour, re-captured on this head):
Transition recording — fixer's badge fades in when a loop arms, then fades out when the loop stops (real
autonudge_stateframes pushed over the page's own/api/ws); there is no yellow intermediate state:Drawer block none → active → stopped (unchanged, re-recorded):
Pattern harvest
Rule candidate: design-lane / AUTOSDE — a per-item status mark on an avatar or row (dot, badge, pill) renders only while its positive state holds; a standing placeholder for the "off" state is a finding. Pattern:
condition ? <on-mark/> : <off-mark/>where the off branch renders a persistent glyph.