Goal
Make the kernel operable from the outside through its three sibling clients — REST API
(with token auth, public contract), CLI, and MCP — all thin wrappers over the SDK, none
importing another (enforced by import-linter).
Exit criterion
The full M1+M2 flow executed three ways: (a) curl with a bearer token, (b) the CLI,
(c) Claude Code over MCP stdio.
Workstreams
WS-1 Auth (tokens end to end)
WS-2 REST endpoints for the full cycle
WS-3 Contract quality: errors, OpenAPI drift gate, TS client generation
WS-4 CLI: visionset ui + flow commands
WS-5 MCP tools + real-agent validation
Constraints
Every capability lands in the API and is evaluated as an MCP tool in the same PR
(parity rule, vision doc principle 8) from this milestone on.
No logic in the server "because it was faster there": surfaces wrap existing, tested
services only.
Tracked issues
server: real AuthProvider — persisted per-workspace tokens, create/revoke, bearer auth across the whole API #25 (WS-1)
cli: visionset token create/list/revoke with persistence #26 (WS-1)
kernel: SQLite concurrency posture — WAL, busy_timeout, OperationalError → domain error (closes the "database is locked" gap before background ingest) #80 (WS-2 — lands before server: ingest endpoints (create source, launch ingest, progress) with long-running handling #28 : SQLite concurrency posture, added by the 2026-07-27 audit)
server: project and schema endpoints (CRUD + versioning) #27 (WS-2)
server: ingest endpoints (create source, launch ingest, progress) with long-running handling #28 (WS-2)
server: batch/job endpoints — approve, partition, "next N pending assets", annotation submission, progress (the third-party-app contract) #29 (WS-2)
server: dataset/release/export endpoints + blob and thumbnail download by hash #30 (WS-2)
server: uniform error handling — domain errors → HTTP with stable codes and detail (part of the contract) #31 (WS-3)
ci: openapi.json drift gate on regeneration + TS client regeneration in ui-core (real pnpm generate:client) #32 (WS-3)
cli: visionset ui — starts uvicorn serving the API + static assets from _static/ #33 (WS-4)
cli: flow commands — project create, ingest, batch approve, release publish, export (the full cycle without touching Python) #34 (WS-4)
cli: visionset init — create a workspace from the command line #104 (WS-4 — visionset init, filed by cli: visionset ui — starts uvicorn serving the API + static assets from _static/ #33 and absorbed by cli: flow commands — project create, ingest, batch approve, release publish, export (the full cycle without touching Python) #34 )
mcp: real tools over the SDK — management, schema, ingest, jobs, annotation, releases (the Part III §4 list), confirm:true on destructive ops #35 (WS-5)
mcp: validate the tool set against a real Claude Code workflow and adjust (open topic 7 from the vision doc) #36 (WS-5)
release: three-surface e2e + 0.0.1-alpha.3 close-out #37 (WS-5)
Goal
Make the kernel operable from the outside through its three sibling clients — REST API
(with token auth, public contract), CLI, and MCP — all thin wrappers over the SDK, none
importing another (enforced by import-linter).
Exit criterion
The full M1+M2 flow executed three ways: (a)
curlwith a bearer token, (b) the CLI,(c) Claude Code over MCP stdio.
Workstreams
visionset ui+ flow commandsConstraints
(parity rule, vision doc principle 8) from this milestone on.
services only.
Tracked issues
visionset init, filed by cli: visionset ui — starts uvicorn serving the API + static assets from _static/ #33 and absorbed by cli: flow commands — project create, ingest, batch approve, release publish, export (the full cycle without touching Python) #34)