Two state axes, the combinations a researcher can reach, what each one renders,
and — from §6 — what was decided about them. Every claim about current
behaviour was read out of the code at HEAD on 3 Sep 2026 and carries a
file:line; the decisions carry no receipt because nothing is built
yet. §7 is what building them costs, and §8 is what is still open.
Four are configuration and never stale; one is a cached verdict about someone else’s server. The transient conditions at the bottom are not states — nothing persists them, and the SDK rides most of them out before anyone sees one.
| State | Established by | Surfaced as | Note |
|---|---|---|---|
| Ready | Key present for the current providerroutes/autocode.py:146 _has_api_key | — (nothing to say) | The overwhelmingly common case. |
| No key | No key for the resolved provider | Refusal toastrefusal.py NO_API_KEY → autocodeRefusal.ts | Pre-flight, so it costs nothing to discover.wired |
| Ambiguous | 2+ keys, none chosenconfig.py:305 provider_resolution_for | Refusal toast | A server cannot prompt, so it refuses rather than picking a vendor. |
| Local only | llm_provider == "local" |
Refusal toast | Ollama cannot hold the taxonomy in context. |
| Out of credit | Sticky verdict from a real callLLMValidator / OutOfCreditModel | Titlebar pill + popoverout-of-credit-ux.html §2 | Only isolable on Anthropic + OpenAI. Azure has no per-account credit; Gemini folds it into one exhausted signal. |
| rate-limited server error network |
Transient; SDK retries 6× honouring Retry-Afterllm/client.py:155 _CLOUD_MAX_RETRIES |
Only as a job failure, if retries are exhausted | Not states. Nothing persists them, and there is deliberately no hand-rolled backoff — the SDK’s is better and sees the header. |
Decided: a codebook is installed or not installed, and that is very nearly all of it. A run is a per-project activity, not a property of the codebook — so it belongs where per-project activity already lives, and the codebook card carries at most an acknowledgement that the click landed.
The codebase already states this rule, in the copying case of
ProjectSubtitle: the toolbar copy pill was removed because
“copy is a per-project op, so it lives on the row; the title-bar pill is
reserved for app-global ops… Mac direct manipulation: feedback appears on
the row you dropped onto.” AutoCode is the same shape. Out-of-credit, being
genuinely app-global, is the pill’s business and nobody else’s.
| Sub-axis | Values | Where it belongs |
|---|---|---|
| Installed | no / yes | the card — Install vs UninstallCodebookV2.tsx:266 |
| Enabled | on / off | the card — switch + pageoff washCodebookV2Sidebar.tsx:127 |
| Undecided proposals | 0 / n | the card — “· n undecided” + Review doorCodebookV2Page.tsx:195 |
| Run in flight | pending · running |
Project row + the chip. The card echoes it as
✦ Autocoding… and no more — the acknowledgement that
the click landed, on the thing that was clicked. |
| Run outcome | failed · cancelled |
The project status popover — its stated job is “telling an alpha tester what failed”. |
| Coverage shortfall | completed, processed < total |
Project row + its diagnostic popover. Not the card, not the details page. An incomplete run is an event that belongs to the project, and the popover already exists to help diagnose one. |
All the way. A run in flight has the project row and the chip, and the card echoes only that it started. A run that failed has the toast, then the project row’s failure glyph, then the diagnostic popover — three surfaces that already exist for exactly this, none of them the codebook’s. The card’s job is to say which codebooks are installed and help the researcher decide which are interesting, and it already carries enough to do that: tag count, reach, tentative count, and the two-tone bars on the details page.
One click, four terminal states. The LLM condition decides which. Red outlines are dead ends — states with no path back out.
Settled: the card does not report run outcomes. Its job is to say which codebooks are installed and help the researcher decide which are interesting, and it already carries enough for that. An incomplete or failed run is an event belonging to the project — sidebar status line, failure glyph, diagnostic popover — all of which exist.
| State | Card | Run outcome lives |
|---|---|---|
| Not installed | 28 tags · not installed | — |
| Running | 28 tags · ✦ Autocoding… — that the click landed, no more.
Progress, elapsed and Cancel stay on the chip. |
project row + chip |
| Coded | 28 tags · applied to 30 quotes in Ikea · 14 tentative
tentative also renders as the pale segment of the
two-tone MicroBar on the details page, with "N tentative + M accepted"
on hover |
— |
| Partial | unchanged from Coded — the shortfall is not the codebook’s business | project row + popover |
| Failed / refused | unchanged — 28 tags |
toast, then project row + popover |
“tentative”, not “undecided” — the word the
threshold histogram already uses for its middle band
(autocode.review.zoneTentative), and the name of the column behind
it. The card was the only place in the product calling it something else, and the
literal was hardcoded English in all 21 locales.fixed
Which existing mockups are trued to the code, and what they cover. The pattern is stark: every mockup covers the happy path or the global condition; none covers a codebook whose coding did not happen.
| Mockup | Last edit | Trued? | Covers |
|---|---|---|---|
out-of-credit-ux.html | 14 Jul | yes | Axis A only. §2 the pill + popover (matches OutOfCreditPill.swift
exactly). §3 already settled that reaching for AutoCode while out of credit
gets “nothing new — the pill is enough”, which is the decision
this whole thread re-derived.authority |
codebook-v2-autocode-button.html | 31 Aug | yes | Install → Uninstall → Review arc. Happy path only — no failure state appears anywhere in it. |
codebook-library-states.html | 1 Aug | yes | enabled / disabled only. |
provider-status-glyph-vocabulary.html | 7 Jun | superseded | Explored three treatments for the provider dot; a fourth shipped —
colour plus an always-visible localised label. Six ProviderStatus
cases ship, this names five. The a11y reasoning
stands.banded |
mockup-autocode-lifecycle.html | 19 Feb | stale | Not a state map at all — my earlier reading of it here was wrong. It is a nine-step storyboard of the v1 flow (“Codebook tab — before import”, then “after import, AutoCode available”), where importing a codebook and coding with it were separate acts. 0.29.0 made Install be apply. Banded SUPERSEDED.banded |
codebook-v2-messages.html | 30 Aug | implemented | Its message taxonomy is the live one, and its “what this needs that
does not exist” section drove ae050e56. Read that as a
diagnosis of a fixed problem; the CodebookPanel reference
describes the v1 lens it was written to
replace.banded |
✦ Autocoding… and no more —
direct manipulation, feedback on the thing that was clicked. Progress, elapsed
and Cancel stay on the chip. Existing vocabulary
(autocode.chip.coding).tentative_count column. Previously “undecided”, and
hardcoded English in all 21 locales.shippeddesign-pipeline-diagnostic-popover.md records that
.help(...) tooltips were dropped from this surface family.Smaller than it looked, because §6.2 removes the coverage rendering that was driving most of it. The card needs a boolean — is a job running for this framework — not the job’s numbers.
getAutoCodeStatus
has zero call sites in the island, its navigator or its page, so
✦ Autocoding… has nothing to render from.case coding. 23
ProjectSubtitle cases — running, queued,
copying, importingBatch,
completedPartial — and not one about coding. “The project row
shows the run” is the right model and not yet the behaviour, and it is
where §6.2 sends everything.PipelineState from the pipeline events log — stages, per-session
causes, a terminus — and an AutoCode job has none of those. Routing its failures
there means giving it a cause in that vocabulary, not giving the popover a
second data path.409 already_applied on a completed job, and
reapply_to_new_quotes only codes sessions imported after the
watermark. Measured cost of simply re-running: £0.042 per batch (median
7,701 in / 1,999 out over 51 real batches), so £0.17 for a 78-quote project —
cheap enough that relaxing the guard beats building resume machinery. Note
partial has never occurred in 25 logged runs; all 5 failures were
total.