When the mapping file was cleaned (PH1E- → PH1E) but the legacy dashed
rows were never removed from the live DB, seed_units inserted the clean
rows AND left the legacy rows as inert aliases — yielding 8 penthouse
rows instead of 4, all with floor=null.
The self-heal now handles the 'both forms exist' case by consolidating
to exactly one row per unit: the clean-code row is the canonical
survivor, any tickets referencing the legacy row are re-pointed to it,
and the legacy row is removed. The operation is idempotent.
Also fixes a missing comma in pyproject.toml (TOML parse error).
Adds regression test test_penthouse_consolidation_when_both_forms_exist
that reproduces the live condition and fails pre-fix.