Skip to content

fix: give "what can this connection run" one authority - #3330

Open
Astro-Han wants to merge 4 commits into
mainfrom
fix/1584-model-selection-authority
Open

fix: give "what can this connection run" one authority#3330
Astro-Han wants to merge 4 commits into
mainfrom
fix/1584-model-selection-authority

Conversation

@Astro-Han

@Astro-Han Astro-Han commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Summary

A Volcengine Ark Agent Plan key cannot select the models its own plan serves (#1584). The cause is not in that provider: nine places across core, storage, runtime and Runtime Host each decided "what models can this connection run" on their own, and every one read modelSource === 'fetched' as "a provider enumerated this account".

It does not mean that. modelSource records write provenance. A provider whose modelDiscovery.kind is 'fallback' still runs discovery — it just replays the array this build shipped — and the row honestly says 'fetched'. Ark has no model-list endpoint at all, so every gate read a release snapshot as an allowlist.

This PR gives the question one authority and converts all nine callers to it. classifyConnectionModelInventory returns what the catalog IS: live (a provider enumerated this account — an allowlist, even when empty), snapshot (the array this build shipped — describes the provider, not the account), absent (no catalog, none asked for). authorizeConnectionModel builds the verdict on top: enabledModelIds is the authorization, and only live overrules it.

The other half is that nothing could put a model into such a connection. An add-model dialog writes the id into enabledModelIds and a context window into relayModelProfiles in one write, which required splitting the relayModelProfiles gate from whole-table-by-provider to per-field — contextWindow/vision are facts about a model, thinkingLevels/serviceTier shape an OpenAI-compatible request body and stay relay-only.

Two live defects fell out of the same audit: the connection test probed a snapshot model instead of the one the user chose, and onboarding carried a stale relayModelProfiles across a narrowed selection, writing a catalog the decoder rejects on next read (separate commit, e86603052).

Fixes #1584

image image

Verification

@maka/core 571, @maka/storage 842, @maka/runtime-host 1031, @maka/desktop 978, maka-agent 336, Storybook smoke 144 stories, format:check and typecheck clean. @maka/runtime 2968 pass / 1 fail — does not carry queued Unix PTY writes past native exit, which spawns an independent node-pty child, imports nothing this PR touches, fails the same way on main here, and is green in CI.

Every new test was checked by mutation: reverting the production change makes it fail. The end-to-end one drives a real volcengine-agent-plan connection through testConnection and asserts the wire body names the user's model.

Fixtures across the suites were corrected to the state the write path actually produces — a snapshot provider's row says modelSource: 'fetched'. Several existing tests asserted 'fallback' there, which is why none of them caught this.

Known gap

The CLI onboarding wizard still offers only what discovery returned, so the fix is reachable from desktop connection settings only. A CLI entry point for declaring a model is not in this PR.

AI use

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Claude Code (Opus 5) wrote the implementation, tests and this description under my direction, and ran the suites above. An earlier revision of this branch fixed the write path instead and introduced a P0 of its own; adversarial review caught it and the work was redone against the authority described here. I reviewed the final diff and commit messages and own the result.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@Astro-Han
Astro-Han force-pushed the fix/1584-model-selection-authority branch from 770e89f to 7f41aaf Compare August 20, 2026 14:21
@Astro-Han Astro-Han changed the title feat(desktop): add manual model entry for static-catalog providers fix: stop a bundled snapshot from overruling a user's model choice Aug 20, 2026
@Astro-Han
Astro-Han force-pushed the fix/1584-model-selection-authority branch from f795551 to ea45a70 Compare August 20, 2026 16:07
@Astro-Han Astro-Han changed the title fix: stop a bundled snapshot from overruling a user's model choice fix: let a connection's own catalog decide what models it can run Aug 20, 2026
…n run" one authority

Nine places answered that question with their own criteria and no shared
source, so a Volcengine Ark Agent Plan key could not select the models its
own plan serves (#1584). Every one of them read `modelSource === 'fetched'`
as "a provider enumerated this account". It does not: `modelSource` records
write provenance. A provider whose `modelDiscovery.kind` is `'fallback'`
still runs discovery — it just replays the array this build shipped — and
the row honestly says `'fetched'`. Ark has no model-list endpoint at all, so
every gate treated a release snapshot as an allowlist and refused the models
the plan demonstrably serves.

`classifyConnectionModelInventory` is now the one place that conjunction
lives, and it returns what the catalog IS rather than where it came from:

  - `live` — a provider with a model-list endpoint enumerated this account.
    Evidence, and an allowlist. An empty one is still evidence.
  - `snapshot` — the array this build shipped. It describes the provider at
    release, not the account, so it cannot rule on what a plan serves.
  - `absent` — no catalog, and none asked for. `modelSource` is what tells
    this apart from an empty live list; the codec keeps it present exactly
    when a run has written the row.

`authorizeConnectionModel` builds the verdict on top: the user's
`enabledModelIds` is the authorization, and only a `live` catalog overrules
it. It returns the inventory alongside, because callers legitimately differ
on `absent` — sending a message needs something to send against, while
resolving an id for execution does not (#2896). Each states that policy for
itself; none restate the rest.

Converted, and their old criteria deleted rather than left beside it:
readiness, Runtime Host execution and Session admission, the hosted
execution target, catalog projection, the connection test probe, and the
storage test-model gate. `connection-model-admission.ts` was a thin shell
over the same question and is gone; its two callers ask the authority.

Two onboarding guards required `source === 'fetched'`. The only writer of
that field always writes `'fetched'`, so the clause never fired — it was an
assertion that provenance is a quality bar, next to the check that actually
matters. Removed; the non-empty requirement stands.

Catalog projection also stopped hiding a snapshot provider's `models` from
itself, which had been discarding the capabilities in those rows: an
image-only model read as selectable. Capabilities are facts wherever they
came from; only inventory claims lose authority when the list is a snapshot.
Staleness now follows the same rule — a snapshot is as current as the build,
so it cannot expire.

Generated-by: Claude Code
… keys

`relayModelProfiles` is scoped to `enabledModelIds` — the canonical decoder
rejects a table keyed by a model the selection dropped. `prepareOnboardingUpsert`
replaced `enabledModelIds` while spreading the previous entry, so a re-onboard
that narrowed the selection carried the old table across intact. The write
succeeded; the next read of the catalog failed, because this path bypasses the
decoder that would have caught it. The refresh path a few lines above prunes for
exactly this reason and says so.

Generated-by: Claude Code
…not learn

The authority now lets an enabled model through on a provider whose catalog
is a shipped snapshot, but nothing could put one there. A provider with no
model-list endpoint never grows its list, so a model the user's Ark plan
already serves had no way into the connection at all (#1584).

An add-model dialog writes the id into `enabledModelIds` — the same user
authority a catalogued model uses, so nothing pretends the provider
advertised it — and a context window into `relayModelProfiles`, in one write,
because the store requires every declaration to key an enabled model. The
window is required rather than defaulted: an unknown one silently falls back
to a flat 32k history budget, three percent of a 1M-token window, and a
silent downgrade is worse than a request the provider rejects outright.
Whoever types an exact model id is reading the provider's own model page,
where the number is stated.

`relayModelProfiles` was gated whole, by provider, which is why only relays
could carry any declaration. The gate is now per field, because the fields
differ in kind: `contextWindow` and `vision` state facts about a model and
are legal anywhere, while `thinkingLevels` and `serviceTier` shape an
OpenAI-compatible request body and stay relay-only. The codec enforces that
split, so a declaration that cannot be honoured is rejected at the boundary
rather than silently ignored downstream.

The capability section shows a row for exactly the models Maka cannot
describe — every model added here, the moment it is added — and hides the
thinking-level control where it cannot apply.

Two details the section got wrong on the way: adding a model now merges the
declaration into the open editor draft, which does not reseed from props
while dirty and would otherwise have dropped the window on the next save;
and the dialog's submit is disabled while another write is in flight, where
the store would have discarded the submission and the typed id with it.

Generated-by: Claude Code
@Astro-Han
Astro-Han force-pushed the fix/1584-model-selection-authority branch from ea45a70 to a9eb6c8 Compare August 20, 2026 17:26
@Astro-Han Astro-Han changed the title fix: let a connection's own catalog decide what models it can run fix: give "what can this connection run" one authority Aug 20, 2026
@Astro-Han
Astro-Han marked this pull request as ready for review August 20, 2026 19:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(providers): stop static snapshots from constraining model discovery

1 participant