You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This feature spans the kernel, the wire, the server, the CLI, MCP and the UI. It sits between
the ModelProvider port that declares how a model is asked for a prediction (#418) and the work
that surfaces model provenance and confidence in the review loop (#417).
It carries deferred-needs-input because the two open questions at the bottom block UI placement
and persistence design. They do not block the kernel work.
Summary
VisionSet never bundles or auto-downloads inference models. Auto-labeling operates
against model connections the user creates: a new top-level configuration surface
where connections to local or remote models are created, set up, tested, and managed.
The auto-labeling feature itself is always present (not an optional extra); only the
local runtime ships as visionset[local-inference].
Ratified direction (Armando, 2026-08-07), recorded in full on the port issue (#418):
ModelProvider adapters are instantiated from user-created connections, never from a
bundled default.
VisionSet never downloads weights at install time; download is an explicit user
action during local-connection setup, with the size shown beforehand.
Nothing may preclude cloud execution later — a hosted adapter is just another
connection type against the same port.
The user journey (design target)
Empty state. Centered card: "Connect a model to enable auto-labeling", primary CTA Add connection. Meta line stating the policy as a value proposition: "VisionSet
never downloads models on its own — you choose what runs and where."
List. Compact rows (density principle): connection name · type chip (Local / HTTP) · model identity (grounding-dino-base @ <revision>) · status (Ready / Not set up / Unreachable), semantic token + text, never color alone. Per-row
overflow: edit, test, delete.
Create — two steps. Step 1: pick type. Step 2 by type:
Local: HF model id + revision (suggested default; download size shown before
confirming), device, precision. If local-inference is not installed, the form stays
usable and shows the exact command (pip install "visionset[local-inference]") —
never a bare disabled control (design principle 9). Creating the connection downloads
nothing; the row lands at Not set up with a Download weights action.
HTTP: endpoint URL, optional credential, and a Test button that makes a real
call and reports what answered. The endpoint contract is defined by this project —
the same contract a future hosted adapter implements, and anyone may implement it.
Third-party inference protocols are not adopted as the contract.
Download weights runs as a background job on the existing infrastructure (SQLite
queue in visionset.db, workers in the FastAPI lifespan, /background-jobs routes,
observable progress).
Delete states its blast radius accurately: annotation provenance stores model
identity denormalized (id + revision copied at write time, no FK to the
connection), so deleting a connection never breaks provenance. Dialog copy: "Annotations
keep their model provenance; only this configuration is removed."
Scope by layer
Kernel (visionset.kernel) — one home, one spelling:
New aggregate InferenceConnection: id, name, type (local | http), model
reference (id + revision), per-type parameters, setup state.
New workspace-scoped table (like background_job: no project_id), narrow port
methods only.
Wire + server:
ConnectionOut with allowed_actions derived from the same transition tables the
service enforces (standing contract): download_weights only for local + not-set-up; test only for HTTP; delete always, with the blast-radius message.
Routes under /inference/connections. Weight download responds 202 pointing at its
background job. Regenerate and commit openapi.json.
CLI + MCP (SDK-first parity):
visionset inference list|create|test|download with --json.
Equivalent MCP tools — an agent must be able to make a workspace auto-label-ready
without a browser.
UI:
Screens in ui-core, navigation as callbacks, render allowed_actions only, existing
semantic status tokens — zero new colors.
Annotation-workspace suture: when auto-labeling is offered in the editor with no
connections configured, principle 10 forbids forcing navigation out of the editor or
losing work — same pattern as in-editor quick class creation, or minimally a
state-preserving link. Design explicitly, do not improvise at implementation time.
Open questions — Armando's, do not decide (deferred-needs-input)
Credential storage. HTTP-connection credentials would land in plain SQLite inside
the workspace. Local-first makes this defensible, but it ships only as an explicit
decision, never a silent default. Options to prepare: plain storage documented as
such; OS keyring integration; env-var indirection.
Non-goals
No model marketplace/registry — out of scope for this distribution.
This feature spans the kernel, the wire, the server, the CLI, MCP and the UI. It sits between
the
ModelProviderport that declares how a model is asked for a prediction (#418) and the workthat surfaces model provenance and confidence in the review loop (#417).
It carries
deferred-needs-inputbecause the two open questions at the bottom block UI placementand persistence design. They do not block the kernel work.
Summary
VisionSet never bundles or auto-downloads inference models. Auto-labeling operates
against model connections the user creates: a new top-level configuration surface
where connections to local or remote models are created, set up, tested, and managed.
The auto-labeling feature itself is always present (not an optional extra); only the
local runtime ships as
visionset[local-inference].Ratified direction (Armando, 2026-08-07), recorded in full on the port issue (#418):
ModelProvideradapters are instantiated from user-created connections, never from abundled default.
action during local-connection setup, with the size shown beforehand.
connection type against the same port.
The user journey (design target)
Empty state. Centered card: "Connect a model to enable auto-labeling", primary CTA
Add connection. Meta line stating the policy as a value proposition: "VisionSet
never downloads models on its own — you choose what runs and where."
List. Compact rows (density principle): connection name · type chip (
Local/HTTP) · model identity (grounding-dino-base @ <revision>) · status (Ready/Not set up/Unreachable), semantic token + text, never color alone. Per-rowoverflow: edit, test, delete.
Create — two steps. Step 1: pick type. Step 2 by type:
confirming), device, precision. If
local-inferenceis not installed, the form staysusable and shows the exact command (
pip install "visionset[local-inference]") —never a bare disabled control (design principle 9). Creating the connection downloads
nothing; the row lands at
Not set upwith a Download weights action.call and reports what answered. The endpoint contract is defined by this project —
the same contract a future hosted adapter implements, and anyone may implement it.
Third-party inference protocols are not adopted as the contract.
Download weights runs as a background job on the existing infrastructure (SQLite
queue in
visionset.db, workers in the FastAPI lifespan,/background-jobsroutes,observable progress).
Delete states its blast radius accurately: annotation provenance stores model
identity denormalized (id + revision copied at write time, no FK to the
connection), so deleting a connection never breaks provenance. Dialog copy: "Annotations
keep their model provenance; only this configuration is removed."
Scope by layer
Kernel (
visionset.kernel) — one home, one spelling:InferenceConnection: id, name, type (local|http), modelreference (id + revision), per-type parameters, setup state.
ModelProviderport (ModelProvider: declare the kernel port for autolabeling — local and cloud adapters both ordinary #418) is unchanged. Resolving a connection to an adapter happens inthe composition root, outside the kernel, so the kernel knows the configuration and the
protocol and never torch or transformers.
only determines who infers.
Persistence:
background_job: noproject_id), narrow portmethods only.
Wire + server:
ConnectionOutwithallowed_actionsderived from the same transition tables theservice enforces (standing contract):
download_weightsonly for local + not-set-up;testonly for HTTP;deletealways, with the blast-radius message./inference/connections. Weight download responds 202 pointing at itsbackground job. Regenerate and commit
openapi.json.CLI + MCP (SDK-first parity):
visionset inference list|create|test|downloadwith--json.without a browser.
UI:
ui-core, navigation as callbacks, renderallowed_actionsonly, existingsemantic status tokens — zero new colors.
connections configured, principle 10 forbids forcing navigation out of the editor or
losing work — same pattern as in-editor quick class creation, or minimally a
state-preserving link. Design explicitly, do not improvise at implementation time.
Open questions — Armando's, do not decide (
deferred-needs-input)Inferencesection re-opens the closed-rail rule setby the routes-and-composition work (app: routes and composition — deliberately thin; all domain logic lives in ui-core (the enterprise rule) #58), which fixed the rail at "Home, Projects, avatar —
nothing else". Two options are prepared rather than picked: (a) a new rail entry
Inference; (b) another placement that leaves the app: routes and composition — deliberately thin; all domain logic lives in ui-core (the enterprise rule) #58 rule intact. Whichever is chosen isrecorded as a superseding decision on that rule in the same turn it is confirmed.
the workspace. Local-first makes this defensible, but it ships only as an explicit
decision, never a silent default. Options to prepare: plain storage documented as
such; OS keyring integration; env-var indirection.
Non-goals