feat(assets): item pictures on the marketplace and the character sheet (Phase 5) #38
Reference in New Issue
Block a user
No description provided.
Delete Branch "feat/asset-bridge-p5"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Phase 5 of the Asset Bridge, website half (
docs/link/v8.md§5, §11, §11.1, §12). Pairs with servuo-plugins#32 and docs#240.linkneeded nothing — it forwards verbatim in both directions.Both places this site already knew an item's
(ItemID, hue)and could only print it as text now show the picture. The shard does the hueing: whether a hue repaints every pixel or only the grey ones is a flag intiledata.mul, which a browser has no way to read.Ingest warms; the route only serves
Org lead, 2026-09-11. A page never waits on the shard and never causes a fetch — it renders what is stored and leaves out what is not, which is the state every install was in before this phase and which every surface already handles. Fetching happens behind that, on a timer, from the keys the site's own rows name.
Fetching on first request was rejected on one number: the shard's asset plane serves one request at a time by design (§3.2), so a URL that fetched would let any anonymous visitor walk 49,152 ids × 3,000 hues through that single slot and park an operator's own import behind it. Warming from the site's own data has no such surface — the ceiling is the number of distinct
(item, hue)pairs the shard has already told us about.The wanted set is derived, not queued
SELECT DISTINCT item_id, hue FROM shard_vendor_items. Self-healing by construction: a restart loses nothing, and a key stops being wanted the moment the vendor row naming it is deleted. A queue table would need writing on the ingest path, draining, retrying, pruning and reconciling — for the same answer.The bounded in-memory hint set on top is only for the character sheet, which is fetched live from the shard per request and stored nowhere. Nothing on disk would ever name those keys, so noticing them as they go past is the only way a pass can find them.
Staleness without a manifest (§7)
Every row records the shard's
catalogid — a hash of the files that decide its bytes. A client patch changes it; a restart does not. So "is this picture out of date?" is a per-row column comparison, and pictures nobody looks at any more are simply never re-fetched, which is why this is lazy rather than a sweep.The alternative — a
staticmanifest family enumerating 39,189 rows with hashes — would cost a 34-second scan of the whole art file per Update to answer a question about maybe three hundred pictures.Three things worth not rediscovering
shard_asset_metais never written by a warm pass. It is the body catalogue's singleton — what an Update compares a manifest against — and a warm pass touching it would tell the body import that a client it never looked at is unchanged. The creature catalogue would quietly stop updating. Tested.h0is not a key. Hue 0 on the wire means "not hued", sostaticKeyproduces the plain key. The shard refuses/h0for the same reason; the two agreeing is what stops one PNG being stored twice under two names and diffed separately forever. Tested.An older overlay is a reported state, not a warning loop
assets.sourcesnow reports which families an overlay serves. A phase-3 or phase-4 plugin serves the creature catalogue and nothing else, and every static key sent to it comes back refused — once per pass, forever, with no picture ever appearing. Checked once instead, withcode: "UNSUPPORTED"and a sentence naming the fix.Added
POST /admin/shard/assets/warm— run a pass now instead of waiting for the timer;{force}recovers a wiped uploads volume,{limit}bounds it.GET /admin/shard/assetsnow reportsloaded.items/loaded.landandshard.families.shard_assets.catalogcolumn; pictures underuploads/items/, content-addressed like the creature portraits.arton market listings and on character-sheet equipment — a filename, never a URL, the same contractshard_spawn_creatures.artuses.ItemIconon the marketplace, the vendor page and the sheet, where it replaces the empty swatch the sheet has always drawn.Checks
🤖 Generated with Claude Code
https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4