FA-45721 / Data systems / Open access
Temporal enrichment selects dimension versions after fact time · case 01
Temporal enrichment selects dimension versions after fact time.
ROOT CAUSE
temporal-dimension-lookup: Temporal enrichment selects dimension versions after fact time.
VERIFIED REPAIR
Preserve the stated physical representation and operation order: Enrich facts [id,key,event-time] from versioned dimension rows [key,valid-from,revision,payload,tombstone]. For matching non-null key, use the greatest (valid-from,revision) no later than fact time. A selected tombstone yields None and blocks fallback to older versions. Emit [fact-id,payload-or-None].
Unsuccessful approach: Selecting only future versions still reverses as-of visibility.
Case contract
Enrich facts [id,key,event-time] from versioned dimension rows [key,valid-from,revision,payload,tombstone]. For matching non-null key, use the greatest (valid-from,revision) no later than fact time. A selected tombstone yields None and blocks fallback to older versions. Emit [fact-id,payload-or-None].
Why this case matters
A bounded deterministic data engine model makes representation and changelog faults reproducible.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(d):
try:
facts,versions=d
out=[]
for ident,key,time in facts:
candidates=[r for r in versions if key is not None and r[0]==key and True]
if not candidates: out.append([ident,None]); continue
chosen=max(candidates,key=lambda r:(r[1],r[2]))
out.append([ident,None if chosen[4] else chosen[3]])
return out
except (IndexError, KeyError, ValueError, StopIteration) as exc:
return {"representation_error": type(exc).__name__}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
if N == 1:
check('future ignored', solve([[[10, 'a', 2]], [['a', 1, 1, 'old', False], ['a', 3, 1, 'future', False]]]), [[10, 'old']])
check('exact effective time', solve([[[10, 'a', 1]], [['a', 1, 1, 'current', False]]]), [[10, 'current']])
check('revision precedence', solve([[[10, 'a', 1]], [['a', 1, 1, 'old', False], ['a', 1, 2, 'new', False]]]), [[10, 'new']])
check('tombstone blocks old', solve([[[10, 'a', 2]], [['a', 1, 1, 'old', False], ['a', 2, 1, None, True]]]), [[10, None]])
check('tombstone hidden payload', solve([[[10, 'a', 1]], [['a', 1, 1, 'hidden', True]]]), [[10, None]])
check('other key', solve([[[10, 'a', 2]], [['a', 1, 1, 'right', False], ['b', 2, 1, 'wrong', False], [None, 2, 2, 'wildcard', False]]]), [[10, 'right']])
check('absent dimension', solve([[[10, 'a', 1]], []]), [[10, None]])
elif N == 2:
check('future ignored', solve([[[10, 'a', 3]], [['a', 2, 1, 'old', False], ['a', 4, 1, 'future', False]]]), [[10, 'old']])
check('exact effective time', solve([[[10, 'a', 2]], [['a', 2, 1, 'current', False]]]), [[10, 'current']])
check('revision precedence', solve([[[10, 'a', 2]], [['a', 2, 1, 'old', False], ['a', 2, 2, 'new', False]]]), [[10, 'new']])
check('tombstone blocks old', solve([[[10, 'a', 3]], [['a', 2, 1, 'old', False], ['a', 3, 1, None, True]]]), [[10, None]])
check('tombstone hidden payload', solve([[[10, 'a', 2]], [['a', 2, 1, 'hidden', True]]]), [[10, None]])
check('other key', solve([[[10, 'a', 3]], [['a', 2, 1, 'right', False], ['b', 3, 1, 'wrong', False], [None, 3, 2, 'wildcard', False]]]), [[10, 'right']])
check('absent dimension', solve([[[10, 'a', 2]], []]), [[10, None]])
elif N == 3:
check('future ignored', solve([[[10, 'a', 4]], [['a', 3, 1, 'old', False], ['a', 5, 1, 'future', False]]]), [[10, 'old']])
check('exact effective time', solve([[[10, 'a', 3]], [['a', 3, 1, 'current', False]]]), [[10, 'current']])
check('revision precedence', solve([[[10, 'a', 3]], [['a', 3, 1, 'old', False], ['a', 3, 2, 'new', False]]]), [[10, 'new']])
check('tombstone blocks old', solve([[[10, 'a', 4]], [['a', 3, 1, 'old', False], ['a', 4, 1, None, True]]]), [[10, None]])
check('tombstone hidden payload', solve([[[10, 'a', 3]], [['a', 3, 1, 'hidden', True]]]), [[10, None]])
check('other key', solve([[[10, 'a', 4]], [['a', 3, 1, 'right', False], ['b', 4, 1, 'wrong', False], [None, 4, 2, 'wildcard', False]]]), [[10, 'right']])
check('absent dimension', solve([[[10, 'a', 3]], []]), [[10, None]])
elif N == 4:
check('future ignored', solve([[[10, 'a', 5]], [['a', 4, 1, 'old', False], ['a', 6, 1, 'future', False]]]), [[10, 'old']])
check('exact effective time', solve([[[10, 'a', 4]], [['a', 4, 1, 'current', False]]]), [[10, 'current']])
check('revision precedence', solve([[[10, 'a', 4]], [['a', 4, 1, 'old', False], ['a', 4, 2, 'new', False]]]), [[10, 'new']])
check('tombstone blocks old', solve([[[10, 'a', 5]], [['a', 4, 1, 'old', False], ['a', 5, 1, None, True]]]), [[10, None]])
check('tombstone hidden payload', solve([[[10, 'a', 4]], [['a', 4, 1, 'hidden', True]]]), [[10, None]])
check('other key', solve([[[10, 'a', 5]], [['a', 4, 1, 'right', False], ['b', 5, 1, 'wrong', False], [None, 5, 2, 'wildcard', False]]]), [[10, 'right']])
check('absent dimension', solve([[[10, 'a', 4]], []]), [[10, None]])
elif N == 5:
check('future ignored', solve([[[10, 'a', 6]], [['a', 5, 1, 'old', False], ['a', 7, 1, 'future', False]]]), [[10, 'old']])
check('exact effective time', solve([[[10, 'a', 5]], [['a', 5, 1, 'current', False]]]), [[10, 'current']])
check('revision precedence', solve([[[10, 'a', 5]], [['a', 5, 1, 'old', False], ['a', 5, 2, 'new', False]]]), [[10, 'new']])
check('tombstone blocks old', solve([[[10, 'a', 6]], [['a', 5, 1, 'old', False], ['a', 6, 1, None, True]]]), [[10, None]])
check('tombstone hidden payload', solve([[[10, 'a', 5]], [['a', 5, 1, 'hidden', True]]]), [[10, None]])
check('other key', solve([[[10, 'a', 6]], [['a', 5, 1, 'right', False], ['b', 6, 1, 'wrong', False], [None, 6, 2, 'wildcard', False]]]), [[10, 'right']])
check('absent dimension', solve([[[10, 'a', 5]], []]), [[10, None]])
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 |
|---|---|---|---|
| future ignored | [[10, 'future']] | [[10, 'old']] | Failed |
| exact effective time | [[10, 'current']] | [[10, 'current']] | Passed |
| revision precedence | [[10, 'new']] | [[10, 'new']] | Passed |
| tombstone blocks old | [[10, None]] | [[10, None]] | Passed |
| tombstone hidden payload | [[10, None]] | [[10, None]] | Passed |
| other key | [[10, 'right']] | [[10, 'right']] | Passed |
| absent dimension | [[10, None]] | [[10, None]] | Passed |
SHA-256 / 2889d28617380f0d962f9c91fffa79d401ab4def6ca2f4727b15c9d6b91e1f07
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(d):
try:
facts,versions=d
out=[]
for ident,key,time in facts:
candidates=[r for r in versions if key is not None and r[0]==key and r[1]>=time]
if not candidates: out.append([ident,None]); continue
chosen=max(candidates,key=lambda r:(r[1],r[2]))
out.append([ident,None if chosen[4] else chosen[3]])
return out
except (IndexError, KeyError, ValueError, StopIteration) as exc:
return {"representation_error": type(exc).__name__}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
if N == 1:
check('future ignored', solve([[[10, 'a', 2]], [['a', 1, 1, 'old', False], ['a', 3, 1, 'future', False]]]), [[10, 'old']])
check('exact effective time', solve([[[10, 'a', 1]], [['a', 1, 1, 'current', False]]]), [[10, 'current']])
check('revision precedence', solve([[[10, 'a', 1]], [['a', 1, 1, 'old', False], ['a', 1, 2, 'new', False]]]), [[10, 'new']])
check('tombstone blocks old', solve([[[10, 'a', 2]], [['a', 1, 1, 'old', False], ['a', 2, 1, None, True]]]), [[10, None]])
check('tombstone hidden payload', solve([[[10, 'a', 1]], [['a', 1, 1, 'hidden', True]]]), [[10, None]])
check('other key', solve([[[10, 'a', 2]], [['a', 1, 1, 'right', False], ['b', 2, 1, 'wrong', False], [None, 2, 2, 'wildcard', False]]]), [[10, 'right']])
check('absent dimension', solve([[[10, 'a', 1]], []]), [[10, None]])
elif N == 2:
check('future ignored', solve([[[10, 'a', 3]], [['a', 2, 1, 'old', False], ['a', 4, 1, 'future', False]]]), [[10, 'old']])
check('exact effective time', solve([[[10, 'a', 2]], [['a', 2, 1, 'current', False]]]), [[10, 'current']])
check('revision precedence', solve([[[10, 'a', 2]], [['a', 2, 1, 'old', False], ['a', 2, 2, 'new', False]]]), [[10, 'new']])
check('tombstone blocks old', solve([[[10, 'a', 3]], [['a', 2, 1, 'old', False], ['a', 3, 1, None, True]]]), [[10, None]])
check('tombstone hidden payload', solve([[[10, 'a', 2]], [['a', 2, 1, 'hidden', True]]]), [[10, None]])
check('other key', solve([[[10, 'a', 3]], [['a', 2, 1, 'right', False], ['b', 3, 1, 'wrong', False], [None, 3, 2, 'wildcard', False]]]), [[10, 'right']])
check('absent dimension', solve([[[10, 'a', 2]], []]), [[10, None]])
elif N == 3:
check('future ignored', solve([[[10, 'a', 4]], [['a', 3, 1, 'old', False], ['a', 5, 1, 'future', False]]]), [[10, 'old']])
check('exact effective time', solve([[[10, 'a', 3]], [['a', 3, 1, 'current', False]]]), [[10, 'current']])
check('revision precedence', solve([[[10, 'a', 3]], [['a', 3, 1, 'old', False], ['a', 3, 2, 'new', False]]]), [[10, 'new']])
check('tombstone blocks old', solve([[[10, 'a', 4]], [['a', 3, 1, 'old', False], ['a', 4, 1, None, True]]]), [[10, None]])
check('tombstone hidden payload', solve([[[10, 'a', 3]], [['a', 3, 1, 'hidden', True]]]), [[10, None]])
check('other key', solve([[[10, 'a', 4]], [['a', 3, 1, 'right', False], ['b', 4, 1, 'wrong', False], [None, 4, 2, 'wildcard', False]]]), [[10, 'right']])
check('absent dimension', solve([[[10, 'a', 3]], []]), [[10, None]])
elif N == 4:
check('future ignored', solve([[[10, 'a', 5]], [['a', 4, 1, 'old', False], ['a', 6, 1, 'future', False]]]), [[10, 'old']])
check('exact effective time', solve([[[10, 'a', 4]], [['a', 4, 1, 'current', False]]]), [[10, 'current']])
check('revision precedence', solve([[[10, 'a', 4]], [['a', 4, 1, 'old', False], ['a', 4, 2, 'new', False]]]), [[10, 'new']])
check('tombstone blocks old', solve([[[10, 'a', 5]], [['a', 4, 1, 'old', False], ['a', 5, 1, None, True]]]), [[10, None]])
check('tombstone hidden payload', solve([[[10, 'a', 4]], [['a', 4, 1, 'hidden', True]]]), [[10, None]])
check('other key', solve([[[10, 'a', 5]], [['a', 4, 1, 'right', False], ['b', 5, 1, 'wrong', False], [None, 5, 2, 'wildcard', False]]]), [[10, 'right']])
check('absent dimension', solve([[[10, 'a', 4]], []]), [[10, None]])
elif N == 5:
check('future ignored', solve([[[10, 'a', 6]], [['a', 5, 1, 'old', False], ['a', 7, 1, 'future', False]]]), [[10, 'old']])
check('exact effective time', solve([[[10, 'a', 5]], [['a', 5, 1, 'current', False]]]), [[10, 'current']])
check('revision precedence', solve([[[10, 'a', 5]], [['a', 5, 1, 'old', False], ['a', 5, 2, 'new', False]]]), [[10, 'new']])
check('tombstone blocks old', solve([[[10, 'a', 6]], [['a', 5, 1, 'old', False], ['a', 6, 1, None, True]]]), [[10, None]])
check('tombstone hidden payload', solve([[[10, 'a', 5]], [['a', 5, 1, 'hidden', True]]]), [[10, None]])
check('other key', solve([[[10, 'a', 6]], [['a', 5, 1, 'right', False], ['b', 6, 1, 'wrong', False], [None, 6, 2, 'wildcard', False]]]), [[10, 'right']])
check('absent dimension', solve([[[10, 'a', 5]], []]), [[10, None]])
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 |
|---|---|---|---|
| future ignored | [[10, 'future']] | [[10, 'old']] | Failed |
| exact effective time | [[10, 'current']] | [[10, 'current']] | Passed |
| revision precedence | [[10, 'new']] | [[10, 'new']] | Passed |
| tombstone blocks old | [[10, None]] | [[10, None]] | Passed |
| tombstone hidden payload | [[10, None]] | [[10, None]] | Passed |
| other key | [[10, None]] | [[10, 'right']] | Failed |
| absent dimension | [[10, None]] | [[10, None]] | Passed |
SHA-256 / d88f056f71d7b1f5ad14813eedd926d7b22b60331591ea055266fc46eb9145fa
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(d):
try:
facts,versions=d
out=[]
for ident,key,time in facts:
candidates=[r for r in versions if key is not None and r[0]==key and r[1]<=time]
if not candidates: out.append([ident,None]); continue
chosen=max(candidates,key=lambda r:(r[1],r[2]))
out.append([ident,None if chosen[4] else chosen[3]])
return out
except (IndexError, KeyError, ValueError, StopIteration) as exc:
return {"representation_error": type(exc).__name__}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
if N == 1:
check('future ignored', solve([[[10, 'a', 2]], [['a', 1, 1, 'old', False], ['a', 3, 1, 'future', False]]]), [[10, 'old']])
check('exact effective time', solve([[[10, 'a', 1]], [['a', 1, 1, 'current', False]]]), [[10, 'current']])
check('revision precedence', solve([[[10, 'a', 1]], [['a', 1, 1, 'old', False], ['a', 1, 2, 'new', False]]]), [[10, 'new']])
check('tombstone blocks old', solve([[[10, 'a', 2]], [['a', 1, 1, 'old', False], ['a', 2, 1, None, True]]]), [[10, None]])
check('tombstone hidden payload', solve([[[10, 'a', 1]], [['a', 1, 1, 'hidden', True]]]), [[10, None]])
check('other key', solve([[[10, 'a', 2]], [['a', 1, 1, 'right', False], ['b', 2, 1, 'wrong', False], [None, 2, 2, 'wildcard', False]]]), [[10, 'right']])
check('absent dimension', solve([[[10, 'a', 1]], []]), [[10, None]])
elif N == 2:
check('future ignored', solve([[[10, 'a', 3]], [['a', 2, 1, 'old', False], ['a', 4, 1, 'future', False]]]), [[10, 'old']])
check('exact effective time', solve([[[10, 'a', 2]], [['a', 2, 1, 'current', False]]]), [[10, 'current']])
check('revision precedence', solve([[[10, 'a', 2]], [['a', 2, 1, 'old', False], ['a', 2, 2, 'new', False]]]), [[10, 'new']])
check('tombstone blocks old', solve([[[10, 'a', 3]], [['a', 2, 1, 'old', False], ['a', 3, 1, None, True]]]), [[10, None]])
check('tombstone hidden payload', solve([[[10, 'a', 2]], [['a', 2, 1, 'hidden', True]]]), [[10, None]])
check('other key', solve([[[10, 'a', 3]], [['a', 2, 1, 'right', False], ['b', 3, 1, 'wrong', False], [None, 3, 2, 'wildcard', False]]]), [[10, 'right']])
check('absent dimension', solve([[[10, 'a', 2]], []]), [[10, None]])
elif N == 3:
check('future ignored', solve([[[10, 'a', 4]], [['a', 3, 1, 'old', False], ['a', 5, 1, 'future', False]]]), [[10, 'old']])
check('exact effective time', solve([[[10, 'a', 3]], [['a', 3, 1, 'current', False]]]), [[10, 'current']])
check('revision precedence', solve([[[10, 'a', 3]], [['a', 3, 1, 'old', False], ['a', 3, 2, 'new', False]]]), [[10, 'new']])
check('tombstone blocks old', solve([[[10, 'a', 4]], [['a', 3, 1, 'old', False], ['a', 4, 1, None, True]]]), [[10, None]])
check('tombstone hidden payload', solve([[[10, 'a', 3]], [['a', 3, 1, 'hidden', True]]]), [[10, None]])
check('other key', solve([[[10, 'a', 4]], [['a', 3, 1, 'right', False], ['b', 4, 1, 'wrong', False], [None, 4, 2, 'wildcard', False]]]), [[10, 'right']])
check('absent dimension', solve([[[10, 'a', 3]], []]), [[10, None]])
elif N == 4:
check('future ignored', solve([[[10, 'a', 5]], [['a', 4, 1, 'old', False], ['a', 6, 1, 'future', False]]]), [[10, 'old']])
check('exact effective time', solve([[[10, 'a', 4]], [['a', 4, 1, 'current', False]]]), [[10, 'current']])
check('revision precedence', solve([[[10, 'a', 4]], [['a', 4, 1, 'old', False], ['a', 4, 2, 'new', False]]]), [[10, 'new']])
check('tombstone blocks old', solve([[[10, 'a', 5]], [['a', 4, 1, 'old', False], ['a', 5, 1, None, True]]]), [[10, None]])
check('tombstone hidden payload', solve([[[10, 'a', 4]], [['a', 4, 1, 'hidden', True]]]), [[10, None]])
check('other key', solve([[[10, 'a', 5]], [['a', 4, 1, 'right', False], ['b', 5, 1, 'wrong', False], [None, 5, 2, 'wildcard', False]]]), [[10, 'right']])
check('absent dimension', solve([[[10, 'a', 4]], []]), [[10, None]])
elif N == 5:
check('future ignored', solve([[[10, 'a', 6]], [['a', 5, 1, 'old', False], ['a', 7, 1, 'future', False]]]), [[10, 'old']])
check('exact effective time', solve([[[10, 'a', 5]], [['a', 5, 1, 'current', False]]]), [[10, 'current']])
check('revision precedence', solve([[[10, 'a', 5]], [['a', 5, 1, 'old', False], ['a', 5, 2, 'new', False]]]), [[10, 'new']])
check('tombstone blocks old', solve([[[10, 'a', 6]], [['a', 5, 1, 'old', False], ['a', 6, 1, None, True]]]), [[10, None]])
check('tombstone hidden payload', solve([[[10, 'a', 5]], [['a', 5, 1, 'hidden', True]]]), [[10, None]])
check('other key', solve([[[10, 'a', 6]], [['a', 5, 1, 'right', False], ['b', 6, 1, 'wrong', False], [None, 6, 2, 'wildcard', False]]]), [[10, 'right']])
check('absent dimension', solve([[[10, 'a', 5]], []]), [[10, None]])
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 |
|---|---|---|---|
| future ignored | [[10, 'old']] | [[10, 'old']] | Passed |
| exact effective time | [[10, 'current']] | [[10, 'current']] | Passed |
| revision precedence | [[10, 'new']] | [[10, 'new']] | Passed |
| tombstone blocks old | [[10, None]] | [[10, None]] | Passed |
| tombstone hidden payload | [[10, None]] | [[10, None]] | Passed |
| other key | [[10, 'right']] | [[10, 'right']] | Passed |
| absent dimension | [[10, None]] | [[10, None]] | Passed |
SHA-256 / a1a05f3bfda2c86083022adb1dac1aefe34ae9e687c4dfd4e7afa571b1d6cf77
Verification & scope
Offline stipulated semantics over valid small inputs; no performance, concurrency, or production-engine conformance claim. 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:44:25.076833+00:00.
Case digest / 967903ee90ecaa889b8be68e2c8e94d6e717724aab2c7ae2c58178d05573206e