Rule handbook metadata

Rule
DET.HASH.MARKERS · lane deterministic
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.py copies the After example HTML from this handbook page onto the defect fixture, then invoke-det-ruleset-remediation-verify.sh re-audits and expects zero findings for this rule.
  • Production sites: run-website-ux-remediation-loop.sh runs handbook_html_patch (HTML patches in lib/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 example hash="Hbk" and data-ks-hash="Hbk").
  • Marker values match /^[A-Za-z]{3}$/ (exactly three ASCII letters). Python ks_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 as showcase/preview-handbook.html.
  • ksVisualHashReport.validUnique lists discovered hashes; invalidRaw, mismatches, and incompleteMarkers are empty for the page.
  • instanceCountByHash shows 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 example data-ks-hash="abcd", hash="12", or placeholder tokens copied from docs.
  • mismatches (minor): hash="Hbk" and data-ks-hash="Xyz" on the same node — often a partial edit or manual HTML paste.
  • incompleteMarkers (warn): Only data-ks-hash without hash=, or only hash= without data-ks-hash on a governed root.
  • instanceCountByHash > 1 (warn): Same hash on multiple elements (for example two data-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)

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 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):

  1. Plan — Identify the visual root in visual-registry.yaml (hash, type, name). Do not invent ad hoc tokens.
  2. Do — In Python renderers, use ks_hash_attrs(hash_id, visual_type, name) or layout/chrome helpers; in React, use ksReactPrimitiveAttrs() / ksVisualAttrs(). Never set only one of hash or data-ks-hash.
  3. Check — Re-run analyze-website-ux.mjs on the built tree; confirm DET.HASH.MARKERS is clean, then run DET.HASH.REGISTRY_ROW and node tools/design-catalog/check-visual-catalog.mjs --repo ..
  4. Adjust — For intentional duplicate instances, document repetition in the design contract; for consumer sites, bump the kitchensink submodule 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.