docs(website): the spawn atlas API, the admin panel, and the delay-unit trap #68

Merged
whitlocktech merged 3 commits from docs/spawn-atlas-api into edge 2026-07-29 00:53:56 +00:00
Member

Docs half of website #113 — Protocol 3.0 Part C, second website PR.

Also carries the atlas rewrite that missed #67. That PR merged at 21:16 and the "derive from the tree on every boot" commit was pushed to its branch at 21:45, after the merge — so edge today describes the build-a-committed-artifact design that was rejected in review, not what actually shipped in website #112. That commit rides along here.

SPAWN_ATLAS.md — the API and the panel

The six public routes and the five admin ones, plus three behaviours that read as bugs unless they are written down:

  • An unreadable tree answers 200 with status: "unavailable", not 500. refresh() reports outcomes rather than throwing so the boot path is never blocked by a bad tree, and that contract is preserved at the API — the admin needs to be told what is wrong with their path.
  • Setting the ServUO path deliberately does not import. Moving the mount and reloading the world are separate decisions.
  • points is a COUNT, spawners is the LIST. Named apart so one key never means a number on one route and an array on another.

Plus why the routes sit outside /shard (nothing touches the sidecar) while still being siteMode-gated (a bestiary is site content), and why ?facet= is an exact EXISTS match rather than JSON_SEARCH, whose %/_ wildcards would make ?facet=% match everything.

The delay-unit trap

XmlSpawner stores MinDelay/MaxDelay in minutes or seconds per record, decided by that record's own DelayInSec flag. A 5 is five minutes on one spawner and five seconds on the next, and both are plausible respawn times — which is what makes it silent. 170 of 6,455 stock spawners are second-flagged. Recorded next to the other three quirks in the source data, because it belongs in the same list.

PARSER_VERSION

Stored in shard_atlas_meta beside the source hashes and bumped whenever the parser derives different data from identical files. It exists because hashing the tree alone is a trap: an install whose maps never change would keep serving whatever an older build derived, and a deploy that corrects the parse would never reach the data. Documented in both SPAWN_ATLAS.md and BACKEND_DESIGN.md, with the rule stated as an instruction for the next person to touch the parser.

BACKEND_DESIGN.md / v3.md

The eleven new routes in the API contract, the atlas.router.js entry in the router map, and the parser-version rule. v3.md marks Part C done and adds §6.3 recording what the API half found — kept as a diff against §6 like §6.1 and §6.2, since each one is a trap the next person would otherwise re-enter.

api-route-inventory.json refreshed from the live manifest. It had drifted to 200 routes before this PR — the real count on edge was 204 — and is now 215.

PROJECT_TREE.md is left alone; it is auto-generated by the sync-project-tree workflow.


  • AI-assisted: written with Claude Code (Claude Opus 5), reviewed before opening.

🤖 Generated with Claude Code

https://claude.ai/code/session_01U7CBg11prhLimL9iHSX1bP

Docs half of website [#113](https://gitea.whitlocktech.com/RunicGateway/website/pulls/113) — Protocol 3.0 Part C, second website PR. > **Also carries the atlas rewrite that missed #67.** That PR merged at 21:16 and the *"derive from the tree on every boot"* commit was pushed to its branch at 21:45, after the merge — so `edge` today describes the build-a-committed-artifact design that was **rejected in review**, not what actually shipped in website #112. That commit rides along here. ## SPAWN_ATLAS.md — the API and the panel The six public routes and the five admin ones, plus three behaviours that read as bugs unless they are written down: - **An unreadable tree answers 200 with `status: "unavailable"`, not 500.** `refresh()` reports outcomes rather than throwing so the boot path is never blocked by a bad tree, and that contract is preserved at the API — the admin needs to be told what is wrong with their path. - **Setting the ServUO path deliberately does not import.** Moving the mount and reloading the world are separate decisions. - **`points` is a COUNT, `spawners` is the LIST.** Named apart so one key never means a number on one route and an array on another. Plus why the routes sit outside `/shard` (nothing touches the sidecar) while still being `siteMode`-gated (a bestiary is site content), and why `?facet=` is an exact `EXISTS` match rather than `JSON_SEARCH`, whose `%`/`_` wildcards would make `?facet=%` match everything. ## The delay-unit trap XmlSpawner stores `MinDelay`/`MaxDelay` in **minutes or seconds per record**, decided by that record's own `DelayInSec` flag. A `5` is five minutes on one spawner and five seconds on the next, and both are plausible respawn times — which is what makes it silent. 170 of 6,455 stock spawners are second-flagged. Recorded next to the other three quirks in the source data, because it belongs in the same list. ## `PARSER_VERSION` Stored in `shard_atlas_meta` beside the source hashes and bumped whenever the parser derives different data from identical files. It exists because hashing the tree alone is a trap: an install whose maps never change would keep serving whatever an older build derived, and a deploy that corrects the parse would never reach the data. Documented in both SPAWN_ATLAS.md and BACKEND_DESIGN.md, with the rule stated as an instruction for the next person to touch the parser. ## BACKEND_DESIGN.md / v3.md The eleven new routes in the API contract, the `atlas.router.js` entry in the router map, and the parser-version rule. `v3.md` marks **Part C done** and adds §6.3 recording what the API half found — kept as a diff against §6 like §6.1 and §6.2, since each one is a trap the next person would otherwise re-enter. `api-route-inventory.json` refreshed from the live manifest. It had drifted to 200 routes before this PR — the real count on `edge` was 204 — and is now 215. `PROJECT_TREE.md` is left alone; it is auto-generated by the sync-project-tree workflow. --- - [x] AI-assisted: written with **Claude Code** (Claude Opus 5), reviewed before opening. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01U7CBg11prhLimL9iHSX1bP
wtclaude added 3 commits 2026-07-29 00:52:55 +00:00
Follows the redesign in website #112. Two decisions from the original §6 were
rejected in review and replaced; the docs now describe what was actually built.

**The committed artifact is gone.** A shard's maps change over its life, so a
snapshot in the repo silently drifts from the world players actually see. The
ServUO tree is the single source of truth and the atlas is re-derived on every
server boot, hash-gated so an unchanged tree costs one read pass and no write.

**Nothing may name a facet.** The first implementation carried a lookup table of
the six stock UO facets. A shard may add facets, replace them outright, or rename
them when its maps are updated, and a built-in list mishandles all three
silently. Reconciliation is now by matching against the facet set discovered from
the shard's own data, with an unmatched name keeping its own rather than being
forced into a wrong bucket.

## Changes

- **`website/SPAWN_ATLAS.md`** rewritten: the two ideas that shape the design,
  how to configure the tree path, the boot flow as a decision tree, the
  approve/reject flow, and the code layout. The artwork policy is unchanged and
  still explicit — no art ever ships, operators extract their own from their own
  client files.
- **`link/v3.md` §6.1 (new)** records the two rejected decisions plus the two
  boot-path contracts. The old "what real data changed" list becomes §6.2. §6's
  now-superseded passages — the artifact bullet, the payload budget, the operator
  re-run story — are marked rather than deleted, so the reasoning stays legible.
- **`website/BACKEND_DESIGN.md`** documents `shard_atlas_pending` and the two
  contracts that make it safe: a facet removal is staged for a human, and the
  boot refresh can never block startup.

The two contracts are the part worth reviewing. Losing a facet is
indistinguishable at boot from a half-copied or mid-update tree, so it is staged
rather than applied; and no failure mode of the atlas — missing path, unreadable
mount, malformed file, database error — is allowed to stop the site coming up.

---

- [x] AI-assisted: written with **Claude Code** (Claude Opus 5), reviewed before opening.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U7CBg11prhLimL9iHSX1bP
Docs half of website #113 (Protocol 3.0 Part C, second website PR).

Carries the atlas rewrite that missed #67: that PR merged before the "derive
from the tree on every boot" commit was pushed, so `edge` currently describes
the build/import-artifact design that was rejected in review, not what shipped
in website #112. It lands here.

New in SPAWN_ATLAS.md: the six public routes and five admin ones, and three
behaviours that read as bugs unless they are written down — an unreadable tree
answers 200 with status "unavailable" rather than 500 (refresh reports outcomes
so boot is never blocked by a bad tree, and the contract is preserved at the
API), setting the ServUO path deliberately does not import, and `points` is a
count while `spawners` is the list.

Also the delay-unit trap: XmlSpawner stores MinDelay/MaxDelay in minutes OR
seconds per record, decided by that record's own DelayInSec flag, so a `5` is
five minutes on one spawner and five seconds on the next. Both are plausible
respawn times, which is what makes it silent. 170 of 6,455 stock spawners are
second-flagged. And PARSER_VERSION, which exists because hashing the tree alone
would strand an install whose maps never change on whatever an older parser
derived.

BACKEND_DESIGN.md gains the routes, the router-map entry, and the parser-version
rule. v3.md marks Part C done and records in 6.3 what the API half found.

api-route-inventory.json refreshed from the live manifest — it had drifted to
200 routes before this PR (real count was 204) and is now 215.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U7CBg11prhLimL9iHSX1bP
whitlocktech approved these changes 2026-07-29 00:53:48 +00:00
whitlocktech merged commit 64fb7edc3e into edge 2026-07-29 00:53:56 +00:00
whitlocktech deleted branch docs/spawn-atlas-api 2026-07-29 00:53:57 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RunicGateway/docs#68
No description provided.