Skip to content

Add check:cards — enforce the style-library card contract - #12

Open
Mimmo2026 wants to merge 1 commit into
nateherkai:mainfrom
Mimmo2026:pr/check-cards
Open

Mimmo2026 wants to merge 1 commit into
nateherkai:mainfrom
Mimmo2026:pr/check-cards

Conversation

@Mimmo2026

Copy link
Copy Markdown

What

Adds npm run check:cards, a mechanical gate for the card contract in style-library/GUIDE.md.

style-library/SKILL.md already warns that the catalog holds "draft resources, not a promise that every card has passed rendered QA". Nothing checked the contract itself, so a card that Agent 3 cannot mount — or whose own default copy overflows the slot limit it declares — only surfaces at render time.

It checks: root attributes, exactly one timeline keyed to the composition id, slots declared in both directions, default copy against its own maxChars, determinism, tier background discipline, standalone GSAP loading, and token use.

What it found in the shipped library — 21 failures across 406 cards

15 × slot-overflow. A card's own default copy exceeds the maxChars its style.json entry declares, so Agent 3 is told a limit the card already breaks:

Card Slot Default Declared
01-vox-explainer/.../t2-lb-definition.html detail 100 70
01-vox-explainer/.../t2-lb-spotlight.html detail 96 70
01-vox-explainer/.../t1-stat-footnote.html footnote 96 90
01-vox-explainer/.../t2-lb-pullquote.html term 38 22
01-vox-explainer/.../t1-overview-grid6.html g1 27 22

(ten more, all in 01-vox-explainer)

3 × undeclared slot. Present in the HTML, absent from style.json, so they can never be filled:

  • t1-stat-trend.htmlsign-wedge
  • t1-stat-tape.htmlheadline-display
  • t1-stat-spotlight.htmlstat-blur

3 × determinism. GUIDE requires cards be deterministic — no Date.now(), no unseeded Math.random():

  • 02-kallaway/.../t1-section-drift-grid.htmlMath.random()
  • 02-kallaway/.../t1-section-particles.htmlMath.random()
  • 02-kallaway/.../t2-lt-clockname.htmlDate.now()

These 21 are reported, not fixed. Raising a declared cap and shortening the default copy are different calls, and seeding a particle field changes how it looks — those are yours to make.

What this PR does fix

Two defects that are unambiguous and both live in _blueprint, so every scaffolded style inherits them:

  1. Blueprint cards used gsap without loading it. Every shipped card in 01/02 pulls gsap@3.14.2 from jsDelivr; the blueprint omits it, so a card scaffolded from it cannot preview or render standalone — which is exactly what GUIDE says a card must be able to do.
  2. The blueprint's tier2 card hardcoded rgba(0, 0, 0, 0.55) instead of a token, against its own "never hardcode" rule. Added --scrim to the blueprint tokens; output is identical.

After both, a freshly scaffolded style passes check:cards with 0 failures and 0 warnings.

Known limits

  • The hardcoded warning is noisy on the existing styles (510 hits, mostly literal rgba inside gradients). It is a warning, never a failure — the signal is in the failures.
  • Cards that attach data-slot in JavaScript at runtime (14 instances) are reported as unverifiable warnings rather than failures, since a static scan cannot see them.
  • A clean pass is the contract only. It does not render. docs/SHORT-FORM.md already says validators "do not prove a compelling hook, factual claims, rights to footage, correct visual cropping, or audible sync" — that still stands, and the script says so on every run.

No new dependencies. npm run check and npm test both still pass.

GUIDE.md defines what every card MUST do and style-library/SKILL.md warns the
catalog holds 'draft resources, not a promise that every card has passed
rendered QA'. Nothing checked the contract itself, so a card that cannot mount,
or whose default copy overflows its own declared slot, surfaces only at render.

Checks root attributes, exactly one timeline keyed to the composition id, slots
declared both ways, default copy against its own maxChars, determinism, tier
background discipline, standalone GSAP loading, and token use.

Run against the shipped library it reports 21 failures (detail in the PR body).
Those are left for you to judge - raising a cap and shortening copy are
different calls, and seeding a particle field changes its look.

Two are fixed here because they are unambiguous and both live in _blueprint,
so every scaffolded style inherits them:
  - cards used gsap without loading it, so they could not render standalone
  - the tier2 card hardcoded rgba(0,0,0,0.55) instead of a token

After both, a freshly scaffolded style passes clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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