FAILURE MAP
← Case archive

FA-11936 / Scientific pipeline provenance / Open access

A reprocessed artifact retains the previous processing provenance · case 01

A reprocessed artifact retains the previous processing provenance.

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

ROOT CAUSE

A new artifact inherits its parent processing history without recording the new run.

VERIFIED REPAIR

Append the new run to inherited ordered history without mutating the input.

Unsuccessful approach: Replacing history with the latest run discards earlier processing.

Case contract

Return inherited ordered run IDs followed by the current run ID; repeated run IDs represent separate executions and are retained.

Why this case matters

A deterministic offline model of scientific workflow bookkeeping; the fixtures test provenance contracts without modeling instruments or biological inference.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(history, run):
    return list(history)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
r='run'+str(N)
check('reprocessing records both runs', solve(['raw','filter'], r), ['raw','filter',r])
check('initial processing', solve([], r), [r])
check('same run repeated', solve([r], r), [r,r])
check('one previous run', solve(['raw'], r), ['raw',r])
check('order of ancestors retained', solve(['z','a'], r), ['z','a',r])
h=['raw']
solve(h,r)
check('parent provenance immutable', h, ['raw'])
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
reprocessing records both runs['raw', 'filter']['raw', 'filter', 'run1']Failed
initial processing[]['run1']Failed
same run repeated['run1']['run1', 'run1']Failed
one previous run['raw']['raw', 'run1']Failed
order of ancestors retained['z', 'a']['z', 'a', 'run1']Failed
parent provenance immutable['raw']['raw']Passed

SHA-256 / eaae151133dff2d21be7cc30d1b7e90c29e0cf53a61b26716b56cc8c68fd107b

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(history, run):
    return [run]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
r='run'+str(N)
check('reprocessing records both runs', solve(['raw','filter'], r), ['raw','filter',r])
check('initial processing', solve([], r), [r])
check('same run repeated', solve([r], r), [r,r])
check('one previous run', solve(['raw'], r), ['raw',r])
check('order of ancestors retained', solve(['z','a'], r), ['z','a',r])
h=['raw']
solve(h,r)
check('parent provenance immutable', h, ['raw'])
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
reprocessing records both runs['run1']['raw', 'filter', 'run1']Failed
initial processing['run1']['run1']Passed
same run repeated['run1']['run1', 'run1']Failed
one previous run['run1']['raw', 'run1']Failed
order of ancestors retained['run1']['z', 'a', 'run1']Failed
parent provenance immutable['raw']['raw']Passed

SHA-256 / 0b3685ec5ba00cb80b8b40e38e4e89cb3993c35655ab87e3b9f21259e384addd

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(history, run):
    return list(history)+[run]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
r='run'+str(N)
check('reprocessing records both runs', solve(['raw','filter'], r), ['raw','filter',r])
check('initial processing', solve([], r), [r])
check('same run repeated', solve([r], r), [r,r])
check('one previous run', solve(['raw'], r), ['raw',r])
check('order of ancestors retained', solve(['z','a'], r), ['z','a',r])
h=['raw']
solve(h,r)
check('parent provenance immutable', h, ['raw'])
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
reprocessing records both runs['raw', 'filter', 'run1']['raw', 'filter', 'run1']Passed
initial processing['run1']['run1']Passed
same run repeated['run1', 'run1']['run1', 'run1']Passed
one previous run['raw', 'run1']['raw', 'run1']Passed
order of ancestors retained['z', 'a', 'run1']['z', 'a', 'run1']Passed
parent provenance immutable['raw']['raw']Passed

SHA-256 / 221837544f04a2e671edd34a3a6db4589becf870c9b3a36c55321185c9963bb9

Verification & scope

In-memory symbolic records only; no instrument, assay, or production workflow validation. 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:52.365213+00:00.

Case digest / d4842024bd238f914813f8b71de8638e67c5054f2b982a373eaad8972faa5f3a