feat(dashboard): say what a Codex install still cannot do - #8684
Conversation
Two changes to the Agent Backend switch, both about what the row tells an operator who is choosing between harnesses. ## Being installed is not being signed in `_probe_codex` covers the binary question completely — the adapter ships its own Codex binary, so `installed` really is the whole install fact — and a session can still die on its first turn for want of a credential, with nothing on the page having said which. The remedy also has two branches, so a failure message alone would not have told the operator which one they wanted: finish Codex's own sign-in, or name a `model_provider` in `~/.codex/config.toml` when the credentials come from somewhere else entirely. Stated as a standing caveat, next to Claude's, and deliberately NOT probed. Reading those files would make it a measurement, and a measurement here gates the control: `missing` disables the chip, and the checkable paths are not the only ones that authenticate a Codex — an ambient key, a relocated `CODEX_HOME`, a `CODEX_ACP_BIN` adapter carrying its own configuration. Each of those is an operator whose switch we would have disabled while they were already signed in, which `backend_install` itself names as the more expensive mistake. A sentence that claims no measurement cannot be wrong in that direction, and it says so out loud rather than letting silence read as a green light. `CODEX` is named for the caveat alone and stays out of `NAMED`: this frontend has no translated label for it, so the chip keeps the server's `policy_id` rather than rendering empty. ## KAS sits beside Kiro CLI, not behind the adapters KAS is not an adapter: it is kiro-cli's own ACP relay, resolved from the same binary and sharing kiro's install verdict (`_probe_kas` delegates to `_probe_kiro`). Sorted by `policy_id` alone it fell on 'k', which put the two harnesses that are really one install either side of every adapter whose id happens to start earlier — `claude`, `codex` — and reads to the operator as a rank rather than an alphabet. The comparator now pins it second, ahead of the byte order that still owns the tail. ## Tests Four cases pin the disclosure and the order: both remedy branches, the disclaimer, its absence on the harnesses that authenticate through Crew's own identity store, and the chip sequence (revert-verified — dropping the KAS pin fails it). The onboarding spec's Codex table records why stage 5 stops at the binary, and the panel's capture harness gains the two Codex scenes, which also re-shoots its four existing frames because the order moved KAS in every one.
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: |
Design Review (Fable 5) — ✅ PASSDesign-level review of Design-Verdict: PASS A real first-turn failure gets named in the panel; the deliberate non-probe (caveat over measurement) is the right trade and is documented where the next reader looks. [DESIGN-REVIEWED] 0b2ae35 |
UX Review (Fable 5) — 🟡 CONCERNSUX-level review of UX-Verdict: CONCERNS The panel discloses Codex honestly, but refuses to name it: a lowercase wire id Watch
Suggestions
[UX-REVIEWED] 0b2ae35 |
First Principles Review (Fable 5) — 🟡 CONCERNSPremise-level review of All evidence checked: codex is genuinely in First-Principles-Verdict: CONCERNS The Codex caveat is derived and earns its place; the KAS reorder is a declared-unrelated move justified only by grouping logic, with no named operator who misread the old order. What this change shipsIntent: tell an operator who installed Codex that a session can still die unsigned-in, and which of two remedies applies. ADDITION.
Watch
Subtractions
[FIRST-PRINCIPLES-REVIEWED] 0b2ae35 |
Opus 4.8 Review — ✅ no blocking findingsReviewed Review detailsEverything verifies: the en.manual key resolves to No findings. [OPUS-REVIEWED] 0b2ae35 Verdict parsed from the review's SHA-scoped output markers for commit False positive or not applicable? A repository writer can comment: |
|
Dispositions for the UX Review CONCERNS on
|
|
Dispositions for the First Principles CONCERNS on
|
Problem / Motivation
Developer > Agent Backend tells an operator whether a harness is installed, and for Codex that verdict answers less than it looks like it does.
codex-acpships its own Codex binary, soinstalledreally is the whole install fact — and a session can still die on its first turn for want of a credential, with nothing on the page having said which. The remedy has two branches (Codex's own sign-in, or amodel_providerin~/.codex/config.tomlwhen the credentials come from somewhere else entirely), so even a failure message would not have told the operator which one they wanted.Second, unrelated to Codex but on the same row: KAS sorted under
kbypolicy_id, which put it behind every adapter whose id happens to start earlier —claude,codex.Why it matters
Codex ships selectable (it is in
BASELINE_SELECTABLE_BACKENDS), so this is a live path, not a dormant seam: an operator picks Codex, the chip says installed, the session dies, and the panel never named what was missing. That is the same failure the install probe was added to close, one layer up.The order matters because KAS is not an adapter — it is kiro-cli's own ACP relay, resolved from the same binary and sharing kiro's install verdict (
_probe_kasdelegates to_probe_kiro). Splitting the two harnesses that are really one install, with third-party adapters between them, reads to the operator as a rank rather than an alphabet.What changed (motivation → approach → change)
The credential line is a standing caveat, deliberately NOT a probe line. Reading
~/.codex/auth.jsonorconfig.tomlwould make it a measurement, and a measurement in this panel gates the control:missingdisables the chip. The checkable paths are not the only ones that authenticate a Codex — an ambient key, a relocatedCODEX_HOME, aCODEX_ACP_BINadapter carrying its own configuration — and each of those is an operator whose switch would have been disabled while they were already signed in.agent_sdk/backend_install.pynames that direction as the more expensive mistake, so the line claims no measurement and says so out loud (Neither is checked here — the adapter reads them, not KiroCrew) rather than letting silence read as a green light. It renders through the existingcaveatseam, beside Claude's, so nothing about the probe payload or the wire contract changes.CODEXis named for the caveat alone and stays out ofNAMED: this frontend has no translated label for it, so the chip keeps the server'spolicy_idrather than rendering an empty chip.The order is a comparator pin, not a new list.
KIROfirst (default and floor), thenKAS, then the existing byte order overpolicy_idfor the tail — the byte order is kept for the reason it was chosen, that it reproduces the order the probe endpoint already returns and cannot reshuffle per reader locale.The English string lives in
en.manual.json, noten.json:website/docs/i18n-catalog.mdmakesen.jsonthe codemod's wholesale output, and hand-authored English with no source literal belongs in the manual catalog the codemod never touches. All 11 target catalogs carry the key anden-XA.jsonis regenerated.Tests
website/src/test/AgentBackendTab.test.tsx, four cases:~/.codex/config.tomlrender on the Codex row.Neither is checked here, which is what stops silence reading as a verified green light.Kiro CLI, KAS (kiro-agent), Claude Code, codex. Revert-verified: deleting the two-line KAS pin fails this case and only this case.Manual verification
website/scripts/capture-agent-backend-probe.mjsgains the two Codex scenes and renders the real built SPA behind fixture API payloads; each shot waits for the literal caveat text (and forcodex-acpin the missing scene) before firing, so a frame cannot be taken pre-hydration. Its four existing frames are re-shot because the order change moves KAS in every one of them.Local gate sweep on this head: all 47 profile gates run, 45 green. Two reds are inherited and reproduce on a pristine base — the backend suite (this diff contains zero Python files; the failures are this host's
/local/homesymlink spelling,AF_UNIX path too longon a long worktree path, and ownership 403s) andscrub-lint(/home/téstintest/test_atomic_write_named_duplicates.py, present verbatim atorigin/main).Screenshots / video
Codex installed — the install verdict is positive and the caveat is what the row adds:
Adapter missing — the two lines together, and only the first one disables the chip:
The four pre-existing scenes, re-shot for the new order
Related Issues
no linked issue: this closes a gap the Codex onboarding table already named as open, rather than a filed report.
docs/system-specs/modules/harness-onboarding.md's Codex table records why stage 5 stops at the binary, so the next reader of that table finds the decision rather than re-deriving it.Checklist
feat|fix|docs|refactor|perf|test|chore|ci|build|revert: ...)