FA-65991 / Aviation weight and balance / Open access
Ballast lever measured to the current CG · case 01
The computed ballast leaves the CG slightly outside the limit.
ROOT CAUSE
The denominator uses distance from ballast arm to the current CG instead of to the target limit.
THE FAILURE
The denominator uses distance from ballast arm to the current CG instead of to the target limit.
Unsuccessful approach: Always using the aft limit in the denominator is right for aft violations but wrong for forward ones.
Case contract
Input [W lb, CG, fwd limit, aft limit, ballast arm, max weight]. Inside inclusive limits -> 0. Otherwise ballast B brings CG to the violated limit: B = W*(CG-limit)/(limit-arm), rounded up to whole lb; ballast arm not on the corrective side of that limit -> 'ERR_BALLAST_ARM'; W+B above max -> 'ERR_OVERWEIGHT'.
Why this case matters
Ballast adds weight at a fixed station; the required amount depends on the distance from the ballast arm to the violated limit, and adds to gross weight.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
W, cg, fwd, aft, ba, maxw = x
if fwd <= cg <= aft: return 0
lim = aft if cg > aft else fwd
if (cg > aft and ba >= aft) or (cg < fwd and ba <= fwd): return 'ERR_BALLAST_ARM'
b = math.ceil(round(W * (cg - lim) / (cg - ba), 6))
if W + b > maxw: return 'ERR_OVERWEIGHT'
return b
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['aft CG nose ballast', [1800, 48.0, 35.0, 47.3, 10.0, 2550], 34], ['forward CG tail ballast', [1700, 34.2, 35.05, 47.3, 150.0, 2550], 13], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 21.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2250, 36.0, 36.0, 46.0, 101.0, 2700], 0], ['sampled case 2', [2220, 44.7, 33.9, 44.7, 121.5, 2550], 0], ['sampled case 3', [2400, 39.05, 36.3, 46.8, 9.5, 2400], 0], ['regression: ballast lever distance', [1765, 32.01, 34.1, 46.8, 54.4, 2550], 182]], [['aft CG nose ballast', [1800, 48.1, 35.0, 47.3, 10.0, 2550], 39], ['forward CG tail ballast', [1700, 34.2, 35.1, 47.3, 150.0, 2550], 14], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 22.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2035, 44.73, 36.5, 45.1, 11.9, 3000], 0], ['sampled case 2', [1925, 46.69, 36.9, 45.7, 120.5, 2550], 'ERR_BALLAST_ARM'], ['sampled case 3', [2440, 47.5, 35.1, 47.5, 46.2, 2400], 0]], [['aft CG nose ballast', [1800, 48.199999999999996, 35.0, 47.3, 10.0, 2550], 44], ['forward CG tail ballast', [1700, 34.2, 35.15, 47.3, 150.0, 2550], 15], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 23.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2510, 41.12, 36.1, 47.4, 155.2, 2700], 0], ['sampled case 2', [1785, 32.94, 35.6, 44.4, 94.3, 2400], 81], ['sampled case 3', [2400, 37.65, 34.3, 45.9, 140.6, 2550], 0]], [['aft CG nose ballast', [1800, 48.3, 35.0, 47.3, 10.0, 2550], 49], ['forward CG tail ballast', [1700, 34.2, 35.2, 47.3, 150.0, 2550], 15], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 24.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [1590, 30.16, 33.1, 46.2, 118.7, 2550], 55], ['sampled case 2', [1710, 32.9, 34.8, 45.0, 129.9, 2550], 35], ['sampled case 3', [1755, 35.34, 36.3, 47.0, 127.7, 2700], 19]], [['aft CG nose ballast', [1800, 48.4, 35.0, 47.3, 10.0, 2550], 54], ['forward CG tail ballast', [1700, 34.2, 35.25, 47.3, 150.0, 2550], 16], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 25.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [1745, 31.68, 34.3, 46.9, 112.4, 2550], 59], ['sampled case 2', [1645, 34.52, 36.5, 47.5, 5.2, 2400], 'ERR_BALLAST_ARM'], ['sampled case 3', [1850, 32.93, 34.5, 46.9, 56.9, 2700], 130]]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| aft CG nose ballast | 34 | 34 | Passed |
| forward CG tail ballast | 13 | 13 | Passed |
| in envelope | 0 | 0 | Passed |
| exactly on aft limit | 0 | 0 | Passed |
| exactly on forward limit | 0 | 0 | Passed |
| ballast arm behind aft limit | ERR_BALLAST_ARM | ERR_BALLAST_ARM | Passed |
| forward case ballast in nose | ERR_BALLAST_ARM | ERR_BALLAST_ARM | Passed |
| ballast would overweight | ERR_OVERWEIGHT | ERR_OVERWEIGHT | Passed |
| ballast reaches exactly max | 10 | 10 | Passed |
| sampled case 1 | 0 | 0 | Passed |
| sampled case 2 | 0 | 0 | Passed |
| sampled case 3 | 0 | 0 | Passed |
| regression: ballast lever distance | 165 | 182 | Failed |
SHA-256 / 40853ba382efd627fe4fc19ee3fd60385bca837d7fdbda3d0f93c7dd21af65fd
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
W, cg, fwd, aft, ba, maxw = x
if fwd <= cg <= aft: return 0
lim = aft if cg > aft else fwd
if (cg > aft and ba >= aft) or (cg < fwd and ba <= fwd): return 'ERR_BALLAST_ARM'
b = math.ceil(round(W * (cg - lim) / (aft - ba), 6))
if W + b > maxw: return 'ERR_OVERWEIGHT'
return b
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['aft CG nose ballast', [1800, 48.0, 35.0, 47.3, 10.0, 2550], 34], ['forward CG tail ballast', [1700, 34.2, 35.05, 47.3, 150.0, 2550], 13], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 21.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2250, 36.0, 36.0, 46.0, 101.0, 2700], 0], ['sampled case 2', [2220, 44.7, 33.9, 44.7, 121.5, 2550], 0], ['sampled case 3', [2400, 39.05, 36.3, 46.8, 9.5, 2400], 0], ['regression: ballast lever distance', [1765, 32.01, 34.1, 46.8, 54.4, 2550], 182]], [['aft CG nose ballast', [1800, 48.1, 35.0, 47.3, 10.0, 2550], 39], ['forward CG tail ballast', [1700, 34.2, 35.1, 47.3, 150.0, 2550], 14], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 22.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2035, 44.73, 36.5, 45.1, 11.9, 3000], 0], ['sampled case 2', [1925, 46.69, 36.9, 45.7, 120.5, 2550], 'ERR_BALLAST_ARM'], ['sampled case 3', [2440, 47.5, 35.1, 47.5, 46.2, 2400], 0]], [['aft CG nose ballast', [1800, 48.199999999999996, 35.0, 47.3, 10.0, 2550], 44], ['forward CG tail ballast', [1700, 34.2, 35.15, 47.3, 150.0, 2550], 15], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 23.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [2510, 41.12, 36.1, 47.4, 155.2, 2700], 0], ['sampled case 2', [1785, 32.94, 35.6, 44.4, 94.3, 2400], 81], ['sampled case 3', [2400, 37.65, 34.3, 45.9, 140.6, 2550], 0]], [['aft CG nose ballast', [1800, 48.3, 35.0, 47.3, 10.0, 2550], 49], ['forward CG tail ballast', [1700, 34.2, 35.2, 47.3, 150.0, 2550], 15], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 24.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [1590, 30.16, 33.1, 46.2, 118.7, 2550], 55], ['sampled case 2', [1710, 32.9, 34.8, 45.0, 129.9, 2550], 35], ['sampled case 3', [1755, 35.34, 36.3, 47.0, 127.7, 2700], 19]], [['aft CG nose ballast', [1800, 48.4, 35.0, 47.3, 10.0, 2550], 54], ['forward CG tail ballast', [1700, 34.2, 35.25, 47.3, 150.0, 2550], 16], ['in envelope', [2000, 40.0, 35.0, 47.3, 10.0, 2550], 0], ['exactly on aft limit', [2000, 47.3, 35.0, 47.3, 10.0, 2550], 0], ['exactly on forward limit', [2000, 35.0, 35.0, 47.3, 150.0, 2550], 0], ['ballast arm behind aft limit', [1900, 48.0, 35.0, 47.3, 60.0, 2550], 'ERR_BALLAST_ARM'], ['forward case ballast in nose', [1900, 34.0, 35.0, 47.3, 25.0, 2550], 'ERR_BALLAST_ARM'], ['ballast would overweight', [2500, 48.5, 35.0, 47.3, 10.0, 2550], 'ERR_OVERWEIGHT'], ['ballast reaches exactly max', [2000, 47.5, 35.0, 47.3, 7.3, 2010], 10], ['sampled case 1', [1745, 31.68, 34.3, 46.9, 112.4, 2550], 59], ['sampled case 2', [1645, 34.52, 36.5, 47.5, 5.2, 2400], 'ERR_BALLAST_ARM'], ['sampled case 3', [1850, 32.93, 34.5, 46.9, 56.9, 2700], 130]]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| aft CG nose ballast | 34 | 34 | Passed |
| forward CG tail ballast | 15 | 13 | Failed |
| in envelope | 0 | 0 | Passed |
| exactly on aft limit | 0 | 0 | Passed |
| exactly on forward limit | 0 | 0 | Passed |
| ballast arm behind aft limit | ERR_BALLAST_ARM | ERR_BALLAST_ARM | Passed |
| forward case ballast in nose | ERR_BALLAST_ARM | ERR_BALLAST_ARM | Passed |
| ballast would overweight | ERR_OVERWEIGHT | ERR_OVERWEIGHT | Passed |
| ballast reaches exactly max | 10 | 10 | Passed |
| sampled case 1 | 0 | 0 | Passed |
| sampled case 2 | 0 | 0 | Passed |
| sampled case 3 | 0 | 0 | Passed |
| regression: ballast lever distance | 486 | 182 | Failed |
SHA-256 / ef38e08183157944ec0edfe5ac31775fff77cddf686112107ac8ce33d20c5541
HELD IN THE MEMBER ARCHIVE
The verified repair and its recorded checks are member-only.
This mechanism has 13 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.
Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.
Member access is invitation-based. Sign in with your invited account to inspect the repair.
Sign in to the archive ↗Verification & scope
A deterministic toy loading model with stipulated constants; it is not an approved aircraft flight manual procedure and makes no claim of regulatory conformance. 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:47:39.125425+00:00.
Case digest / f956d2a5d9d6a1b80d4aad9911787b89b2c7ecf47ab4b76cb1b9e38ac490f176