FAILURE MAP
← Case archive

FA-57976 / Double-entry ledger accounting / Open access

Foreign currency period-end revaluation: liability gain sign · case 01

A weakening home currency reports a gain on foreign-currency payables.

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

ROOT CAUSE

Revaluation deltas on liabilities are booked with the asset sign.

VERIFIED REPAIR

Treat an increase in a liability home amount as a loss.

Unsuccessful approach: Always booking liability deltas as losses is wrong when the liability shrinks.

Case contract

x = {'bid': [num, den], 'ask': [num, den], 'accounts': [[name, 'asset'|'liability', monetary, foreign units, carried home cents]]}. Monetary assets are revalued at the bid rate and monetary liabilities at the ask rate: home = foreign * num / den rounded half-up per account. Non-monetary accounts keep their carried amount. Unrealized gain sums (new - carried) for assets and (carried - new) for liabilities. Return {'balances': [[name, home]], 'unrealized_gain'}.

Why this case matters

Ledger software must keep debits equal to credits and apply normal-balance, period and cutoff rules exactly; small sign or boundary slips silently misstate financial statements.

1 / The failure

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

N = 1
observations = []
def solve(x):
    def to_home(amount, rate):
        num, den = rate
        q, r = divmod(amount * num, den)
        return q + (1 if 2 * r >= den else 0)
    gain = 0
    out = []
    for name, kind, monetary, foreign, carried in x['accounts']:
        if not monetary:
            out.append([name, carried])
            continue
        rate = x['bid'] if kind == 'asset' else x['ask']
        new = to_home(foreign, rate)
        delta = new - carried
        gain += delta
        out.append([name, new])
    return {'balances': out, 'unrealized_gain': gain}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: liability gain sign', {'bid': [124, 100], 'ask': [125, 100], 'accounts': [['a0', 'liability', True, 7, 14], ['a1', 'liability', False, 7, 7], ['a2', 'liability', True, 5, 8]]}, {'balances': [['a0', 9], ['a1', 7], ['a2', 6]], 'unrealized_gain': 7}], ['control 1', {'bid': [3, 4], 'ask': [4, 4], 'accounts': [['a0', 'asset', True, 7, 10], ['a1', 'asset', False, 7, 500]]}, {'balances': [['a0', 5], ['a1', 500]], 'unrealized_gain': -5}], ['control 2', {'bid': [8, 4], 'ask': [11, 4], 'accounts': [['a0', 'asset', True, 1000, 1000], ['a1', 'asset', False, 7, 7], ['a2', 'asset', True, 250, 250], ['a3', 'liability', False, 5, 8], ['a4', 'liability', False, 1000, 1000]]}, {'balances': [['a0', 2000], ['a1', 7], ['a2', 500], ['a3', 8], ['a4', 1000]], 'unrealized_gain': 1250}], ['control 3', {'bid': [5, 8], 'ask': [6, 8], 'accounts': [['a0', 'asset', True, 101, 101], ['a1', 'asset', False, 1, 4]]}, {'balances': [['a0', 63], ['a1', 4]], 'unrealized_gain': -38}], ['control 4', {'bid': [5, 2], 'ask': [8, 2], 'accounts': [['a0', 'liability', True, 1, 4], ['a1', 'asset', True, 250, 500]]}, {'balances': [['a0', 4], ['a1', 625]], 'unrealized_gain': 125}], ['control 5', {'bid': [1, 2], 'ask': [2, 2], 'accounts': [['a0', 'asset', True, 999, 1998], ['a1', 'liability', False, 999, 999], ['a2', 'asset', True, 250, 500]]}, {'balances': [['a0', 500], ['a1', 999], ['a2', 125]], 'unrealized_gain': -1873}], ['control 6', {'bid': [20, 10], 'ask': [21, 10], 'accounts': [['a0', 'asset', True, 5, 5], ['a1', 'asset', True, 250, 253], ['a2', 'asset', True, 5, 8], ['a3', 'asset', True, 7, 14]]}, {'balances': [['a0', 10], ['a1', 500], ['a2', 10], ['a3', 14]], 'unrealized_gain': 254}]], [['regression: liability gain sign', {'bid': [133, 100], 'ask': [135, 100], 'accounts': [['a0', 'liability', False, 3, 6], ['a1', 'asset', True, 1, 1], ['a2', 'liability', True, 7, 500], ['a3', 'liability', True, 3, 6]]}, {'balances': [['a0', 6], ['a1', 1], ['a2', 9], ['a3', 4]], 'unrealized_gain': 493}], ['control 1', {'bid': [119, 100], 'ask': [120, 100], 'accounts': [['a0', 'asset', False, 5, 500], ['a1', 'liability', False, 999, 500]]}, {'balances': [['a0', 500], ['a1', 500]], 'unrealized_gain': 0}], ['control 2', {'bid': [188, 100], 'ask': [189, 100], 'accounts': [['a0', 'asset', False, 1000, 1000], ['a1', 'asset', False, 1000, 1000], ['a2', 'asset', False, 5, 5], ['a3', 'asset', True, 1000, 1003]]}, {'balances': [['a0', 1000], ['a1', 1000], ['a2', 5], ['a3', 1880]], 'unrealized_gain': 877}], ['control 3', {'bid': [15, 8], 'ask': [16, 8], 'accounts': [['a0', 'asset', True, 999, 500], ['a1', 'asset', False, 3, 6], ['a2', 'asset', True, 999, 1998], ['a3', 'asset', True, 3, 3], ['a4', 'asset', True, 1, 4]]}, {'balances': [['a0', 1873], ['a1', 6], ['a2', 1873], ['a3', 6], ['a4', 2]], 'unrealized_gain': 1249}], ['control 4', {'bid': [16, 8], 'ask': [18, 8], 'accounts': [['a0', 'liability', False, 3, 6], ['a1', 'asset', True, 999, 1002]]}, {'balances': [['a0', 6], ['a1', 1998]], 'unrealized_gain': 996}], ['control 5', {'bid': [10, 8], 'ask': [11, 8], 'accounts': [['a0', 'asset', True, 1, 500], ['a1', 'asset', False, 999, 999], ['a2', 'asset', True, 250, 250], ['a3', 'liability', False, 999, 1002]]}, {'balances': [['a0', 1], ['a1', 999], ['a2', 313], ['a3', 1002]], 'unrealized_gain': -436}], ['control 6', {'bid': [8, 4], 'ask': [9, 4], 'accounts': [['a0', 'liability', False, 3, 3], ['a1', 'asset', True, 3, 6], ['a2', 'asset', False, 1000, 1000], ['a3', 'liability', False, 5, 500], ['a4', 'asset', True, 101, 500]]}, {'balances': [['a0', 3], ['a1', 6], ['a2', 1000], ['a3', 500], ['a4', 202]], 'unrealized_gain': -298}]], [['regression: liability gain sign', {'bid': [12, 10], 'ask': [14, 10], 'accounts': [['a0', 'asset', False, 1000, 2000], ['a1', 'liability', True, 1, 2], ['a2', 'liability', True, 3, 3], ['a3', 'liability', True, 999, 1002]]}, {'balances': [['a0', 2000], ['a1', 1], ['a2', 4], ['a3', 1399]], 'unrealized_gain': -397}], ['control 1', {'bid': [2, 2], 'ask': [3, 2], 'accounts': [['a0', 'asset', True, 3, 3], ['a1', 'asset', False, 5, 500], ['a2', 'asset', False, 999, 1998], ['a3', 'asset', True, 5, 5], ['a4', 'liability', False, 7, 14]]}, {'balances': [['a0', 3], ['a1', 500], ['a2', 1998], ['a3', 5], ['a4', 14]], 'unrealized_gain': 0}], ['control 2', {'bid': [130, 100], 'ask': [132, 100], 'accounts': [['a0', 'asset', True, 1, 4], ['a1', 'asset', True, 7, 500]]}, {'balances': [['a0', 1], ['a1', 9]], 'unrealized_gain': -494}], ['control 3', {'bid': [81, 100], 'ask': [83, 100], 'accounts': [['a0', 'asset', True, 1, 500], ['a1', 'asset', False, 1000, 500], ['a2', 'asset', True, 1000, 1003]]}, {'balances': [['a0', 1], ['a1', 500], ['a2', 810]], 'unrealized_gain': -692}], ['control 4', {'bid': [6, 4], 'ask': [7, 4], 'accounts': [['a0', 'liability', False, 999, 999], ['a1', 'asset', False, 999, 1002], ['a2', 'asset', True, 1, 4]]}, {'balances': [['a0', 999], ['a1', 1002], ['a2', 2]], 'unrealized_gain': -2}], ['control 5', {'bid': [9, 8], 'ask': [12, 8], 'accounts': [['a0', 'asset', True, 1, 500], ['a1', 'asset', True, 101, 500], ['a2', 'asset', True, 1000, 1003]]}, {'balances': [['a0', 1], ['a1', 114], ['a2', 1125]], 'unrealized_gain': -763}], ['control 6', {'bid': [18, 10], 'ask': [20, 10], 'accounts': [['a0', 'liability', True, 1, 2], ['a1', 'asset', True, 999, 1998], ['a2', 'asset', True, 250, 500]]}, {'balances': [['a0', 2], ['a1', 1798], ['a2', 450]], 'unrealized_gain': -250}]], [['regression: liability gain sign', {'bid': [3, 2], 'ask': [4, 2], 'accounts': [['a0', 'liability', True, 999, 500], ['a1', 'liability', False, 3, 3], ['a2', 'liability', True, 5, 10]]}, {'balances': [['a0', 1998], ['a1', 3], ['a2', 10]], 'unrealized_gain': -1498}], ['regression: liability gain sign, partial-repair probe', {'bid': [8, 10], 'ask': [9, 10], 'accounts': [['a0', 'liability', True, 1, 4], ['a1', 'asset', True, 250, 500], ['a2', 'asset', False, 101, 104], ['a3', 'asset', True, 1, 1]]}, {'balances': [['a0', 1], ['a1', 200], ['a2', 104], ['a3', 1]], 'unrealized_gain': -297}], ['control 1', {'bid': [6, 8], 'ask': [8, 8], 'accounts': [['a0', 'liability', False, 3, 500], ['a1', 'liability', True, 101, 101], ['a2', 'asset', True, 999, 1998], ['a3', 'liability', False, 3, 3], ['a4', 'asset', True, 999, 1002]]}, {'balances': [['a0', 500], ['a1', 101], ['a2', 749], ['a3', 3], ['a4', 749]], 'unrealized_gain': -1502}], ['control 2', {'bid': [8, 8], 'ask': [9, 8], 'accounts': [['a0', 'asset', False, 101, 101], ['a1', 'asset', False, 5, 500]]}, {'balances': [['a0', 101], ['a1', 500]], 'unrealized_gain': 0}], ['control 3', {'bid': [7, 10], 'ask': [9, 10], 'accounts': [['a0', 'asset', False, 250, 500], ['a1', 'asset', True, 250, 250], ['a2', 'asset', False, 7, 14]]}, {'balances': [['a0', 500], ['a1', 175], ['a2', 14]], 'unrealized_gain': -75}], ['control 4', {'bid': [15, 10], 'ask': [18, 10], 'accounts': [['a0', 'asset', True, 5, 5], ['a1', 'liability', False, 250, 250], ['a2', 'liability', False, 250, 500], ['a3', 'liability', False, 7, 500]]}, {'balances': [['a0', 8], ['a1', 250], ['a2', 500], ['a3', 500]], 'unrealized_gain': 3}], ['control 5', {'bid': [5, 2], 'ask': [8, 2], 'accounts': [['a0', 'asset', True, 999, 1998], ['a1', 'asset', True, 250, 250], ['a2', 'asset', True, 999, 999]]}, {'balances': [['a0', 2498], ['a1', 625], ['a2', 2498]], 'unrealized_gain': 2374}]], [['regression: liability gain sign', {'bid': [158, 100], 'ask': [159, 100], 'accounts': [['a0', 'liability', True, 1, 1], ['a1', 'asset', False, 999, 1002], ['a2', 'liability', True, 1, 2], ['a3', 'liability', False, 1000, 1003]]}, {'balances': [['a0', 2], ['a1', 1002], ['a2', 2], ['a3', 1003]], 'unrealized_gain': -1}], ['regression: liability gain sign, partial-repair probe', {'bid': [9, 10], 'ask': [10, 10], 'accounts': [['a0', 'liability', False, 101, 500], ['a1', 'asset', False, 7, 14], ['a2', 'liability', True, 7, 10], ['a3', 'asset', False, 101, 101]]}, {'balances': [['a0', 500], ['a1', 14], ['a2', 7], ['a3', 101]], 'unrealized_gain': 3}], ['control 1', {'bid': [2, 4], 'ask': [3, 4], 'accounts': [['a0', 'asset', True, 5, 500], ['a1', 'asset', True, 5, 500], ['a2', 'asset', True, 5, 8], ['a3', 'asset', True, 3, 500]]}, {'balances': [['a0', 3], ['a1', 3], ['a2', 3], ['a3', 2]], 'unrealized_gain': -1497}], ['control 2', {'bid': [6, 4], 'ask': [7, 4], 'accounts': [['a0', 'asset', False, 999, 500], ['a1', 'asset', True, 999, 999], ['a2', 'asset', True, 101, 104]]}, {'balances': [['a0', 500], ['a1', 1499], ['a2', 152]], 'unrealized_gain': 548}], ['control 3', {'bid': [4, 2], 'ask': [7, 2], 'accounts': [['a0', 'asset', True, 1, 4], ['a1', 'asset', True, 101, 101]]}, {'balances': [['a0', 2], ['a1', 202]], 'unrealized_gain': 99}], ['control 4', {'bid': [9, 4], 'ask': [11, 4], 'accounts': [['a0', 'asset', True, 7, 14], ['a1', 'asset', True, 3, 6], ['a2', 'asset', True, 3, 6], ['a3', 'asset', False, 250, 253]]}, {'balances': [['a0', 16], ['a1', 7], ['a2', 7], ['a3', 253]], 'unrealized_gain': 4}], ['control 5', {'bid': [2, 2], 'ask': [5, 2], 'accounts': [['a0', 'asset', False, 7, 7], ['a1', 'liability', False, 101, 500]]}, {'balances': [['a0', 7], ['a1', 500]], 'unrealized_gain': 0}]]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'raised ' + type(exc).__name__
    check(label, actual, 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
regression: liability gain sign{'balances': [['a0', 9], ['a1', 7], ['a2', 6]], 'unrealized_gain': -7}{'balances': [['a0', 9], ['a1', 7], ['a2', 6]], 'unrealized_gain': 7}Failed
control 1{'balances': [['a0', 5], ['a1', 500]], 'unrealized_gain': -5}{'balances': [['a0', 5], ['a1', 500]], 'unrealized_gain': -5}Passed
control 2{'balances': [['a0', 2000], ['a1', 7], ['a2', 500], ['a3', 8], ['a4', 1000]], 'unrealized_gain': 1250}{'balances': [['a0', 2000], ['a1', 7], ['a2', 500], ['a3', 8], ['a4', 1000]], 'unrealized_gain': 1250}Passed
control 3{'balances': [['a0', 63], ['a1', 4]], 'unrealized_gain': -38}{'balances': [['a0', 63], ['a1', 4]], 'unrealized_gain': -38}Passed
control 4{'balances': [['a0', 4], ['a1', 625]], 'unrealized_gain': 125}{'balances': [['a0', 4], ['a1', 625]], 'unrealized_gain': 125}Passed
control 5{'balances': [['a0', 500], ['a1', 999], ['a2', 125]], 'unrealized_gain': -1873}{'balances': [['a0', 500], ['a1', 999], ['a2', 125]], 'unrealized_gain': -1873}Passed
control 6{'balances': [['a0', 10], ['a1', 500], ['a2', 10], ['a3', 14]], 'unrealized_gain': 254}{'balances': [['a0', 10], ['a1', 500], ['a2', 10], ['a3', 14]], 'unrealized_gain': 254}Passed

SHA-256 / 48fca24053faec07ac0660147ba14a1f11dab34c0c5c0e2c648f2ebae87d9af7

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(x):
    def to_home(amount, rate):
        num, den = rate
        q, r = divmod(amount * num, den)
        return q + (1 if 2 * r >= den else 0)
    gain = 0
    out = []
    for name, kind, monetary, foreign, carried in x['accounts']:
        if not monetary:
            out.append([name, carried])
            continue
        rate = x['bid'] if kind == 'asset' else x['ask']
        new = to_home(foreign, rate)
        delta = new - carried
        gain += delta if kind == 'asset' else -abs(delta)
        out.append([name, new])
    return {'balances': out, 'unrealized_gain': gain}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: liability gain sign', {'bid': [124, 100], 'ask': [125, 100], 'accounts': [['a0', 'liability', True, 7, 14], ['a1', 'liability', False, 7, 7], ['a2', 'liability', True, 5, 8]]}, {'balances': [['a0', 9], ['a1', 7], ['a2', 6]], 'unrealized_gain': 7}], ['control 1', {'bid': [3, 4], 'ask': [4, 4], 'accounts': [['a0', 'asset', True, 7, 10], ['a1', 'asset', False, 7, 500]]}, {'balances': [['a0', 5], ['a1', 500]], 'unrealized_gain': -5}], ['control 2', {'bid': [8, 4], 'ask': [11, 4], 'accounts': [['a0', 'asset', True, 1000, 1000], ['a1', 'asset', False, 7, 7], ['a2', 'asset', True, 250, 250], ['a3', 'liability', False, 5, 8], ['a4', 'liability', False, 1000, 1000]]}, {'balances': [['a0', 2000], ['a1', 7], ['a2', 500], ['a3', 8], ['a4', 1000]], 'unrealized_gain': 1250}], ['control 3', {'bid': [5, 8], 'ask': [6, 8], 'accounts': [['a0', 'asset', True, 101, 101], ['a1', 'asset', False, 1, 4]]}, {'balances': [['a0', 63], ['a1', 4]], 'unrealized_gain': -38}], ['control 4', {'bid': [5, 2], 'ask': [8, 2], 'accounts': [['a0', 'liability', True, 1, 4], ['a1', 'asset', True, 250, 500]]}, {'balances': [['a0', 4], ['a1', 625]], 'unrealized_gain': 125}], ['control 5', {'bid': [1, 2], 'ask': [2, 2], 'accounts': [['a0', 'asset', True, 999, 1998], ['a1', 'liability', False, 999, 999], ['a2', 'asset', True, 250, 500]]}, {'balances': [['a0', 500], ['a1', 999], ['a2', 125]], 'unrealized_gain': -1873}], ['control 6', {'bid': [20, 10], 'ask': [21, 10], 'accounts': [['a0', 'asset', True, 5, 5], ['a1', 'asset', True, 250, 253], ['a2', 'asset', True, 5, 8], ['a3', 'asset', True, 7, 14]]}, {'balances': [['a0', 10], ['a1', 500], ['a2', 10], ['a3', 14]], 'unrealized_gain': 254}]], [['regression: liability gain sign', {'bid': [133, 100], 'ask': [135, 100], 'accounts': [['a0', 'liability', False, 3, 6], ['a1', 'asset', True, 1, 1], ['a2', 'liability', True, 7, 500], ['a3', 'liability', True, 3, 6]]}, {'balances': [['a0', 6], ['a1', 1], ['a2', 9], ['a3', 4]], 'unrealized_gain': 493}], ['control 1', {'bid': [119, 100], 'ask': [120, 100], 'accounts': [['a0', 'asset', False, 5, 500], ['a1', 'liability', False, 999, 500]]}, {'balances': [['a0', 500], ['a1', 500]], 'unrealized_gain': 0}], ['control 2', {'bid': [188, 100], 'ask': [189, 100], 'accounts': [['a0', 'asset', False, 1000, 1000], ['a1', 'asset', False, 1000, 1000], ['a2', 'asset', False, 5, 5], ['a3', 'asset', True, 1000, 1003]]}, {'balances': [['a0', 1000], ['a1', 1000], ['a2', 5], ['a3', 1880]], 'unrealized_gain': 877}], ['control 3', {'bid': [15, 8], 'ask': [16, 8], 'accounts': [['a0', 'asset', True, 999, 500], ['a1', 'asset', False, 3, 6], ['a2', 'asset', True, 999, 1998], ['a3', 'asset', True, 3, 3], ['a4', 'asset', True, 1, 4]]}, {'balances': [['a0', 1873], ['a1', 6], ['a2', 1873], ['a3', 6], ['a4', 2]], 'unrealized_gain': 1249}], ['control 4', {'bid': [16, 8], 'ask': [18, 8], 'accounts': [['a0', 'liability', False, 3, 6], ['a1', 'asset', True, 999, 1002]]}, {'balances': [['a0', 6], ['a1', 1998]], 'unrealized_gain': 996}], ['control 5', {'bid': [10, 8], 'ask': [11, 8], 'accounts': [['a0', 'asset', True, 1, 500], ['a1', 'asset', False, 999, 999], ['a2', 'asset', True, 250, 250], ['a3', 'liability', False, 999, 1002]]}, {'balances': [['a0', 1], ['a1', 999], ['a2', 313], ['a3', 1002]], 'unrealized_gain': -436}], ['control 6', {'bid': [8, 4], 'ask': [9, 4], 'accounts': [['a0', 'liability', False, 3, 3], ['a1', 'asset', True, 3, 6], ['a2', 'asset', False, 1000, 1000], ['a3', 'liability', False, 5, 500], ['a4', 'asset', True, 101, 500]]}, {'balances': [['a0', 3], ['a1', 6], ['a2', 1000], ['a3', 500], ['a4', 202]], 'unrealized_gain': -298}]], [['regression: liability gain sign', {'bid': [12, 10], 'ask': [14, 10], 'accounts': [['a0', 'asset', False, 1000, 2000], ['a1', 'liability', True, 1, 2], ['a2', 'liability', True, 3, 3], ['a3', 'liability', True, 999, 1002]]}, {'balances': [['a0', 2000], ['a1', 1], ['a2', 4], ['a3', 1399]], 'unrealized_gain': -397}], ['control 1', {'bid': [2, 2], 'ask': [3, 2], 'accounts': [['a0', 'asset', True, 3, 3], ['a1', 'asset', False, 5, 500], ['a2', 'asset', False, 999, 1998], ['a3', 'asset', True, 5, 5], ['a4', 'liability', False, 7, 14]]}, {'balances': [['a0', 3], ['a1', 500], ['a2', 1998], ['a3', 5], ['a4', 14]], 'unrealized_gain': 0}], ['control 2', {'bid': [130, 100], 'ask': [132, 100], 'accounts': [['a0', 'asset', True, 1, 4], ['a1', 'asset', True, 7, 500]]}, {'balances': [['a0', 1], ['a1', 9]], 'unrealized_gain': -494}], ['control 3', {'bid': [81, 100], 'ask': [83, 100], 'accounts': [['a0', 'asset', True, 1, 500], ['a1', 'asset', False, 1000, 500], ['a2', 'asset', True, 1000, 1003]]}, {'balances': [['a0', 1], ['a1', 500], ['a2', 810]], 'unrealized_gain': -692}], ['control 4', {'bid': [6, 4], 'ask': [7, 4], 'accounts': [['a0', 'liability', False, 999, 999], ['a1', 'asset', False, 999, 1002], ['a2', 'asset', True, 1, 4]]}, {'balances': [['a0', 999], ['a1', 1002], ['a2', 2]], 'unrealized_gain': -2}], ['control 5', {'bid': [9, 8], 'ask': [12, 8], 'accounts': [['a0', 'asset', True, 1, 500], ['a1', 'asset', True, 101, 500], ['a2', 'asset', True, 1000, 1003]]}, {'balances': [['a0', 1], ['a1', 114], ['a2', 1125]], 'unrealized_gain': -763}], ['control 6', {'bid': [18, 10], 'ask': [20, 10], 'accounts': [['a0', 'liability', True, 1, 2], ['a1', 'asset', True, 999, 1998], ['a2', 'asset', True, 250, 500]]}, {'balances': [['a0', 2], ['a1', 1798], ['a2', 450]], 'unrealized_gain': -250}]], [['regression: liability gain sign', {'bid': [3, 2], 'ask': [4, 2], 'accounts': [['a0', 'liability', True, 999, 500], ['a1', 'liability', False, 3, 3], ['a2', 'liability', True, 5, 10]]}, {'balances': [['a0', 1998], ['a1', 3], ['a2', 10]], 'unrealized_gain': -1498}], ['regression: liability gain sign, partial-repair probe', {'bid': [8, 10], 'ask': [9, 10], 'accounts': [['a0', 'liability', True, 1, 4], ['a1', 'asset', True, 250, 500], ['a2', 'asset', False, 101, 104], ['a3', 'asset', True, 1, 1]]}, {'balances': [['a0', 1], ['a1', 200], ['a2', 104], ['a3', 1]], 'unrealized_gain': -297}], ['control 1', {'bid': [6, 8], 'ask': [8, 8], 'accounts': [['a0', 'liability', False, 3, 500], ['a1', 'liability', True, 101, 101], ['a2', 'asset', True, 999, 1998], ['a3', 'liability', False, 3, 3], ['a4', 'asset', True, 999, 1002]]}, {'balances': [['a0', 500], ['a1', 101], ['a2', 749], ['a3', 3], ['a4', 749]], 'unrealized_gain': -1502}], ['control 2', {'bid': [8, 8], 'ask': [9, 8], 'accounts': [['a0', 'asset', False, 101, 101], ['a1', 'asset', False, 5, 500]]}, {'balances': [['a0', 101], ['a1', 500]], 'unrealized_gain': 0}], ['control 3', {'bid': [7, 10], 'ask': [9, 10], 'accounts': [['a0', 'asset', False, 250, 500], ['a1', 'asset', True, 250, 250], ['a2', 'asset', False, 7, 14]]}, {'balances': [['a0', 500], ['a1', 175], ['a2', 14]], 'unrealized_gain': -75}], ['control 4', {'bid': [15, 10], 'ask': [18, 10], 'accounts': [['a0', 'asset', True, 5, 5], ['a1', 'liability', False, 250, 250], ['a2', 'liability', False, 250, 500], ['a3', 'liability', False, 7, 500]]}, {'balances': [['a0', 8], ['a1', 250], ['a2', 500], ['a3', 500]], 'unrealized_gain': 3}], ['control 5', {'bid': [5, 2], 'ask': [8, 2], 'accounts': [['a0', 'asset', True, 999, 1998], ['a1', 'asset', True, 250, 250], ['a2', 'asset', True, 999, 999]]}, {'balances': [['a0', 2498], ['a1', 625], ['a2', 2498]], 'unrealized_gain': 2374}]], [['regression: liability gain sign', {'bid': [158, 100], 'ask': [159, 100], 'accounts': [['a0', 'liability', True, 1, 1], ['a1', 'asset', False, 999, 1002], ['a2', 'liability', True, 1, 2], ['a3', 'liability', False, 1000, 1003]]}, {'balances': [['a0', 2], ['a1', 1002], ['a2', 2], ['a3', 1003]], 'unrealized_gain': -1}], ['regression: liability gain sign, partial-repair probe', {'bid': [9, 10], 'ask': [10, 10], 'accounts': [['a0', 'liability', False, 101, 500], ['a1', 'asset', False, 7, 14], ['a2', 'liability', True, 7, 10], ['a3', 'asset', False, 101, 101]]}, {'balances': [['a0', 500], ['a1', 14], ['a2', 7], ['a3', 101]], 'unrealized_gain': 3}], ['control 1', {'bid': [2, 4], 'ask': [3, 4], 'accounts': [['a0', 'asset', True, 5, 500], ['a1', 'asset', True, 5, 500], ['a2', 'asset', True, 5, 8], ['a3', 'asset', True, 3, 500]]}, {'balances': [['a0', 3], ['a1', 3], ['a2', 3], ['a3', 2]], 'unrealized_gain': -1497}], ['control 2', {'bid': [6, 4], 'ask': [7, 4], 'accounts': [['a0', 'asset', False, 999, 500], ['a1', 'asset', True, 999, 999], ['a2', 'asset', True, 101, 104]]}, {'balances': [['a0', 500], ['a1', 1499], ['a2', 152]], 'unrealized_gain': 548}], ['control 3', {'bid': [4, 2], 'ask': [7, 2], 'accounts': [['a0', 'asset', True, 1, 4], ['a1', 'asset', True, 101, 101]]}, {'balances': [['a0', 2], ['a1', 202]], 'unrealized_gain': 99}], ['control 4', {'bid': [9, 4], 'ask': [11, 4], 'accounts': [['a0', 'asset', True, 7, 14], ['a1', 'asset', True, 3, 6], ['a2', 'asset', True, 3, 6], ['a3', 'asset', False, 250, 253]]}, {'balances': [['a0', 16], ['a1', 7], ['a2', 7], ['a3', 253]], 'unrealized_gain': 4}], ['control 5', {'bid': [2, 2], 'ask': [5, 2], 'accounts': [['a0', 'asset', False, 7, 7], ['a1', 'liability', False, 101, 500]]}, {'balances': [['a0', 7], ['a1', 500]], 'unrealized_gain': 0}]]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'raised ' + type(exc).__name__
    check(label, actual, 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
regression: liability gain sign{'balances': [['a0', 9], ['a1', 7], ['a2', 6]], 'unrealized_gain': -7}{'balances': [['a0', 9], ['a1', 7], ['a2', 6]], 'unrealized_gain': 7}Failed
control 1{'balances': [['a0', 5], ['a1', 500]], 'unrealized_gain': -5}{'balances': [['a0', 5], ['a1', 500]], 'unrealized_gain': -5}Passed
control 2{'balances': [['a0', 2000], ['a1', 7], ['a2', 500], ['a3', 8], ['a4', 1000]], 'unrealized_gain': 1250}{'balances': [['a0', 2000], ['a1', 7], ['a2', 500], ['a3', 8], ['a4', 1000]], 'unrealized_gain': 1250}Passed
control 3{'balances': [['a0', 63], ['a1', 4]], 'unrealized_gain': -38}{'balances': [['a0', 63], ['a1', 4]], 'unrealized_gain': -38}Passed
control 4{'balances': [['a0', 4], ['a1', 625]], 'unrealized_gain': 125}{'balances': [['a0', 4], ['a1', 625]], 'unrealized_gain': 125}Passed
control 5{'balances': [['a0', 500], ['a1', 999], ['a2', 125]], 'unrealized_gain': -1873}{'balances': [['a0', 500], ['a1', 999], ['a2', 125]], 'unrealized_gain': -1873}Passed
control 6{'balances': [['a0', 10], ['a1', 500], ['a2', 10], ['a3', 14]], 'unrealized_gain': 254}{'balances': [['a0', 10], ['a1', 500], ['a2', 10], ['a3', 14]], 'unrealized_gain': 254}Passed

SHA-256 / 42e87ab676cf2f624cb910df78208af4c888223a08744d78610ae7706807ee12

3 / The verified repair

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

N = 1
observations = []
def solve(x):
    def to_home(amount, rate):
        num, den = rate
        q, r = divmod(amount * num, den)
        return q + (1 if 2 * r >= den else 0)
    gain = 0
    out = []
    for name, kind, monetary, foreign, carried in x['accounts']:
        if not monetary:
            out.append([name, carried])
            continue
        rate = x['bid'] if kind == 'asset' else x['ask']
        new = to_home(foreign, rate)
        delta = new - carried
        gain += delta if kind == 'asset' else -delta
        out.append([name, new])
    return {'balances': out, 'unrealized_gain': gain}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: liability gain sign', {'bid': [124, 100], 'ask': [125, 100], 'accounts': [['a0', 'liability', True, 7, 14], ['a1', 'liability', False, 7, 7], ['a2', 'liability', True, 5, 8]]}, {'balances': [['a0', 9], ['a1', 7], ['a2', 6]], 'unrealized_gain': 7}], ['control 1', {'bid': [3, 4], 'ask': [4, 4], 'accounts': [['a0', 'asset', True, 7, 10], ['a1', 'asset', False, 7, 500]]}, {'balances': [['a0', 5], ['a1', 500]], 'unrealized_gain': -5}], ['control 2', {'bid': [8, 4], 'ask': [11, 4], 'accounts': [['a0', 'asset', True, 1000, 1000], ['a1', 'asset', False, 7, 7], ['a2', 'asset', True, 250, 250], ['a3', 'liability', False, 5, 8], ['a4', 'liability', False, 1000, 1000]]}, {'balances': [['a0', 2000], ['a1', 7], ['a2', 500], ['a3', 8], ['a4', 1000]], 'unrealized_gain': 1250}], ['control 3', {'bid': [5, 8], 'ask': [6, 8], 'accounts': [['a0', 'asset', True, 101, 101], ['a1', 'asset', False, 1, 4]]}, {'balances': [['a0', 63], ['a1', 4]], 'unrealized_gain': -38}], ['control 4', {'bid': [5, 2], 'ask': [8, 2], 'accounts': [['a0', 'liability', True, 1, 4], ['a1', 'asset', True, 250, 500]]}, {'balances': [['a0', 4], ['a1', 625]], 'unrealized_gain': 125}], ['control 5', {'bid': [1, 2], 'ask': [2, 2], 'accounts': [['a0', 'asset', True, 999, 1998], ['a1', 'liability', False, 999, 999], ['a2', 'asset', True, 250, 500]]}, {'balances': [['a0', 500], ['a1', 999], ['a2', 125]], 'unrealized_gain': -1873}], ['control 6', {'bid': [20, 10], 'ask': [21, 10], 'accounts': [['a0', 'asset', True, 5, 5], ['a1', 'asset', True, 250, 253], ['a2', 'asset', True, 5, 8], ['a3', 'asset', True, 7, 14]]}, {'balances': [['a0', 10], ['a1', 500], ['a2', 10], ['a3', 14]], 'unrealized_gain': 254}]], [['regression: liability gain sign', {'bid': [133, 100], 'ask': [135, 100], 'accounts': [['a0', 'liability', False, 3, 6], ['a1', 'asset', True, 1, 1], ['a2', 'liability', True, 7, 500], ['a3', 'liability', True, 3, 6]]}, {'balances': [['a0', 6], ['a1', 1], ['a2', 9], ['a3', 4]], 'unrealized_gain': 493}], ['control 1', {'bid': [119, 100], 'ask': [120, 100], 'accounts': [['a0', 'asset', False, 5, 500], ['a1', 'liability', False, 999, 500]]}, {'balances': [['a0', 500], ['a1', 500]], 'unrealized_gain': 0}], ['control 2', {'bid': [188, 100], 'ask': [189, 100], 'accounts': [['a0', 'asset', False, 1000, 1000], ['a1', 'asset', False, 1000, 1000], ['a2', 'asset', False, 5, 5], ['a3', 'asset', True, 1000, 1003]]}, {'balances': [['a0', 1000], ['a1', 1000], ['a2', 5], ['a3', 1880]], 'unrealized_gain': 877}], ['control 3', {'bid': [15, 8], 'ask': [16, 8], 'accounts': [['a0', 'asset', True, 999, 500], ['a1', 'asset', False, 3, 6], ['a2', 'asset', True, 999, 1998], ['a3', 'asset', True, 3, 3], ['a4', 'asset', True, 1, 4]]}, {'balances': [['a0', 1873], ['a1', 6], ['a2', 1873], ['a3', 6], ['a4', 2]], 'unrealized_gain': 1249}], ['control 4', {'bid': [16, 8], 'ask': [18, 8], 'accounts': [['a0', 'liability', False, 3, 6], ['a1', 'asset', True, 999, 1002]]}, {'balances': [['a0', 6], ['a1', 1998]], 'unrealized_gain': 996}], ['control 5', {'bid': [10, 8], 'ask': [11, 8], 'accounts': [['a0', 'asset', True, 1, 500], ['a1', 'asset', False, 999, 999], ['a2', 'asset', True, 250, 250], ['a3', 'liability', False, 999, 1002]]}, {'balances': [['a0', 1], ['a1', 999], ['a2', 313], ['a3', 1002]], 'unrealized_gain': -436}], ['control 6', {'bid': [8, 4], 'ask': [9, 4], 'accounts': [['a0', 'liability', False, 3, 3], ['a1', 'asset', True, 3, 6], ['a2', 'asset', False, 1000, 1000], ['a3', 'liability', False, 5, 500], ['a4', 'asset', True, 101, 500]]}, {'balances': [['a0', 3], ['a1', 6], ['a2', 1000], ['a3', 500], ['a4', 202]], 'unrealized_gain': -298}]], [['regression: liability gain sign', {'bid': [12, 10], 'ask': [14, 10], 'accounts': [['a0', 'asset', False, 1000, 2000], ['a1', 'liability', True, 1, 2], ['a2', 'liability', True, 3, 3], ['a3', 'liability', True, 999, 1002]]}, {'balances': [['a0', 2000], ['a1', 1], ['a2', 4], ['a3', 1399]], 'unrealized_gain': -397}], ['control 1', {'bid': [2, 2], 'ask': [3, 2], 'accounts': [['a0', 'asset', True, 3, 3], ['a1', 'asset', False, 5, 500], ['a2', 'asset', False, 999, 1998], ['a3', 'asset', True, 5, 5], ['a4', 'liability', False, 7, 14]]}, {'balances': [['a0', 3], ['a1', 500], ['a2', 1998], ['a3', 5], ['a4', 14]], 'unrealized_gain': 0}], ['control 2', {'bid': [130, 100], 'ask': [132, 100], 'accounts': [['a0', 'asset', True, 1, 4], ['a1', 'asset', True, 7, 500]]}, {'balances': [['a0', 1], ['a1', 9]], 'unrealized_gain': -494}], ['control 3', {'bid': [81, 100], 'ask': [83, 100], 'accounts': [['a0', 'asset', True, 1, 500], ['a1', 'asset', False, 1000, 500], ['a2', 'asset', True, 1000, 1003]]}, {'balances': [['a0', 1], ['a1', 500], ['a2', 810]], 'unrealized_gain': -692}], ['control 4', {'bid': [6, 4], 'ask': [7, 4], 'accounts': [['a0', 'liability', False, 999, 999], ['a1', 'asset', False, 999, 1002], ['a2', 'asset', True, 1, 4]]}, {'balances': [['a0', 999], ['a1', 1002], ['a2', 2]], 'unrealized_gain': -2}], ['control 5', {'bid': [9, 8], 'ask': [12, 8], 'accounts': [['a0', 'asset', True, 1, 500], ['a1', 'asset', True, 101, 500], ['a2', 'asset', True, 1000, 1003]]}, {'balances': [['a0', 1], ['a1', 114], ['a2', 1125]], 'unrealized_gain': -763}], ['control 6', {'bid': [18, 10], 'ask': [20, 10], 'accounts': [['a0', 'liability', True, 1, 2], ['a1', 'asset', True, 999, 1998], ['a2', 'asset', True, 250, 500]]}, {'balances': [['a0', 2], ['a1', 1798], ['a2', 450]], 'unrealized_gain': -250}]], [['regression: liability gain sign', {'bid': [3, 2], 'ask': [4, 2], 'accounts': [['a0', 'liability', True, 999, 500], ['a1', 'liability', False, 3, 3], ['a2', 'liability', True, 5, 10]]}, {'balances': [['a0', 1998], ['a1', 3], ['a2', 10]], 'unrealized_gain': -1498}], ['regression: liability gain sign, partial-repair probe', {'bid': [8, 10], 'ask': [9, 10], 'accounts': [['a0', 'liability', True, 1, 4], ['a1', 'asset', True, 250, 500], ['a2', 'asset', False, 101, 104], ['a3', 'asset', True, 1, 1]]}, {'balances': [['a0', 1], ['a1', 200], ['a2', 104], ['a3', 1]], 'unrealized_gain': -297}], ['control 1', {'bid': [6, 8], 'ask': [8, 8], 'accounts': [['a0', 'liability', False, 3, 500], ['a1', 'liability', True, 101, 101], ['a2', 'asset', True, 999, 1998], ['a3', 'liability', False, 3, 3], ['a4', 'asset', True, 999, 1002]]}, {'balances': [['a0', 500], ['a1', 101], ['a2', 749], ['a3', 3], ['a4', 749]], 'unrealized_gain': -1502}], ['control 2', {'bid': [8, 8], 'ask': [9, 8], 'accounts': [['a0', 'asset', False, 101, 101], ['a1', 'asset', False, 5, 500]]}, {'balances': [['a0', 101], ['a1', 500]], 'unrealized_gain': 0}], ['control 3', {'bid': [7, 10], 'ask': [9, 10], 'accounts': [['a0', 'asset', False, 250, 500], ['a1', 'asset', True, 250, 250], ['a2', 'asset', False, 7, 14]]}, {'balances': [['a0', 500], ['a1', 175], ['a2', 14]], 'unrealized_gain': -75}], ['control 4', {'bid': [15, 10], 'ask': [18, 10], 'accounts': [['a0', 'asset', True, 5, 5], ['a1', 'liability', False, 250, 250], ['a2', 'liability', False, 250, 500], ['a3', 'liability', False, 7, 500]]}, {'balances': [['a0', 8], ['a1', 250], ['a2', 500], ['a3', 500]], 'unrealized_gain': 3}], ['control 5', {'bid': [5, 2], 'ask': [8, 2], 'accounts': [['a0', 'asset', True, 999, 1998], ['a1', 'asset', True, 250, 250], ['a2', 'asset', True, 999, 999]]}, {'balances': [['a0', 2498], ['a1', 625], ['a2', 2498]], 'unrealized_gain': 2374}]], [['regression: liability gain sign', {'bid': [158, 100], 'ask': [159, 100], 'accounts': [['a0', 'liability', True, 1, 1], ['a1', 'asset', False, 999, 1002], ['a2', 'liability', True, 1, 2], ['a3', 'liability', False, 1000, 1003]]}, {'balances': [['a0', 2], ['a1', 1002], ['a2', 2], ['a3', 1003]], 'unrealized_gain': -1}], ['regression: liability gain sign, partial-repair probe', {'bid': [9, 10], 'ask': [10, 10], 'accounts': [['a0', 'liability', False, 101, 500], ['a1', 'asset', False, 7, 14], ['a2', 'liability', True, 7, 10], ['a3', 'asset', False, 101, 101]]}, {'balances': [['a0', 500], ['a1', 14], ['a2', 7], ['a3', 101]], 'unrealized_gain': 3}], ['control 1', {'bid': [2, 4], 'ask': [3, 4], 'accounts': [['a0', 'asset', True, 5, 500], ['a1', 'asset', True, 5, 500], ['a2', 'asset', True, 5, 8], ['a3', 'asset', True, 3, 500]]}, {'balances': [['a0', 3], ['a1', 3], ['a2', 3], ['a3', 2]], 'unrealized_gain': -1497}], ['control 2', {'bid': [6, 4], 'ask': [7, 4], 'accounts': [['a0', 'asset', False, 999, 500], ['a1', 'asset', True, 999, 999], ['a2', 'asset', True, 101, 104]]}, {'balances': [['a0', 500], ['a1', 1499], ['a2', 152]], 'unrealized_gain': 548}], ['control 3', {'bid': [4, 2], 'ask': [7, 2], 'accounts': [['a0', 'asset', True, 1, 4], ['a1', 'asset', True, 101, 101]]}, {'balances': [['a0', 2], ['a1', 202]], 'unrealized_gain': 99}], ['control 4', {'bid': [9, 4], 'ask': [11, 4], 'accounts': [['a0', 'asset', True, 7, 14], ['a1', 'asset', True, 3, 6], ['a2', 'asset', True, 3, 6], ['a3', 'asset', False, 250, 253]]}, {'balances': [['a0', 16], ['a1', 7], ['a2', 7], ['a3', 253]], 'unrealized_gain': 4}], ['control 5', {'bid': [2, 2], 'ask': [5, 2], 'accounts': [['a0', 'asset', False, 7, 7], ['a1', 'liability', False, 101, 500]]}, {'balances': [['a0', 7], ['a1', 500]], 'unrealized_gain': 0}]]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'raised ' + type(exc).__name__
    check(label, actual, 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
regression: liability gain sign{'balances': [['a0', 9], ['a1', 7], ['a2', 6]], 'unrealized_gain': 7}{'balances': [['a0', 9], ['a1', 7], ['a2', 6]], 'unrealized_gain': 7}Passed
control 1{'balances': [['a0', 5], ['a1', 500]], 'unrealized_gain': -5}{'balances': [['a0', 5], ['a1', 500]], 'unrealized_gain': -5}Passed
control 2{'balances': [['a0', 2000], ['a1', 7], ['a2', 500], ['a3', 8], ['a4', 1000]], 'unrealized_gain': 1250}{'balances': [['a0', 2000], ['a1', 7], ['a2', 500], ['a3', 8], ['a4', 1000]], 'unrealized_gain': 1250}Passed
control 3{'balances': [['a0', 63], ['a1', 4]], 'unrealized_gain': -38}{'balances': [['a0', 63], ['a1', 4]], 'unrealized_gain': -38}Passed
control 4{'balances': [['a0', 4], ['a1', 625]], 'unrealized_gain': 125}{'balances': [['a0', 4], ['a1', 625]], 'unrealized_gain': 125}Passed
control 5{'balances': [['a0', 500], ['a1', 999], ['a2', 125]], 'unrealized_gain': -1873}{'balances': [['a0', 500], ['a1', 999], ['a2', 125]], 'unrealized_gain': -1873}Passed
control 6{'balances': [['a0', 10], ['a1', 500], ['a2', 10], ['a3', 14]], 'unrealized_gain': 254}{'balances': [['a0', 10], ['a1', 500], ['a2', 10], ['a3', 14]], 'unrealized_gain': 254}Passed

SHA-256 / 8f25150c2705bf579232f4ce95be485b22e751a270db9df415d7d19f768008f5

Verification & scope

A deterministic bounded teaching model with stipulated toy bookkeeping rules stated in the contract; amounts are integer cents; it makes no claim of conformance to any accounting standard or product. 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:46:22.191497+00:00.

Case digest / 6aacc125e1e1053f7d7d3c35e7360613d3cbb46b92cc70746306496d5f568170