A READ-ONLY audit of the JS tree found URIs parsed and composed BY HAND across ~30 production files: Category A (manual PARSING — indexOf(":")/slice/split/regex to pull scheme/authority/path/query/fragment) and Category B (manual CONSTRUCTION — scheme + ":" + … string-concat). The canonical helpers themselves offend: shared/nav.js navUri concatenates and navAuthorize hand-splits — the helper that should BE the fix. Rule: ONLY the URI class (new URI / uri._parse / URI.make / .toString) and the nav/refKey helpers (built ON it) may parse or compose a URI. This is a behavior-PRESERVING refactor — the existing suite (esp. plain/tlv byte-parity) is the safety net. Highest value: views/status/status.js:322 bypasses navUri (the scope-leak class URI-012 fixed on the RESOLVE side, still open on the BAKE side), the nav helpers hand-roll, and ~39 ?branch#sha refs-key concats want ONE shared refKey(). Method Issues.
indexOf/slice/split/regex over a URI) and B (manual construct: string-concat instead of URI.make). ~30 production files; the idioms CLUSTER (not scattered).shared/nav.js:13 navUri (scheme + ":" + a + (a&&path?"/":"") + path) and :24-29 navAuthorize (indexOf(":") + slice + rest.slice(0,2)==="//"). Fix these FIRST so every caller can route through them.views/status/status.js:322 bakes ("diff:"|"cat:") + navPath bypassing navUri, so click-targets DROP the //authority — the URI-012 bug on the BAKE side (URI-012 fixed only the RESOLVE side).<scheme>: by slice then re-prepend + re-parse (A9/B5/B6 — collapses to one uri._parse); ~39 sites concat ?branch#sha / path#sha refs-log keys (B10 — one refKey()).?/# presence) via indexOf because .query/.fragment collapse undefined vs "" — see URI-009; leave + link, needs a binding API.new URI/uri._parse; every URI BUILT via URI.make/.toString or a nav/refKey helper.shared/nav.js navUri + navAuthorize reimplemented on the URI class, idempotent, BYTE-IDENTICAL output.status.js emits click-targets via navlib.navUri (authority-scoped) — closes the bake-side scope leak (twin of URI-012).refKey(branch, sha) (URI.make-based) replaces the ~39 ?b#sha concats.URI.make / uri._parse / new URI / .toString + shared/nav.js. No new hand-parsing anywhere.indexOf; leave it, link URI-009.URI.make must reproduce the exact old string (leading /, empty ?/#, empty authority) — verify against plain/tlv parity tests.ctest -j16 + commit (no concurrent ninja/jab in the shared wt) (Issues).nav.js) + add refKey so the systemic clusters collapse into helper calls, not open-coded URI.make repeated 39×.URI.make DIRECTLY to avoid a hard dep on W1's helper landing first; consolidate to refKey/navUri in a follow-up sweep if needed.shared/nav.js (navUri B0, navAuthorize A1), shared/hunkrows.js (A3), view/bro.js (A2 statusURI), shared/store.js (B10 keyURI + DEFINE refKey).views/status/status.js (B1:322 via navUri, B2 joinPrefix, B10 294/296/332), views/diff/diff.js (B9:375 hunk-uri, B5:426 re-scheme).views/{cat,blob,sha1,tree,size,type,log,commit,spot} strip/re-scheme dance (A9/B5/B6); LEAVE A8 presence-scan, link URI-009.verbs/{get,put,post,patch,head} ?b#sha concats (B10) + head A5/B4, put A6 → URI.make/refKey.core/loop.js (A10/A11/B7), core/discover.js (B8), shared/wire.js (A4), shared/submount.js (A7/B3), shared/ingest.js (B10).ctest -j16 (byte-parity green) + commit; final grep proves zero remaining Cat-A/Cat-B in production JS (except the URI-009-gated A8 sites).undefined vs empty) blocks fully retiring the A8 indexOf("?"|"#") presence scans — leave them, linked.refKey adoption is a soft dep (W4/W5 want W1's helper); mitigate by using URI.make directly, consolidate later.URI.make edge cases (empty authority, empty ?, path leading slash) MUST match the old concat exactly — parity tests are the gate.