Skip to content

UX: Retry grouping — separate startup errors from real turns #44

@lis186

Description

@lis186

Problem

Codex sessions mix startup 502 errors (DNS retry, 0.1s, no usage) with real API turns (85-249s, has usage/cost) in the same turn list. Users see 4/6 turns with red !http badges and think the session is broken.

Expert consensus (Tufte/Norman/Charity Majors roundtable):

  • Tufte: proportional ink violation — 0.1s noise = same area as 249s real turn
  • Norman: conceptual model mismatch — user's "turn" ≠ system's "turn"
  • Charity: alert fatigue — trains users to ignore red badges

Design

  1. Turn list: only show entries with usage. Retries stay in allEntries for drill-down.
  2. Session card: gpt-5.5 · 2t (4 retries).
  3. Drill-down: preserves full retry list.

Detection: isRetry = !isHttpStatusOk(status) && !usage

~1.5h. Main risk: addEntry is the central function.

Before / After UI

BEFORE                                     AFTER
┌─────────────────────────┐                ┌─────────────────────────┐
│ Session: sess_abc123    │                │ Session: sess_abc123    │
│ ? · 6t                  │                │ gpt-5.5 · 2t (4 retries)│
└─────────────────────────┘                └─────────────────────────┘

Turn list:                                 Turn list:
┌───┬────────┬──────┬─────┐                ┌───┬────────┬──────┬─────┐
│ # │ Status │ Time │ Cost│                │ # │ Status │ Time │ Cost│
├───┼────────┼──────┼─────┤                ├───┼────────┼──────┼─────┤
│ 1 │ !http  │ 0.1s │  -  │                │ 1 │  200   │  85s │$0.42│
│ 2 │ !http  │ 0.1s │  -  │                │ 2 │  200   │ 249s │$1.87│
│ 3 │ !http  │ 0.1s │  -  │                └───┴────────┴──────┴─────┘
│ 4 │  200   │  85s │$0.42│
│ 5 │ !http  │ 0.1s │  -  │                (4 retries accessible via
│ 6 │  200   │ 249s │$1.87│                 session drill-down)
└───┴────────┴──────┴─────┘

Architecture

addEntry(entry)
│
├─ isRetry? ─── !isHttpStatusOk(status) && !usage
│
├─ YES (retry)
│   ├─ sess.retryCount++
│   ├─ push to sess.allEntries     (preserved for drill-down)
│   └─ SKIP DOM card               (no turn card rendered)
│
└─ NO (real turn)
    ├─ sess.turnCount++
    ├─ push to sess.allEntries
    ├─ render DOM turn card         (normal turn numbering)
    └─ compute gap timing           (from prev real turn or session start)

Value

For users

  • No more false "66% failure rate" impression
  • Turn count reflects actual API conversations
  • Session health assessment is accurate at a glance

For developers

  • isRetry heuristic is simple: !isHttpStatusOk(status) && !usage
  • Adding new retry patterns = adjusting the heuristic, no UI changes needed
  • allEntries still has full data for debugging

Side Effects

Test Plan

  • Unit: isRetry heuristic with various status/usage combinations
  • Smoke: mixed session with retries + real turns → verify turn count, card rendering, drill-down access
  • Regression: Claude sessions (no retries) must be completely unaffected

Metadata

Metadata

Assignees

No one assigned

    Labels

    codex-parityCodex dashboard parity gapsuxUX/UI improvements

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions