---
id: LSN-0042
ticket: palette-management-in-studio
title: Schema-Driven Palette Authoring and Local Metadata Events
created: 2026-04-23
tags:
  - studio
  - glyph-bank
  - palette-management
  - color-schema
  - local-events
---

## Context

The glyph-bank palette workflow originally treated palette candidates as extracted tile artifacts. That made grouping, recoloring, and final bank palette selection compete in the same surface.

The completed palette-management work split the workflow into two authored layers:

1. `Color Schema Groups`, where selected tiles are grouped into a shared index structure.
2. `Palette Overhauling`, where palettes are authored and selected against already-ready schemas.

The durable implementation lesson is that schema edits, palette edits, and build selection are all local glyph-material metadata operations first. They should update local metadata projections directly instead of forcing a full asset-details reload.

## Key Decisions

### Schema Owns Index Semantics

**What:** A schema is the authored index structure for a group of selected glyph-bank tiles. It owns `material_indices`, artifact bindings, fingerprint snapshots, version, and status.

**Why:** The source PNG stays unchanged, while Studio records how tile colors map into stable bank-local indices. This keeps tile grouping separate from recoloring.

**Trade-offs:** Schema invalidation must be explicit. When selected tile fingerprints drift, the schema can become inconsistent and dependent palettes become invalid or stale.

### Palettes Are Schema-Scoped

**What:** A palette always belongs to exactly one schema. It stores concrete `#RRGGBB` colors for that schema's visible indices and carries the schema version it was authored against.

**Why:** Multiple recolors can safely exist for one index structure without duplicating tile grouping metadata.

**Trade-offs:** Duplicate detection must use the tuple `schemaId + colors + order`, not display name or source tile identity.

### Original Palettes Are Synthetic and Read-Only

**What:** The original palette is the synthetic `schema-<schemaId>-original` projection derived from the current schema colors. It is not a persisted user palette.

**Why:** Updating the schema should update the original palette automatically. The original represents the schema's source color meaning, not a user-authored recolor.

**Trade-offs:** Users cannot edit or delete the original palette directly. If they want a changed palette, they create or edit a separate persisted palette for the same schema.

### Local Metadata Events Beat Global Reloads

**What:** Schema and palette metadata mutations should publish `StudioGlyphMaterialMetadataChangedEvent` and let interested sections rebind local state.

**Why:** Global asset refresh and selection events can close edit mode, reset form state, and make small metadata edits feel destructive.

**Trade-offs:** Controls must keep their local coordinators robust: stale button handlers should read the current view model at click time, and metadata replacement must preserve edit-mode drafts where possible.

## Patterns and Algorithms

### `glyph-material.json`

`glyph-material.json` is the Studio-owned support file for glyph-bank material authoring. It persists schemas and user-authored palettes, while derived original palettes remain a view projection.

Schema records store:

- stable `schema_id`
- `status`
- `version`
- dense visible `material_indices`
- artifact bindings with fingerprint snapshots

Palette records store:

- stable `palette_id`
- persisted `name`
- parent `schema_id`
- schema `version`
- concrete `colors`

### Palette Names

Palette names are persisted even when the user leaves the name field blank. The blank-name path resolves to a deterministic, simple generated name such as `snow white`, `fog twist`, or `ember bloom`.

The generated name is a convenience label only. Palette identity remains `palette_id`, and duplicate detection remains schema plus ordered colors.

### Original Palette Projection

Every ready schema projects a synthetic original palette from the schema's current `material_indices`.

This projection must always exist in the palette view, even if a user-authored palette has the same colors. A saved palette with the same schema and colors is still user-authored and can be deleted.

## Pitfalls

- Do not treat same colors as proof that a palette is original. Original means "synthetic schema projection", not "matches current schema colors".
- Do not publish global asset refresh events for local schema or palette metadata changes. Use local metadata events unless pack/runtime state truly changed.
- Do not let button handlers capture stale preview objects. Fetch the current coordinator view model at click time for destructive actions.
- Do not let blank palette names remain blank on disk. Resolve the generated name before persisting.
- Do not open the palette wizard for synthetic original palettes. They are read-only projections.

## Takeaways

- Schema formation and palette authoring are separate lifecycle stages.
- Original palettes are derived views, not persisted editable records.
- User-created palettes remain editable and removable even when they share a schema or colors with an original.
- Local metadata events preserve form continuity better than full asset refreshes.
