SIGN IN SIGN UP

fix: guard claim epoch against int32 wrap (#6)

* fix: guard claim epoch against int32 wrap

epoch is compared against Int32Array claim slots but grew as a plain JS
number: past 2^31 the stored stamp truncates while the number keeps
growing, so claim tests never match again and conflict detection
silently turns off for the life of the process. Reachable in ~25 days
of SSR uptime at 1k merges/s once the recurring class vocabulary
outgrows the whole-string cache (every call then misses and bumps the
epoch).

Truncate the increment to int32 and clear the claim tables when it
wraps through 0 — unclaimed slots read as claimed there: static
conflicts drop every class and variant-context conflicts spin forever
in claimTest's probe loop.

All existing suites pass with the bug present, so tests/hardening.mjs
patches the epoch start into dist and diffs both boundary crossings
against tailwind-merge (the epoch-0 case in a child under a timeout,
since that regression is a hang). Size tripwire 10,500 -> 10,550: the
fix costs 20 gzip bytes over the 10,487 baseline and no correct guard
fits the old 13-byte headroom (smallest found was 10,501).

* ci: drop cache restore from the publish workflow

The Actions cache is writable from lower-privileged workflow runs, and
the release job publishes with provenance — install from the registry,
verified by the lockfile, instead of restoring a shared cache. Costs a
slower install on the rare release run.
S
shadcn committed
9018306b788de760eb9c1e0104a6daef512f08a0
Parent: 67e2d93
Committed by GitHub <noreply@github.com> on 9/1/2026, 6:48:34 PM