feat(adapter): Lit component scaffold + drift report (WHYNOT-WP-0002 T07)
Extend make adapt-lit beyond tokens: parse src/elements/*.js, compare each IR component contract against its <wn-*> element, and emit per-component drift reports + a machine roll-up (adapters/lit/drift/), with write-once stubs (adapters/lit/stubs/) for genuinely new components. Never overwrites hand-authored sources. - Severity split: actionable drift (prop-missing, attribute-mismatch, variant-axis-missing, tag-mismatch) gates with exit 3; non-portable + prop-extra are informational (the IR carries React style/onClick; Lit is richer than the minimal designbook) and don't gate. - Current state: 7 ok, 3 actionable drift for human triage — PipelineStrip (wn-pipeline-strip vs hand-authored wn-pipeline rename), PageHeader (actions is a slot, not a prop), Sidebar (IR 'current' axis absent on the element). - _report.json reuses generatedAt/irRef when drift is unchanged (no git churn). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
14
adapters/lit/drift/Button.md
Normal file
14
adapters/lit/drift/Button.md
Normal file
@@ -0,0 +1,14 @@
|
||||
<!-- @generated by make adapt-lit (WHYNOT-WP-0002 T07) — overwritten each run; do not hand-edit. -->
|
||||
# Drift — Button `<wn-button>`
|
||||
|
||||
**Status:** ok — ✓ in sync with the IR contract.
|
||||
|
||||
| severity | kind | prop | detail |
|
||||
| --- | --- | --- | --- |
|
||||
| info | non-portable | `onClick` | type=function; not attribute-mappable — handle explicitly, never drop. |
|
||||
| info | non-portable | `style` | type=object; not attribute-mappable — handle explicitly, never drop. |
|
||||
| info | prop-extra | `size` | on <wn-button> (attribute 'size'), not in IR contract. |
|
||||
| info | prop-extra | `iconEnd` | on <wn-button> (attribute 'icon-end'), not in IR contract. |
|
||||
| info | prop-extra | `type` | on <wn-button> (attribute 'type'), not in IR contract. |
|
||||
| info | prop-extra | `disabled` | on <wn-button> (attribute 'disabled'), not in IR contract. |
|
||||
| info | prop-extra | `href` | on <wn-button> (attribute 'href'), not in IR contract. |
|
||||
9
adapters/lit/drift/Eyebrow.md
Normal file
9
adapters/lit/drift/Eyebrow.md
Normal file
@@ -0,0 +1,9 @@
|
||||
<!-- @generated by make adapt-lit (WHYNOT-WP-0002 T07) — overwritten each run; do not hand-edit. -->
|
||||
# Drift — Eyebrow `<wn-eyebrow>`
|
||||
|
||||
**Status:** ok — ✓ in sync with the IR contract.
|
||||
|
||||
| severity | kind | prop | detail |
|
||||
| --- | --- | --- | --- |
|
||||
| info | non-portable | `style` | type=object; not attribute-mappable — handle explicitly, never drop. |
|
||||
| info | prop-extra | `strong` | on <wn-eyebrow> (attribute 'strong'), not in IR contract. |
|
||||
8
adapters/lit/drift/Icon.md
Normal file
8
adapters/lit/drift/Icon.md
Normal file
@@ -0,0 +1,8 @@
|
||||
<!-- @generated by make adapt-lit (WHYNOT-WP-0002 T07) — overwritten each run; do not hand-edit. -->
|
||||
# Drift — Icon `<wn-icon>`
|
||||
|
||||
**Status:** ok — ✓ in sync with the IR contract.
|
||||
|
||||
| severity | kind | prop | detail |
|
||||
| --- | --- | --- | --- |
|
||||
| info | non-portable | `style` | type=object; not attribute-mappable — handle explicitly, never drop. |
|
||||
9
adapters/lit/drift/PageHeader.md
Normal file
9
adapters/lit/drift/PageHeader.md
Normal file
@@ -0,0 +1,9 @@
|
||||
<!-- @generated by make adapt-lit (WHYNOT-WP-0002 T07) — overwritten each run; do not hand-edit. -->
|
||||
# Drift — PageHeader `<wn-page-header>`
|
||||
|
||||
**Status:** drift — ⚠ drift detected — resolve per `.claude/rules/designbook-propagation.md`.
|
||||
|
||||
| severity | kind | prop | detail |
|
||||
| --- | --- | --- | --- |
|
||||
| **drift** | prop-missing | `actions` | in IR (attribute 'actions'), absent on <wn-page-header> |
|
||||
| info | prop-extra | `hasActions` | on <wn-page-header> (attribute 'hasactions'), not in IR contract. |
|
||||
8
adapters/lit/drift/PipelineStrip.md
Normal file
8
adapters/lit/drift/PipelineStrip.md
Normal file
@@ -0,0 +1,8 @@
|
||||
<!-- @generated by make adapt-lit (WHYNOT-WP-0002 T07) — overwritten each run; do not hand-edit. -->
|
||||
# Drift — PipelineStrip `<wn-pipeline-strip>`
|
||||
|
||||
**Status:** drift — ⚠ drift detected — resolve per `.claude/rules/designbook-propagation.md`.
|
||||
|
||||
| severity | kind | prop | detail |
|
||||
| --- | --- | --- | --- |
|
||||
| **drift** | tag-mismatch | — | IR contract tag 'wn-pipeline-strip' has no element; 'wn-pipeline' looks like the hand-authored counterpart (rename — resolve in Claude Design or realign the element). |
|
||||
11
adapters/lit/drift/Sidebar.md
Normal file
11
adapters/lit/drift/Sidebar.md
Normal file
@@ -0,0 +1,11 @@
|
||||
<!-- @generated by make adapt-lit (WHYNOT-WP-0002 T07) — overwritten each run; do not hand-edit. -->
|
||||
# Drift — Sidebar `<wn-sidebar>`
|
||||
|
||||
**Status:** drift — ⚠ drift detected — resolve per `.claude/rules/designbook-propagation.md`.
|
||||
|
||||
| severity | kind | prop | detail |
|
||||
| --- | --- | --- | --- |
|
||||
| **drift** | prop-missing | `current` | in IR (attribute 'current'), absent on <wn-sidebar> |
|
||||
| **drift** | variant-axis-missing | `current` | IR variant axis 'current' (doc:) has no Lit property. |
|
||||
| info | non-portable | `onNav` | type=function; not attribute-mappable — handle explicitly, never drop. |
|
||||
| info | prop-extra | `activation` | on <wn-sidebar> (attribute 'activation'), not in IR contract. |
|
||||
8
adapters/lit/drift/StageDot.md
Normal file
8
adapters/lit/drift/StageDot.md
Normal file
@@ -0,0 +1,8 @@
|
||||
<!-- @generated by make adapt-lit (WHYNOT-WP-0002 T07) — overwritten each run; do not hand-edit. -->
|
||||
# Drift — StageDot `<wn-stage-dot>`
|
||||
|
||||
**Status:** ok — ✓ in sync with the IR contract.
|
||||
|
||||
| severity | kind | prop | detail |
|
||||
| --- | --- | --- | --- |
|
||||
| info | non-portable | `style` | type=object; not attribute-mappable — handle explicitly, never drop. |
|
||||
8
adapters/lit/drift/Stamp.md
Normal file
8
adapters/lit/drift/Stamp.md
Normal file
@@ -0,0 +1,8 @@
|
||||
<!-- @generated by make adapt-lit (WHYNOT-WP-0002 T07) — overwritten each run; do not hand-edit. -->
|
||||
# Drift — Stamp `<wn-stamp>`
|
||||
|
||||
**Status:** ok — ✓ in sync with the IR contract.
|
||||
|
||||
| severity | kind | prop | detail |
|
||||
| --- | --- | --- | --- |
|
||||
| info | non-portable | `style` | type=object; not attribute-mappable — handle explicitly, never drop. |
|
||||
8
adapters/lit/drift/Tag.md
Normal file
8
adapters/lit/drift/Tag.md
Normal file
@@ -0,0 +1,8 @@
|
||||
<!-- @generated by make adapt-lit (WHYNOT-WP-0002 T07) — overwritten each run; do not hand-edit. -->
|
||||
# Drift — Tag `<wn-tag>`
|
||||
|
||||
**Status:** ok — ✓ in sync with the IR contract.
|
||||
|
||||
| severity | kind | prop | detail |
|
||||
| --- | --- | --- | --- |
|
||||
| info | non-portable | `style` | type=object; not attribute-mappable — handle explicitly, never drop. |
|
||||
11
adapters/lit/drift/TopNav.md
Normal file
11
adapters/lit/drift/TopNav.md
Normal file
@@ -0,0 +1,11 @@
|
||||
<!-- @generated by make adapt-lit (WHYNOT-WP-0002 T07) — overwritten each run; do not hand-edit. -->
|
||||
# Drift — TopNav `<wn-top-nav>`
|
||||
|
||||
**Status:** ok — ✓ in sync with the IR contract.
|
||||
|
||||
| severity | kind | prop | detail |
|
||||
| --- | --- | --- | --- |
|
||||
| info | non-portable | `onNew` | type=function; not attribute-mappable — handle explicitly, never drop. |
|
||||
| info | prop-extra | `logoSrc` | on <wn-top-nav> (attribute 'logo-src'), not in IR contract. |
|
||||
| info | prop-extra | `brand` | on <wn-top-nav> (attribute 'brand'), not in IR contract. |
|
||||
| info | prop-extra | `slug` | on <wn-top-nav> (attribute 'slug'), not in IR contract. |
|
||||
222
adapters/lit/drift/_report.json
Normal file
222
adapters/lit/drift/_report.json
Normal file
@@ -0,0 +1,222 @@
|
||||
{
|
||||
"stack": "lit",
|
||||
"generatedAt": "2026-06-30T07:01:40.219Z",
|
||||
"irRef": "17f2ad9",
|
||||
"components": [
|
||||
{
|
||||
"name": "Button",
|
||||
"status": "ok",
|
||||
"tag": "wn-button",
|
||||
"issues": [
|
||||
{
|
||||
"kind": "non-portable",
|
||||
"prop": "onClick",
|
||||
"detail": "type=function; not attribute-mappable — handle explicitly, never drop.",
|
||||
"severity": "info"
|
||||
},
|
||||
{
|
||||
"kind": "non-portable",
|
||||
"prop": "style",
|
||||
"detail": "type=object; not attribute-mappable — handle explicitly, never drop.",
|
||||
"severity": "info"
|
||||
},
|
||||
{
|
||||
"kind": "prop-extra",
|
||||
"prop": "size",
|
||||
"detail": "on <wn-button> (attribute 'size'), not in IR contract.",
|
||||
"severity": "info"
|
||||
},
|
||||
{
|
||||
"kind": "prop-extra",
|
||||
"prop": "iconEnd",
|
||||
"detail": "on <wn-button> (attribute 'icon-end'), not in IR contract.",
|
||||
"severity": "info"
|
||||
},
|
||||
{
|
||||
"kind": "prop-extra",
|
||||
"prop": "type",
|
||||
"detail": "on <wn-button> (attribute 'type'), not in IR contract.",
|
||||
"severity": "info"
|
||||
},
|
||||
{
|
||||
"kind": "prop-extra",
|
||||
"prop": "disabled",
|
||||
"detail": "on <wn-button> (attribute 'disabled'), not in IR contract.",
|
||||
"severity": "info"
|
||||
},
|
||||
{
|
||||
"kind": "prop-extra",
|
||||
"prop": "href",
|
||||
"detail": "on <wn-button> (attribute 'href'), not in IR contract.",
|
||||
"severity": "info"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Eyebrow",
|
||||
"status": "ok",
|
||||
"tag": "wn-eyebrow",
|
||||
"issues": [
|
||||
{
|
||||
"kind": "non-portable",
|
||||
"prop": "style",
|
||||
"detail": "type=object; not attribute-mappable — handle explicitly, never drop.",
|
||||
"severity": "info"
|
||||
},
|
||||
{
|
||||
"kind": "prop-extra",
|
||||
"prop": "strong",
|
||||
"detail": "on <wn-eyebrow> (attribute 'strong'), not in IR contract.",
|
||||
"severity": "info"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Icon",
|
||||
"status": "ok",
|
||||
"tag": "wn-icon",
|
||||
"issues": [
|
||||
{
|
||||
"kind": "non-portable",
|
||||
"prop": "style",
|
||||
"detail": "type=object; not attribute-mappable — handle explicitly, never drop.",
|
||||
"severity": "info"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "PageHeader",
|
||||
"status": "drift",
|
||||
"tag": "wn-page-header",
|
||||
"issues": [
|
||||
{
|
||||
"kind": "prop-missing",
|
||||
"prop": "actions",
|
||||
"detail": "in IR (attribute 'actions'), absent on <wn-page-header>",
|
||||
"severity": "drift"
|
||||
},
|
||||
{
|
||||
"kind": "prop-extra",
|
||||
"prop": "hasActions",
|
||||
"detail": "on <wn-page-header> (attribute 'hasactions'), not in IR contract.",
|
||||
"severity": "info"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "PipelineStrip",
|
||||
"status": "drift",
|
||||
"tag": "wn-pipeline-strip",
|
||||
"issues": [
|
||||
{
|
||||
"kind": "tag-mismatch",
|
||||
"expected": "wn-pipeline-strip",
|
||||
"actual": "wn-pipeline",
|
||||
"detail": "IR contract tag 'wn-pipeline-strip' has no element; 'wn-pipeline' looks like the hand-authored counterpart (rename — resolve in Claude Design or realign the element).",
|
||||
"severity": "drift"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Sidebar",
|
||||
"status": "drift",
|
||||
"tag": "wn-sidebar",
|
||||
"issues": [
|
||||
{
|
||||
"kind": "prop-missing",
|
||||
"prop": "current",
|
||||
"detail": "in IR (attribute 'current'), absent on <wn-sidebar>",
|
||||
"severity": "drift"
|
||||
},
|
||||
{
|
||||
"kind": "non-portable",
|
||||
"prop": "onNav",
|
||||
"detail": "type=function; not attribute-mappable — handle explicitly, never drop.",
|
||||
"severity": "info"
|
||||
},
|
||||
{
|
||||
"kind": "variant-axis-missing",
|
||||
"prop": "current",
|
||||
"detail": "IR variant axis 'current' (doc:) has no Lit property.",
|
||||
"severity": "drift"
|
||||
},
|
||||
{
|
||||
"kind": "prop-extra",
|
||||
"prop": "activation",
|
||||
"detail": "on <wn-sidebar> (attribute 'activation'), not in IR contract.",
|
||||
"severity": "info"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "StageDot",
|
||||
"status": "ok",
|
||||
"tag": "wn-stage-dot",
|
||||
"issues": [
|
||||
{
|
||||
"kind": "non-portable",
|
||||
"prop": "style",
|
||||
"detail": "type=object; not attribute-mappable — handle explicitly, never drop.",
|
||||
"severity": "info"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Stamp",
|
||||
"status": "ok",
|
||||
"tag": "wn-stamp",
|
||||
"issues": [
|
||||
{
|
||||
"kind": "non-portable",
|
||||
"prop": "style",
|
||||
"detail": "type=object; not attribute-mappable — handle explicitly, never drop.",
|
||||
"severity": "info"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Tag",
|
||||
"status": "ok",
|
||||
"tag": "wn-tag",
|
||||
"issues": [
|
||||
{
|
||||
"kind": "non-portable",
|
||||
"prop": "style",
|
||||
"detail": "type=object; not attribute-mappable — handle explicitly, never drop.",
|
||||
"severity": "info"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TopNav",
|
||||
"status": "ok",
|
||||
"tag": "wn-top-nav",
|
||||
"issues": [
|
||||
{
|
||||
"kind": "non-portable",
|
||||
"prop": "onNew",
|
||||
"detail": "type=function; not attribute-mappable — handle explicitly, never drop.",
|
||||
"severity": "info"
|
||||
},
|
||||
{
|
||||
"kind": "prop-extra",
|
||||
"prop": "logoSrc",
|
||||
"detail": "on <wn-top-nav> (attribute 'logo-src'), not in IR contract.",
|
||||
"severity": "info"
|
||||
},
|
||||
{
|
||||
"kind": "prop-extra",
|
||||
"prop": "brand",
|
||||
"detail": "on <wn-top-nav> (attribute 'brand'), not in IR contract.",
|
||||
"severity": "info"
|
||||
},
|
||||
{
|
||||
"kind": "prop-extra",
|
||||
"prop": "slug",
|
||||
"detail": "on <wn-top-nav> (attribute 'slug'), not in IR contract.",
|
||||
"severity": "info"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user