Rule handbook metadata
- Rule
DET.APP.PERSISTENT_CHROME· lanedeterministic- Page status
- current
- page_version
1d09413b2bebf6089bc9f8253fdceea08b04c854b166747b11f65cf8badd4b94- generated_at
- 2026-05-19T18:45:00.000Z
- registry_fingerprint
2ce40848effce579d3e4879f6ca85535183a14db201870a6c007da424624550c
How this rule is fixed
Pilot deterministic fixer: handbook_after · harness mode multi_page · 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-app-persistent-chrome. Scroll down for Before / After examples and Evidence and remediation steps.
Purpose
Kitchen Sink desktop interfaces (data-ks-type="desktop-interface", museum studio shell Msm, Lenses-style operator UIs) often promise a persistent shell: chrome stays put while only the workspace pane swaps. Operators rely on that continuity to know where they are and what global actions remain available.
This deterministic rule runs during route crawl. For each origin it fingerprints visible shell regions outside main — header, nav, aside, footer, and explicit [data-shell-region] roots — using role, stable id, data-ks-hash, and a sorted link signature from visible anchor text. The first crawled route becomes the baseline; later routes are compared.
Persistence is assumed when any of these signals appear: data-persistent-chrome="true", data-shell-persistent="true", data-route-contract containing "persistent", [data-shell-regions] / [data-shell-region], [data-ks-type="desktop-interface"], or body classes such as museum-studio, forge-studio, ks-app-shell, or workspace-lens.
Plan: Crawl two or more routes on the same app origin. Do: Mount contracted shell regions outside main, reuse the same visual root hash per region, and keep global nav labels/hrefs stable. Check: appPersistentChromeReport.violations is empty and route crawl finds no missing-region, hash-drift, or nav-drift. Adjust: Move route-specific links into main; re-mount dropped aside/header roots; align hashes with the design contract.
Passing signals
- Contract signals (
data-persistent-chrome,data-shell-regions,data-ks-type="desktop-interface") match measurable shell landmarks outsidemain. header,nav, andaside(ordata-shell-region="header|nav|aside") appear on every crawled route with the sameidanddata-ks-hash(for exampleMsmon the studio root and stable child hashes where contracted).- Global navigation link sets are identical across routes (same visible labels and href targets in the persistent shell); route-specific actions live inside
main. - Only
main/data-shell-region="main"content changes between routes — workspace cards, wizard panels, diagnostics — not the outer shell anatomy. data-shell-regions="header,nav,main"(or equivalent) documents which regions are promised persistent for auditors and implementers.
Failing signals
missing-region: Baseline route hadaside#app-nav(ornavoutside main) but a later route omits it or moves nav insidemainso it no longer fingerprints as shell.nav-drift: Primary shellheaderornavlink signature changes between routes (for example baselinehome|docs|flowbecomesback|settingson a child route).hash-drift: Same contracted shell region (role+id) carries a differentdata-ks-hashon a later route without an intentional contract update.promised-no-regions: Page declares persistence (data-persistent-chrome="true", desktop-interface type, etc.) but no visibleheader/nav/aside/footer/data-shell-regionexists outsidemain.- Full shell remount per route — different header markup, swapped side rails, or duplicate competing nav bands — even when individual landmarks still exist.
Before example
Before (failing example)
Settings
API tokens
Route-local nav replaced the global shell; aside rail from baseline is gone.
Failing KS markup: /settings route rewrites global header links, drops the side session rail, and nests wayfinding inside main (baseline /flow had persistent header + nav outside main).
After example
After (passing example)
Settings
API tokens
Create and rotate tokens for automation jobs.
Passing KS markup: same Msm shell on every route — stable header + nav outside main, global links unchanged; only workspace body inside main swaps.
Evidence and remediation
Evidence: Route-crawl findings include appPersistentChromeReport.violations[] with kinds missing-region, hash-drift, nav-drift, or promised-no-regions. Each finding cites role, id, baseline vs current hash or link signature, crawled URL, and baseline URL. Capture paired screenshots of baseline and failing routes with the same viewport width; highlight header/nav/aside deltas.
Remediate (in order):
- Restore missing regions — re-mount contracted
header,nav,aside, orfooteroutsidemainon every route; do not tuck global rails into the workspace pane. - Stabilize global nav — keep the same anchor labels and hrefs in persistent shell; move route-specific tabs and breadcrumbs into
main(DET.NAV.DEDUP/DET.NAV.BREADCRUMBas needed). - Fix hash drift — reuse the same
data-ks-hashon persistent roots across routes, or update the design contract when shell anatomy intentionally changes. - Emit contract markers — add
data-shell-regionsanddata-shell-regionon persistent roots whendata-persistent-chrome="true"so auditors can measure regions (promised-no-regionsotherwise fires). - Re-crawl — run
analyze-website-ux.mjsacross at least two app routes on the same origin; confirm violations clear before closing remediation.