NAMEFRAME Frame the world. Name the frames.

Quality, checks and scoring

A synthetic dataset that looks right and is subtly wrong costs more than no dataset at all. NameFrame checks in two places: pre-flight gates against the raw dump before labelling, and a scored validation of the assembled dataset afterwards.

The 12 pre-flight checks#

nameframe verify <dump> runs all of them and writes verify.json into the dump. Each one exists because of a real failure.

CheckWhat it proves
schemaThe dump matches the raw capture contract at all.
configuration-snapshot-integrityThe recorded configuration matches what was actually run.
spawn-manifest-integrityThe spawn manifest agrees with the actors present in the frames.
color-collisionsNo two instances share an ID colour. A collision merges two objects into one label.
determinismRe-running the same seed reproduces the same frames.
fragmentsInstances are not shattered into disconnected pixel islands.
pixels-vs-transformsThe pixels agree with the recorded transforms. This is the core anti-drift check.
missing-visible-peopleNothing visible in the image is missing from the labels.
native-bones-vs-offsetsEngine bone positions agree with derived offsets, within 0.30 m.
environment-rangesEnvironment values actually varied across the run.
actor-ground-contactActors stand on the ground instead of floating or sinking.
population-spacingThe population respects the configured minimum spacing.
A crashing check is a failing check

If a check raises, it gets reported as failed, loudly, rather than skipped. Silence is never treated as success.

Reading a failure

Failing checkUsually meansFix
color-collisionsToo many instances for the ID colour space, or duplicated IDsReduce instances per frame, or check for duplicated actors
pixels-vs-transformsThe scene moved after the transform was recordedRaise settle time, and check that nothing animates mid-capture
missing-visible-peopleActors are visible but unassigned to a classFix the class assignment, or mark them ignored
environment-rangesYou configured a range but got one valueThe randomiser is not being applied. Check the weather driver and the recipe
actor-ground-contactNo ground actor was hitSet the ground actor prefix, or pick ground on the zone
population-spacingSpacing too large for the zone areaEnlarge the zone, lower the count, or reduce spacing

Dataset scoring#

nameframe validate <dataset> inspects the assembled dataset rather than the dump, and scores it. Every check contributes a bounded, documented penalty, subtracted from 100.

nameframe validate _demo/dataset --out _demo/validation
ScoreGradeReading
90 to 100AShip it.
80 to 89BUsable. Read the penalties before scaling up.
70 to 79CSomething real is wrong. Fix it before a large run.
60 to 69DDo not train on this.
under 60FA mechanism is broken, not a parameter.

When both YOLO and COCO are exported, each gets scored separately and the reported score is the lower of the two. A dataset is only as good as its worst format.

What the validator looks at

Gating on the score

nameframe generate --demo --samples 200 --seed 7 --output _local/runs/x --fail-under 80

--fail-under makes the process exit non-zero below the threshold, which is all CI needs. See the CI section.

Reproducibility and corruption#

nameframe hardening-smoke _build/hardening --frames 8 --seed 42

An offline smoke test that checks the pipeline is reproducible and that corrupt inputs get rejected rather than silently mislabelled. Fast enough to run in CI.

Comparing runs#

A single score tells you whether a dataset is sound. Comparison tells you whether a change helped.

nameframe metadata-compare _local/metadata.sqlite --baseline run_a --candidate run_b

It compares stable metrics and frozen configuration between two indexed runs, so a difference in the numbers is attributable to a difference in the configuration.

Closing the loop with a model#

Dataset quality only really means "did the model get better". These commands connect the two:

  1. Profile both sides

    nameframe real-dataset-import _local/real _local/profiles/real.json
    nameframe dataset-profile _local/datasets/synth _local/profiles/synth.json
  2. Measure the gap

    nameframe compare-profiles _local/profiles/real.json _local/profiles/synth.json _local/profiles/cmp.json
    nameframe domain-gap _local/profiles/cmp.json _local/reports/gap
  3. Evaluate by slice

    nameframe model-eval _local/results.json _local/eval.json
    nameframe failure-mine _local/eval.json _local/failures.json
  4. Generate against the failures

    nameframe hard-cases _local/failures.json _local/plans/hard_cases.json
  5. Gate the next release

    nameframe regression-campaign --name nightly --evaluations _local/eval.json --out _local/campaign.json

Coverage works the same way. Declare the axes you care about, evaluate what you have, and plan corrections for what is missing.

nameframe coverage-eval _local/coverage/axes.json _local/coverage/observations.json _local/coverage/matrix.json