Bristlenose · macOS sidebar · design spec

Project row status vocabulary

Every state a sidebar project row can be in, drawn 1:1 with the shipped cell. Geometry is ProjectCellSpec's measured constants; glyphs are the real SF Symbols rendered out of AppKit and masked, so the tint stays a token and both themes are correct.

Authority: docs/design-desktop-project-status.md (precedence chain, the 18 Jun kind rulings, Schema E) and docs/design-pipeline-diagnostic-popover.md (the five-kind MessageKind vocabulary; new glyphs are forbidden). Contract pinned by BristlenoseTests/SubtitleGlyphContractTests.swift and tests/test_sidebar_status_line_contract.py.

The full vocabulary

Every state the row can be in, drawn 1:1 with the shipped cell — geometry from ProjectCellSpec's measured constants, glyphs rendered out of AppKit rather than approximated. Dashed outlines on hover mark click targets.

The rule

Two questions, decided separately. Conflating them is how a sidebar grows controls.

StateGlyph — is this news?Door — is there detail with no other home?
failed · completedPartial✗ / ⚠diagnostics — a list of per-session failures
unreachable⚠ / ✗ by reasondiagnostics — the reason, and the folder path
cantFind⚠ reason-specificnone — its one fact is already on the row; Locate is a project verb
deltaOnly(.missing)files — which recordings have vanished
deltaOnly(.unanalysed)files — which are waiting, plus Analyse
stopped · partial · running · …nonenone

The glyph marks news, not opportunity. Stopped and Transcribed both have something the researcher could do — resume, analyse — and get nothing, because they caused them and already know. +3 unanalysed has the same shape of act and does get a glyph, because the app noticed something that happened outside it.

A glyph buys attention, not action, so it owes no click — and a door implies a glyph, because a click target nobody can see is worse than none. Where there is a door, the glyph and its text are one control: 10pt is a small target, and they are one message.

The screenshot, before and after

Before — 26 Aug
ProjectZ
Taking too long to respond.
New Project1
Taking too long to respond.
New Project2
Taking too long to respond.
IKEA with uxfriends1
Taking too long to respond.
After
ProjectZ
Not responding
New Project1
Not responding
New Project2
Folder not found
IKEA with uxfriends1
Project file damaged
info — fine, but worth knowing warning — may resolve itself error — something must change Dimmed — can't be opened right now

The five glyphs, at 2×

The whole vocabulary — new glyphs are forbidden. Fill weight carries meaning alongside colour: filled for states that demand the eye, outline for those that ride alongside text. Shape and colour are redundant, so the signal survives colour-blindness.

success
checkmark.circle
info
info.circle
warning
exclamationmark.triangle.fill
error
xmark.circle.fill
skipped
minus.circle.fill

Distress — glyph and door

Run outcome · unreachable
Pricing Pilot12
Run failed
Onboarding Q342
Partial completion
Field Study
Not responding
Diary Wave 2
Can't be read
Pilot A
Project file damaged
Can't find the folder — glyph, no door
Backup Study
Backup Drive · missing
Shared Research
nas.local · unreachable
Moved Project
missing
Data drift — ⓘ and ⚠, both open the files popover
Accessibility Round 29
+3 unanalysed
Retail Ethnography18
2 missing

The cantFind rows carry a glyph and no dashed outline — that is the rule working, not an omission. Their one fact, the volume or host name, is already in the subtitle, so there is nothing to disclose; Locate is a general project verb and lives in right-click.

Extra files are blue ⓘ. Nothing went wrong — there is more material than the report has read, and the researcher put it there; orange would be the app scolding someone for using Finder. ⓘ is also the platform's disclosure control, which is the better argument for it than the kind taxonomy. Files that were analysed and have since vanished stay : the report cites recordings that are gone.

Progress and rest — no glyph, by the rule

In flight
Pricing Pilot12
Finding quotes · 7 of 12 · ~4 min left
Onboarding Q342
Stopping…
Diary Wave 26
Queued · position 2
New Intake
Copying · 63%
Meet Import
3 of 4
Terminal · resting · right slot
Banking Onboarding8
Stopped
Quick Pass4
Transcribed
Pricing Pilot12
Cloud Study5
Transcribed
Shared with Agents7
Stopped
Note
Row three is .placeholder — Schema E, a clean row is silent and collapses to a single 32pt line. Rows four and five show the trailing slot's other occupants: the iCloud arrow and the agent-exposure antenna, both markers, neither a control.

Behind the glyph — two popovers, one surface

The popover is the row's non-modal detail surface: attention plus detail that has no other home. It may act on the thing it is showing and nothing else — general project verbs stay in right-click, which is what stops it becoming a second menu.

Not responding Show Log
The folder didn't answer — it may be a disconnected drive or network share.
/Volumes/Backup Drive/Field Study 3
Unanalysed files Analyse
+3 unanalysed
2026-08-15 1042 — session 07.mp47.9 MB
2026-08-16 0913 — session 08.mp46.1 MB
2026-08-16 1512 — session 09.mp45.6 MB
These files were added after the last analysis.
Missing files Analyse
2 missing
2026-07-02 1130 — session 03.mp4
2026-07-02 1400 — session 04.mp4
These files are no longer in the project folder.
+1 unanalysed
2026-08-16 1512 — session 09.mp45.6 MB
These files were added after the last analysis.

Why these are popovers and not the modal they replace. A context menu shows verbs and cannot show a list, so "which three files are waiting" has nowhere else to live — and a modal is the wrong price to pay for reading three filenames. The sheet this replaces (NewFilesSheet) carried three separate retirement notices, including its own header and design-cloud-import.md calling it "the codebase's worked example of a data view wrongly living in native chrome".

Analyse is bordered, not prominent. It is the point of opening the popover, but a prominent button turns a detail surface into a dialog and invites the next verb to join it — matched instead to Show Log's weight in its sibling. When both conditions are true, missing leads: vanished source is the more urgent fact, and it is what the row's glyph is about.