feat(consumer): versioned IR manifest + drift-check (WHYNOT-WP-0003 T03-T07,T09)
Make ir/ the unit of versioned downstream consumption so consuming repos can pin a version, inspect it, and follow changes at their own pace. - T03 ir/manifest.json: per-version inventory + diff anchor with deterministic sha256-over-canonicalised-JSON hashes; no-churn generatedAt; manifest schema. - T07 ir/INDEX.md: human-readable catalog generated by make ir. - T04 .whynot-design.lock sync-point format + lock schema. - T05 npx @whynot/design drift: consumer drift-check (bin entry), exit 0/2/3, --json/--update/--manifest/--version/--lock. - T06 CONSUMING.md guide + examples/consumer-fixture/ runnable demo; README + MultiFrameworkSupport cross-links; fix README version pin (@0.3.0 not @v0.3.0). - T09 CONSUMER_CONTRACT_PARITY.md design-only note (live-UI parity deferred). T02 (publish) and T08 (showcase, blocked on WP-0002 T11) remain wait. Repo stays in dev mode; no outward publish performed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
39
ir/SCHEMA.md
39
ir/SCHEMA.md
@@ -24,11 +24,50 @@ ir/
|
||||
schema/
|
||||
tokens.schema.json ← JSON Schema for tokens.json (W3C DTCG)
|
||||
component.schema.json ← JSON Schema for each components/<Name>.json
|
||||
manifest.schema.json ← JSON Schema for manifest.json (version + hashes)
|
||||
tokens.json ← all design tokens, W3C DTCG format (emitted by T05)
|
||||
components/<Name>.json ← one contract per component (emitted by T05)
|
||||
exemplars/<Name>.{png,html} ← reference render from the designbook (emitted by T05)
|
||||
manifest.json ← per-version inventory + diff anchor (WHYNOT-WP-0003 T03)
|
||||
INDEX.md ← human-readable catalog (WHYNOT-WP-0003 T07)
|
||||
```
|
||||
|
||||
## Version manifest (`manifest.json`) — the diff anchor
|
||||
|
||||
`ir/manifest.json` is the unit of **versioned consumption**. A consuming repo never
|
||||
reads the Lit internals; it pins a published `@whynot/design@X.Y.Z` and tracks the
|
||||
manifest. Shape:
|
||||
|
||||
```json
|
||||
{
|
||||
"schemaVersion": "1.0.0",
|
||||
"designVersion": "0.3.0",
|
||||
"generatedAt": "2026-06-27T17:28:08.913Z",
|
||||
"tokensHash": "sha256:426f565a9ce6c36f",
|
||||
"components": [
|
||||
{ "name": "Button", "group": "atoms", "hash": "sha256:4a32713049e433dd" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- **Each `hash`** is `sha256:` + the first 16 hex chars of a sha256 over the
|
||||
*canonicalised* contract (keys sorted recursively, no insignificant whitespace).
|
||||
Canonicalisation makes the hash invariant to formatting and sensitive **only** to
|
||||
meaningful change — re-running `make ir` after a no-op edit yields the same hash.
|
||||
- **`tokensHash`** is a single coarse hash of the whole token set. Per-token diff
|
||||
granularity is a deliberate later refinement (start coarse, refine if consumers ask).
|
||||
- **`schemaVersion`** governs hash stability: any extractor change that would alter
|
||||
existing hashes *without* a real design change must bump it, so a consumer can tell
|
||||
a re-canonicalisation apart from a genuine design move. It is distinct from
|
||||
`designVersion` (the package/tag version) and from the component schema's own shape.
|
||||
- **`generatedAt`** is informational and never hashed; it is reused from the prior
|
||||
manifest when nothing hashed changed, so a no-op `make ir` produces no git churn.
|
||||
|
||||
The downstream consumer `drift` check (WHYNOT-WP-0003 T05) compares a target
|
||||
manifest against the consumer's adopted `.whynot-design.lock` and reports added /
|
||||
changed / removed components plus token changes — the mirror of the upstream adapter
|
||||
drift, sharing the `0` ok · `3` drift exit-code convention.
|
||||
|
||||
## Tokens — `ir/tokens.json`
|
||||
|
||||
Adopts the **W3C Design Tokens Community Group** format: every token is an object
|
||||
|
||||
Reference in New Issue
Block a user