Rule handbook metadata
- Rule
DET.NAV.DEDUP· lanedeterministic- Page status
- current
- page_version
c3ab59adb095d9ee61013db48b1e31c8d82b9fe44864b413efe78f18279abe2c- generated_at
- 2026-05-25T17:00:00.000Z
- registry_fingerprint
2ce40848effce579d3e4879f6ca85535183a14db201870a6c007da424624550c
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-nav-dedup. Scroll down for Before / After examples and Evidence and remediation steps.
Purpose
Handbook and product shells expose several navigation bands outside main: Kpn product primary nav (nav.fs-primary-nav-global), handbook doc rail (Ksr, aside.forge-sidebar, #ks-sidebar-aside), mobile/offcanvas disclosure (Kco, .offcanvas), optional Kbc breadcrumb, in-page ToC (Ktx), and footer utilities. Each band has a distinct job — curated site IA, section tree, mobile collapse, orientation trail — and repeating the same destination in conflicting bands creates redundant choice, keyboard noise, and ambiguous “where am I?” signals.
This deterministic rule builds a same-origin link graph from visible anchors in chrome roots outside main. It normalizes paths (strips /index.html, trailing slashes, lowercases hash fragments) and flags two violation kinds:
duplicate-destination— the same pathname appears in conflicting peer bands: primary ↔ sidebar, primary ↔ offcanvas, or sidebar ↔ offcanvas.duplicate-primary-roots— two distinct primary nav roots (for example nested.site-header navtrees plusKpn) link to the same destination, violating the single masthead horizon in the Kpn contract.
Breadcrumb hierarchy is intentional: when Kbc (nav.ks-doc-breadcrumb) repeats a destination that also appears in exactly one other chrome band, the duplicate is exempt — the trail orients; the rail navigates. Footer and ToC links are not treated as conflicting peers with primary/sidebar/offcanvas in this check. Skip links, theme toggles, and cookie/consent anchors are ignored.
Plan: Map each chrome band’s allowed destinations per layout contract. Do: Keep section links in Ksr, curated top-level IA in Kpn, and mobile mirrors in offcanvas only when they replace — not duplicate — desktop rails. Check: navDedupReport.violations is empty. Adjust: Remove mirrored handbook trees from the header; collapse competing primary nav roots; use Kbc for hierarchy instead of copying sidebar hrefs into masthead nav.
Passing signals
Kpn(nav.fs-primary-nav-global) carries curated top-level IA (Overview, Trust, Quickstart) whileKsr(aside.forge-sidebar,#ks-sidebar-aside) holds the handbook section tree — no shared pathname between bands unlessKbcprovides hierarchy.- Mobile
.offcanvas/#fsNavrepeats sidebar links only when desktop sidebar is hidden at the breakpoint — not simultaneously visible with the same destinations inKpnandKsr. Kbcmay repeat a parent segment (for example/docs) whileKsrholds the same href — auditor treats breadcrumb + one chrome band as intentional hierarchy.- A single primary nav horizon: one visible
Kpn/.site-header navroot outsidemain; no nested masthead insidemainlinking to the same routes. - Footer utility links (
footer nav,.ks-site-footer-region nav) may repeat destinations without triggering peer-band conflicts (footer is not a conflicting peer). - Auxiliary controls excluded: skip-to-content,
#mainfragments, theme switchers, and consent links do not pollute the graph.
Failing signals
duplicate-destinationwithbands=primary+sidebar(orprimary+offcanvas,sidebar+offcanvas) — same normalized pathname (for example/docs/start) and visible labels like “Getting started” in bothKpn/.site-header navandKsr.duplicate-primary-roots— two primary band roots (differentprimaryRootId) both expose/platformor/docs(nested site header insidemainplus globalKpn).- Full handbook tree copied into header nav and left intact in
.forge-sidebar— classic handbook IA smell; often co-failsDET.CONTEXT.BURDENandDET.PAGE.MODEon product/home routes. - Offcanvas panel open on desktop while sidebar and primary both list identical section hrefs.
- Evidence shape:
nav_dedup pathname="/docs" bands=primary+sidebar kind=duplicate-destination labels="Docs | Documentation".
Before example
Before (failing example)
Forge
Chapter
Body
Same section links in header nav and doc sidebar — redundant IA.
Failing KS markup: handbook-style shell mirrors /docs/start in both .site-header nav and Ksr sidebar — conflicting primary + sidebar bands without breadcrumb exemption.
After example
After (passing example)
Forge
Getting started
Body
Primary IA, breadcrumb trail, and sidebar each own distinct destinations.
Passing KS markup: Kpn carries site-level IA; Ksr owns the handbook tree; Kbc orients without duplicating conflicting bands.
Evidence and remediation
Evidence: Metrics phase emits navDedupReport with linkEntryCount and violations[]. Each violation includes kind (duplicate-destination or duplicate-primary-roots), normalized pathname, conflicting bands, optional labels, and selectorHint (for example primary.nav-link or sidebar). Findings use area informationArchitecture, severity warn (or major for competing primary roots), and evidence such as nav_dedup pathname="/docs/start" bands=primary+sidebar kind=duplicate-destination labels="Getting started | Getting started". Capture a viewport screenshot highlighting both nav roots and the duplicated anchor.
Remediate (in order):
- Split IA by band — move handbook section links exclusively into
Ksr; keepKpn/.site-header navto curated site-level destinations that do not repeat sidebar paths. - Remove nested mastheads — delete duplicate
.site-header navor in-mainnav trees that compete withKpn; enforce one primary horizon per Kpn contract. - Fix mobile mirroring — offcanvas should replace hidden desktop rails at small breakpoints, not stack identical hrefs beside visible sidebar + primary links.
- Use breadcrumb for hierarchy — when a parent segment must appear twice, emit
Kbcso orientation is explicit; do not copy the full sidebar tree into the header strip. - Re-audit — run
analyze-website-ux.mjson handbook hub and product overview URLs; confirmnavDedupReport.violationsis empty. Harness:auditor-tests/invoke-det-ruleset-harness.sh --only-rule DET.NAV.DEDUP.