Rule handbook metadata

Rule
DET.NAV.DEDUP · lane deterministic
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.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-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:

  1. duplicate-destination — the same pathname appears in conflicting peer bands: primary ↔ sidebar, primary ↔ offcanvas, or sidebar ↔ offcanvas.
  2. duplicate-primary-roots — two distinct primary nav roots (for example nested .site-header nav trees plus Kpn) 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) while Ksr (aside.forge-sidebar, #ks-sidebar-aside) holds the handbook section tree — no shared pathname between bands unless Kbc provides hierarchy.
  • Mobile .offcanvas / #fsNav repeats sidebar links only when desktop sidebar is hidden at the breakpoint — not simultaneously visible with the same destinations in Kpn and Ksr.
  • Kbc may repeat a parent segment (for example /docs) while Ksr holds the same href — auditor treats breadcrumb + one chrome band as intentional hierarchy.
  • A single primary nav horizon: one visible Kpn / .site-header nav root outside main; no nested masthead inside main linking 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, #main fragments, theme switchers, and consent links do not pollute the graph.

Failing signals

  • duplicate-destination with bands=primary+sidebar (or primary+offcanvas, sidebar+offcanvas) — same normalized pathname (for example /docs/start) and visible labels like “Getting started” in both Kpn / .site-header nav and Ksr.
  • duplicate-primary-roots — two primary band roots (different primaryRootId) both expose /platform or /docs (nested site header inside main plus global Kpn).
  • Full handbook tree copied into header nav and left intact in .forge-sidebar — classic handbook IA smell; often co-fails DET.CONTEXT.BURDEN and DET.PAGE.MODE on 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)

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)

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

  1. Split IA by band — move handbook section links exclusively into Ksr; keep Kpn / .site-header nav to curated site-level destinations that do not repeat sidebar paths.
  2. Remove nested mastheads — delete duplicate .site-header nav or in-main nav trees that compete with Kpn; enforce one primary horizon per Kpn contract.
  3. Fix mobile mirroring — offcanvas should replace hidden desktop rails at small breakpoints, not stack identical hrefs beside visible sidebar + primary links.
  4. Use breadcrumb for hierarchy — when a parent segment must appear twice, emit Kbc so orientation is explicit; do not copy the full sidebar tree into the header strip.
  5. Re-audit — run analyze-website-ux.mjs on handbook hub and product overview URLs; confirm navDedupReport.violations is empty. Harness: auditor-tests/invoke-det-ruleset-harness.sh --only-rule DET.NAV.DEDUP.