Frontend Compliance Rule Index
This page is an index, not a second copy of the contract. The Portable UI Contract owns the normative rule statements; the links below provide detailed implementation guidance.
| Rule | Detailed guidance | Deterministic result |
|---|---|---|
| FE-PORT-001 | Portable UI Contract | Reject private portability assumptions |
| FE-UI-001 | Portable UI Contract | Reject raw or hand-rolled standard controls |
| FE-UI-002 | Portable UI Contract | Require affordance analysis |
| FE-UI-003 | Portable UI Contract | Require sibling contract and alternate-theme evidence |
| FE-UI-004 | Portable UI Contract | Require PrimeVue setup when controls exist |
| FE-UI-005 | Portable UI Contract | Reject invented props and APIs |
| FE-TW-001 | Tailwind Contract | Resolve selected Wippy preset |
| FE-TW-002 | Tailwind Contract | Reject compile-time values documented as runtime |
| FE-TW-003 | Tailwind Contract | Reject fixed sibling values without invariant classification |
| FE-TW-004 | Tailwind Contract | Reject protected mapping overrides |
| FE-TOKEN-001 | Token Catalogue | Reject undeclared --p-* references |
| FE-TOKEN-002 | Token Catalogue | Reject inferred or invented token names |
| FE-STYLE-001 | Theme Authoring | Reject private facade classes and module-local .p-* theming |
| FE-A11Y-001 | Portable UI Contract | Reject invalid or inaccessible custom controls |
Required checker groups
- Token CSS parsed with PostCSS; generated token snapshot compared byte-for-byte.
- Actual Tailwind configuration resolved and representative utilities compiled.
- Emitted declarations classified as runtime variable, compiled constant, arbitrary literal, or internal/transient.
- Raw controls, missing PrimeVue setup, protected mapping overrides, undeclared tokens, private facade dependencies, and contract hash drift rejected.
- Import-map externals compared with the complete pinned snapshot.
- Build output checked against the configured registry and served asset.
- Theme switching uses
host.setThemeMode()and verifies propagated AppConfig state; direct theme-class manipulation and internal proxy wires are rejected. - Generated catalogues checked for provenance, version tuple, and source hashes.
- Copyable examples parsed, built where applicable, and checked for nested interactive content.
- Project-bound mode returns exactly
UNSUPPORTED, and standard CI fails.
Promptmap may generate leads. It is not evidence for token existence, utility resolution, reachability, or deletion.
Generated publication gates
The generated token and Tailwind sections may not contain a pending marker at publication. Every new runtime token needs a real Wippy CSS consumer, a computed-style mutation test, and a documented portable-consumer purpose.
Publication keeps runtime evidence outside the repository. Set:
WIPPY_THEME_ROOTto the selected@wippy-fe/themepackage.WIPPY_FE_EVIDENCE_ROOTto the release evidence directory containingruntime-acceptance-evidence.json,visual-evidence-index.json, their relative scenario manifests, and screenshots.WIPPY_FE_RUNTIME_EVIDENCE_SHA256to the lowercase SHA-256 of the exactruntime-acceptance-evidence.jsonbytes.
FRONTEND_DOCS_PUBLICATION=1 node scripts/check-frontend-docs.mjs invokes the
selected theme's canonical acceptance checker with that evidence path and hash,
then validates and recomputes the visual evidence. Normal documentation
freshness checks do not require local release evidence.
Deterministic visual verification
Every component affected by an appearance change has a scenario manifest and immutable before/after/diff evidence. The baseline and candidate use the same browser build, device-pixel ratio, fonts, fixture data, theme, viewport, reduced motion setting, and settling rule. Capture all applicable states, including light and dark themes, interaction states, overlays, disabled/error states, and the desktop layouts the product supports. Do not invent a narrow/mobile requirement for a desktop-only product.
Each scenario captures the component crop and surrounding application context. It also captures the full page when an overlay, overflow, or page layout can be affected. A component index declares the complete applicable matrix and points to one immutable manifest per scenario:
{
"schemaVersion": "1.0.0",
"componentId": "module.component",
"applicability": {
"themes": ["light", "dark"],
"viewports": [{ "id": "desktop", "width": 1440, "height": 900 }],
"states": ["default"],
"overlay": false
},
"finalBuild": {
"candidateCommit": "generated-candidate-commit",
"candidateBuildHash": "sha256:generated-candidate-build-hash",
"recapturedAfterBuild": true
},
"scenarios": [
{
"scenarioId": "module.component.light.default",
"theme": "light",
"viewport": "desktop",
"state": "default",
"manifest": "scenarios/module.component.light.default.json"
},
{
"scenarioId": "module.component.dark.default",
"theme": "dark",
"viewport": "desktop",
"state": "default",
"manifest": "scenarios/module.component.dark.default.json"
}
]
}
The checker expands the applicability cross-product and fails if any declared
theme, viewport, or state has no unique scenario. When overlay is true, every
scenario also requires the full-page capture scope. The final build commit and
hash must match every scenario's candidate and
recapturedAfterBuild must be true.
Each scenario manifest records hashes rather than trusting filenames:
{
"schemaVersion": "1.0.0",
"scenarioId": "module.component.light.default",
"componentId": "module.component",
"state": {
"theme": "light",
"viewport": { "width": 1440, "height": 900 },
"interaction": "default"
},
"runtime": {
"browserVersion": "pinned-browser-version",
"devicePixelRatio": 1,
"fontsHash": "sha256:generated-font-set-hash",
"fixtureHash": "sha256:generated-fixture-hash"
},
"baseline": {
"commit": "generated-baseline-commit",
"buildHash": "sha256:generated-baseline-build-hash"
},
"candidate": {
"commit": "generated-candidate-commit",
"buildHash": "sha256:generated-candidate-build-hash",
"recapturedAfterBuild": true
},
"requiredScopes": ["component", "context"],
"captures": [
{
"scope": "component",
"before": {
"artifactId": "component-before",
"path": "screenshots/component-before.png",
"sha256": "sha256:generated-before-hash"
},
"after": {
"artifactId": "component-after",
"path": "screenshots/component-after.png",
"sha256": "sha256:generated-after-hash"
},
"diff": {
"artifactId": "component-diff",
"path": "screenshots/component-diff.png",
"sha256": "sha256:generated-diff-hash"
}
},
{
"scope": "context",
"before": {
"artifactId": "context-before",
"path": "screenshots/context-before.png",
"sha256": "sha256:generated-before-hash"
},
"after": {
"artifactId": "context-after",
"path": "screenshots/context-after.png",
"sha256": "sha256:generated-after-hash"
},
"diff": {
"artifactId": "context-diff",
"path": "screenshots/context-diff.png",
"sha256": "sha256:generated-diff-hash"
}
}
],
"diff": {
"changedPixels": 0,
"totalPixels": 1296000,
"changedRatio": 0,
"pixelDeltaThreshold": 8,
"changedRatioThreshold": 0.001,
"disposition": "within-threshold",
"result": "passed",
"waiver": null
},
"console": { "unexpectedErrors": [] },
"fixtureCleanup": { "temporaryArtifactsRemaining": [], "verified": true }
}
The values above show the required shape, not valid evidence. Publication fails when a changed component or required state has no scenario, a required capture scope is absent, a referenced image or hash is missing, builds are stale, unexpected console errors remain, temporary fixture code remains, or the diff exceeds tolerance without a reviewed design waiver. A waiver records the exact changed pixels, design reason, reviewer, and affected scenario; it cannot waive missing captures, console errors, or fixture cleanup.