Skip to content

0.2.0 scope: more formats #365

Description

@JArmandoAnaya

Draft — planning seed, not an implementation ticket. It captures partial information as of 2026-08-06; a dedicated design session will produce the real spec. Do not pick this up for implementation.

What exists (verified at HEAD)

The plugin system. Formats are discovered through the visionset.formats entry-point group,
read with importlib.metadata in src/visionset/formats/registry.py"never a hardcoded dict
and never an if fmt == "coco" chain. That is the whole plugin promise: a third-party
distribution registers into the same group and is indistinguishable from a built-in here."
The
kernel structurally cannot resolve a plugin name, because import-linter forbids
visionset.kernel importing visionset.formats, so ReleaseService.export takes an Exporter
instance and the composition happens at the surface. Plugins are keyed by their own
format_name, not by the entry-point name.

The lossiness contract (kernel/ports/exporter.py) is three declarations, each answering a
different question.

  • lossy: bool — a property of the format, not of a release. "A bbox-only format loses a
    polygon whether or not today's dataset happens to hold one."
    A True costs the caller a
    LossyExportNotConsented once, via the allow_lossy gate word.
  • supported_geometries: frozenset[GeometryType]"the checkable half of lossy", which
    arrived with the export-validation work that reports excluded classes and annotations before a
    run (kernel: export validation — exact report of excluded classes/annotations before running #65). It is declared over the full GeometryType rather than only the implemented subset,
    so a format that will one day write masks says so once. This is what turns "this format is
    lossy" into a countable report.
  • degraded_geometriescarried, but reduced. It was added (formats: the export report says polygons are not carried while YOLO and VOC write them as bounding boxes #158) because
    supported_geometries was being read with two intents at once: YOLO and VOC write a polygon as
    its axis-aligned bounding box, which is neither "absent from the output" nor "written as it
    stands", and the model had no word for it.

The principle underneath all three: declare what the format carries; refuse silent drops.

Eight shipped exporters, plus one no-op. The [project.entry-points."visionset.formats"]
table in pyproject.toml registers nine entries: yolo, coco, voc, the five lane formats
that came out of the lanes port (#223) — tusimple, curvelanes, bdd100k-lane, culane and
openlane-2d, five plugins over v1's six exporter functions, since CULane's annotation file and
its segmentation mask are two artifacts of one format — and dummy, which is
visionset.formats._dummy and writes nothing.

The import side is a declared port with no implementation. kernel/ports/importer.py holds a
@runtime_checkable Importer Protocol — format_name plus read(src: Path) -> Iterable[Annotation]
documented as discovered through the same entry-point group. The registry filters by port with
isinstance(plugin, Exporter) precisely "because the group carries importers too". Nothing
implements it, so provenance="import" — the third of the three values in
Provenance = Literal["human", "model", "import"] — currently has no producer.

Open questions (to name, not to answer here)

  • Candidate list and priority. Name the families here; decide nothing. Detection and
    segmentation formats (COCO variants, Pascal VOC beyond what ships, CreateML, TFRecord), the
    YOLO dialect spread (v5, v8, OBB, segmentation), the 3D families that follow from the 3D and
    point-cloud scope issue (0.2.0 scope: 3D and point clouds #363), and whatever the video-tracking scope issue (0.2.0 scope: video tracking — object identity across frames #364) implies,
    given that MOT-style formats have no home in the current model.
  • Import-side counterparts. Which of these formats need to read as well as write, and is that
    decided per format, or is the pair the default? The scope issue for importing external datasets
    (0.2.0 scope: import of external datasets #411) describes the shape of the reading half.
  • A public extension story in OSS. The mechanism already admits third-party distributions, but
    there is no documented contract for writing one: no versioning statement on the Exporter and
    Importer protocols, no stability promise, and no worked example outside this repository.
    Deciding whether OSS VisionSet offers that is a product call rather than a technical one.

Related open threads

The AI-assist substrate issue (#81) still carries a live Importer bullet at HEAD: "Importer
port made real (COCO/YOLO in) — the third provenance value, import, currently has no producer;
imports are also the cheapest path to pre-annotations from external models."
The ModelProvider
bullets in that same issue are a separate thread and are not this milestone's concern.

Metadata

Metadata

Assignees

No one assigned

    Labels

    deferred-needs-inputBlocked on a decision that belongs to the founder

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions