FA-11876 / Search retrieval semantics / Open access
Old document versions remain searchable after replacement · case 01
Old document versions remain searchable after replacement.
ROOT CAUSE
A term posting from any historical version is treated as a live match.
VERIFIED REPAIR
Select the highest revision of each document before checking its term membership.
Unsuccessful approach: Selecting the newest matching revision still ignores a newer nonmatching replacement.
Case contract
Records are [id,revision,tokens], with unique id/revision pairs. Return sorted IDs whose greatest-revision record contains the term. Record order is arbitrary.
Why this case matters
An offline deterministic retrieval model isolates this search contract from tokenization, storage, and network behavior.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(records, term):
return sorted({ident for ident,revision,tokens in records if term in tokens})
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('replacement removes term', solve([['a',N,['x']],['a',N+1,[]]],'x'),[])
check('replacement adds term', solve([['a',N,[]],['a',N+1,['x']]],'x'),['a'])
check('out of order revisions', solve([['a',N+1,[]],['a',N,['x']]],'x'),[])
check('separate documents', solve([['b',N,['x']],['a',N,['x']]],'x'),['a','b'])
check('unrelated term', solve([['a',N,['y']]],'x'),[])
check('empty index', solve([],'x'),[])
check('unchanged term', solve([['a',N,['x']],['a',N+1,['x']]],'x'),['a'])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| replacement removes term | ['a'] | [] | Failed |
| replacement adds term | ['a'] | ['a'] | Passed |
| out of order revisions | ['a'] | [] | Failed |
| separate documents | ['a', 'b'] | ['a', 'b'] | Passed |
| unrelated term | [] | [] | Passed |
| empty index | [] | [] | Passed |
| unchanged term | ['a'] | ['a'] | Passed |
SHA-256 / fb03e5f5046409f7c7813d5046965132248735d61f4ff116291f29bc04c95847
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(records, term):
latest={}
for ident,revision,tokens in records:
if term in tokens and (ident not in latest or revision>latest[ident]): latest[ident]=revision
return sorted(latest)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('replacement removes term', solve([['a',N,['x']],['a',N+1,[]]],'x'),[])
check('replacement adds term', solve([['a',N,[]],['a',N+1,['x']]],'x'),['a'])
check('out of order revisions', solve([['a',N+1,[]],['a',N,['x']]],'x'),[])
check('separate documents', solve([['b',N,['x']],['a',N,['x']]],'x'),['a','b'])
check('unrelated term', solve([['a',N,['y']]],'x'),[])
check('empty index', solve([],'x'),[])
check('unchanged term', solve([['a',N,['x']],['a',N+1,['x']]],'x'),['a'])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| replacement removes term | ['a'] | [] | Failed |
| replacement adds term | ['a'] | ['a'] | Passed |
| out of order revisions | ['a'] | [] | Failed |
| separate documents | ['a', 'b'] | ['a', 'b'] | Passed |
| unrelated term | [] | [] | Passed |
| empty index | [] | [] | Passed |
| unchanged term | ['a'] | ['a'] | Passed |
SHA-256 / bb9fccac9265d19ce2daafb2498448ad9c0b3cc906f14b88b393689fb740b43f
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(records, term):
latest={}
for ident,revision,tokens in records:
if ident not in latest or revision>latest[ident][0]: latest[ident]=(revision,tokens)
return sorted(ident for ident,(revision,tokens) in latest.items() if term in tokens)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('replacement removes term', solve([['a',N,['x']],['a',N+1,[]]],'x'),[])
check('replacement adds term', solve([['a',N,[]],['a',N+1,['x']]],'x'),['a'])
check('out of order revisions', solve([['a',N+1,[]],['a',N,['x']]],'x'),[])
check('separate documents', solve([['b',N,['x']],['a',N,['x']]],'x'),['a','b'])
check('unrelated term', solve([['a',N,['y']]],'x'),[])
check('empty index', solve([],'x'),[])
check('unchanged term', solve([['a',N,['x']],['a',N+1,['x']]],'x'),['a'])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| replacement removes term | [] | [] | Passed |
| replacement adds term | ['a'] | ['a'] | Passed |
| out of order revisions | [] | [] | Passed |
| separate documents | ['a', 'b'] | ['a', 'b'] | Passed |
| unrelated term | [] | [] | Passed |
| empty index | [] | [] | Passed |
| unchanged term | ['a'] | ['a'] | Passed |
SHA-256 / 3387e05a55bd2f79572025692141a6fd04f20979ccb0c58965132937b733bedf
Verification & scope
Inputs are already tokenized or scored; this model makes no claim about production engine performance or linguistic analysis. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:38:51.750796+00:00.
Case digest / 5a9b55aceb9dcfbc790158ce3bf034db78ae1ddf5230d32716f7b131a1430f18