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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
This commit is contained in:
2026-09-14 08:10:49 -05:00
parent ae0efe26b3
commit fc2d4872f6
4 changed files with 83 additions and 11 deletions

View File

@@ -82,7 +82,7 @@ account-linking routes and the sidecar config under `/admin/uo-link` are in the
| GET | `/shard/clilocs` | cliloc-table status (`adminOnly`): every source found now (base first, then `custom/` overlays in merge order), what each contributed at the last import, readability, drift across the set, the entry count, and `missingSources`. `configured:false` is a supported state — item names then render as ids. No public counterpart: the table is never served *as* a table. |
| POST | `/shard/clilocs/import` | reload after a client patch or an overlay edit; `{force}` ignores the hash gate, `{approve}` accepts a **vanished** source (refused by default — see the table notes above). **A missing path — or the likely mistake of pointing at the client's own COMPRESSED `Cliloc.enu` — answers 200 with `status:"unavailable"` and a `code`, not 500.** `COMPRESSED` is called out by name: a 500 would say only "something broke", and the operator needs to be told which file to convert. |
| GET | `/shard/assets` | client-asset import status (`adminOnly`, Protocol 8): the imported body catalogue, how many sprites are on disk, how many atlas creatures resolved to a body id, and the shard's own client files beside them. `drift:true` means the client was patched. `shard.imaging.ok:false` is the named `NO_IMAGING` state — a Linux shard host with no `libgdiplus` cannot decode a sprite at all, and the reason names the package. No public counterpart: the pictures are served as ordinary files under `/uploads`. |
| POST | `/shard/assets/import` | import creature artwork from the shard's UO client; `{force}` ignores the hash gate, `{approve}` accepts a catalogue that no longer offers assets this site holds (refused by default — an unmounted client volume and a deliberate downgrade are indistinguishable, and the wrong guess deletes artwork). **This is the ONLY thing that imports** — boot deliberately never calls the shard. An operator's `spawnAtlas.art.json` always wins over an imported sprite. A body this client has no art for is **not** a failure: about half the addressable body range is in that state on a stock client. |
| POST | `/shard/assets/import` | import creature artwork from the shard's UO client; `{force}` ignores the hash gate, `{approve}` accepts a catalogue that no longer offers assets this site holds (refused by default — an unmounted client volume and a deliberate downgrade are indistinguishable, and the wrong guess deletes artwork; a `needsReview` reply names each vanished key **with the picture the site is currently serving for it**, because a key is not something anyone can look at). **This is the ONLY thing that imports** — boot deliberately never calls the shard. An operator's `spawnAtlas.art.json` always wins over an imported sprite. A body this client has no art for is **not** a failure: about half the addressable body range is in that state on a stock client. |
| POST | `/shard/assets/warm` | fetch item and land pictures this site is missing, now, instead of waiting for the warm timer (`adminOnly`, Protocol 8 phase 5). The pass works out which item pictures the site's own rows name — every distinct (ItemID, hue) on a player vendor, plus anything a character sheet has shown since the last pass — and fetches the ones it does not hold, **hued on the shard**, into `uploads/items/`. There is deliberately **no manifest and no bulk import**: the client addresses 49,152 item graphics times 3,000 hues, so the working set is what the site displays. `{force}` re-fetches pictures already held (how an operator recovers a wiped uploads volume); `{limit}` bounds one pass, default 400, because the shard serves one asset request at a time. A plugin overlay older than phase 5 answers `status:"unavailable"`, `code:"UNSUPPORTED"` with a sentence naming the fix. |
| PUT | `/shard/clilocs/path` | point the site at a different cliloc base file or directory (persisted as `cliloc_client_path`, which wins over `UO_CLIENT_PATH`). Overlays are read from `custom/` beside it either way. Blank clears it. Deliberately **does not import**, same reasoning as the atlas path. |