1d557f1b0e
Equals(object?) was delegating to GetHashCode() comparison, which is the textbook hash-collision anti-pattern: two distinct ChatCode values could in principle share a hash and be wrongly reported as equal. The current GetHashCode implementation packs Type/Source/Target into 24 bits and happens to be collision-free, but the contract is fragile — any future change to GetHashCode silently breaks Equals. Replaced with direct field-by-field comparison of Type, Source, Target. GetHashCode is left unchanged so dictionary/HashSet behavior stays identical. Pre-existing upstream issue (CodeRabbit critical finding); fixed in v1.0.0 standalone cut where we own the codebase.