Found by the coverage wave (spikersoft-backend PR #454) while writing ElementRegistryTests.
SpikerSoft.GameServer/Data/Elements.cs registers 22 elements, but two IncompatibleWith lists reference symbols that are never registered:
H.IncompatibleWith = ["O", "F", "Cl"] — F and Cl don't exist in the registry
O.IncompatibleWith = ["H", "Na", "K"] — Na and K don't exist in the registry
Consequences today:
ElementRegistry.AreCompatible("H", "F") returns false, but only because Get("F") is null (unknown-element path), not because of the declared incompatibility — the intent is ambiguous.
GetIncompatibleElements("H") returns symbols (F, Cl) that Get() can't resolve, so callers that look up the returned symbols get nulls.
Fix options: register F/Cl/Na/K, or prune the dangling references. Until then, ElementRegistryTests.GetAll_KnownDanglingIncompatibilityReferences_ArePinned pins the exact dangling set and will fail when this is fixed (update the test to the strict invariant then).
Found by the coverage wave (spikersoft-backend PR #454) while writing `ElementRegistryTests`.
`SpikerSoft.GameServer/Data/Elements.cs` registers 22 elements, but two `IncompatibleWith` lists reference symbols that are never registered:
- `H.IncompatibleWith = ["O", "F", "Cl"]` — **F and Cl don't exist** in the registry
- `O.IncompatibleWith = ["H", "Na", "K"]` — **Na and K don't exist** in the registry
Consequences today:
- `ElementRegistry.AreCompatible("H", "F")` returns `false`, but only because `Get("F")` is null (unknown-element path), not because of the declared incompatibility — the intent is ambiguous.
- `GetIncompatibleElements("H")` returns symbols (`F`, `Cl`) that `Get()` can't resolve, so callers that look up the returned symbols get nulls.
Fix options: register F/Cl/Na/K, or prune the dangling references. Until then, `ElementRegistryTests.GetAll_KnownDanglingIncompatibilityReferences_ArePinned` pins the exact dangling set and will fail when this is fixed (update the test to the strict invariant then).
Audited against origin/master — STILL BROKEN, verdict unchanged, but two details in the body have drifted.
The defect holds.SpikerSoft.GameServer/Data/Elements.cs:126 — H → ["O","F","Cl"]; :186 — O → ["H","Li","Na","K","Mg"]. Grepping for Symbol = "F", "Cl", "Na", "K" returns nothing, so all four referenced elements are still unregistered.
Note correction 1 — the O snippet is stale. The ticket quotes O.IncompatibleWith = ["H","Na","K"]; the code now reads ["H","Li","Na","K","Mg"]. Li and Mgare registered, so the dangling set is still exactly Na and K and the verdict is unaffected — but the quoted snippet no longer matches, and someone diffing against it would be confused.
Note correction 2 — the element count may be off by one. The body says "22 elements"; counting Symbol = entries gives 23. Most likely the author deliberately excluded the He3 isotope entry at :457. Flagging rather than asserting an error.
Worth knowing: the pin test does not carry the drift.ElementRegistryTests.cs:41-53 computes the dangling set dynamically via .Where(other => !all.ContainsKey(other)) rather than hard-coding the three-entry list. So the test stays correct as the registry evolves — the staleness is ticket-only, which is the right way round.
Priority context — this one is latent.AreCompatible (:516) and GetIncompatibleElements (:528) have no production caller; they appear only at their declarations and in tests. So no gameplay path currently consumes the bad data.
From the same eleven-ticket sweep: #792, #808 and #840 are latent (no production caller), while #811 (broken AES on a live network path), #793, #794, #795, #797 and #799 are on live paths. If these get worked as a batch, that's the split I'd use to order them.
Audited against `origin/master` — **STILL BROKEN, verdict unchanged, but two details in the body have drifted.**
**The defect holds.** `SpikerSoft.GameServer/Data/Elements.cs:126` — `H → ["O","F","Cl"]`; `:186` — `O → ["H","Li","Na","K","Mg"]`. Grepping for `Symbol = "F"`, `"Cl"`, `"Na"`, `"K"` returns nothing, so all four referenced elements are still unregistered.
**Note correction 1 — the `O` snippet is stale.** The ticket quotes `O.IncompatibleWith = ["H","Na","K"]`; the code now reads `["H","Li","Na","K","Mg"]`. `Li` and `Mg` *are* registered, so the dangling set is still exactly `Na` and `K` and the verdict is unaffected — but the quoted snippet no longer matches, and someone diffing against it would be confused.
**Note correction 2 — the element count may be off by one.** The body says "22 elements"; counting `Symbol =` entries gives 23. Most likely the author deliberately excluded the `He3` isotope entry at `:457`. Flagging rather than asserting an error.
**Worth knowing: the pin test does not carry the drift.** `ElementRegistryTests.cs:41-53` computes the dangling set *dynamically* via `.Where(other => !all.ContainsKey(other))` rather than hard-coding the three-entry list. So the test stays correct as the registry evolves — the staleness is ticket-only, which is the right way round.
**Priority context — this one is latent.** `AreCompatible` (`:516`) and `GetIncompatibleElements` (`:528`) have **no production caller**; they appear only at their declarations and in tests. So no gameplay path currently consumes the bad data.
From the same eleven-ticket sweep: **#792, #808 and #840 are latent** (no production caller), while **#811** (broken AES on a live network path), **#793**, **#794**, **#795**, **#797** and **#799** are on live paths. If these get worked as a batch, that's the split I'd use to order them.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Found by the coverage wave (spikersoft-backend PR #454) while writing
ElementRegistryTests.SpikerSoft.GameServer/Data/Elements.csregisters 22 elements, but twoIncompatibleWithlists reference symbols that are never registered:H.IncompatibleWith = ["O", "F", "Cl"]— F and Cl don't exist in the registryO.IncompatibleWith = ["H", "Na", "K"]— Na and K don't exist in the registryConsequences today:
ElementRegistry.AreCompatible("H", "F")returnsfalse, but only becauseGet("F")is null (unknown-element path), not because of the declared incompatibility — the intent is ambiguous.GetIncompatibleElements("H")returns symbols (F,Cl) thatGet()can't resolve, so callers that look up the returned symbols get nulls.Fix options: register F/Cl/Na/K, or prune the dangling references. Until then,
ElementRegistryTests.GetAll_KnownDanglingIncompatibilityReferences_ArePinnedpins the exact dangling set and will fail when this is fixed (update the test to the strict invariant then).Audited against
origin/master— STILL BROKEN, verdict unchanged, but two details in the body have drifted.The defect holds.
SpikerSoft.GameServer/Data/Elements.cs:126—H → ["O","F","Cl"];:186—O → ["H","Li","Na","K","Mg"]. Grepping forSymbol = "F","Cl","Na","K"returns nothing, so all four referenced elements are still unregistered.Note correction 1 — the
Osnippet is stale. The ticket quotesO.IncompatibleWith = ["H","Na","K"]; the code now reads["H","Li","Na","K","Mg"].LiandMgare registered, so the dangling set is still exactlyNaandKand the verdict is unaffected — but the quoted snippet no longer matches, and someone diffing against it would be confused.Note correction 2 — the element count may be off by one. The body says "22 elements"; counting
Symbol =entries gives 23. Most likely the author deliberately excluded theHe3isotope entry at:457. Flagging rather than asserting an error.Worth knowing: the pin test does not carry the drift.
ElementRegistryTests.cs:41-53computes the dangling set dynamically via.Where(other => !all.ContainsKey(other))rather than hard-coding the three-entry list. So the test stays correct as the registry evolves — the staleness is ticket-only, which is the right way round.Priority context — this one is latent.
AreCompatible(:516) andGetIncompatibleElements(:528) have no production caller; they appear only at their declarations and in tests. So no gameplay path currently consumes the bad data.From the same eleven-ticket sweep: #792, #808 and #840 are latent (no production caller), while #811 (broken AES on a live network path), #793, #794, #795, #797 and #799 are on live paths. If these get worked as a batch, that's the split I'd use to order them.