From fc2d4872f6a17d34d3001ff0e5dac1a4b5f771af Mon Sep 17 00:00:00 2001 From: wtclaude Date: Mon, 14 Sep 2026 08:10:49 -0500 Subject: [PATCH] docs(link): the panel, and the two deletions it could see and no test could (Phase 8) v8.md section 12.2 records the admin surface as built: one page, Admin -> Client Files, over the creature catalogue, item and land art, and the cliloc table -- one page because they come off one client install and change on one event. The four decisions are written down, including the one that kept the phase to a single repo: section 14's "activity view" is the last import's own summary rather than a filtered feed, which would have needed a core activity filter, a `ctx.activity.list` helper and a MODULE_API bump to re-read rows the panel can keep itself. The part worth reading twice is what the walk found. Two of the three defects were DELETIONS, both predate phase 8, and neither was reachable by a test that did not already suspect them: * the body import diffing its manifest against every family's rows, so 313 item pictures were staged for deletion under a sentence that was wrong about what had happened; * an approved vanish unlinking the sprite and keeping the row, so the key came back for review forever and the count never moved. The rule they share is now stated: after phase 5, `shard_assets` is three collections in one table, and every read of it that feeds a decision has to say which one it means. Two of the three that did not were deletions. CLILOCS.md and SPAWN_ATLAS.md now name the button that exists (Admin -> Client Files) instead of the one they promised, and modules/uo/API.md records that a `needsReview` reply carries each vanished key's picture. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4 --- link/v8.md | 80 ++++++++++++++++++++++++++++++++++++++---- modules/uo/API.md | 2 +- website/CLILOCS.md | 10 ++++-- website/SPAWN_ATLAS.md | 2 +- 4 files changed, 83 insertions(+), 11 deletions(-) diff --git a/link/v8.md b/link/v8.md index 355ef48..aafcfbc 100644 --- a/link/v8.md +++ b/link/v8.md @@ -1492,6 +1492,67 @@ would put a second, weaker parser of §5's key scheme in the schema. winning spelling of the spawn type token rather than inventing a display label — so the import has something `ScriptCompiler.FindTypeByName` will resolve without storing it twice. +### 12.2 What phase 8 built, and the two deletions the panel exposed + +The admin surface is one page, **Admin → Client Files**, covering all three things that come off the +operator's UO client: the creature catalogue, item and land art, and the cliloc table. One page +rather than three because they are one job — they live in the same client install, cross the same +bridge, and all change at the same moment, when the operator patches that client (org lead, +2026-09-14). The cliloc pair had had no UI at all since phase 2, which meant that on an install +where boot deliberately never calls the shard, the only way to import 67,496 names was `curl`. + +Four decisions were put before any code: + +| | Decided | +|---|---| +| Scope | **One page**, three sections, one nav row | +| The "activity view" (§14) | **The last import's own summary**, not a filtered feed. Rejected: a `prefix` filter on core's activity list plus a `ctx.activity.list` read helper — it would have made a `module-uo`-only phase a three-repo one with a `MODULE_API` bump, to re-read rows the panel can keep itself | +| A vanished key | **Held in the page, not a table** — see below | +| Import vs Update | **Two named buttons**, §6's own vocabulary, rather than one button and a `force` checkbox | + +**The review is in-session by construction, and that is why it needs no table.** The atlas persists +its equivalent (`shard_atlas_pending`) because *boot* re-parses the tree and would otherwise +re-prompt on every restart forever. An asset import only ever happens because somebody pressed a +button on this page, so the review is already in front of the person who caused it; declining is +not a decision to remember, it is not pressing the other button. What the panel adds is the +**pictures**: `body/820/a23` names nothing a human recognises, and "is it right that these +disappear?" cannot be answered from a list of keys. So `needsReview` now returns +`[{ key, file }]` and the page renders each one. + +`shard_asset_meta` gained a `last` block — what the import did, and who pressed it. It is written +**after** the rows commit, because the interesting half (how many atlas creatures resolved) does not +exist until another shard round trip has happened, and widening the rows-and-meta transaction to +cover a network call is how an import holds a write lock for the length of a timeout. It is +cosmetic, so a failure to write it is logged and swallowed rather than failing an import that has +already applied. + +#### The two defects, and why only this phase could find them + +Both are **deletions**, both predate phase 8, and both were invisible until a screen displayed the +numbers side by side on a stock rig. + +**One: every item picture reported as vanished.** The import diffs what the site holds against the +manifest, and a manifest is of one family by construction (§14 — one reply, one catalogue id). The +held side read the **whole table**. That was correct when phase 3 wrote it and stopped being correct +in phase 5, which put `static` and `land` rows in the same table: the body manifest never mentions +item art, so on the walk's rig **313 item pictures were staged for deletion** with a sentence saying +the shard had stopped offering them. The gate hid it for a while — an Update whose client files are +unchanged never reads a manifest — so the state that exposes it is the ordinary one: import, let the +warm pass run for a day, then patch the client. + +**Two: an approved vanish deleted the picture and kept the row.** `removeSprite` unlinked the file; +nothing deleted the row. So the catalogue still counted a portrait that was gone, the atlas +derivation could still point a creature page at a missing file, and the next forced import staged +the same key for review **again** — reporting "nothing was changed" about a file it had already +deleted. The removals now go into `saveAssets`'s own transaction, beside the rows and the meta. + +The third finding is smaller and the same shape: `countAssets()` was whole-table too, so the panel's +first render of a working install announced a **1,408-row creature catalogue** (1,095 portraits plus +313 item pictures) on the one screen an operator checks to see whether the import worked. + +**The rule worth keeping: after phase 5, `shard_assets` is three collections in one table, and every +read of it that feeds a decision has to say which.** Two of the three that did not were deletions. + --- ## 13. Visibility @@ -1590,11 +1651,18 @@ change every consumer *does* see, exactly as §7 intends. command explicitly and has no generic `/assets/*` forwarder, so `link` is in the phase too. The table now says so. -**Website admin** (`Admin → Shard`, admin-only): status, **Import**, **Update**, approve/reject for -a vanished key, and the existing path settings. Every action to the admin activity log, as -`shard.assets.*`. Phase 3 shipped the two that make it reachable — `GET /admin/shard/assets` and -`POST /admin/shard/assets/import`, mirroring the cliloc pair — so the phase could be accepted on a -real rig; the full panel is phase 8 (org lead, 2026-09-10). +**Website admin** — `Admin → Client Files`, admin-only, **built in phase 8** (§12.2). Status, +**Update**, **Re-import everything**, approve/decline for a vanished key, the item-art warm pass and +the cliloc path setting, in three sections on one page. Every action goes to the admin activity log +as `shard.assets.*` / `shard.clilocs.*`, and the panel additionally keeps the **last import's own +summary** beside the catalogue, because that log is one unfiltered list of every admin action on the +site and an import from three client patches ago is not findable in it. + +Phase 3 shipped the two routes that make it reachable — `GET /admin/shard/assets` and +`POST /admin/shard/assets/import`, mirroring the cliloc pair — so that phase could be accepted on a +real rig. The route surface did not grow in phase 8; what changed is that `needsReview` returns each +vanished key **with the picture the site currently serves for it**, and the status carries `linked` +and the `last` block. --- @@ -1629,7 +1697,7 @@ disagree, so a split bump means the next bundle silently fails to compose. | 5 | **DONE 2026-09-11.** Item statics and land on demand (§11.1): the `static` and `land` families, hue applied on the shard from `tiledata.mul`, the byte-bounded art cache, `assets.fetch` made family-aware, `families` on `assets.sources`. Website side: the warm pass, per-row `catalog` staleness, and pictures on the marketplace and the character sheet. **39,189 statics and 4,244 land tiles served; the only refusals are the 9,963 + 12,140 empty index slots §4.5 predicted.** Two traps found — the library's bitmap cache poisons a hued sprite, and `PartialHue` decides the picture from a file only the shard has. Protocol stays 8; `EXTRACTOR_VERSION` stays 2 | servuo-plugins, module-uo | | 6 | **DONE 2026-09-11, and not what this row said.** The measurement came first and changed the phase: a complete one-direction animation set is **174,453 frames / 281.5 MB**, not the ~119,000 estimated, and **the site displays still pictures** — so the deep keys and the bulk-fill switch were **not built** (§11.2, org lead 2026-09-11). What shipped is what the still-picture site was missing: the **73 bodies with no art at action 0 and real art deeper** (a horse at `body/820/a23`), the catalogue key carrying its action, the atlas join that reads it, and §4.10's per-body **action ceiling** — without which the fallback walk itself would serve **452 validated pictures of the next body**. Catalogue **1,022 → 1,095**; `EXTRACTOR_VERSION` 2 → 3; protocol stays 8 | servuo-plugins, module-uo | | 7 | **DONE 2026-09-14.** The atlas over the sidecar (§10); shared-filesystem requirement retired. The measurement came first again and changed the shape: `tree/