Skip to content

Annotation workspace redesign — class system, top bar, objects panel #368

Description

@JArmandoAnaya

The annotation workspace is being redesigned around one idea: the editor is where annotation work happens, start to finish. Class selection moves out of a side-panel tab and into a top-bar combobox with typeahead and a create-new escape hatch; the side panel becomes a single Annotations view (tag chips + object list + per-row reassignment); the top bar reorganizes into three zones with exactly one workflow primary rendered from allowed_actions; undo/redo become visible controls; and a new ratified design principle says no flow may force the annotator out of the editor and no exit may lose work. Behind it, schema versions gain a nullable provenance so versions published mid-annotation can be collapsed in the history instead of burying the curated ones. Every product decision below is settled; the four work streams that follow are execution.


Decision record

Decision (Armando, 2026-08-05) — supersedes any prior direction:

  1. Class selection moves to a top-bar combobox (swatch + name + hotkey readout;
    typeahead; hotkeys 1–9 stay global). The Labels tab is removed.
  2. The side panel becomes a single "Annotations" view: a classification-tag chip strip
    (when the pinned schema declares tag classes) above the objects list. No tabs. The
    Tabs segmented variant is retired.
  3. Top bar reorganizes into three zones (location / class / workflow); the Save button
    is removed (⌘S + save-state text remain); exactly one workflow primary rendered
    from allowed_actions; Skip stays visible as a secondary; zoom + fullscreen move
    to a floating widget on the stage.
  4. Undo/redo become visible tool-strip buttons (shortcuts unchanged).
  5. Design principle 10 (ratified, immovable): the annotation workspace is
    self-sufficient — no flow may force navigation out of the editor, and no exit may
    lose work. Back/grid navigation must save-or-ask first.
  6. Quick class creation: one dialog session = one published schema version
    (Create and add another accumulates; confirm publishes all). Mid-job blast radius
    is option 1: publish, then repin only this job's batch (the shipped feat(kernel): a batch can re-pin to the active schema version #229/feat(app): a new label can be created from the annotation page #233
    chain — save-first, compose on active classes, canRepin preflight per F23 — is
    preserved exactly).
  7. Schema versions gain a nullable provenance (curated | annotation); the
    version history collapses consecutive annotation runs into one expandable row;
    milestones always render individually; diffs stay fetched on demand (option D3).
  8. No schema-scoped capability is introduced (option E1): publishing is refused by
    facts on disk; the dialog keeps gating on BatchAction.REPIN + the 409.
  9. Out of scope, tracked separately: server-side schema draft entity;
    canvas-anchored reassignment picker; assisted pre-annotation; any
    publish-and-repin-project kernel operation; F14.

Work streams

Sequential — they share AnnotationPage.tsx above all. One worktree, one PR, merged green before the next starts. Every WS PR body carries cf. #<this issue>; the WS4 PR closes it.

  • WS1 — Backend: schema provenance. SchemaProvenance StrEnum, nullable field on AnnotationSchema, keyword-only provenance on SchemaService.create_version, migration 5 (schema_provenance, FORMAT_VERSION → 5), wire field on SchemaVersionCreate/SchemaVersionOut, and each writing surface declaring its own value (browser Schema tab and CLI schema applycurated; AddClassDialogannotation; MCP gains an optional parameter defaulting to curated). Existing versions are never backfilled.
  • WS2 — Combobox primitive, top bar, tool strip, navigation guard. An in-house Combobox (no new dependency), the top-bar class field with a C host action and a Create class "<text>" no-match row, the three-zone top bar with a single workflow primary derived from allowed_actions, the floating zoom/fullscreen widget, undo/redo in the tool strip, and the principle-10 save-first guard on back and grid.
  • WS3 — The Annotations panel. Tabs removed; filter input; classification-tag chip strip preserving the Labels tab's only non-selection capability; per-row class reassignment with geometry-incompatible classes disabled and the reason inline; activeClass/onActivateClass dropped from the panel entirely; the segmented Tabs variant retired.
  • WS4 — Dialog sessions, badge popover, version history. Create and add another accumulating into one published version, the v{n} badge as a pin-vs-active popover with an on-demand diff, and consecutive annotation-provenance versions collapsed into one expandable row in VersionNavigator.

Invariants that hold across all four

  • Kernel purity and the headless-annotator boundary (AGENTS.md) are never relaxed.
  • The frontend never computes legality: it renders allowed_actions and refusal prose from the wire. No new client-side gating rules.
  • classColor stays the single colour derivation; ClassFields stays the single class form.
  • Annotations are validated against the batch pin only; nothing reads the project's active version on a write path.
  • Schema versions stay immutable, 1..N, additive-by-publish. No update, no delete.
  • Hiding is a view concern: nothing about visibility enters the document/store commands.
  • Copy per DESIGN.md: sentence case, no "successfully", errors = what happened + what to do.

Visual context — the surfaces as they ship today

Four screenshots of the current state accompany this issue (attached separately; see the comment below). What they establish:

  1. Project → Schema tab. Version 1 active · saving creates v2, a Why this version? (optional) note field, Add class, Save version; the class list filter; the ClassFields form (name, geometry with Singular — picking a class picks a tool., colour with Derived from name / Derive, hotkey chip, attributes block); and Version history — a flat table (Version / Published / Why / Classes) with one row per version. That table is what WS4 §3 collapses for consecutive annotation runs.
  2. Batch view (obj-track.mp4, completed, 12 of 12 annotated). Establishes the grid the principle-10 guard has to protect on the way out of the editor, and the View affordance that lands in the annotator.
  3. Annotator, Objects tab. The top bar as it ships: back · v1 · asset navigator · grid · annotated · ✓ Saved · Save (disabled) · Skip · Submit for review · Accept (disabled) · 1 / 13 annotated · Finish job (disabled) · zoom − 100% + · fullscreen — one undifferentiated row, three disabled workflow buttons rendered at once. WS2 replaces this with three zones, one primary, no disabled-without-reason, and zoom moved to the stage. The side panel shows the Objects/Labels tab pair and the object list (swatch, N. class, eye, trash) that WS3 keeps.
  4. Annotator, Labels tab. The panel WS1–WS3 delete: a select row plus the pinned schema's classes with hotkey digit, swatch, name and geometry. Its class-activation job moves to the WS2 combobox; its only other capability — toggling classification tags — is preserved as WS3's chip strip.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    epicMilestone/phase epic — tracks a group of issuesfrontendannotator / ui-core / app packagesui-corefrontend/ui-core work

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions