FAILURE MAP
← Case archive

FA-97296 / Recipe scaling and nutrition / Open access

Backward recipe step scheduler: step duration offset · case 01

Every step is shown starting at the moment it must finish.

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

ROOT CAUSE

The step duration is not subtracted from its deadline.

VERIFIED REPAIR

Start = deadline - duration.

Unsuccessful approach: Adding one minute of slack makes every step late.

Case contract

Steps [name, minutes, depends_on]; a step must finish before any step depending on it starts. Latest start = min(latest start of dependents, serve time) - minutes. Unknown dependency -> "error: unknown step X"; a cycle -> "error: cycle". Serve "HH:MM"; starts print as "HH:MM" modulo 24h (previous day wraps). Output [[name, time]] sorted by absolute start then name.

Why this case matters

Dinner-party and restaurant prep planners schedule long marinades and roasts backward from service.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(steps, serve):
    by = {s[0]: s for s in steps}
    for s in steps:
        for d in s[2]:
            if d not in by:
                return 'error: unknown step ' + d
    h, m = serve.split(':')
    T = int(h) * 60 + int(m)
    latest = {}
    visiting = set()
    def ls(n):
        if n in latest:
            return latest[n]
        if n in visiting:
            return None
        visiting.add(n)
        finish = T
        for s in steps:
            if n in s[2]:
                v = ls(s[0])
                if v is None:
                    return None
                finish = min(finish, v)
        visiting.discard(n)
        latest[n] = finish
        return latest[n]
    rows = []
    for s in steps:
        v = ls(s[0])
        if v is None:
            return 'error: cycle'
        rows.append((v, s[0]))
    rows.sort()
    return [[n, '%02d:%02d' % divmod(v % 1440, 60)] for v, n in rows]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['chain', [[['prep', 10, []], ['roast', 90, ['prep']], ['rest', 15, ['roast']]], '18:30'],
   [['prep', '16:35'], ['roast', '16:45'], ['rest', '18:15']]],
  ['overnight marinade', [[['marinate', 480, []], ['grill', 20, ['marinate']]], '12:00'],
   [['marinate', '03:40'], ['grill', '11:40']]],
  ['cycle', [[['a', 5, ['b']], ['b', 5, ['a']]], '18:00'], 'error: cycle'],
  ['regression: step duration offset',
   [[['roast', 240, ['marinate']], ['sauce', 240, ['prep']], ['marinate', 30, []], ['prep', 10, []]],
    '19:45'],
   [['marinate', '15:15'], ['prep', '15:35'], ['roast', '15:45'], ['sauce', '15:45']]],
  ['repair check: step duration offset',
   [[['sauce', 15, ['prep']], ['prep', 45, []], ['rest', 240, []], ['roast', 15, ['prep']],
     ['marinate', 45, ['prep']]],
    '00:30'],
   [['rest', '20:30'], ['prep', '23:00'], ['marinate', '23:45'], ['roast', '00:15'], ['sauce', '00:15']]],
  ['generated control 1',
   [[['sauce', 45, ['shop']], ['roast', 45, ['prep', 'marinate']], ['marinate', 90, []], ['prep', 15, []],
     ['rest', 10, ['sauce']]],
    '00:30'],
   'error: unknown step shop'],
  ['generated control 2',
   [[['sauce', 30, ['prep', 'marinate', 'shop']], ['rest', 45, ['roast']], ['marinate', 5, []],
     ['prep', 5, []], ['roast', 5, ['prep']]],
    '19:45'],
   'error: unknown step shop'],
  ['generated control 3',
   [[['roast', 10, ['prep', 'marinate']], ['marinate', 15, []], ['prep', 45, ['roast']]], '12:00'],
   'error: cycle']],
 [['overnight marinade', [[['marinate', 480, []], ['grill', 20, ['marinate']]], '12:00'],
   [['marinate', '03:40'], ['grill', '11:40']]],
  ['cycle', [[['a', 5, ['b']], ['b', 5, ['a']]], '18:00'], 'error: cycle'],
  ['unknown dependency', [[['a', 5, ['shop']]], '18:00'], 'error: unknown step shop'],
  ['regression: step duration offset',
   [[['marinate', 240, []], ['plate', 5, ['prep', 'roast', 'rest']], ['sauce', 5, ['prep']],
     ['roast', 30, ['prep', 'marinate']], ['prep', 45, []], ['rest', 30, ['roast', 'sauce']]],
    '01:15'],
   [['marinate', '20:10'], ['prep', '23:25'], ['roast', '00:10'], ['sauce', '00:35'], ['rest', '00:40'],
    ['plate', '01:10']]],
  ['repair check: step duration offset',
   [[['prep', 15, []], ['plate', 10, ['rest']], ['rest', 10, ['marinate']], ['marinate', 240, ['prep']],
     ['sauce', 45, ['roast']], ['roast', 15, ['marinate']]],
    '18:30'],
   [['prep', '13:15'], ['marinate', '13:30'], ['roast', '17:30'], ['sauce', '17:45'], ['rest', '18:10'],
    ['plate', '18:20']]],
  ['generated control 1',
   [[['marinate', 10, []], ['plate', 45, ['prep', 'sauce']], ['rest', 90, ['prep', 'marinate', 'sauce']],
     ['sauce', 45, ['marinate']], ['prep', 90, []], ['roast', 15, ['prep']]],
    '19:45'],
   [['prep', '16:45'], ['marinate', '17:20'], ['sauce', '17:30'], ['rest', '18:15'], ['plate', '19:00'],
    ['roast', '19:30']]],
  ['generated control 2',
   [[['prep', 90, []], ['sauce', 10, ['prep', 'marinate']], ['roast', 30, ['prep']],
     ['marinate', 15, ['prep']]],
    '12:00'],
   [['prep', '10:00'], ['roast', '11:30'], ['marinate', '11:35'], ['sauce', '11:50']]],
  ['generated control 3',
   [[['prep', 15, []], ['sauce', 30, []], ['marinate', 10, []], ['rest', 10, ['shop']],
     ['roast', 240, ['prep', 'marinate']]],
    '19:45'],
   'error: unknown step shop']],
 [['cycle', [[['a', 5, ['b']], ['b', 5, ['a']]], '18:00'], 'error: cycle'],
  ['unknown dependency', [[['a', 5, ['shop']]], '18:00'], 'error: unknown step shop'],
  ['chain', [[['prep', 10, []], ['roast', 90, ['prep']], ['rest', 15, ['roast']]], '18:30'],
   [['prep', '16:35'], ['roast', '16:45'], ['rest', '18:15']]],
  ['regression: step duration offset',
   [[['prep', 240, []], ['roast', 90, []], ['marinate', 45, ['prep']]], '12:00'],
   [['prep', '07:15'], ['roast', '10:30'], ['marinate', '11:15']]],
  ['repair check: step duration offset',
   [[['prep', 30, []], ['roast', 5, []], ['sauce', 15, ['prep', 'marinate']], ['marinate', 30, ['prep']]],
    '01:15'],
   [['prep', '00:00'], ['marinate', '00:30'], ['sauce', '01:00'], ['roast', '01:10']]],
  ['generated control 1',
   [[['roast', 45, ['prep', 'marinate']], ['marinate', 30, ['prep']], ['sauce', 5, ['prep', 'marinate']],
     ['prep', 240, ['sauce']]],
    '02:00'],
   'error: cycle'],
  ['generated control 2',
   [[['rest', 15, ['roast', 'sauce']], ['roast', 90, []], ['prep', 15, []],
     ['marinate', 45, ['prep', 'shop']], ['sauce', 10, ['roast']]],
    '02:00'],
   'error: unknown step shop'],
  ['generated control 3',
   [[['marinate', 15, []], ['roast', 15, ['prep', 'marinate']], ['prep', 15, []],
     ['rest', 90, ['prep', 'marinate', 'roast']], ['sauce', 45, ['shop']]],
    '02:00'],
   'error: unknown step shop']],
 [['unknown dependency', [[['a', 5, ['shop']]], '18:00'], 'error: unknown step shop'],
  ['chain', [[['prep', 10, []], ['roast', 90, ['prep']], ['rest', 15, ['roast']]], '18:30'],
   [['prep', '16:35'], ['roast', '16:45'], ['rest', '18:15']]],
  ['overnight marinade', [[['marinate', 480, []], ['grill', 20, ['marinate']]], '12:00'],
   [['marinate', '03:40'], ['grill', '11:40']]],
  ['regression: step duration offset',
   [[['sauce', 5, []], ['roast', 15, ['prep', 'marinate']], ['prep', 15, []], ['rest', 10, ['prep']],
     ['marinate', 10, ['prep']]],
    '01:15'],
   [['prep', '00:35'], ['marinate', '00:50'], ['roast', '01:00'], ['rest', '01:05'], ['sauce', '01:10']]],
  ['repair check: step duration offset',
   [[['roast', 10, ['prep', 'marinate']], ['prep', 30, []], ['sauce', 90, ['marinate', 'roast']],
     ['marinate', 240, []], ['rest', 10, ['prep', 'sauce']]],
    '19:45'],
   [['marinate', '13:55'], ['prep', '17:25'], ['roast', '17:55'], ['sauce', '18:05'], ['rest', '19:35']]],
  ['generated control 1',
   [[['rest', 240, ['prep', 'roast', 'sauce']], ['marinate', 90, []], ['sauce', 5, ['prep', 'marinate']],
     ['roast', 45, []], ['prep', 15, ['rest']]],
    '18:30'],
   'error: cycle'],
  ['generated control 2', [[['roast', 15, ['prep']], ['prep', 15, []], ['marinate', 10, []]], '00:30'],
   [['prep', '00:00'], ['roast', '00:15'], ['marinate', '00:20']]],
  ['generated control 3',
   [[['rest', 240, ['roast']], ['roast', 45, ['prep', 'shop']], ['marinate', 10, []],
     ['sauce', 45, ['prep', 'roast']], ['prep', 240, []]],
    '01:15'],
   'error: unknown step shop']],
 [['chain', [[['prep', 10, []], ['roast', 90, ['prep']], ['rest', 15, ['roast']]], '18:30'],
   [['prep', '16:35'], ['roast', '16:45'], ['rest', '18:15']]],
  ['overnight marinade', [[['marinate', 480, []], ['grill', 20, ['marinate']]], '12:00'],
   [['marinate', '03:40'], ['grill', '11:40']]],
  ['cycle', [[['a', 5, ['b']], ['b', 5, ['a']]], '18:00'], 'error: cycle'],
  ['regression: step duration offset',
   [[['prep', 10, []], ['rest', 30, ['marinate', 'roast', 'sauce']], ['sauce', 30, []],
     ['plate', 90, ['prep', 'roast', 'sauce', 'rest']], ['marinate', 30, ['prep']],
     ['roast', 30, ['marinate']]],
    '01:15'],
   [['prep', '22:05'], ['marinate', '22:15'], ['roast', '22:45'], ['sauce', '22:45'], ['rest', '23:15'],
    ['plate', '23:45']]],
  ['repair check: step duration offset',
   [[['roast', 45, ['prep', 'marinate']], ['rest', 90, ['prep']], ['prep', 10, []],
     ['marinate', 15, ['prep']], ['plate', 10, ['roast']], ['sauce', 5, ['prep', 'marinate']]],
    '19:45'],
   [['prep', '18:05'], ['rest', '18:15'], ['marinate', '18:35'], ['roast', '18:50'], ['plate', '19:35'],
    ['sauce', '19:40']]],
  ['generated control 1',
   [[['prep', 45, []], ['marinate', 5, []], ['roast', 240, []], ['sauce', 30, ['roast']]], '02:00'],
   [['roast', '21:30'], ['prep', '01:15'], ['sauce', '01:30'], ['marinate', '01:55']]],
  ['generated control 2',
   [[['plate', 15, []], ['marinate', 240, ['prep']], ['prep', 15, []], ['roast', 15, []],
     ['rest', 15, ['marinate']], ['sauce', 45, ['marinate']]],
    '18:30'],
   [['prep', '13:30'], ['marinate', '13:45'], ['sauce', '17:45'], ['plate', '18:15'], ['rest', '18:15'],
    ['roast', '18:15']]],
  ['generated control 3',
   [[['marinate', 240, ['shop']], ['plate', 45, ['prep', 'sauce']], ['rest', 90, []], ['prep', 90, ['plate']],
     ['sauce', 240, ['marinate', 'roast']], ['roast', 15, ['prep', 'marinate']]],
    '19:45'],
   'error: unknown step shop']]]
for label, args, expected in fixtures[N - 1]:
    check(label, solve(*args), expected)
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
chain[['prep', '18:30'], ['rest', '18:30'], ['roast', '18:30']][['prep', '16:35'], ['roast', '16:45'], ['rest', '18:15']]Failed
overnight marinade[['grill', '12:00'], ['marinate', '12:00']][['marinate', '03:40'], ['grill', '11:40']]Failed
cycleerror: cycleerror: cyclePassed
regression: step duration offset[['marinate', '19:45'], ['prep', '19:45'], ['roast', '19:45'], ['sauce', '19:45']][['marinate', '15:15'], ['prep', '15:35'], ['roast', '15:45'], ['sauce', '15:45']]Failed
repair check: step duration offset[['marinate', '00:30'], ['prep', '00:30'], ['rest', '00:30'], ['roast', '00:30'], ['sauce', '00:30']][['rest', '20:30'], ['prep', '23:00'], ['marinate', '23:45'], ['roast', '00:15'], ['sauce', '00:15']]Failed
generated control 1error: unknown step shoperror: unknown step shopPassed
generated control 2error: unknown step shoperror: unknown step shopPassed
generated control 3error: cycleerror: cyclePassed

SHA-256 / 935c8abe821b2b9ddab2d1c0236d1d10d2b8350477ec33901a07cd3fa5031d99

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(steps, serve):
    by = {s[0]: s for s in steps}
    for s in steps:
        for d in s[2]:
            if d not in by:
                return 'error: unknown step ' + d
    h, m = serve.split(':')
    T = int(h) * 60 + int(m)
    latest = {}
    visiting = set()
    def ls(n):
        if n in latest:
            return latest[n]
        if n in visiting:
            return None
        visiting.add(n)
        finish = T
        for s in steps:
            if n in s[2]:
                v = ls(s[0])
                if v is None:
                    return None
                finish = min(finish, v)
        visiting.discard(n)
        latest[n] = finish - by[n][1] + 1
        return latest[n]
    rows = []
    for s in steps:
        v = ls(s[0])
        if v is None:
            return 'error: cycle'
        rows.append((v, s[0]))
    rows.sort()
    return [[n, '%02d:%02d' % divmod(v % 1440, 60)] for v, n in rows]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['chain', [[['prep', 10, []], ['roast', 90, ['prep']], ['rest', 15, ['roast']]], '18:30'],
   [['prep', '16:35'], ['roast', '16:45'], ['rest', '18:15']]],
  ['overnight marinade', [[['marinate', 480, []], ['grill', 20, ['marinate']]], '12:00'],
   [['marinate', '03:40'], ['grill', '11:40']]],
  ['cycle', [[['a', 5, ['b']], ['b', 5, ['a']]], '18:00'], 'error: cycle'],
  ['regression: step duration offset',
   [[['roast', 240, ['marinate']], ['sauce', 240, ['prep']], ['marinate', 30, []], ['prep', 10, []]],
    '19:45'],
   [['marinate', '15:15'], ['prep', '15:35'], ['roast', '15:45'], ['sauce', '15:45']]],
  ['repair check: step duration offset',
   [[['sauce', 15, ['prep']], ['prep', 45, []], ['rest', 240, []], ['roast', 15, ['prep']],
     ['marinate', 45, ['prep']]],
    '00:30'],
   [['rest', '20:30'], ['prep', '23:00'], ['marinate', '23:45'], ['roast', '00:15'], ['sauce', '00:15']]],
  ['generated control 1',
   [[['sauce', 45, ['shop']], ['roast', 45, ['prep', 'marinate']], ['marinate', 90, []], ['prep', 15, []],
     ['rest', 10, ['sauce']]],
    '00:30'],
   'error: unknown step shop'],
  ['generated control 2',
   [[['sauce', 30, ['prep', 'marinate', 'shop']], ['rest', 45, ['roast']], ['marinate', 5, []],
     ['prep', 5, []], ['roast', 5, ['prep']]],
    '19:45'],
   'error: unknown step shop'],
  ['generated control 3',
   [[['roast', 10, ['prep', 'marinate']], ['marinate', 15, []], ['prep', 45, ['roast']]], '12:00'],
   'error: cycle']],
 [['overnight marinade', [[['marinate', 480, []], ['grill', 20, ['marinate']]], '12:00'],
   [['marinate', '03:40'], ['grill', '11:40']]],
  ['cycle', [[['a', 5, ['b']], ['b', 5, ['a']]], '18:00'], 'error: cycle'],
  ['unknown dependency', [[['a', 5, ['shop']]], '18:00'], 'error: unknown step shop'],
  ['regression: step duration offset',
   [[['marinate', 240, []], ['plate', 5, ['prep', 'roast', 'rest']], ['sauce', 5, ['prep']],
     ['roast', 30, ['prep', 'marinate']], ['prep', 45, []], ['rest', 30, ['roast', 'sauce']]],
    '01:15'],
   [['marinate', '20:10'], ['prep', '23:25'], ['roast', '00:10'], ['sauce', '00:35'], ['rest', '00:40'],
    ['plate', '01:10']]],
  ['repair check: step duration offset',
   [[['prep', 15, []], ['plate', 10, ['rest']], ['rest', 10, ['marinate']], ['marinate', 240, ['prep']],
     ['sauce', 45, ['roast']], ['roast', 15, ['marinate']]],
    '18:30'],
   [['prep', '13:15'], ['marinate', '13:30'], ['roast', '17:30'], ['sauce', '17:45'], ['rest', '18:10'],
    ['plate', '18:20']]],
  ['generated control 1',
   [[['marinate', 10, []], ['plate', 45, ['prep', 'sauce']], ['rest', 90, ['prep', 'marinate', 'sauce']],
     ['sauce', 45, ['marinate']], ['prep', 90, []], ['roast', 15, ['prep']]],
    '19:45'],
   [['prep', '16:45'], ['marinate', '17:20'], ['sauce', '17:30'], ['rest', '18:15'], ['plate', '19:00'],
    ['roast', '19:30']]],
  ['generated control 2',
   [[['prep', 90, []], ['sauce', 10, ['prep', 'marinate']], ['roast', 30, ['prep']],
     ['marinate', 15, ['prep']]],
    '12:00'],
   [['prep', '10:00'], ['roast', '11:30'], ['marinate', '11:35'], ['sauce', '11:50']]],
  ['generated control 3',
   [[['prep', 15, []], ['sauce', 30, []], ['marinate', 10, []], ['rest', 10, ['shop']],
     ['roast', 240, ['prep', 'marinate']]],
    '19:45'],
   'error: unknown step shop']],
 [['cycle', [[['a', 5, ['b']], ['b', 5, ['a']]], '18:00'], 'error: cycle'],
  ['unknown dependency', [[['a', 5, ['shop']]], '18:00'], 'error: unknown step shop'],
  ['chain', [[['prep', 10, []], ['roast', 90, ['prep']], ['rest', 15, ['roast']]], '18:30'],
   [['prep', '16:35'], ['roast', '16:45'], ['rest', '18:15']]],
  ['regression: step duration offset',
   [[['prep', 240, []], ['roast', 90, []], ['marinate', 45, ['prep']]], '12:00'],
   [['prep', '07:15'], ['roast', '10:30'], ['marinate', '11:15']]],
  ['repair check: step duration offset',
   [[['prep', 30, []], ['roast', 5, []], ['sauce', 15, ['prep', 'marinate']], ['marinate', 30, ['prep']]],
    '01:15'],
   [['prep', '00:00'], ['marinate', '00:30'], ['sauce', '01:00'], ['roast', '01:10']]],
  ['generated control 1',
   [[['roast', 45, ['prep', 'marinate']], ['marinate', 30, ['prep']], ['sauce', 5, ['prep', 'marinate']],
     ['prep', 240, ['sauce']]],
    '02:00'],
   'error: cycle'],
  ['generated control 2',
   [[['rest', 15, ['roast', 'sauce']], ['roast', 90, []], ['prep', 15, []],
     ['marinate', 45, ['prep', 'shop']], ['sauce', 10, ['roast']]],
    '02:00'],
   'error: unknown step shop'],
  ['generated control 3',
   [[['marinate', 15, []], ['roast', 15, ['prep', 'marinate']], ['prep', 15, []],
     ['rest', 90, ['prep', 'marinate', 'roast']], ['sauce', 45, ['shop']]],
    '02:00'],
   'error: unknown step shop']],
 [['unknown dependency', [[['a', 5, ['shop']]], '18:00'], 'error: unknown step shop'],
  ['chain', [[['prep', 10, []], ['roast', 90, ['prep']], ['rest', 15, ['roast']]], '18:30'],
   [['prep', '16:35'], ['roast', '16:45'], ['rest', '18:15']]],
  ['overnight marinade', [[['marinate', 480, []], ['grill', 20, ['marinate']]], '12:00'],
   [['marinate', '03:40'], ['grill', '11:40']]],
  ['regression: step duration offset',
   [[['sauce', 5, []], ['roast', 15, ['prep', 'marinate']], ['prep', 15, []], ['rest', 10, ['prep']],
     ['marinate', 10, ['prep']]],
    '01:15'],
   [['prep', '00:35'], ['marinate', '00:50'], ['roast', '01:00'], ['rest', '01:05'], ['sauce', '01:10']]],
  ['repair check: step duration offset',
   [[['roast', 10, ['prep', 'marinate']], ['prep', 30, []], ['sauce', 90, ['marinate', 'roast']],
     ['marinate', 240, []], ['rest', 10, ['prep', 'sauce']]],
    '19:45'],
   [['marinate', '13:55'], ['prep', '17:25'], ['roast', '17:55'], ['sauce', '18:05'], ['rest', '19:35']]],
  ['generated control 1',
   [[['rest', 240, ['prep', 'roast', 'sauce']], ['marinate', 90, []], ['sauce', 5, ['prep', 'marinate']],
     ['roast', 45, []], ['prep', 15, ['rest']]],
    '18:30'],
   'error: cycle'],
  ['generated control 2', [[['roast', 15, ['prep']], ['prep', 15, []], ['marinate', 10, []]], '00:30'],
   [['prep', '00:00'], ['roast', '00:15'], ['marinate', '00:20']]],
  ['generated control 3',
   [[['rest', 240, ['roast']], ['roast', 45, ['prep', 'shop']], ['marinate', 10, []],
     ['sauce', 45, ['prep', 'roast']], ['prep', 240, []]],
    '01:15'],
   'error: unknown step shop']],
 [['chain', [[['prep', 10, []], ['roast', 90, ['prep']], ['rest', 15, ['roast']]], '18:30'],
   [['prep', '16:35'], ['roast', '16:45'], ['rest', '18:15']]],
  ['overnight marinade', [[['marinate', 480, []], ['grill', 20, ['marinate']]], '12:00'],
   [['marinate', '03:40'], ['grill', '11:40']]],
  ['cycle', [[['a', 5, ['b']], ['b', 5, ['a']]], '18:00'], 'error: cycle'],
  ['regression: step duration offset',
   [[['prep', 10, []], ['rest', 30, ['marinate', 'roast', 'sauce']], ['sauce', 30, []],
     ['plate', 90, ['prep', 'roast', 'sauce', 'rest']], ['marinate', 30, ['prep']],
     ['roast', 30, ['marinate']]],
    '01:15'],
   [['prep', '22:05'], ['marinate', '22:15'], ['roast', '22:45'], ['sauce', '22:45'], ['rest', '23:15'],
    ['plate', '23:45']]],
  ['repair check: step duration offset',
   [[['roast', 45, ['prep', 'marinate']], ['rest', 90, ['prep']], ['prep', 10, []],
     ['marinate', 15, ['prep']], ['plate', 10, ['roast']], ['sauce', 5, ['prep', 'marinate']]],
    '19:45'],
   [['prep', '18:05'], ['rest', '18:15'], ['marinate', '18:35'], ['roast', '18:50'], ['plate', '19:35'],
    ['sauce', '19:40']]],
  ['generated control 1',
   [[['prep', 45, []], ['marinate', 5, []], ['roast', 240, []], ['sauce', 30, ['roast']]], '02:00'],
   [['roast', '21:30'], ['prep', '01:15'], ['sauce', '01:30'], ['marinate', '01:55']]],
  ['generated control 2',
   [[['plate', 15, []], ['marinate', 240, ['prep']], ['prep', 15, []], ['roast', 15, []],
     ['rest', 15, ['marinate']], ['sauce', 45, ['marinate']]],
    '18:30'],
   [['prep', '13:30'], ['marinate', '13:45'], ['sauce', '17:45'], ['plate', '18:15'], ['rest', '18:15'],
    ['roast', '18:15']]],
  ['generated control 3',
   [[['marinate', 240, ['shop']], ['plate', 45, ['prep', 'sauce']], ['rest', 90, []], ['prep', 90, ['plate']],
     ['sauce', 240, ['marinate', 'roast']], ['roast', 15, ['prep', 'marinate']]],
    '19:45'],
   'error: unknown step shop']]]
for label, args, expected in fixtures[N - 1]:
    check(label, solve(*args), expected)
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
chain[['prep', '16:38'], ['roast', '16:47'], ['rest', '18:16']][['prep', '16:35'], ['roast', '16:45'], ['rest', '18:15']]Failed
overnight marinade[['marinate', '03:42'], ['grill', '11:41']][['marinate', '03:40'], ['grill', '11:40']]Failed
cycleerror: cycleerror: cyclePassed
regression: step duration offset[['marinate', '15:17'], ['prep', '15:37'], ['roast', '15:46'], ['sauce', '15:46']][['marinate', '15:15'], ['prep', '15:35'], ['roast', '15:45'], ['sauce', '15:45']]Failed
repair check: step duration offset[['rest', '20:31'], ['prep', '23:02'], ['marinate', '23:46'], ['roast', '00:16'], ['sauce', '00:16']][['rest', '20:30'], ['prep', '23:00'], ['marinate', '23:45'], ['roast', '00:15'], ['sauce', '00:15']]Failed
generated control 1error: unknown step shoperror: unknown step shopPassed
generated control 2error: unknown step shoperror: unknown step shopPassed
generated control 3error: cycleerror: cyclePassed

SHA-256 / e26b276f36f690f1d2cde192499ffbfe01c95fc151b9a62fa979a5d6076f7b1f

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(steps, serve):
    by = {s[0]: s for s in steps}
    for s in steps:
        for d in s[2]:
            if d not in by:
                return 'error: unknown step ' + d
    h, m = serve.split(':')
    T = int(h) * 60 + int(m)
    latest = {}
    visiting = set()
    def ls(n):
        if n in latest:
            return latest[n]
        if n in visiting:
            return None
        visiting.add(n)
        finish = T
        for s in steps:
            if n in s[2]:
                v = ls(s[0])
                if v is None:
                    return None
                finish = min(finish, v)
        visiting.discard(n)
        latest[n] = finish - by[n][1]
        return latest[n]
    rows = []
    for s in steps:
        v = ls(s[0])
        if v is None:
            return 'error: cycle'
        rows.append((v, s[0]))
    rows.sort()
    return [[n, '%02d:%02d' % divmod(v % 1440, 60)] for v, n in rows]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['chain', [[['prep', 10, []], ['roast', 90, ['prep']], ['rest', 15, ['roast']]], '18:30'],
   [['prep', '16:35'], ['roast', '16:45'], ['rest', '18:15']]],
  ['overnight marinade', [[['marinate', 480, []], ['grill', 20, ['marinate']]], '12:00'],
   [['marinate', '03:40'], ['grill', '11:40']]],
  ['cycle', [[['a', 5, ['b']], ['b', 5, ['a']]], '18:00'], 'error: cycle'],
  ['regression: step duration offset',
   [[['roast', 240, ['marinate']], ['sauce', 240, ['prep']], ['marinate', 30, []], ['prep', 10, []]],
    '19:45'],
   [['marinate', '15:15'], ['prep', '15:35'], ['roast', '15:45'], ['sauce', '15:45']]],
  ['repair check: step duration offset',
   [[['sauce', 15, ['prep']], ['prep', 45, []], ['rest', 240, []], ['roast', 15, ['prep']],
     ['marinate', 45, ['prep']]],
    '00:30'],
   [['rest', '20:30'], ['prep', '23:00'], ['marinate', '23:45'], ['roast', '00:15'], ['sauce', '00:15']]],
  ['generated control 1',
   [[['sauce', 45, ['shop']], ['roast', 45, ['prep', 'marinate']], ['marinate', 90, []], ['prep', 15, []],
     ['rest', 10, ['sauce']]],
    '00:30'],
   'error: unknown step shop'],
  ['generated control 2',
   [[['sauce', 30, ['prep', 'marinate', 'shop']], ['rest', 45, ['roast']], ['marinate', 5, []],
     ['prep', 5, []], ['roast', 5, ['prep']]],
    '19:45'],
   'error: unknown step shop'],
  ['generated control 3',
   [[['roast', 10, ['prep', 'marinate']], ['marinate', 15, []], ['prep', 45, ['roast']]], '12:00'],
   'error: cycle']],
 [['overnight marinade', [[['marinate', 480, []], ['grill', 20, ['marinate']]], '12:00'],
   [['marinate', '03:40'], ['grill', '11:40']]],
  ['cycle', [[['a', 5, ['b']], ['b', 5, ['a']]], '18:00'], 'error: cycle'],
  ['unknown dependency', [[['a', 5, ['shop']]], '18:00'], 'error: unknown step shop'],
  ['regression: step duration offset',
   [[['marinate', 240, []], ['plate', 5, ['prep', 'roast', 'rest']], ['sauce', 5, ['prep']],
     ['roast', 30, ['prep', 'marinate']], ['prep', 45, []], ['rest', 30, ['roast', 'sauce']]],
    '01:15'],
   [['marinate', '20:10'], ['prep', '23:25'], ['roast', '00:10'], ['sauce', '00:35'], ['rest', '00:40'],
    ['plate', '01:10']]],
  ['repair check: step duration offset',
   [[['prep', 15, []], ['plate', 10, ['rest']], ['rest', 10, ['marinate']], ['marinate', 240, ['prep']],
     ['sauce', 45, ['roast']], ['roast', 15, ['marinate']]],
    '18:30'],
   [['prep', '13:15'], ['marinate', '13:30'], ['roast', '17:30'], ['sauce', '17:45'], ['rest', '18:10'],
    ['plate', '18:20']]],
  ['generated control 1',
   [[['marinate', 10, []], ['plate', 45, ['prep', 'sauce']], ['rest', 90, ['prep', 'marinate', 'sauce']],
     ['sauce', 45, ['marinate']], ['prep', 90, []], ['roast', 15, ['prep']]],
    '19:45'],
   [['prep', '16:45'], ['marinate', '17:20'], ['sauce', '17:30'], ['rest', '18:15'], ['plate', '19:00'],
    ['roast', '19:30']]],
  ['generated control 2',
   [[['prep', 90, []], ['sauce', 10, ['prep', 'marinate']], ['roast', 30, ['prep']],
     ['marinate', 15, ['prep']]],
    '12:00'],
   [['prep', '10:00'], ['roast', '11:30'], ['marinate', '11:35'], ['sauce', '11:50']]],
  ['generated control 3',
   [[['prep', 15, []], ['sauce', 30, []], ['marinate', 10, []], ['rest', 10, ['shop']],
     ['roast', 240, ['prep', 'marinate']]],
    '19:45'],
   'error: unknown step shop']],
 [['cycle', [[['a', 5, ['b']], ['b', 5, ['a']]], '18:00'], 'error: cycle'],
  ['unknown dependency', [[['a', 5, ['shop']]], '18:00'], 'error: unknown step shop'],
  ['chain', [[['prep', 10, []], ['roast', 90, ['prep']], ['rest', 15, ['roast']]], '18:30'],
   [['prep', '16:35'], ['roast', '16:45'], ['rest', '18:15']]],
  ['regression: step duration offset',
   [[['prep', 240, []], ['roast', 90, []], ['marinate', 45, ['prep']]], '12:00'],
   [['prep', '07:15'], ['roast', '10:30'], ['marinate', '11:15']]],
  ['repair check: step duration offset',
   [[['prep', 30, []], ['roast', 5, []], ['sauce', 15, ['prep', 'marinate']], ['marinate', 30, ['prep']]],
    '01:15'],
   [['prep', '00:00'], ['marinate', '00:30'], ['sauce', '01:00'], ['roast', '01:10']]],
  ['generated control 1',
   [[['roast', 45, ['prep', 'marinate']], ['marinate', 30, ['prep']], ['sauce', 5, ['prep', 'marinate']],
     ['prep', 240, ['sauce']]],
    '02:00'],
   'error: cycle'],
  ['generated control 2',
   [[['rest', 15, ['roast', 'sauce']], ['roast', 90, []], ['prep', 15, []],
     ['marinate', 45, ['prep', 'shop']], ['sauce', 10, ['roast']]],
    '02:00'],
   'error: unknown step shop'],
  ['generated control 3',
   [[['marinate', 15, []], ['roast', 15, ['prep', 'marinate']], ['prep', 15, []],
     ['rest', 90, ['prep', 'marinate', 'roast']], ['sauce', 45, ['shop']]],
    '02:00'],
   'error: unknown step shop']],
 [['unknown dependency', [[['a', 5, ['shop']]], '18:00'], 'error: unknown step shop'],
  ['chain', [[['prep', 10, []], ['roast', 90, ['prep']], ['rest', 15, ['roast']]], '18:30'],
   [['prep', '16:35'], ['roast', '16:45'], ['rest', '18:15']]],
  ['overnight marinade', [[['marinate', 480, []], ['grill', 20, ['marinate']]], '12:00'],
   [['marinate', '03:40'], ['grill', '11:40']]],
  ['regression: step duration offset',
   [[['sauce', 5, []], ['roast', 15, ['prep', 'marinate']], ['prep', 15, []], ['rest', 10, ['prep']],
     ['marinate', 10, ['prep']]],
    '01:15'],
   [['prep', '00:35'], ['marinate', '00:50'], ['roast', '01:00'], ['rest', '01:05'], ['sauce', '01:10']]],
  ['repair check: step duration offset',
   [[['roast', 10, ['prep', 'marinate']], ['prep', 30, []], ['sauce', 90, ['marinate', 'roast']],
     ['marinate', 240, []], ['rest', 10, ['prep', 'sauce']]],
    '19:45'],
   [['marinate', '13:55'], ['prep', '17:25'], ['roast', '17:55'], ['sauce', '18:05'], ['rest', '19:35']]],
  ['generated control 1',
   [[['rest', 240, ['prep', 'roast', 'sauce']], ['marinate', 90, []], ['sauce', 5, ['prep', 'marinate']],
     ['roast', 45, []], ['prep', 15, ['rest']]],
    '18:30'],
   'error: cycle'],
  ['generated control 2', [[['roast', 15, ['prep']], ['prep', 15, []], ['marinate', 10, []]], '00:30'],
   [['prep', '00:00'], ['roast', '00:15'], ['marinate', '00:20']]],
  ['generated control 3',
   [[['rest', 240, ['roast']], ['roast', 45, ['prep', 'shop']], ['marinate', 10, []],
     ['sauce', 45, ['prep', 'roast']], ['prep', 240, []]],
    '01:15'],
   'error: unknown step shop']],
 [['chain', [[['prep', 10, []], ['roast', 90, ['prep']], ['rest', 15, ['roast']]], '18:30'],
   [['prep', '16:35'], ['roast', '16:45'], ['rest', '18:15']]],
  ['overnight marinade', [[['marinate', 480, []], ['grill', 20, ['marinate']]], '12:00'],
   [['marinate', '03:40'], ['grill', '11:40']]],
  ['cycle', [[['a', 5, ['b']], ['b', 5, ['a']]], '18:00'], 'error: cycle'],
  ['regression: step duration offset',
   [[['prep', 10, []], ['rest', 30, ['marinate', 'roast', 'sauce']], ['sauce', 30, []],
     ['plate', 90, ['prep', 'roast', 'sauce', 'rest']], ['marinate', 30, ['prep']],
     ['roast', 30, ['marinate']]],
    '01:15'],
   [['prep', '22:05'], ['marinate', '22:15'], ['roast', '22:45'], ['sauce', '22:45'], ['rest', '23:15'],
    ['plate', '23:45']]],
  ['repair check: step duration offset',
   [[['roast', 45, ['prep', 'marinate']], ['rest', 90, ['prep']], ['prep', 10, []],
     ['marinate', 15, ['prep']], ['plate', 10, ['roast']], ['sauce', 5, ['prep', 'marinate']]],
    '19:45'],
   [['prep', '18:05'], ['rest', '18:15'], ['marinate', '18:35'], ['roast', '18:50'], ['plate', '19:35'],
    ['sauce', '19:40']]],
  ['generated control 1',
   [[['prep', 45, []], ['marinate', 5, []], ['roast', 240, []], ['sauce', 30, ['roast']]], '02:00'],
   [['roast', '21:30'], ['prep', '01:15'], ['sauce', '01:30'], ['marinate', '01:55']]],
  ['generated control 2',
   [[['plate', 15, []], ['marinate', 240, ['prep']], ['prep', 15, []], ['roast', 15, []],
     ['rest', 15, ['marinate']], ['sauce', 45, ['marinate']]],
    '18:30'],
   [['prep', '13:30'], ['marinate', '13:45'], ['sauce', '17:45'], ['plate', '18:15'], ['rest', '18:15'],
    ['roast', '18:15']]],
  ['generated control 3',
   [[['marinate', 240, ['shop']], ['plate', 45, ['prep', 'sauce']], ['rest', 90, []], ['prep', 90, ['plate']],
     ['sauce', 240, ['marinate', 'roast']], ['roast', 15, ['prep', 'marinate']]],
    '19:45'],
   'error: unknown step shop']]]
for label, args, expected in fixtures[N - 1]:
    check(label, solve(*args), expected)
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
chain[['prep', '16:35'], ['roast', '16:45'], ['rest', '18:15']][['prep', '16:35'], ['roast', '16:45'], ['rest', '18:15']]Passed
overnight marinade[['marinate', '03:40'], ['grill', '11:40']][['marinate', '03:40'], ['grill', '11:40']]Passed
cycleerror: cycleerror: cyclePassed
regression: step duration offset[['marinate', '15:15'], ['prep', '15:35'], ['roast', '15:45'], ['sauce', '15:45']][['marinate', '15:15'], ['prep', '15:35'], ['roast', '15:45'], ['sauce', '15:45']]Passed
repair check: step duration offset[['rest', '20:30'], ['prep', '23:00'], ['marinate', '23:45'], ['roast', '00:15'], ['sauce', '00:15']][['rest', '20:30'], ['prep', '23:00'], ['marinate', '23:45'], ['roast', '00:15'], ['sauce', '00:15']]Passed
generated control 1error: unknown step shoperror: unknown step shopPassed
generated control 2error: unknown step shoperror: unknown step shopPassed
generated control 3error: cycleerror: cyclePassed

SHA-256 / 7f2af23bb23330970c63e6da52f90a0e2fe28c7a747975197a2a862fe6382795

Verification & scope

A deterministic toy contract stated in full here; it is a bounded teaching model, not an authoritative reference or standards implementation. 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:52:30.769197+00:00.

Case digest / d7d8f9891d27903aa413475bde0a881dfdb90585cbf893bf2a34e1755eb6987f