Skip to content

TextQuoteSelector fuzzy fallback can silently re-anchor to a lookalike quote in a different location after the original text is edited #7571

Description

@antrixy

Spec clause: W3C Web Annotation Data Model — Text Quote Selector. The selector is defined by exact, prefix, and suffix; prefix/suffix exist specifically to disambiguate among multiple occurrences of exact in the document.

Expected behavior: Hypothesis's own blog states the design intent directly: "Hypothesis already deals with minor changes to a document thanks to our fuzzy anchoring algorithm... But sometimes documents change a lot. If an annotation is anchored to a sentence in a paragraph and the whole paragraph is deleted, then even the smartest algorithm isn't going to help — the original text is no longer present and that annotation will fail to anchor. When annotations fail to anchor, we call them orphans." (web.hypothes.is/blog/showing-orphaned-annotations) This case should have produced an orphan. It didn't — it produced a confident, wrong match.

Minimal witness:

<!-- captured against -->
<div>
  <p id="alpha">Team Alpha reported that the new deployment reduced latency by twelve percent across all regions.</p>
  <p id="beta">Team Beta reported that the new deployment reduced latency by twelve percent across all regions.</p>
</div>
<!-- selector captured on Alpha's sentence: -->
{ "exact": "reduced latency by twelve percent across all regions",
  "prefix": "eported that the new deployment ",
  "suffix": ".Team Beta reported that the new" }

<!-- page later edited to: -->
<div>
  <p id="alpha">Team Alpha reported that the new deployment reduced latency by twenty percent across all regions after further optimization.</p>
  <p id="beta">Team Beta reported that the new deployment reduced latency by twelve percent across all regions.</p>
</div>

Expected vs. actual: Per Hypothesis's own stated design, this should orphan — the original text no longer exists at its captured location. Actual: toRange() returns a confident, non-null match — silently re-anchored inside <p id="beta">, a different paragraph with different authorship, based on a decoy occurrence. No signal is surfaced that the match moved.

Mechanism: the captured prefix ("eported that the new deployment ") is identical in both paragraphs — the disambiguating token (Alpha vs Beta) sits outside the fixed 32-character context window, so the fuzzy search can't distinguish them once the original location's exact text is gone.

Affected-implementation matrix:

Strategy Result on this case
DOM-path (XPath+offset) Fails at the correct location — wrong content, doesn't move elements
Text-position (global offset) Same — wrong content, correctly contained
web-highlighter (tag+index+offset) Same — wrong content, correctly contained
dom-anchor-text-quote (fuzzy text-quote) Confidently anchors in a different element entirely

Related work, checked before filing:

Oracle citation: TextQuoteSelector's own spec text (disambiguation is the stated purpose of prefix/suffix) plus Hypothesis's own orphans-design blog post (large changes should orphan, not silently reattach).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions