Skip to content

fix(formats): yolov5 declares its three tasks, and an exporter must declare a target - #809

Merged
JArmandoAnaya merged 5 commits into
mainfrom
feat/targets-closeout-backend
Aug 26, 2026
Merged

fix(formats): yolov5 declares its three tasks, and an exporter must declare a target#809
JArmandoAnaya merged 5 commits into
mainfrom
feat/targets-closeout-backend

Conversation

@JArmandoAnaya

Copy link
Copy Markdown
Contributor

Summary

The backend and documentation half of the export-targets closeout. yolov5 was declared as a detect-only target, so a polygon or a tag in a release addressed to it was stripped without a word; it now declares the three tasks its trainer accepts. The Exporter port promised at least one target per exporter and never checked it; the scan now refuses an exporter that declares none. The rest pins behaviour that already held and had no test or no prose: task derivation follows the target, the yolo alias is silent on REST and MCP, and three documents said something the code does not do.

Part of the closeout of #784; the epic is closed by the companion frontend pull request.

What changed

fix(formats): yolov5 trains segment and classify as well as detectyolov5 declares detect, segment and classify with the geometries behind them, mirroring yolov8 and yolo11. The generated catalog table in docs/content/releases.md is regenerated. Two new tests in tests/formats/test_registry.py pin the exact set of ten YOLO target names with each one's task set, and assert that every task the dialect lays out has its geometry behind it on the target that declares it — so a dropped or narrowed target fails a test rather than only the doc-table diff.

feat(kernel): an exporter without a target is refused at scanvalidate_targets raises InvalidExportTarget on an empty targets; validate_installed and therefore registry.exporters() inherit the refusal. The error's docstring now covers both defects it names. Tests: the empty declaration refused directly and through the installed set (tests/kernel/test_export_target.py), and a fake entry point whose plugin passes the port's isinstance filter with no target refused at registry.exporters() (tests/formats/test_registry.py). The seam test's ImageWriter double, which carried targets = frozenset(), now declares a real one. The three scan-time rules are written out in docs/content/architecture/backend/formats.md.

test(formats): task derivation follows the target, not the dialecttests/formats/test_yolo_writer.py covers derive_task's three branches directly. tests/formats/test_ultralytics.py gains three service-level exports through the real ultralytics plugin: a tags-only release addressed to yolov10 writes the detect layout and no class tree; a polygon release addressed to yolov10 writes five-column detect rows; the same polygon addressed to yolov5 keeps its vertices. No port change.

test(server,mcp): the yolo alias is accepted on REST and MCP without a warning — one REST test and one MCP test that format=yolo resolves to ultralytics, reports format_name as the real name on the job result and the compatibility report, and carries no deprecation text. docs/content/releases.md (§The YOLO dialects) and docs/content/api.md say that the alias is accepted silently on REST and MCP and warns only on the CLI, until its removal in the release after next.

docs(releases): the 422 for target and format, and the polygon claimdocs/content/api.md §The two shapes of 422 states the export address refusal: both or neither of target and format on export and compatibility is a 422 VALIDATION_ERROR with loc: ["query"] and msg: "give exactly one of target and format". docs/content/releases.md no longer claims that YOLO reduces a polygon to its box — ultralytics writes polygons as segment rows with an empty degraded_geometries, and only yolov5-yaml and voc reduce — and cites the test by its real name, test_the_general_formats_declare_polyline_truthfully. The Export row of docs/content/examples.md now describes what examples/mcp_end_to_end.py calls (list_formats then export_release(format="dummy")) and points at the Recipe row as the target-addressed export of the same release, rather than being read as a second way to address a trainer.

Found, not fixed

  • yolo26 declares semantic and depth beyond the five tasks its siblings share. Neither task has a geometry VisionSet produces, so the declaration is an absence rather than a drop, but whether the catalog should advertise tasks nothing can reach needs a ruling; the task set is left as it was and pinned as-is by the new test.
  • The example in examples/mcp_end_to_end.py addresses its plain export by format="dummy"; the task asked for the docs row to address by target, but the row describes the script and the script is out of scope here, so the row was made accurate and the target-addressed call stays in the Recipe row.
  • docs/content/api.md still carries #328 in prose ("the generic surface Embedded job system: a JobQueue port, a SQLite adapter, and an in-process spawn dispatcher #328 added"); untouched, since the line is outside this change.

Test plan

  • uv run pytest tests/formats tests/kernel/test_export_target.py tests/kernel/test_export_seam.py tests/architecture tests/server/test_releases.py tests/mcp/test_release_tools.py tests/cli/test_export_commands.py — green per commit.
  • uv run pytest tests/formats/test_ultralytics_roundtrip.py under uv sync --group yolo: 3 passed; synced back after.
  • The empty-target check was mutated out (if False and not exporter.targets) and the three new tests failed, then restored.
  • uv run mypy src/visionset/kernel, uv run ruff check ., uv run lint-imports — green.
  • bash scripts/check.sh:
check.sh: PASSED  ran=python,frontend,generated,browser  skipped=docs

@JArmandoAnaya
JArmandoAnaya force-pushed the feat/targets-closeout-backend branch from b89ccd2 to 2c4f01e Compare August 26, 2026 14:11
@JArmandoAnaya
JArmandoAnaya merged commit 977bb95 into main Aug 26, 2026
15 checks passed
@JArmandoAnaya
JArmandoAnaya deleted the feat/targets-closeout-backend branch August 26, 2026 14:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant