bristlenose/ui_kinds.py, the shipped .autocode-toast, and the
existing sidebar status line and popover.ui_kinds.py says so in its own docstring,
and the toast already renders it with a spinner and a progress track rather than a glyph.L4 is a state the code already produces and nothing reports. autocode.py:425 logs
"Batch failed: %s" and carries on, so a job can complete having tagged a subset. Today that
finishes as an unqualified success and the researcher is told a number that is quietly short. It is the
clearest case in this table for WARNING: complete, usable, and not what was asked for.
L3 is not a failure and must not look like one. A codebook that finds nothing has run correctly and
disagreed with the corpus — which is a finding about the corpus. INFO.
LLMFailureKind in
bristlenose/llm/failure_classifier.py already distinguishes all seven, and
CauseCategoryEnum already has a case for each. No new category is proposed here.F1 against F2 is the one that has bitten before. The popover doc records a bankrupt account being
told to wait, because out-of-credit was rendered as rate-limited. Anthropic returns 400 for
exhausted billing rather than 402, which is exactly why the classifier exists. These two must
never share a string.
The kinds split on whether waiting fixes it. F2, F4 and F6 are WARNING — transient,
retry is the remedy. F1, F3, F5 and F7 are ERROR — terminal until the researcher changes
something. That is the whole rule, and it is why F2 is not an error despite stopping the run.
Today none of this survives the trip. autocode.py:458 catches bare
Exception and stores str(exc), so the job's error_message is raw
exception text — unclassified, unbounded, and occasionally a stack-adjacent string. The classifier is
imported nowhere in the autocode path. Wiring it is the prerequisite for every row in this table.
0. The palette can colour one of the five kinds. Measured across
bristlenose/theme and frontend/src: --bn-colour-success,
--bn-colour-danger and --bn-colour-warning are used sixteen times and
defined nowhere. Eleven uses carry a hard-coded fallback and work; five do not, and two of
those five are the surfaces on this page — .toast-check and .toast-error
(autocode-toast.css:32,37), plus both activity-chip states and the autocode report. An
undefined custom property makes color invalid at computed-value time, so it inherits: the
tick and the cross on the shipped autocode toast have no colour at all.
--bn-colour-danger is simply a misspelling of --bn-colour-negative, which
does exist — light-dark(#dc2626, #ef4444). Worse, the eleven fallbacks pin its
light-mode hex, so every one of them is wrong in dark mode. --bn-colour-success and
--bn-colour-warning have no counterpart token at all, and the loose greens disagree with each
other (#22c55e against #16a34a). A five-kind taxonomy needs three semantic colours
and the palette defines one.
1. The SPA toast has two kinds, not five. autocode-toast.css ships
.toast-check and .toast-error. Warning, info and skipped have no treatment, and
toast() itself takes (message, duration) with no kind at all. Completing that is
finishing an existing pattern with the existing vocabulary — not new UX.
2. The autocode path never classifies. Bare except Exception → str(exc).
classify_exception() already exists and is not called.
3. Nothing under bristlenose/server/ writes to the events log (Q17), which is what feeds
the Mac glyph and popover. Every macOS rendering above is therefore a drawing of a surface that exists, fed
by a channel that does not.
4. Pre-flight configuration refusals want a durable home, not a four-second toast. Named, not solved.
Nothing here reaches the Mac today, and three of them never can as written. A pre-flight refusal creates no
AutoCodeJob, so there is no job for a status line to describe. P5 and P6 are fine — they are answers to a click and the toast is the whole message. But P1, P2, P3 and P7 are configuration problems that outlive the click, and a toast that vanishes in four seconds is the wrong home for a state that will still be true tomorrow. Those belong in the same place a missing API key already belongs, not invented here.The HTTP details are developer copy and must not be shown. Today
CodebookPanelrenderserr.detailstraight into the toast. Those strings name framework ids in quotes and, in one case, tell the researcher to runbristlenose use <provider>— a shell command, inside a Mac app. Every sentence above replaces one of them.