Skip to content

fix(agent): install a colour palette in one mutation, not one per token - #317

Merged
DavidBabinec merged 1 commit into
mainfrom
fix/palette-token-batch-write
Jul 31, 2026
Merged

fix(agent): install a colour palette in one mutation, not one per token#317
DavidBabinec merged 1 commit into
mainfrom
fix/palette-token-batch-write

Conversation

@DavidBabinec

@DavidBabinec DavidBabinec commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

site_set_color_tokens could report a successful batch update even when only part of the batch was persisted. This change makes palette updates atomic at the editor-store mutation boundary and turns refused writes into explicit errors.

Root cause

runSetColorTokens previously called createFrameworkColorToken once per token. Each call performed its own mutateSite, while collaboration document binding could temporarily mark the site as not writable during the same synchronous batch. Later writes were then refused as syncing.

The failure was silent because the per-token action returned a token without checking whether mutateSite accepted the write, and the runner reported every requested token as created.

Changes

  • Add upsertFrameworkColorTokens to create or update an entire color-token batch in one site mutation.
  • Plan slugs and category labels against the growing batch so in-batch uniqueness matches sequential updates.
  • Return an accepted result and fail the tool call when the collaboration gate refuses the batch.
  • Make the font-token, type-scale, and spacing-scale tool paths verify their writes instead of reporting unpersisted values as successful.

Verification

Added src/__tests__/collab/paletteBurstWrite.test.ts covering:

  • a multi-token palette is stored in one mutation
  • slugs remain unique within a batch
  • repeated updates modify existing tokens instead of creating suffixed duplicates
  • a refused batch returns ok: false and stores nothing

Full test suite: 6461 passing, 0 failing.

`site_set_color_tokens` looped `createFrameworkColorToken` once per token.
Each of those is its own site mutation, and any mutation that ensures a
not-yet-bound collab doc registers a write gate at `synced: false` — so
every remaining write in the same synchronous tick was refused with
`syncing`. The action returned a token object either way and the runner
recorded it as created, so the tool answered "14 tokens created" for a
palette of which only the first 7 reached the relay and the database.

Authored CSS then referenced `var(--case)` and `var(--rock)` that did not
exist. Nothing in the flow said so: the header simply rendered white.

Colour tokens now go through a single `upsertFrameworkColorTokens` action —
one mutation, one gate check — which plans slugs against a growing copy so
in-batch uniqueness and category canonicalization match what a sequence of
single-token calls produced. It returns `accepted`, and the runner reports a
refused batch as an error instead of a list of tokens nobody stored.

The font and scale runners had the same silent-success shape; both now read
their writes back and fail loudly when the value is absent.

Test: 8 tokens land in one mutation; slugs stay unique inside a batch;
re-running updates in place; a refused batch returns ok:false and stores
nothing.
@DavidBabinec
DavidBabinec merged commit fd40a7b into main Jul 31, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant