Clears the 124 CODE_SMELL findings from the SonarQube scan (server, client,
and bot). All changes are behaviour-preserving refactors — no route, protocol,
schema, or config changes — verified against the full server (381) and client
(43) test suites plus a clean client build.
By rule:
- S3776 (20, cognitive complexity): extract helpers/handlers so each function
drops under the threshold — shard model upsert builders, page/wiki update,
block validation, notification stream mapping (dispatch table), SSO mobile
login, shard ingest deps, uo-link socket backfill/connect, the bot slash-
command dispatchers + discord manager, and the Shard/UserDetail/HeroEditor/
CharacterStats React components.
- S4624 (34, nested template literals): pull inner templates into locals /
a withQs() helper; rewrite shardEvents.describe() as a formatter table.
- S3358 (35, nested ternaries): lift to if/else vars, lookup maps, small
components, or guarded JSX expressions.
- S6479 (12, array-index React keys): key by stable content instead of index
(two in-editor lists left as-is; index matches their by-index edit model).
- S6353 (6): [0-9]/[^0-9] -> \d/\D. S125 (5): reword state-shape comments that
parsed as code. S3800/S3782 (botScore): JSDoc-type PATH_WEIGHTS tuples.
- S6481 (2): memoize Auth/Site context values (and SiteContext brand).
- S4144: dedupe HeroEditor upload handler into useImageUpload().
- S1126 (2), S6035, S5869 (redundant A-Z under /i), S5843 (town-name regex ->
prefix list): assorted one-liners.
Co-Authored-By: Claude <noreply@anthropic.com>
Phase 2: the public UI for the four new boards, following the ChampSpawns live
pattern (snapshot via useAsync + merge SSE deltas with useShardFeed).
- Players Online widget (components/PlayersOnline.jsx): total + region breakdown
rolled up into display buckets (data/regionBuckets.js — the one place to retune
the grouping); live via presence.online. Placed on the Shard page, replacing the
static players-online stat tile.
- Guilds (/site/guilds): searchable board of rosters/alliances/leaders with a
"recently joined" strip from guild.join.
- Governors (/site/governors): one card per city with a placeholder crest
(data/cityCrests.js — swap for real art without touching components), election
phase badge + autoPickAt countdown, and an on-demand "past governors" term
history (the look-back reads the ledger captured in Phase 1). Clean empty state
when City Loyalty isn't enabled.
- Houses (/site/houses): searchable registry with decay badges; price labelled
"placement value", not a for-sale flag.
- API client methods + nav links (Guilds / Governors / Houses).
Client build clean (240 modules).
Refs .plans/protocol2-integration.md (Phase 2).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>