← Back
โ Back
# Mavis HQ โ Starred tab cleanup for ADHD-friendliness
## Goal
Make the Starred tab on `https://panel.freshvibeapps.com/mavis` easier to scan on mobile.
Today each pinned-project card has 3 lines of header, 1 technical "HQ] thread=..." line,
1 boilerplate "star_reason" line, and 1-2 bulletins that often repeat the same "starred by..."
boilerplate. The operator (G) wants: clear human name as the heading, the most-recent
meaningful bulletin as the summary, and a click-to-expand for detail. Plus a link to the
plan each sub-thread is tied to.
## Constraints
- Touch ONLY the Starred tab render in the SPA (`renderStarred` function, ~lines 716-840
of the SPA HTML).
- Don't change data shape, API endpoints, or other tabs.
- Don't break: VPS card, state banner, category emoji chips.
- Mobile-friendly (390x844 iPhone 13 minimum, no horizontal overflow, 44px tap targets).
- Keep the existing `catBl()` classifier (works fine โ issue is layout, not data).
- Backwards-compatible: if new fields are absent, fall back to current behaviour.
## Audit findings (what's actually wrong)
1. **Card face has 5 distinct text elements crammed in**: ๐ emoji, thread name, id,
"starred X ago" timestamp, status pill, "HQ] thread=..." technical line, "star_reason"
boilerplate, then 1-3 bulletin rows. The "starred by operator-panel-mavis" bulletin
(b000586-b000590) is itself the boilerplate.
2. **star_reason field** is set at star-time to "a478 v3 sub-thread (per G directive
relayed via helper-mavis b566/b585)" โ identical on all 5 pinned sub-threads. Useless
on the card face. Move to detail view only.
3. **HQ] thread=... line** is operator-style technical signal. Useful for debugging but
noise at the card level. Move to detail view only.
4. **Most recent bulletin is always the "starred" bulletin** because no other bulletins
exist on the 5 sub-threads yet. Need to either show "no activity yet" or render a
useful fallback (e.g. a hand-written one-liner per sub-thread).
5. **No plan link** โ each sub-thread is tied to a478 v3 (artifact 490) but the SPA
doesn't show the plan id anywhere on the card.
6. **Thread name as @a478-v3-fvre-bridge** is technical slug, not human. Need a
`display_name` field OR a name-to-label mapping.
## Steps (numbered, each verifiable)
1. **Add a label registry** at the top of the SPA JS that maps thread names to short
human labels: e.g. `a478-v3-fvre-bridge` โ `FvRE bridge`, `a478-v3-chrome-decouple`
โ `Chrome decouple`, `a478-v3-fvs-gallery-widgets` โ `Gallery widgets`,
`a478-v3-fvs-vibecoder` โ `VibeCoder FVS`, `a478-v3-vibechat-multicontext` โ
`VibeChat multi-context`. Fallback: strip `a478-v3-` prefix and title-case the rest.
- **Done when**: `displayLabel('a478-v3-fvre-bridge')` returns `'FvRE bridge'`.
- **Verify**: run in browser console, check 5 known names.
2. **Add a `meta.one_liner` field to thread rows** so future stars can carry a useful
summary. For now, hardcode the 5 sub-threads' one-liners (a one-line "what this thread
is about" in the voice the operator uses). Add a `threadOneLiner(name)` function.
- **Done when**: `threadOneLiner('a478-v3-fvre-bridge')` returns the FvRE bridge
one-liner from a478 v3 ยง3 (e.g. "wcp-catalog.json + fes_bridge.py + 6-endpoint
microservice").
- **Verify**: console test the 5 known names, check 5 strings returned.
3. **Rewrite the card layout** in `renderStarred()`:
- Top: ๐ข/โช status dot (big, 14px) + label (16px, bold) + "sub-thread" sub-line
- Middle: one-liner (13px, full text, wraps)
- Footer: `๐ a490` (clickable plan id, 12px) + `โ open thread` link
- "HQ] thread=..." line + star_reason โ only in the click-to-expand detail block
- Recent bulletins โ only in the detail block
- **Done when**: a 5-card grid fits in 1 mobile screen (under 600px tall total
excluding topbar/tabs/state banner).
- **Verify**: Playwright iPhone 13 screenshot, measure total height.
4. **Add the click-to-expand** (existing pattern, but currently wired to navigate
away โ change to in-place expand). Click on a card body (not the plan link) โ
expands inline below the card, showing: HQ] line, star_reason, last 5 bulletins.
Click again โ collapse. ESC โ collapse all.
- **Done when**: clicking a card expands the detail block without navigating.
- **Verify**: Playwright click test, measure detail block visibility.
5. **Add the plan link** to each card. The 5 sub-threads are all sub-threads of
plan a478 v3 (artifact 490). The link should go to `https://artifacts.freshvibeapps.com/
fvcms-v3-world-class-plan/2026-08-03-fvCMS-v3-world-class-plan/index.html` (or
whichever live URL a490 maps to). Use a helper `planUrlFor(name)` that returns
the right URL per thread.
- **Done when**: clicking the ๐ a490 chip opens the plan in a new tab.
- **Verify**: click test in Playwright, check `target="_blank"` + rel attributes.
6. **Filter boilerplate bulletins** โ if a bulletin message starts with "starred by
operator-panel-mavis" (or matches `/^starred by /`), don't show it in the
recent-bulletins list. Show a "no other activity yet" line instead.
- **Done when**: the 5 sub-thread cards show 0 boilerplate bulletins.
- **Verify**: visual check on live SPA, no "starred by" text in card faces.
7. **Mobile media queries** โ add specific rules for `max-width: 480px` to make
cards stack with full-width tap targets, status dot 16px, label 17px, one-liner
14px, plan link 13px, expand chevron 44px tap target.
- **Done when**: on iPhone 13 (390px wide), cards are 14-16px text minimum,
44px tap targets, no horizontal scroll.
- **Verify**: Playwright iPhone 13 measurement.
## Acceptance criteria (the plan is done when ALL true)
- [ ] A pinned-project card on mobile shows: status dot + label + one-liner + plan link
- [ ] No "HQ] thread=..." visible on the card face
- [ ] No "starred by operator-panel-mavis" boilerplate visible on the card face
- [ ] No "starred X ago" โ replaced with "last activity X" or "no activity yet"
- [ ] Click card โ expands detail inline (not navigate away)
- [ ] Detail block has: HQ] line, star_reason, last 5 bulletins
- [ ] Plan link `๐ a490` opens the plan in a new tab
- [ ] 5 cards fit in 1 mobile screen
- [ ] All 5 sub-threads show distinct human labels (not all `@a478-v3-...`)
- [ ] No regressions in VPS card, state banner, other tabs
## Open questions (need operator input)
- Q1: Where does a478 v3 artifact 490 live on the artifacts.freshvibeapps.com CDN?
Currently I think `https://artifacts.freshvibeapps.com/fvcms-v3-world-class-plan/...`
but the path needs verification. Could also be at `artifacts.freshvibeapps.com/
fvcms/2026-08-03-v3-plan/` or similar โ I need to find the right URL by querying the
artifacts API. (Default: I'll find it via the SPA's existing plan link if there is one.)
- Q2: Should the 5 sub-threads' one-liners be hardcoded in the SPA, or fetched from
`meta.one_liner` on the plan? Hardcoding is faster to ship but stale. (Default: hardcode
for now, replace with API call when plan sub-shape is ready.)
- Q3: Should the expand/collapse state be persisted in localStorage so the operator's
last selection survives a page reload? (Default: yes, 1 key per thread name.)
## Off-track triggers (STOP and flag, don't push through)
- Touching the Overview tab (not Starred) โ different scope, will balloon the change.
- Renaming the threads via the rename endpoint โ that's a data change, not a UI change.
- Adding new API endpoints โ this is a UI cleanup, not a backend change.
- Changing the catBl() classifier โ it works; the issue is layout, not categorization.
- Any change that takes more than 30 min without a test result โ that's a sign I'm
rabbit-holing.
## Risks
- **Existing thread-name regex `^(a\d+-v\d+)`** for project grouping: the 5 sub-threads
all start with `a478-v3-`, so they group under one project. If I add labels, I need
to keep the project grouping intact.
- **Touching the SPA HTML inline** (it's one 200KB file, no module system) โ every edit
is in-place. I should test before/after, keep backups, and the operator has the git
history.
- **The current `b000586`-style auto-bulletins** will keep being posted whenever I star
something. The cleanup needs to filter them, not suppress the auto-post.
## Out of scope
- Changing the data model (no new fields on `hq_threads`)
- Changing the API (no new endpoints, no payload changes)
- Changing other tabs (Overview, Timeline, Repos, Plans, Artifacts, Inbox, Agenda)
- Mobile-app integration (the SPA is a web app; mobile is via browser)