Rule handbook metadata
- Rule
DET.HASH.MARKERS· lanedeterministic- Page status
- stale
- page_version
d7c8001eff82b529e9c4f8919173e977dcb44b91fb8b98ac1acf792f9c81780b- generated_at
- 2026-05-19T22:20:00.000Z
- registry_fingerprint
6773fda516344e110b5a7b1435e655e1264e773825ca8bbe62194189891c42ba
How this rule is fixed
Pilot deterministic fixer: handbook_after · harness mode standalone · verify expect_rule_clean.
- Harness:
apply-harness-fixture-remediation.pycopies the After example HTML from this handbook page onto the defect fixture, theninvoke-det-ruleset-remediation-verify.shre-audits and expects zero findings for this rule. - Production sites:
run-website-ux-remediation-loop.shrunshandbook_html_patch(HTML patches inlib/ux-deterministic-fixers/fixers/patches/) before invoking the Cursor agent when the quality gate still fails.
Detection module: docs/design/ux-audit/deterministic-design-rules.md#det-hash-markers. Scroll down for Before / After examples and Evidence and remediation steps.
Purpose
Kitchen Sink assigns every reusable visual root (layout shell, chrome region, page, section, component, diagram block, React primitive root) a three-letter hash registered in docs/design/catalog/visual-registry.yaml. Emitted HTML must expose that hash twice on the same element: hash="XYZ" and data-ks-hash="XYZ", plus data-ks-type and data-ks-name where the catalog defines them. The pair lets crawlers, auditors, and remediation plans locate governed surfaces in raw HTML without relying on class names alone.
This deterministic rule evaluates metrics.ksVisualHashReport from the UX auditor crawl (lib/dom-metrics.js). It flags invalid token shapes, attribute mismatches, one-sided markers, and (as a warning) repeated hashes on multiple nodes. Registry membership is DET.HASH.REGISTRY_ROW; contract file presence is DET.CONTRACT.PATH. Python source should use ks_hash_attrs() (components/ks_hash_attrs.py) so builds fail before shipping one-sided markers.
Plan: Allocate or reuse a hash when adding a visual surface. Do: Emit both attributes from ks_hash_attrs, layout_shell_attrs, chrome_region_attrs, or React ksVisualAttrs / ksReactPrimitiveAttrs. Check: node tools/website-ux-auditor/analyze-website-ux.mjs on built website/ or showcase/, or grep HTML for [data-ks-hash] and confirm each node has a matching hash=. Adjust: Fix pairing before chasing registry or contract issues — a page can pass DET.HASH.MARKERS while DET.CONTRACT.PATH still fails.
Passing signals
- Every element with
[data-ks-hash]or[hash]that represents a governed visual root has both attributes set to the same three-letter value (for examplehash="Hbk"anddata-ks-hash="Hbk"). - Marker values match
/^[A-Za-z]{3}$/(exactly three ASCII letters). Pythonks_hash_attrs()also requires three distinct letters at build time. - Companion metadata is present where KS emits it:
data-ks-type="layout",data-ks-name="layout-handbook",data-ks-type="chrome-region",data-ks-name="doc-sidebar", and similar pairs on showcase pages such asshowcase/preview-handbook.html. ksVisualHashReport.validUniquelists discovered hashes;invalidRaw,mismatches, andincompleteMarkersare empty for the page.instanceCountByHashshows at most one instance per hash on a page, or duplicates are intentional and documented in the catalog contract.- Consumer sites that submodule KS reproduce the same marker pattern on handbook shells (Hbk, Ksr, Kco, Ksf) and doc pages (Ctr, Fag) after
build-showcase.py/ site generators run.
Failing signals
invalidRaw(minor): Value is not exactly three ASCII letters — for exampledata-ks-hash="abcd",hash="12", or placeholder tokens copied from docs.mismatches(minor):hash="Hbk"anddata-ks-hash="Xyz"on the same node — often a partial edit or manual HTML paste.incompleteMarkers(warn): Onlydata-ks-hashwithouthash=, or onlyhash=withoutdata-ks-hashon a governed root.instanceCountByHash> 1 (warn): Same hash on multiple elements (for example twodata-ks-hash="Ksr"sidebars) — may be valid for reusable chrome but needs catalog justification.- Stray
hash=on non-visual nodes pollutes the scan; remove or align with registry policy. - Findings cap at
MAX_HASH_MARKER_FINDINGS(10) per page with a trailing “additional issues omitted” message when many nodes break at once. - Passing this rule does not imply the hash is registered (
DET.HASH.REGISTRY_ROW) or that contracts exist (DET.CONTRACT.PATH).
Before example
Before (failing example)
Handbook
Governed delivery
Layout root missing hash=; sidebar missing data-ks-hash.
Body
Inner card is not a catalog visual root.
Failing handbook shell: layout root carries data-ks-hash and type metadata but omits the paired hash= attribute. Sidebar has hash= but omits data-ks-hash. Crawl reports incompleteMarkers.
After example
After (passing example)
Handbook
Handbook sample page
Markers pair on every governed root.
Passing handbook shell (aligned with showcase/preview-handbook.html): layout and chrome roots emit matching pairs and type metadata from ks_hash_attrs() / chrome_region_attrs().
Evidence and remediation
Capture: Save the audited URL, raw HTML snippet around each flagged selector ([data-ks-hash="…"]), and the ksVisualHashReport slice from analyze output (invalidRaw, mismatches, incompleteMarkers, instanceCountByHash). For KS repo work, grep showcase/ or rebuilt website/ after python3 generator/build-showcase.py.
Remediation (PDCA):
- Plan — Identify the visual root in
visual-registry.yaml(hash,type,name). Do not invent ad hoc tokens. - Do — In Python renderers, use
ks_hash_attrs(hash_id, visual_type, name)or layout/chrome helpers; in React, useksReactPrimitiveAttrs()/ksVisualAttrs(). Never set only one ofhashordata-ks-hash. - Check — Re-run
analyze-website-ux.mjson the built tree; confirmDET.HASH.MARKERSis clean, then runDET.HASH.REGISTRY_ROWandnode tools/design-catalog/check-visual-catalog.mjs --repo .. - Adjust — For intentional duplicate instances, document repetition in the design contract; for consumer sites, bump the
kitchensinksubmodule after fixing emitters in forgesdlc-kitchensink.
Module: design-rules/deterministic/generated/det-hash-markers.check.js (auditor package). Default severity minor; incomplete pairs and duplicate-instance warnings use warn.