Skip to content

feat(kernel): export targets on the exporter port - #788

Merged
JArmandoAnaya merged 1 commit into
mainfrom
feat/targets-t1-domain
Aug 26, 2026
Merged

feat(kernel): export targets on the exporter port#788
JArmandoAnaya merged 1 commit into
mainfrom
feat/targets-t1-domain

Conversation

@JArmandoAnaya

Copy link
Copy Markdown
Contributor

First phase of the export-targets epic (#784): the kernel now knows what an export target is, and the Exporter port declares them. A target is the model a person will train; it resolves to exactly one exporter, and the catalog every surface will render is derived from what is installed rather than kept anywhere by hand. This phase is kernel and formats only — no route, CLI command, or MCP tool consumes targets yet, and no wire shape changes.

The contract added

  • kernel/domain/export_target.py (new): frozen pydantic models — Task, ResizeStrategy, TargetFamily, PreprocessingHints, and ExportTarget with three validators: the name is a lowercase slug, supported_geometries is non-empty, and a recommended strategy requires a recommended size. ResizeStrategy lives here because the hints reference it.
  • kernel/ports/exporter.py: the port gains targets: frozenset[ExportTarget] beside its five existing attributes, plus two module-level helpers — validate_targets(exporter), holding every target's supported_geometries within the exporter's own, and resolve_target(installed, name), the pure resolution from a target name to (Exporter, ExportTarget).
  • kernel/errors.py: ExportTargetNotFound (carrying the installed target names), ExportTargetConflict, and InvalidExportTarget for the validate_targets refusal.
  • Every shipped exporter declares one self-named target — family other, no trainer tasks, geometries equal to its supported_geometries, hints (None, None, trainer_resizes=True, augmentation_common=False) — spelled once in formats/_targets.py. The dummy exporter declares dummy the same way.

Decisions a reviewer should see

  • The server error table is updated in this phase. tests/server/test_errors.py holds ERROR_RULES in exact correspondence with kernel/errors.py, so the three new errors are mapped now (404 for the missing target; 500 for the conflict and the defective declaration, opaque) and added to the inventory in docs/content/api.md, on the table's own precedent for errors no route reaches yet. The phase that builds the target routes owns the final status and exposure argument.
  • TuSimple's target carries polyline rather than its supported_geometries. That set is empty — everything TuSimple writes arrives degraded — and an empty target geometry set is invalid by design. The subset rule validate_targets enforces therefore cannot hold for an exporter whose entire output is degraded; nothing runs that check against installed plugins yet, and the rule needs a ruling before the registry enforces it at discovery.
  • The yolo exporter's self-named target is a placeholder; the dialect work replaces it with the real trainer targets.

Stack

Position 1 of the export-targets stack (#784); based on main.

Checks

Targeted: tests/kernel, tests/formats, tests/architecture, tests/server, tests/cli, tests/mcp, tests/jobs, tests/packaging (all passing), uv run lint-imports (4 contracts kept), uv run mypy src/visionset (clean), uv run ruff check . and ruff format --check . (clean).

Full gate: bash scripts/check.shcheck.sh: PASSED ran=python,frontend,generated,browser skipped=docs ("All checks passed."; the docs group is CI's, and the only docs change here is the api.md code inventory, which tests/server/test_errors.py gates).

An export target is the model a person will train; each exporter now
declares its targets beside the five existing port attributes. The kernel
gains the frozen ExportTarget model with its Task, TargetFamily and
ResizeStrategy vocabularies and the PreprocessingHints a target carries,
pure resolution from a target name to the declaring exporter, and a
validate_targets check holding every target's geometries within its
exporter's own.

ExportTargetNotFound, ExportTargetConflict and InvalidExportTarget are
typed in kernel/errors.py and mapped in server/errors.py — no route
raises them yet; the exact-correspondence test keeps the table total.

Every shipped exporter declares one self-named target, family other,
with no trainer tasks, so discovery keeps returning them under the
widened port. TuSimple's target names the polyline it writes, because
its supported set is empty — everything it carries arrives degraded.
@JArmandoAnaya
JArmandoAnaya force-pushed the feat/targets-t1-domain branch from d9b2b5d to 307e7ef Compare August 26, 2026 11:14
@JArmandoAnaya
JArmandoAnaya merged commit 7c3ee56 into main Aug 26, 2026
15 checks passed
@JArmandoAnaya
JArmandoAnaya deleted the feat/targets-t1-domain branch August 26, 2026 11:20
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