Rule handbook metadata
- Rule
DET.PY.KS_HASH_ATTRS· lanedeterministic- Page status
- current
- page_version
2714cbe739f8cd59a730c408f5fd8b07d826fbff93b3ad3707bc7ff0aab86d03- generated_at
- 2026-05-25T16:20:00.000Z
- registry_fingerprint
2ce40848effce579d3e4879f6ca85535183a14db201870a6c007da424624550c
How this rule is fixed
Pilot deterministic fixer: repo_overlay · harness mode repo_overlay · verify expect_rule_clean.
- Harness: fixture includes a repo overlay tree;
remediate_repo_overlay()writes catalog/repo files, then applies After HTML when present. - Production:
repo_overlayNode adapter patches the website repository (contracts, registry JSON, CSS, Python stubs).
Detection module: docs/design/ux-audit/deterministic-design-rules.md#det-py-ks_hash_attrs. Scroll down for Before / After examples and Evidence and remediation steps.
Purpose
Kitchen Sink Python generators (components/layouts.py, components/components.py, generator/build-showcase.py, forge-autodoc/forge_autodoc/page.py, and registry-listed emitter modules) stamp governed visual roots with catalog markers: hash="XYZ", data-ks-hash="XYZ", data-ks-type, and data-ks-name. Those attributes must come from ks_hash_attrs() (components/ks_hash_attrs.py) or registry-backed wrappers in components/ks_catalog_hashes.py — layout_shell_attrs(), page_main_attrs(), and chrome_region_attrs() — not from hand-typed attribute strings in f-strings or concatenation.
This deterministic rule runs in the metrics phase on the kitchensink repo root (det-py-ks-hash-attrs.check.js). It scans Python under components/, generator/, and forge-autodoc/ for forbidden inline marker literals and verifies that every marker emitter module calls a canonical helper. DOM rules (DET.HASH.MARKERS, DET.HASH.REGISTRY_ROW) judge built HTML; DET.PY.KS_HASH_ATTRS catches emitters before a bad build ships incomplete or drift-prone markup.
Plan: When adding or editing a layout, chrome region, or showcase shell, resolve the hash in visual-registry.yaml first. Do: Import layout_shell_attrs / chrome_region_attrs from ks_catalog_hashes (or call ks_hash_attrs directly for one-off roots). Check: Run analyze-website-ux.mjs with --repo pointing at forgesdlc-kitchensink so pyKsHashAttrsReport is populated. Adjust: Replace manual literals; rebuild with python3 generator/build-showcase.py, then confirm DET.HASH.MARKERS on showcase/ or consumer website/.
Passing signals
- Marker emitter modules call
ks_hash_attrs(,layout_shell_attrs(,page_main_attrs(, orchrome_region_attrs(, or importks_catalog_hashes— for examplecomponents/layouts.pysets_la_hbk = layout_shell_attrs("handbook_page")and splices the fragment ontoclass="container-fluid px-0". components/components.pyuseschrome_region_attrs("doc-breadcrumb")andchrome_region_attrs("doc-toc-sidebar")when rendering Kbc / Ktx chrome.components/ks_catalog_hashes.pyresolves registry rows and delegates toks_hash_attrsforlayout,chrome-region,page, andlayout-previewtypes.- Built HTML shows paired markers on governed roots — handbook shell
hash="Hbk"/data-ks-hash="Hbk", sidebarKsr, breadcrumbKbc, footerKsf— with matchingdata-ks-typeanddata-ks-nameslugs from the registry. pyKsHashAttrsReport.issuesis empty after scanning the repo root;emitterPathCountincludes base emitters plus active registrysource_pathsending in.pyforlayout,chrome-region, andlayout-previewrows.- Only
components/ks_hash_attrs.pymay contain inlinedata-ks-hash=/hash="XYZ"string literals (canonical helper implementation).
Failing signals
manual-literal(minor): A.pyfile undercomponents/,generator/, orforge-autodoc/contains inlinedata-ks-hash=,data-ks-type=,data-ks-name=, orhash="XYZ"literals outside the exempt helper module — common in bootstrap scripts, defect fixtures, or copy-pasted HTML fragments embedded in Python.missing-helper(minor): A registry-listed emitter module exists but never callsks_hash_attrsorks_catalog_hasheswrappers — emitters lose catalog alignment even if HTML looks correct today.missing-emitter(warn): A registrysource_pathsentry points at a.pyfile that is absent on disk.- Emitted HTML may still fail
DET.HASH.MARKERSwhen Python used partial manual strings — for example layout root with onlydata-ks-hash="Hbk"and no pairedhash="Hbk", or breadcrumb with classks-doc-breadcrumbbut no Kbc markers. - Findings cap at
MAX_PY_KS_HASH_ATTRS_FINDINGS(12) per pass with a trailing “additional issues omitted” message when many files violate at once. - Passing this rule does not prove registry membership (
DET.HASH.REGISTRY_ROW) or contract presence (DET.CONTRACT.PATH).
Before example
Before (failing example)
Handbook
Governed delivery
Markers pasted manually in Python — not from chrome_region_attrs().
Failing emitted fragment (typical of manual Python attribute strings in a layout f-string): layout shell carries only data-ks-hash; doc breadcrumb omits catalog markers. A crawl reports DET.HASH.MARKERS incompleteMarkers even before DET.PY.KS_HASH_ATTRS flags the generator source.
After example
After (passing example)
Handbook
Handbook sample page
Emitters use ks_catalog_hashes helpers.
Passing handbook shell (aligned with handbook_page in components/layouts.py): layout_shell_attrs("handbook_page"), chrome_region_attrs("doc-sidebar"), and chrome_region_attrs("doc-breadcrumb") emit the full helper fragment on each governed root.
Evidence and remediation
Capture: Save pyKsHashAttrsReport from analyze output (issues[] with kind, path, message) and the finding evidence string (python_source=<rel-path> kind=<kind>). For HTML validation, attach a built fragment from showcase/ or website/ and the matching ksVisualHashReport slice when DET.HASH.MARKERS also fires.
| Kind | Severity | Remediation |
|---|---|---|
manual-literal |
minor | Remove inline hash= / data-ks-* strings; call ks_hash_attrs() or layout_shell_attrs / page_main_attrs / chrome_region_attrs. |
missing-helper |
minor | Add from ks_catalog_hashes import chrome_region_attrs, layout_shell_attrs (or equivalent) and splice _{var} = layout_shell_attrs("…") onto visual root class= / tag openers. |
missing-emitter |
warn | Restore the missing .py module or fix source_paths in visual-registry.yaml. |
Remediation (PDCA):
- Plan — Locate the visual root in
docs/design/catalog/visual-registry.yaml(hash,type,slug,source_paths). Prefer registry wrappers over hard-coded three-letter tokens. - Do — In Python emitters, use
layout_shell_attrs("handbook_page"),chrome_region_attrs("doc-breadcrumb"), orks_hash_attrs(hash_id, visual_type, name); rebuild withpython3 generator/build-showcase.py(and consumer site generators after submodule bump). - Check —
node tools/website-ux-auditor/analyze-website-ux.mjs --repo /path/to/forgesdlc-kitchensinkwith metrics includingpyKsHashAttrsReport; grep built HTML for pairedhash="XYZ"anddata-ks-hash="XYZ". - Adjust — For harness-only scripts that intentionally embed marker literals for defect fixtures, relocate strings outside scanned trees or refactor fixtures to call helpers; do not weaken the check for production emitters.
Module: design-rules/deterministic/generated/det-py-ks-hash-attrs.check.js (auditor package). Default severity minor; missing emitter modules use warn.