Instead of crashing when corrupt or null catalog rows are encountered,
the normalizers now gracefully repair them with default values. Refactored
helper functions for clarity and added type predicates to improve type
narrowing.
A change whose thesis is "stop the declared types from lying" should not use
`as` to paper over types.
The four source casts all came from the row normalizers returning `readonly`
arrays into mutably-owned fields. Take and return mutable arrays instead, and
copy at the one caller that holds a readonly projection — where identity is
not load-bearing, unlike the persistence path, whose dirty check compares it.
Tests built deliberately malformed rows by casting a literal. Build a valid
row and `Reflect.set` the bad value onto it, which says outright that the
fixture violates its type; parse the non-array case from JSON, which is how
it actually arrives. Fixtures that were merely incomplete needed no cast at
all — `Repo` requires only the five fields they already had.
Also narrow normalizeLoadedProjectCatalog to the two fields it reads.