Superseded by SPOT-002: fragment grammar re-ruled 2026-07-18 (#L123 line, #needle substr, #/re/, #'tok pattern'; symbol forms dropped).
Several consumers need "find a location in a file" and each is about to roll its own: why: fragment scoping (/todo/WHY/WHY-002), the planned spot-view rebuild (today's views/spot/search.js + match.js, JAB-021), and later cat:/diff: scoped hunks. The C side already fixed the vocabulary: HUNKu8sMakeURI emits #L42 / #sym / #sym:L42 / #'quoted body':L42 (dog/HUNK.c:60), HUNKu8sFragSplit extracts, and symbols are the tokenizer's N-def tags (CAPOFindFunc, spot/CAPO.c:579).
#function foo is out; #authorIdent / #authorIdent:L41 is the form).shared/spot.js: parse a locator string, resolve it over (source bytes, ext) to match spans.
parse(frag) → a typed locator; find(loc, src, ext, toks?) → ascending [{lo, hi, line, col}] byte spans (toks optional: caller may pass a pre-parsed token buffer, else tok.parse inside).L42, L42-60 — line / line range;42.7-43.2 — line.col span (the why-runs form, so a why-runs row is itself a valid locator);sym — a symbol, matched at an N-def token;sym:L42 — symbol with a line hint (nearest def to the hint wins — tolerant to drift);'quoted body' — structural SPOT needle (a-z bind one token, A-Z a block, two-space gap), percent-unescaped per hunk_frag_esc;/re/ — regex needle (the search view's regex matcher).views/spot/match.js matchers (grep/regex/structural) into or under shared/spot.js; the rebuilt spot view and search scaffold consume THIS module.:L-suffixed) strings are locators. Policy note in resolve_hash.js, not a fork of it.tok.parse is lexer-only. Symbol locators need either the new binding (MUST-ASK) or an explicit v1 heuristic; the choice is a design decision below, not an accident.find/window take (text, toks) and skip hidden tags (U=20, O=14) in matching AND line/col math; spans return in hunk byte space. Raw-file callers tok.parse first — one code path, a why/diff hunk never re-tokenizes.clip(text, toks, lo, hi) (HUNKu32sClip twin, CAPOBuildHunk's own move) cuts a sub-hunk — views build their FULL hunk once, then hunks() windows+clips it. Clip boundaries snap to token edges; a hidden O sticks to its visible predecessor (never split a [visible][O] pair)./sym) from the SAME find.sym:L42 needs only nearest-line disambiguation, so the heuristic bar is low.find returns ALL matches; callers pick (first / nearest-to-hint / all) — the resolver does not guess caller policy.parse).(pending)