docs(link): the shard-name fallback, the atlas places shape, and two traps #76

Merged
whitlocktech merged 1 commits from docs/protocol-3-smoke-findings into edge 2026-08-01 06:03:02 +00:00
Member

What & why

Records what the live Protocol 3.0 smoke test turned up, so none of it has to be rediscovered. Pairs with RunicGateway/website#119 and RunicGateway/Android-app#32.

v3.md §5.3 — the ruleset shard fallback

Why the stock ServUO Name=My Shard is treated as unnamed; that the substitute is settings.getInstanceName() (site_title || BRAND_NAME, the same resolution getPublic().brand.name uses, so one install never shows two names); why it is done at ingest rather than on read (the ruleset is also broadcast live, so a read-time fix is undone by the next reconnect's frame); and that the match is whole-value only, so "My Shard Reborn" keeps its name.

Also corrects the backfill note: it says the object-shaped ruleset can't use the array-only snapshot() helper, which was read as licence to write state directly — and that made it a second writer that skipped the normalization. It now says explicitly that it must still go through shardIngest.ingest(), as ingestEach does.

v3.md §7.4 — unscored boards

An empty board renders a placeholder row rather than a blank card, and why it is deliberately not shaped like a real entry. Notes that this is presentation only — the API keeps sending an empty top, so nothing fabricated reaches a consumer — and that web and app render it identically.

android/PLAN.md §9 M11 — the atlas trap, and a testing rule

The section listed two traps for the atlas. Adds the third, which is the one that actually bit: places is a list of {facet, label, spawners, maxAlive} objects, not of place-name strings, it arrives only on the detail route, and typing it List<String> makes that whole route fail to decode while the request itself returns 200.

Adds the rule that came out of it, next to the existing "DTO decode for each new shape" requirement: decode tests must feed real captured JSON, because the fakes under data/api/fake/ construct DTOs in Kotlin and can never catch a wire mismatch — which is how this shipped past a green suite.

How it was tested

Documentation only. Every claim was verified live during the smoke run against ServUO + sidecar + website + AVD; the corresponding code changes are in the two linked PRs.

Checklist

  • I have read CONTRIBUTING.md.
  • The change builds and existing tests/checks pass locally.
  • I have added or updated tests/docs where it makes sense.
  • My commits are reasonably scoped with clear messages.

AI-assisted contributions (required)

  • No AI tools were used to produce this contribution.
  • AI tools were used. Tool(s): Claude Code (Opus 5). I have reviewed and understand every change, and take responsibility for it. AI-authored commits are marked with a Co-Authored-By / Assisted-By trailer.

License

  • I agree that my contribution is licensed under this project's license (GNU GPL v3.0 or later), and I have the right to contribute it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01U7CBg11prhLimL9iHSX1bP

## What & why Records what the live Protocol 3.0 smoke test turned up, so none of it has to be rediscovered. Pairs with RunicGateway/website#119 and RunicGateway/Android-app#32. ### `v3.md` §5.3 — the ruleset `shard` fallback Why the stock ServUO `Name=My Shard` is treated as *unnamed*; that the substitute is `settings.getInstanceName()` (`site_title || BRAND_NAME`, the same resolution `getPublic().brand.name` uses, so one install never shows two names); why it is done at **ingest rather than on read** (the ruleset is also broadcast live, so a read-time fix is undone by the next reconnect's frame); and that the match is whole-value only, so *"My Shard Reborn"* keeps its name. Also corrects the backfill note: it says the object-shaped ruleset can't use the array-only `snapshot()` helper, which was read as licence to write state directly — and that made it a **second writer that skipped the normalization**. It now says explicitly that it must still go through `shardIngest.ingest()`, as `ingestEach` does. ### `v3.md` §7.4 — unscored boards An empty board renders a placeholder row rather than a blank card, and why it is deliberately *not* shaped like a real entry. Notes that this is presentation only — the API keeps sending an empty `top`, so nothing fabricated reaches a consumer — and that web and app render it identically. ### `android/PLAN.md` §9 M11 — the atlas trap, and a testing rule The section listed *two* traps for the atlas. Adds the third, which is the one that actually bit: **`places` is a list of `{facet, label, spawners, maxAlive}` objects, not of place-name strings**, it arrives only on the detail route, and typing it `List<String>` makes that whole route fail to decode while the request itself returns `200`. Adds the rule that came out of it, next to the existing "DTO decode for each new shape" requirement: **decode tests must feed real captured JSON**, because the fakes under `data/api/fake/` construct DTOs in Kotlin and can never catch a wire mismatch — which is how this shipped past a green suite. ## How it was tested Documentation only. Every claim was verified live during the smoke run against ServUO + sidecar + website + AVD; the corresponding code changes are in the two linked PRs. ## Checklist - [x] I have read [CONTRIBUTING.md](CONTRIBUTING.md). - [x] The change builds and existing tests/checks pass locally. - [x] I have added or updated tests/docs where it makes sense. - [x] My commits are reasonably scoped with clear messages. ## AI-assisted contributions (required) - [ ] No AI tools were used to produce this contribution. - [x] AI tools were used. Tool(s): `Claude Code (Opus 5)`. I have reviewed and understand every change, and take responsibility for it. AI-authored commits are marked with a `Co-Authored-By` / `Assisted-By` trailer. ## License - [x] I agree that my contribution is licensed under this project's license (**GNU GPL v3.0 or later**), and I have the right to contribute it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01U7CBg11prhLimL9iHSX1bP
wtclaude added 1 commit 2026-08-01 06:00:44 +00:00
Records what the live Protocol 3.0 smoke test (ServUO + sidecar + website +
AVD) turned up, so none of it has to be rediscovered.

v3.md §5.3 — the ruleset `shard` field now falls back to the instance's own
name when the shard publishes ServUO's stock "My Shard", why that is done at
ingest rather than on read (the frame is also broadcast live), and why the
backfill snapshot must go through the dispatcher instead of writing state
directly: a direct call made it a second writer that skipped the
normalization.

v3.md §7.4 — an unscored board renders a placeholder row rather than a blank
card, and why it is deliberately not shaped like a real entry.

PLAN.md §9 M11 — `places` is a list of {facet,label,spawners,maxAlive} OBJECTS,
not of place-name strings, and typing it `List<String>` makes the whole detail
route fail to decode while the request itself returns 200. Adds the rule that
came out of it: decode tests must feed real captured JSON, because the fakes
build DTOs in Kotlin and can never catch a wire mismatch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U7CBg11prhLimL9iHSX1bP
whitlocktech merged commit eab0a83f26 into edge 2026-08-01 06:03:02 +00:00
whitlocktech deleted branch docs/protocol-3-smoke-findings 2026-08-01 06:03:03 +00:00
Sign in to join this conversation.
No description provided.