icon-registry: add an assetStatus value for shipped house-style art #160

Closed
opened 2026-09-18 18:10:04 +00:00 by peterswimm · 2 comments
Owner

ReservedToken.assetStatus in udg/icon-registry/src/types.ts is typed "openmoji" | "pending-pua". Neither value describes house-style art that has actually shipped. So the registry can't mark the delivered icons as shipped: the first 25 house-style icons, and the 20 spel.dim.* icons from #12.

Ask

  • Add a third assetStatus value for shipped house-style art, and move the delivered icons to it.
  • Rewrite or remove the "Placeholder implementation; adjust to match your canonical clustering" comment in registry.ts (around L262). The shipped artwork now fixes the clustering.

Split out of #12 when it closed. The details are in ville's 2026-08-25 delivery comment there.

`ReservedToken.assetStatus` in `udg/icon-registry/src/types.ts` is typed `"openmoji" | "pending-pua"`. Neither value describes house-style art that has actually shipped. So the registry can't mark the delivered icons as shipped: the first 25 house-style icons, and the 20 `spel.dim.*` icons from #12. ## Ask - Add a third `assetStatus` value for shipped house-style art, and move the delivered icons to it. - Rewrite or remove the "Placeholder implementation; adjust to match your canonical clustering" comment in `registry.ts` (around L262). The shipped artwork now fixes the clustering. Split out of #12 when it closed. The details are in ville's 2026-08-25 delivery comment there.
Member

Decided: add spelwork-pua, and land the whole thing as one change.

spelwork-pua because the other two values name a source — openmoji is an external library, pending-pua is a reserved slot with no art. spelwork-pua is the completed form of pending-pua. The code already uses that word in both places it matters: the credit line is "SPELWork Icon Registry by Toilville LLC", and getComplianceReport already sorts these into spelworkTokens. Toilville owns them; SPELWork is the source, and the field records the source.

The count

45 of the 46 tokens have delivered artwork, one SVG per token, none spare. The only token without art is spel.tribunal.pragmatic. That is where the 25 in the ask comes from — 20 seed plus 6 stage headers, minus that one.

Changing the type is not enough on its own

resolve.ts L46 reads:

const isPlaceholder =
  reserved.assetStatus === "pending-pua" || isPlaceholderGlyph(glyph);

isPlaceholderGlyph (L79) matches any four-character hex string. The four seed PUA tokens store their glyph as the string "E901", so they stay placeholders after the status moves. The stage and dimension tokens store the character itself and flip correctly. Move the icons without touching this and the registry contradicts itself — marked shipped, still resolving as missing.

Drop the second clause and trust assetStatus. The heuristic only existed because the field could not say "we drew it"; once it can, the guess is redundant, and it is wrong on its own terms — /^[E0-9A-F]{4}$/i also matches "FACE" or "1234". It has one caller, and reserveFutureToken sets isPlaceholder directly, so removing it costs nothing.

What lands together

  1. types.ts L22 — the third value.
  2. registry.ts — move the 45 delivered tokens; rewrite the L262 comment, since the family is now drawn to those 20 labels.
  3. resolve.ts — trust assetStatus, delete isPlaceholderGlyph.
  4. spel.tribunal.pragmatic → pending-pua. It is the one token with no art, and it currently claims openmoji while reusing ⚖️ from spel.tribunal.frame-invariant.
  5. registry.test.ts L78 and L87, resolve.test.ts L29-33, artifact.py L61-95 (it hand-copies the whole table), and README.md L60.

resolve.test.ts uses spel.guise as its pending example. That token becomes shipped, so the test needs a new subject — which is what item 4 provides.

Deferred

defaultGlyph holds two encodings: the seed stores "E901" as a string, the generated tokens store the character. types.ts L13 documents both. Normalising that touches every reader of the field, and item 3 removes the need for it here. Separate issue.

**Decided: add `spelwork-pua`, and land the whole thing as one change.** `spelwork-pua` because the other two values name a source — `openmoji` is an external library, `pending-pua` is a reserved slot with no art. `spelwork-pua` is the completed form of `pending-pua`. The code already uses that word in both places it matters: the credit line is "SPELWork Icon Registry by Toilville LLC", and `getComplianceReport` already sorts these into `spelworkTokens`. Toilville owns them; SPELWork is the source, and the field records the source. ## The count 45 of the 46 tokens have delivered artwork, one SVG per token, none spare. The only token without art is `spel.tribunal.pragmatic`. That is where the 25 in the ask comes from — 20 seed plus 6 stage headers, minus that one. ## Changing the type is not enough on its own `resolve.ts` L46 reads: ```ts const isPlaceholder = reserved.assetStatus === "pending-pua" || isPlaceholderGlyph(glyph); ``` `isPlaceholderGlyph` (L79) matches any four-character hex string. The four seed PUA tokens store their glyph as the string `"E901"`, so they stay placeholders after the status moves. The stage and dimension tokens store the character itself and flip correctly. Move the icons without touching this and the registry contradicts itself — marked shipped, still resolving as missing. Drop the second clause and trust `assetStatus`. The heuristic only existed because the field could not say "we drew it"; once it can, the guess is redundant, and it is wrong on its own terms — `/^[E0-9A-F]{4}$/i` also matches `"FACE"` or `"1234"`. It has one caller, and `reserveFutureToken` sets `isPlaceholder` directly, so removing it costs nothing. ## What lands together 1. `types.ts` L22 — the third value. 2. `registry.ts` — move the 45 delivered tokens; rewrite the L262 comment, since the family is now drawn to those 20 labels. 3. `resolve.ts` — trust `assetStatus`, delete `isPlaceholderGlyph`. 4. `spel.tribunal.pragmatic` → `pending-pua`. It is the one token with no art, and it currently claims `openmoji` while reusing `⚖️` from `spel.tribunal.frame-invariant`. 5. `registry.test.ts` L78 and L87, `resolve.test.ts` L29-33, `artifact.py` L61-95 (it hand-copies the whole table), and `README.md` L60. `resolve.test.ts` uses `spel.guise` as its pending example. That token becomes shipped, so the test needs a new subject — which is what item 4 provides. ## Deferred `defaultGlyph` holds two encodings: the seed stores `"E901"` as a string, the generated tokens store the character. `types.ts` L13 documents both. Normalising that touches every reader of the field, and item 3 removes the need for it here. Separate issue.
Member

@peterswimm implemented in PR #163 (fix/icon-registry-spelwork-pua-160).

@peterswimm implemented in PR #163 (fix/icon-registry-spelwork-pua-160).
ville closed this issue 2026-09-24 10:33:03 +00:00
Sign in to join this conversation.
No description provided.