Self's ruling, 2026-09-22 ("the C# reference's alias rule is the rule"): an
alias is a schema *name* with a trailing .vN suffix, resolved against the
descriptor's declared name - never against a hash id. C#'s production call
sites (CultNetSelection.cs:438, CultNetSelectionEvaluator.cs:88,340) all use
the descriptor overload of CultNetSchemaAliasMatching.Matches, never the bare
id-vs-id overload.
- Row gains schema_name() (defaults to schema_id() for rows with no separate
name, e.g. raw wire records); RowSet gains schema_name(schema_id) ->
Option<String>. Both stand in for CultDocumentDescriptor.SchemaName, which
this crate has no type for (D7).
- schema_alias::matches/matches_any now take (candidate, schema_id,
schema_name) and resolve a candidate's inferred name against the declared
name, exactly as the C# descriptor overload does - not against schema_id's
own inferred name, which is what the deleted hash-stripping matcher did.
- Every call site (reachable_schemas, the cites.target door check,
matches_schema_keys_fields's D6 fast path, matches_citation) now resolves
and passes a schema's name instead of comparing two schema-id strings.
- Deleted: the hash-stripping schema_alias::matches(candidate, schema_id)
two-string overload. A hash-shaped alias ("<hash>.v1") is not a wire form
either runtime's production rule ever resolves.
Behaviour verified against a standalone run of the exact C# algorithm
(CultNetSchemaAliasMatching, CultNetDatabase.cs:47-97) covering exact-id
match, bare-name match, .vN alias resolution, MatchesAny's empty-matches-all
convention, ordinal case sensitivity, ".v" with no trailing digits, and
multiple ".v" markers (last one wins) - every case is now a Rust unit test
in schema_alias::tests.
Test fixture (tests/selection.rs) updated: the fixture's hashAlias entries
are now a shared negative check (neither runtime resolves them), and the
nameAlias entries now resolve in Rust too, fixing the confirmed cross-runtime
defect (schemas_by_name_alias). Regenerated
contracts/cultnet/interop/selection-vectors.rs-written.json (15 -> 16
vectors): added refuses_cites_target_by_hash_shaped_alias, renamed
hop_by_role_cites_hash_alias to hop_by_role_cites_name_alias.
cultnet-rs: cargo test 223/223. C# reader (rs-written.json): 14/16 - the two
failures are both the pending unmatched-cites.target door refusal
(CultNetSelection.cs:361-391 has no such check yet), not a Rust defect; the
other Hands' C# door fix covers both.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>