FAILURE MAP
← Case archive

FA-9141 / Build systems / Open access

Build prerequisite closure: Order-only edges contaminate content prerequisites · case 01

Order-only edges contaminate content prerequisites.

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

ROOT CAUSE

The implementation substitutes if True for if kind == 'normal', so order-only edges contaminate content prerequisites.

VERIFIED REPAIR

Traverse exactly normal prerequisite edges.

Unsuccessful approach: The attempted repair substitutes if kind == 'order'. Fixture 3 still yields ['a', 'c'] instead of ['a', 'b'].

Case contract

Return sorted unique reachable target names including roots. Traverse normal prerequisites, exclude order-only prerequisites, retain unknown leaves, and stop cycles.

Why this case matters

An offline model of build prerequisite closure, suitable for testing build and release tooling without external services.

1 / The failure

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

N = 1
observations = []
def solve(roots, edges):
    seen = set()
    stack = list(roots)
    while stack:
        node = stack.pop()
        if node in seen:
            continue
        seen.add(node)
        stack.extend(dep for dep, kind in edges.get(node, []) if True)
    return sorted(seen)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('fixture 1', solve([], {}), [])
check('fixture 2', solve(['a'], {}), ['a'])
check('fixture 3', solve(['a'], {'a': [('b', 'normal'), ('c', 'order')]}), ['a', 'b'])
check('fixture 4', solve(['a'], {'a': [('b', 'normal')], 'b': [('c', 'normal')]}), ['a', 'b', 'c'])
check('fixture 5', solve(['z', 'a'], {}), ['a', 'z'])
check('fixture 6', solve(['a', 'a'], {'a': [('b', 'normal')]}), ['a', 'b'])
check('fixture 7', solve(['a'], {'a': [('b', 'normal')], 'b': [('a', 'normal')]}), ['a', 'b'])
check('fixture 8', solve(['a'], {'a': [('b', 'order')]}), ['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 fixtureActualExpectedOutcome
fixture 1[][]Passed
fixture 2['a']['a']Passed
fixture 3['a', 'b', 'c']['a', 'b']Failed
fixture 4['a', 'b', 'c']['a', 'b', 'c']Passed
fixture 5['a', 'z']['a', 'z']Passed
fixture 6['a', 'b']['a', 'b']Passed
fixture 7['a', 'b']['a', 'b']Passed
fixture 8['a', 'b']['a']Failed

SHA-256 / 47e6c5a8f18633cd1cfa0b1a2a4bc746745bee9bd429fab3733252ea7210a62c

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(roots, edges):
    seen = set()
    stack = list(roots)
    while stack:
        node = stack.pop()
        if node in seen:
            continue
        seen.add(node)
        stack.extend(dep for dep, kind in edges.get(node, []) if kind == 'order')
    return sorted(seen)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('fixture 1', solve([], {}), [])
check('fixture 2', solve(['a'], {}), ['a'])
check('fixture 3', solve(['a'], {'a': [('b', 'normal'), ('c', 'order')]}), ['a', 'b'])
check('fixture 4', solve(['a'], {'a': [('b', 'normal')], 'b': [('c', 'normal')]}), ['a', 'b', 'c'])
check('fixture 5', solve(['z', 'a'], {}), ['a', 'z'])
check('fixture 6', solve(['a', 'a'], {'a': [('b', 'normal')]}), ['a', 'b'])
check('fixture 7', solve(['a'], {'a': [('b', 'normal')], 'b': [('a', 'normal')]}), ['a', 'b'])
check('fixture 8', solve(['a'], {'a': [('b', 'order')]}), ['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 fixtureActualExpectedOutcome
fixture 1[][]Passed
fixture 2['a']['a']Passed
fixture 3['a', 'c']['a', 'b']Failed
fixture 4['a']['a', 'b', 'c']Failed
fixture 5['a', 'z']['a', 'z']Passed
fixture 6['a']['a', 'b']Failed
fixture 7['a']['a', 'b']Failed
fixture 8['a', 'b']['a']Failed

SHA-256 / 90c78b3ad09e0ce28aab2e92817a5bf22b7c8de9dee9c1d6c5341ce079b7c80e

3 / The verified repair

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

N = 1
observations = []
def solve(roots, edges):
    seen = set()
    stack = list(roots)
    while stack:
        node = stack.pop()
        if node in seen:
            continue
        seen.add(node)
        stack.extend(dep for dep, kind in edges.get(node, []) if kind == 'normal')
    return sorted(seen)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('fixture 1', solve([], {}), [])
check('fixture 2', solve(['a'], {}), ['a'])
check('fixture 3', solve(['a'], {'a': [('b', 'normal'), ('c', 'order')]}), ['a', 'b'])
check('fixture 4', solve(['a'], {'a': [('b', 'normal')], 'b': [('c', 'normal')]}), ['a', 'b', 'c'])
check('fixture 5', solve(['z', 'a'], {}), ['a', 'z'])
check('fixture 6', solve(['a', 'a'], {'a': [('b', 'normal')]}), ['a', 'b'])
check('fixture 7', solve(['a'], {'a': [('b', 'normal')], 'b': [('a', 'normal')]}), ['a', 'b'])
check('fixture 8', solve(['a'], {'a': [('b', 'order')]}), ['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 fixtureActualExpectedOutcome
fixture 1[][]Passed
fixture 2['a']['a']Passed
fixture 3['a', 'b']['a', 'b']Passed
fixture 4['a', 'b', 'c']['a', 'b', 'c']Passed
fixture 5['a', 'z']['a', 'z']Passed
fixture 6['a', 'b']['a', 'b']Passed
fixture 7['a', 'b']['a', 'b']Passed
fixture 8['a']['a']Passed

SHA-256 / fb736e0b08304b845b394f4b47290c65c7e176c81d696953ae08cfde7c6b4012

Verification & scope

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

Case digest / 3a021602092aff7d021f17a33e47f37b1ab8376565542a049f70dc5083b94274