Addresses review findings on the metric/column uuid export fix.
- helpers.py: the collision guard only ran in the `not obj` (INSERT)
branch, but the UPDATE branch still did `setattr(obj, "uuid", incoming)`
unconditionally. Re-importing a clone bundle with overwrite=True matched
the child by (table_id, name) and wrote the original's uuid onto the
clone's child, failing with `UNIQUE constraint failed: sql_metrics.uuid`.
Move the guard above both branches so an incoming uuid owned by another
row is dropped on INSERT and UPDATE alike.
- helpers.py: also drop an explicit `uuid: null`. The child schemas accept
it, and on the overwrite UPDATE it would persist a literal NULL over an
existing child's uuid — silently, since the column is nullable and
`unique` permits repeated NULLs — orphaning every folder leaf pointing
at that child.
- helpers.py: document why an ambiguous `MultipleResultsFound` child match
stays a hard error. Preferring the uuid match would rename the
uuid-matched row while the name-matched row still holds that name,
trading a clear failure for an opaque `(table_id, <name>)` violation at
the next flush; callers own the recovery contract.
- import_test.py: regression tests for the overwrite re-import and the
null-uuid paths, and stop overclaiming what the `folders` equality
assertion proves (that JSON round-trips either way; the uuid assertions
are the real gate).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>