FAILURE MAP
← Case archive

FA-45736 / Data systems / Open access

Temporal enrichment skips tombstones and revives older dimension values · case 01

Temporal enrichment skips tombstones and revives older dimension values.

Verified by executionVariant 1 · 7 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

temporal-dimension-lookup: Temporal enrichment skips tombstones and revives older dimension values.

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: Filtering null payload tombstones before selecting a version likewise resurrects history.

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 r[1]<=time and not r[4]]
            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 fixtureActualExpectedOutcome
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, 'old']][[10, None]]Failed
tombstone hidden payload[[10, None]][[10, None]]Passed
other key[[10, 'right']][[10, 'right']]Passed
absent dimension[[10, None]][[10, None]]Passed

SHA-256 / 3ab7a1775462fa77542f95a28e58d43ea9df142a6a28e4ca20cec348f40f8bf2

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 and r[3] is not None]
            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 fixtureActualExpectedOutcome
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, 'old']][[10, None]]Failed
tombstone hidden payload[[10, None]][[10, None]]Passed
other key[[10, 'right']][[10, 'right']]Passed
absent dimension[[10, None]][[10, None]]Passed

SHA-256 / d7e070c0a396371f96e966ac2368717d7811df66baf51c84c3d3fe7bbd78b509

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 fixtureActualExpectedOutcome
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.160225+00:00.

Case digest / 067b7e9625ca735d5e7b8f90e57211905c6400c2aa6772ee788fbc9c23232e27