Coder presents model tiers, never vendor model names #40

Closed AtlantisPleb opened this 5d ago 2 comments

Encode the product invariant: the coder never shows a vendor model name to the user. The only names a reader sees are OpenAgents Coder tiers:

  • Coder Auto — the session's default: the server's default lane answers
  • Coder Flash — the fast tier
  • Coder Pro — the strong tier
  • Coder Local — a local model server answers; nothing leaves the machine

Scope:

  1. The status line at the bottom of openagents coder names the tier, never the model id or a vendor label. A fresh session shows Coder Auto.
  2. Shift+Tab cycles the tier: Auto → Flash → Pro → Local → Auto. Reasoning cycling moves to Tab.
  3. Every other coder surface that named a model follows: fleet rows, resume picker, model-switch notices.
  4. The tier map lives in one module, and the invariant is recorded in INVARIANTS.md with the test that holds it.

Acceptance: coder --dev starts a session whose bottom bar says Coder Auto; Shift+Tab flips through Flash, Pro, and Local; no vendor model name renders anywhere in the interface.

  1. AtlantisPleb opened this issue 5d ago
  2. AtlantisPleb closed this as completed in fb705a5 5d ago
  3. A AtlantisPleb Author 5d ago

    Shipped in fb705a506a: tier labels everywhere (status line, fleet, resume picker, notices, help), Coder Auto as the unpinned default with the proxy naming no model, shift+tab cycling Auto/Flash/Pro/Local with lazy source builds carrying the conversation, tab now cycling reasoning. INVARIANTS.md 'Coder Model Naming' records it; test/coder-tiers.test.ts holds it. 917/917 tests.

  4. A AtlantisPleb Author 5d ago

    Follow-up landed in 4773472fe2: the tier a reader reaches with shift+tab is now checked against what the deployment says it can answer.

    The gap this closes is one the rename itself opened. chooseBackend already read availability from /api/v1/models for the model a session opens with, but buildTier pinned TIER_MODELS[tier] and opened a thread on it regardless — so the tier switch was the one path that never asked. Before #40 a reader who landed on a dead lane at least saw gemini-3.7-flash and could search for it; after #40 they saw Coder Flash fail and were told nothing. The friendlier name made the dead lane a better hiding place.

    tierUnavailable in coder-tiers.ts reads the same catalog and the same available field, and applyPendingTier already did the right thing with a failed build, so a refused tier keeps the session on the tier that was answering and names the ones that can answer. An unreadable catalog allows the tier — "could not ask" is not "serves nothing" — and Coder Local is never refused here, since it answers from the reader's machine rather than the deployment.

    Two things held deliberately:

    • The refusal names tiers only. The invariant does not lapse when the news is bad, and a test asserts no vendor id reaches the message.
    • Availability is the only claim. A test also asserts the refusal quotes no price, because the catalog declares a rate for some lanes and none for others — today gpt-5.6-luna behind Coder Pro has no pricing block at all — and a tier implying a cost the server never quoted would be a worse lie than the vendor name it replaced.

    Eight tests in test/coder-tiers.test.ts, including a session-level one proving the session stays on the answering tier. Neutering the gate fails five of them. INVARIANTS.md "Coder Model Naming" records both rules.

Sign in with GitHub to comment on this issue.