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
deferred-needs-input: the two open questions at the bottom block UI placement and
persistence design — not 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; cf. #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.
Feature spanning kernel + wire + server + CLI + MCP + UI. cf. #417, #418.
deferred-needs-input: the two open questions at the bottom block UI placement andpersistence design — not 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; cf. #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; connection→adapter resolution lives inthe composition root, outside the kernel. The kernel knows the configuration and the
protocol, never torch/transformers.
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-litigates app: routes and composition — deliberately thin; all domain logic lives in ui-core (the enterprise rule) #58 ("Home,Projects, avatar — nothing else" on the rail). Options to prepare, not pick:
(a) new rail entry
Inference; (b) another placement that keeps app: routes and composition — deliberately thin; all domain logic lives in ui-core (the enterprise rule) #58 intact.Whichever is chosen must be recorded as a superseding decision on app: routes and composition — deliberately thin; all domain logic lives in ui-core (the enterprise rule) #58's rule, 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