FAILURE MAP
← Case archive

FA-55381 / Astronomical coordinate conventions / Open access

Orbital phase labels: Folded orbital phase applies the phase-zero offset in the wrong direction · case 01

The adapter reports an incorrect phase while other fields remain valid.

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

ROOT CAUSE

Folded orbital phase applies the phase-zero offset in the wrong direction. Faulty expression: (d['t']%d['P'])/d['P']

VERIFIED REPAIR

Preserve the declared model convention at this site: (d['t']/d['P']+d['q'])%1

Unsuccessful approach: A partial convention repair still uses (d['t']/d['P']-d['q'])%1

Case contract

A folded-orbit coordinate has period P>0, elapsed time t from periastron, and phase offset q in cycles. Phase is fractional cycle, cycle index is floor quotient, mean anomaly is phase times a full turn, and eclipse phase offsets are explicit. No orbital dynamics is solved. Output fields are defined by: phase = (d['t']/d['P']+d['q'])%1; cycle_index = int((d['t']/d['P']+d['q'])//1); mean_anomaly = 360*((d['t']/d['P']+d['q'])%1); phase_zero_epoch = d['epoch']-d['q']*d['P']; eclipse_phase = ((d['t']/d['P']+d['q'])-d['eclipse'])%1; phase_rate = 1/d['P']

Why this case matters

Catalog, detector, sky-coordinate, and spectroscopy adapters must preserve the association between numeric coordinates and their declared reference conventions.

1 / The failure

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

N = 1
observations = []
def solve(d):
    return {'phase': (d['t']%d['P'])/d['P'], 'cycle_index': int((d['t']/d['P']+d['q'])//1), 'mean_anomaly': 360*((d['t']/d['P']+d['q'])%1), 'phase_zero_epoch': d['epoch']-d['q']*d['P'], 'eclipse_phase': ((d['t']/d['P']+d['q'])-d['eclipse'])%1, 'phase_rate': 1/d['P']}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = {1: [({'t': 17, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.95, 'cycle_index': 1, 'mean_anomaly': 342.0, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.44999999999999996, 'phase_rate': 0.1}), ({'t': 0, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.25, 'cycle_index': 0, 'mean_anomaly': 90.0, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.75, 'phase_rate': 0.1}), ({'t': -21, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.1499999999999999, 'cycle_index': -2, 'mean_anomaly': 53.99999999999997, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.6499999999999999, 'phase_rate': 0.1}), ({'t': 17, 'P': 10, 'q': 0, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.7, 'cycle_index': 1, 'mean_anomaly': 251.99999999999997, 'phase_zero_epoch': 100, 'eclipse_phase': 0.19999999999999996, 'phase_rate': 0.1}), ({'t': 10, 'P': 4, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.75, 'cycle_index': 2, 'mean_anomaly': 270.0, 'phase_zero_epoch': 99.0, 'eclipse_phase': 0.25, 'phase_rate': 0.25}), ({'t': 17, 'P': 10, 'q': -0.25, 'eclipse': 0.25, 'epoch': 100}, {'phase': 0.44999999999999996, 'cycle_index': 1, 'mean_anomaly': 161.99999999999997, 'phase_zero_epoch': 102.5, 'eclipse_phase': 0.19999999999999996, 'phase_rate': 0.1})], 2: [({'t': 18, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.04999999999999982, 'cycle_index': 2, 'mean_anomaly': 17.999999999999936, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.5499999999999998, 'phase_rate': 0.1}), ({'t': 1, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.35, 'cycle_index': 0, 'mean_anomaly': 125.99999999999999, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.85, 'phase_rate': 0.1}), ({'t': -20, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.25, 'cycle_index': -2, 'mean_anomaly': 90.0, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.75, 'phase_rate': 0.1}), ({'t': 18, 'P': 10, 'q': 0, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.8, 'cycle_index': 1, 'mean_anomaly': 288.0, 'phase_zero_epoch': 100, 'eclipse_phase': 0.30000000000000004, 'phase_rate': 0.1}), ({'t': 11, 'P': 4, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.0, 'cycle_index': 3, 'mean_anomaly': 0.0, 'phase_zero_epoch': 99.0, 'eclipse_phase': 0.5, 'phase_rate': 0.25}), ({'t': 18, 'P': 10, 'q': -0.25, 'eclipse': 0.25, 'epoch': 100}, {'phase': 0.55, 'cycle_index': 1, 'mean_anomaly': 198.00000000000003, 'phase_zero_epoch': 102.5, 'eclipse_phase': 0.30000000000000004, 'phase_rate': 0.1})], 3: [({'t': 19, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.1499999999999999, 'cycle_index': 2, 'mean_anomaly': 53.99999999999997, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.6499999999999999, 'phase_rate': 0.1}), ({'t': 2, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.45, 'cycle_index': 0, 'mean_anomaly': 162.0, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.95, 'phase_rate': 0.1}), ({'t': -19, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.3500000000000001, 'cycle_index': -2, 'mean_anomaly': 126.00000000000003, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.8500000000000001, 'phase_rate': 0.1}), ({'t': 19, 'P': 10, 'q': 0, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.8999999999999999, 'cycle_index': 1, 'mean_anomaly': 323.99999999999994, 'phase_zero_epoch': 100, 'eclipse_phase': 0.3999999999999999, 'phase_rate': 0.1}), ({'t': 12, 'P': 4, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.25, 'cycle_index': 3, 'mean_anomaly': 90.0, 'phase_zero_epoch': 99.0, 'eclipse_phase': 0.75, 'phase_rate': 0.25}), ({'t': 19, 'P': 10, 'q': -0.25, 'eclipse': 0.25, 'epoch': 100}, {'phase': 0.6499999999999999, 'cycle_index': 1, 'mean_anomaly': 233.99999999999997, 'phase_zero_epoch': 102.5, 'eclipse_phase': 0.3999999999999999, 'phase_rate': 0.1})], 4: [({'t': 20, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.25, 'cycle_index': 2, 'mean_anomaly': 90.0, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.75, 'phase_rate': 0.1}), ({'t': 3, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.55, 'cycle_index': 0, 'mean_anomaly': 198.00000000000003, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.050000000000000044, 'phase_rate': 0.1}), ({'t': -18, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.44999999999999996, 'cycle_index': -2, 'mean_anomaly': 161.99999999999997, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.9500000000000002, 'phase_rate': 0.1}), ({'t': 20, 'P': 10, 'q': 0, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.0, 'cycle_index': 2, 'mean_anomaly': 0.0, 'phase_zero_epoch': 100, 'eclipse_phase': 0.5, 'phase_rate': 0.1}), ({'t': 13, 'P': 4, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.5, 'cycle_index': 3, 'mean_anomaly': 180.0, 'phase_zero_epoch': 99.0, 'eclipse_phase': 0.0, 'phase_rate': 0.25}), ({'t': 20, 'P': 10, 'q': -0.25, 'eclipse': 0.25, 'epoch': 100}, {'phase': 0.75, 'cycle_index': 1, 'mean_anomaly': 270.0, 'phase_zero_epoch': 102.5, 'eclipse_phase': 0.5, 'phase_rate': 0.1})], 5: [({'t': 21, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.3500000000000001, 'cycle_index': 2, 'mean_anomaly': 126.00000000000003, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.8500000000000001, 'phase_rate': 0.1}), ({'t': 4, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.65, 'cycle_index': 0, 'mean_anomaly': 234.0, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.15000000000000002, 'phase_rate': 0.1}), ({'t': -17, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.55, 'cycle_index': -2, 'mean_anomaly': 198.00000000000003, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.050000000000000044, 'phase_rate': 0.1}), ({'t': 21, 'P': 10, 'q': 0, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.10000000000000009, 'cycle_index': 2, 'mean_anomaly': 36.00000000000003, 'phase_zero_epoch': 100, 'eclipse_phase': 0.6000000000000001, 'phase_rate': 0.1}), ({'t': 14, 'P': 4, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.75, 'cycle_index': 3, 'mean_anomaly': 270.0, 'phase_zero_epoch': 99.0, 'eclipse_phase': 0.25, 'phase_rate': 0.25}), ({'t': 21, 'P': 10, 'q': -0.25, 'eclipse': 0.25, 'epoch': 100}, {'phase': 0.8500000000000001, 'cycle_index': 1, 'mean_anomaly': 306.00000000000006, 'phase_zero_epoch': 102.5, 'eclipse_phase': 0.6000000000000001, 'phase_rate': 0.1})]}
for i, (record, expected) in enumerate(fixtures[N]):
    check('astronomical fixture %s' % i, solve(record), 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
astronomical fixture 0{'cycle_index': 1, 'eclipse_phase': 0.44999999999999996, 'mean_anomaly': 342.0, 'phase': 0.7, 'phase_rate': 0.1, 'phase_zero_epoch': 97.5}{'cycle_index': 1, 'eclipse_phase': 0.44999999999999996, 'mean_anomaly': 342.0, 'phase': 0.95, 'phase_rate': 0.1, 'phase_zero_epoch': 97.5}Failed
astronomical fixture 1{'cycle_index': 0, 'eclipse_phase': 0.75, 'mean_anomaly': 90.0, 'phase': 0.0, 'phase_rate': 0.1, 'phase_zero_epoch': 97.5}{'cycle_index': 0, 'eclipse_phase': 0.75, 'mean_anomaly': 90.0, 'phase': 0.25, 'phase_rate': 0.1, 'phase_zero_epoch': 97.5}Failed
astronomical fixture 2{'cycle_index': -2, 'eclipse_phase': 0.6499999999999999, 'mean_anomaly': 53.99999999999997, 'phase': 0.9, 'phase_rate': 0.1, 'phase_zero_epoch': 97.5}{'cycle_index': -2, 'eclipse_phase': 0.6499999999999999, 'mean_anomaly': 53.99999999999997, 'phase': 0.1499999999999999, 'phase_rate': 0.1, 'phase_zero_epoch': 97.5}Failed
astronomical fixture 3{'cycle_index': 1, 'eclipse_phase': 0.19999999999999996, 'mean_anomaly': 251.99999999999997, 'phase': 0.7, 'phase_rate': 0.1, 'phase_zero_epoch': 100}{'cycle_index': 1, 'eclipse_phase': 0.19999999999999996, 'mean_anomaly': 251.99999999999997, 'phase': 0.7, 'phase_rate': 0.1, 'phase_zero_epoch': 100}Passed
astronomical fixture 4{'cycle_index': 2, 'eclipse_phase': 0.25, 'mean_anomaly': 270.0, 'phase': 0.5, 'phase_rate': 0.25, 'phase_zero_epoch': 99.0}{'cycle_index': 2, 'eclipse_phase': 0.25, 'mean_anomaly': 270.0, 'phase': 0.75, 'phase_rate': 0.25, 'phase_zero_epoch': 99.0}Failed
astronomical fixture 5{'cycle_index': 1, 'eclipse_phase': 0.19999999999999996, 'mean_anomaly': 161.99999999999997, 'phase': 0.7, 'phase_rate': 0.1, 'phase_zero_epoch': 102.5}{'cycle_index': 1, 'eclipse_phase': 0.19999999999999996, 'mean_anomaly': 161.99999999999997, 'phase': 0.44999999999999996, 'phase_rate': 0.1, 'phase_zero_epoch': 102.5}Failed

SHA-256 / fb47098e011fc31ac120ac5fe21bee0ef43359eede5a71ec84b9afa2e2a40379

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(d):
    return {'phase': (d['t']/d['P']-d['q'])%1, 'cycle_index': int((d['t']/d['P']+d['q'])//1), 'mean_anomaly': 360*((d['t']/d['P']+d['q'])%1), 'phase_zero_epoch': d['epoch']-d['q']*d['P'], 'eclipse_phase': ((d['t']/d['P']+d['q'])-d['eclipse'])%1, 'phase_rate': 1/d['P']}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = {1: [({'t': 17, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.95, 'cycle_index': 1, 'mean_anomaly': 342.0, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.44999999999999996, 'phase_rate': 0.1}), ({'t': 0, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.25, 'cycle_index': 0, 'mean_anomaly': 90.0, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.75, 'phase_rate': 0.1}), ({'t': -21, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.1499999999999999, 'cycle_index': -2, 'mean_anomaly': 53.99999999999997, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.6499999999999999, 'phase_rate': 0.1}), ({'t': 17, 'P': 10, 'q': 0, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.7, 'cycle_index': 1, 'mean_anomaly': 251.99999999999997, 'phase_zero_epoch': 100, 'eclipse_phase': 0.19999999999999996, 'phase_rate': 0.1}), ({'t': 10, 'P': 4, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.75, 'cycle_index': 2, 'mean_anomaly': 270.0, 'phase_zero_epoch': 99.0, 'eclipse_phase': 0.25, 'phase_rate': 0.25}), ({'t': 17, 'P': 10, 'q': -0.25, 'eclipse': 0.25, 'epoch': 100}, {'phase': 0.44999999999999996, 'cycle_index': 1, 'mean_anomaly': 161.99999999999997, 'phase_zero_epoch': 102.5, 'eclipse_phase': 0.19999999999999996, 'phase_rate': 0.1})], 2: [({'t': 18, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.04999999999999982, 'cycle_index': 2, 'mean_anomaly': 17.999999999999936, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.5499999999999998, 'phase_rate': 0.1}), ({'t': 1, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.35, 'cycle_index': 0, 'mean_anomaly': 125.99999999999999, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.85, 'phase_rate': 0.1}), ({'t': -20, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.25, 'cycle_index': -2, 'mean_anomaly': 90.0, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.75, 'phase_rate': 0.1}), ({'t': 18, 'P': 10, 'q': 0, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.8, 'cycle_index': 1, 'mean_anomaly': 288.0, 'phase_zero_epoch': 100, 'eclipse_phase': 0.30000000000000004, 'phase_rate': 0.1}), ({'t': 11, 'P': 4, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.0, 'cycle_index': 3, 'mean_anomaly': 0.0, 'phase_zero_epoch': 99.0, 'eclipse_phase': 0.5, 'phase_rate': 0.25}), ({'t': 18, 'P': 10, 'q': -0.25, 'eclipse': 0.25, 'epoch': 100}, {'phase': 0.55, 'cycle_index': 1, 'mean_anomaly': 198.00000000000003, 'phase_zero_epoch': 102.5, 'eclipse_phase': 0.30000000000000004, 'phase_rate': 0.1})], 3: [({'t': 19, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.1499999999999999, 'cycle_index': 2, 'mean_anomaly': 53.99999999999997, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.6499999999999999, 'phase_rate': 0.1}), ({'t': 2, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.45, 'cycle_index': 0, 'mean_anomaly': 162.0, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.95, 'phase_rate': 0.1}), ({'t': -19, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.3500000000000001, 'cycle_index': -2, 'mean_anomaly': 126.00000000000003, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.8500000000000001, 'phase_rate': 0.1}), ({'t': 19, 'P': 10, 'q': 0, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.8999999999999999, 'cycle_index': 1, 'mean_anomaly': 323.99999999999994, 'phase_zero_epoch': 100, 'eclipse_phase': 0.3999999999999999, 'phase_rate': 0.1}), ({'t': 12, 'P': 4, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.25, 'cycle_index': 3, 'mean_anomaly': 90.0, 'phase_zero_epoch': 99.0, 'eclipse_phase': 0.75, 'phase_rate': 0.25}), ({'t': 19, 'P': 10, 'q': -0.25, 'eclipse': 0.25, 'epoch': 100}, {'phase': 0.6499999999999999, 'cycle_index': 1, 'mean_anomaly': 233.99999999999997, 'phase_zero_epoch': 102.5, 'eclipse_phase': 0.3999999999999999, 'phase_rate': 0.1})], 4: [({'t': 20, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.25, 'cycle_index': 2, 'mean_anomaly': 90.0, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.75, 'phase_rate': 0.1}), ({'t': 3, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.55, 'cycle_index': 0, 'mean_anomaly': 198.00000000000003, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.050000000000000044, 'phase_rate': 0.1}), ({'t': -18, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.44999999999999996, 'cycle_index': -2, 'mean_anomaly': 161.99999999999997, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.9500000000000002, 'phase_rate': 0.1}), ({'t': 20, 'P': 10, 'q': 0, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.0, 'cycle_index': 2, 'mean_anomaly': 0.0, 'phase_zero_epoch': 100, 'eclipse_phase': 0.5, 'phase_rate': 0.1}), ({'t': 13, 'P': 4, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.5, 'cycle_index': 3, 'mean_anomaly': 180.0, 'phase_zero_epoch': 99.0, 'eclipse_phase': 0.0, 'phase_rate': 0.25}), ({'t': 20, 'P': 10, 'q': -0.25, 'eclipse': 0.25, 'epoch': 100}, {'phase': 0.75, 'cycle_index': 1, 'mean_anomaly': 270.0, 'phase_zero_epoch': 102.5, 'eclipse_phase': 0.5, 'phase_rate': 0.1})], 5: [({'t': 21, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.3500000000000001, 'cycle_index': 2, 'mean_anomaly': 126.00000000000003, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.8500000000000001, 'phase_rate': 0.1}), ({'t': 4, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.65, 'cycle_index': 0, 'mean_anomaly': 234.0, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.15000000000000002, 'phase_rate': 0.1}), ({'t': -17, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.55, 'cycle_index': -2, 'mean_anomaly': 198.00000000000003, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.050000000000000044, 'phase_rate': 0.1}), ({'t': 21, 'P': 10, 'q': 0, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.10000000000000009, 'cycle_index': 2, 'mean_anomaly': 36.00000000000003, 'phase_zero_epoch': 100, 'eclipse_phase': 0.6000000000000001, 'phase_rate': 0.1}), ({'t': 14, 'P': 4, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.75, 'cycle_index': 3, 'mean_anomaly': 270.0, 'phase_zero_epoch': 99.0, 'eclipse_phase': 0.25, 'phase_rate': 0.25}), ({'t': 21, 'P': 10, 'q': -0.25, 'eclipse': 0.25, 'epoch': 100}, {'phase': 0.8500000000000001, 'cycle_index': 1, 'mean_anomaly': 306.00000000000006, 'phase_zero_epoch': 102.5, 'eclipse_phase': 0.6000000000000001, 'phase_rate': 0.1})]}
for i, (record, expected) in enumerate(fixtures[N]):
    check('astronomical fixture %s' % i, solve(record), 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
astronomical fixture 0{'cycle_index': 1, 'eclipse_phase': 0.44999999999999996, 'mean_anomaly': 342.0, 'phase': 0.44999999999999996, 'phase_rate': 0.1, 'phase_zero_epoch': 97.5}{'cycle_index': 1, 'eclipse_phase': 0.44999999999999996, 'mean_anomaly': 342.0, 'phase': 0.95, 'phase_rate': 0.1, 'phase_zero_epoch': 97.5}Failed
astronomical fixture 1{'cycle_index': 0, 'eclipse_phase': 0.75, 'mean_anomaly': 90.0, 'phase': 0.75, 'phase_rate': 0.1, 'phase_zero_epoch': 97.5}{'cycle_index': 0, 'eclipse_phase': 0.75, 'mean_anomaly': 90.0, 'phase': 0.25, 'phase_rate': 0.1, 'phase_zero_epoch': 97.5}Failed
astronomical fixture 2{'cycle_index': -2, 'eclipse_phase': 0.6499999999999999, 'mean_anomaly': 53.99999999999997, 'phase': 0.6499999999999999, 'phase_rate': 0.1, 'phase_zero_epoch': 97.5}{'cycle_index': -2, 'eclipse_phase': 0.6499999999999999, 'mean_anomaly': 53.99999999999997, 'phase': 0.1499999999999999, 'phase_rate': 0.1, 'phase_zero_epoch': 97.5}Failed
astronomical fixture 3{'cycle_index': 1, 'eclipse_phase': 0.19999999999999996, 'mean_anomaly': 251.99999999999997, 'phase': 0.7, 'phase_rate': 0.1, 'phase_zero_epoch': 100}{'cycle_index': 1, 'eclipse_phase': 0.19999999999999996, 'mean_anomaly': 251.99999999999997, 'phase': 0.7, 'phase_rate': 0.1, 'phase_zero_epoch': 100}Passed
astronomical fixture 4{'cycle_index': 2, 'eclipse_phase': 0.25, 'mean_anomaly': 270.0, 'phase': 0.25, 'phase_rate': 0.25, 'phase_zero_epoch': 99.0}{'cycle_index': 2, 'eclipse_phase': 0.25, 'mean_anomaly': 270.0, 'phase': 0.75, 'phase_rate': 0.25, 'phase_zero_epoch': 99.0}Failed
astronomical fixture 5{'cycle_index': 1, 'eclipse_phase': 0.19999999999999996, 'mean_anomaly': 161.99999999999997, 'phase': 0.95, 'phase_rate': 0.1, 'phase_zero_epoch': 102.5}{'cycle_index': 1, 'eclipse_phase': 0.19999999999999996, 'mean_anomaly': 161.99999999999997, 'phase': 0.44999999999999996, 'phase_rate': 0.1, 'phase_zero_epoch': 102.5}Failed

SHA-256 / 2f47fcf4df1d6aa3af0f7e6c302221db9cc09cbdadd3979f0140e906df21d337

3 / The verified repair

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

N = 1
observations = []
def solve(d):
    return {'phase': (d['t']/d['P']+d['q'])%1, 'cycle_index': int((d['t']/d['P']+d['q'])//1), 'mean_anomaly': 360*((d['t']/d['P']+d['q'])%1), 'phase_zero_epoch': d['epoch']-d['q']*d['P'], 'eclipse_phase': ((d['t']/d['P']+d['q'])-d['eclipse'])%1, 'phase_rate': 1/d['P']}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = {1: [({'t': 17, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.95, 'cycle_index': 1, 'mean_anomaly': 342.0, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.44999999999999996, 'phase_rate': 0.1}), ({'t': 0, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.25, 'cycle_index': 0, 'mean_anomaly': 90.0, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.75, 'phase_rate': 0.1}), ({'t': -21, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.1499999999999999, 'cycle_index': -2, 'mean_anomaly': 53.99999999999997, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.6499999999999999, 'phase_rate': 0.1}), ({'t': 17, 'P': 10, 'q': 0, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.7, 'cycle_index': 1, 'mean_anomaly': 251.99999999999997, 'phase_zero_epoch': 100, 'eclipse_phase': 0.19999999999999996, 'phase_rate': 0.1}), ({'t': 10, 'P': 4, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.75, 'cycle_index': 2, 'mean_anomaly': 270.0, 'phase_zero_epoch': 99.0, 'eclipse_phase': 0.25, 'phase_rate': 0.25}), ({'t': 17, 'P': 10, 'q': -0.25, 'eclipse': 0.25, 'epoch': 100}, {'phase': 0.44999999999999996, 'cycle_index': 1, 'mean_anomaly': 161.99999999999997, 'phase_zero_epoch': 102.5, 'eclipse_phase': 0.19999999999999996, 'phase_rate': 0.1})], 2: [({'t': 18, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.04999999999999982, 'cycle_index': 2, 'mean_anomaly': 17.999999999999936, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.5499999999999998, 'phase_rate': 0.1}), ({'t': 1, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.35, 'cycle_index': 0, 'mean_anomaly': 125.99999999999999, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.85, 'phase_rate': 0.1}), ({'t': -20, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.25, 'cycle_index': -2, 'mean_anomaly': 90.0, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.75, 'phase_rate': 0.1}), ({'t': 18, 'P': 10, 'q': 0, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.8, 'cycle_index': 1, 'mean_anomaly': 288.0, 'phase_zero_epoch': 100, 'eclipse_phase': 0.30000000000000004, 'phase_rate': 0.1}), ({'t': 11, 'P': 4, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.0, 'cycle_index': 3, 'mean_anomaly': 0.0, 'phase_zero_epoch': 99.0, 'eclipse_phase': 0.5, 'phase_rate': 0.25}), ({'t': 18, 'P': 10, 'q': -0.25, 'eclipse': 0.25, 'epoch': 100}, {'phase': 0.55, 'cycle_index': 1, 'mean_anomaly': 198.00000000000003, 'phase_zero_epoch': 102.5, 'eclipse_phase': 0.30000000000000004, 'phase_rate': 0.1})], 3: [({'t': 19, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.1499999999999999, 'cycle_index': 2, 'mean_anomaly': 53.99999999999997, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.6499999999999999, 'phase_rate': 0.1}), ({'t': 2, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.45, 'cycle_index': 0, 'mean_anomaly': 162.0, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.95, 'phase_rate': 0.1}), ({'t': -19, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.3500000000000001, 'cycle_index': -2, 'mean_anomaly': 126.00000000000003, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.8500000000000001, 'phase_rate': 0.1}), ({'t': 19, 'P': 10, 'q': 0, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.8999999999999999, 'cycle_index': 1, 'mean_anomaly': 323.99999999999994, 'phase_zero_epoch': 100, 'eclipse_phase': 0.3999999999999999, 'phase_rate': 0.1}), ({'t': 12, 'P': 4, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.25, 'cycle_index': 3, 'mean_anomaly': 90.0, 'phase_zero_epoch': 99.0, 'eclipse_phase': 0.75, 'phase_rate': 0.25}), ({'t': 19, 'P': 10, 'q': -0.25, 'eclipse': 0.25, 'epoch': 100}, {'phase': 0.6499999999999999, 'cycle_index': 1, 'mean_anomaly': 233.99999999999997, 'phase_zero_epoch': 102.5, 'eclipse_phase': 0.3999999999999999, 'phase_rate': 0.1})], 4: [({'t': 20, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.25, 'cycle_index': 2, 'mean_anomaly': 90.0, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.75, 'phase_rate': 0.1}), ({'t': 3, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.55, 'cycle_index': 0, 'mean_anomaly': 198.00000000000003, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.050000000000000044, 'phase_rate': 0.1}), ({'t': -18, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.44999999999999996, 'cycle_index': -2, 'mean_anomaly': 161.99999999999997, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.9500000000000002, 'phase_rate': 0.1}), ({'t': 20, 'P': 10, 'q': 0, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.0, 'cycle_index': 2, 'mean_anomaly': 0.0, 'phase_zero_epoch': 100, 'eclipse_phase': 0.5, 'phase_rate': 0.1}), ({'t': 13, 'P': 4, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.5, 'cycle_index': 3, 'mean_anomaly': 180.0, 'phase_zero_epoch': 99.0, 'eclipse_phase': 0.0, 'phase_rate': 0.25}), ({'t': 20, 'P': 10, 'q': -0.25, 'eclipse': 0.25, 'epoch': 100}, {'phase': 0.75, 'cycle_index': 1, 'mean_anomaly': 270.0, 'phase_zero_epoch': 102.5, 'eclipse_phase': 0.5, 'phase_rate': 0.1})], 5: [({'t': 21, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.3500000000000001, 'cycle_index': 2, 'mean_anomaly': 126.00000000000003, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.8500000000000001, 'phase_rate': 0.1}), ({'t': 4, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.65, 'cycle_index': 0, 'mean_anomaly': 234.0, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.15000000000000002, 'phase_rate': 0.1}), ({'t': -17, 'P': 10, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.55, 'cycle_index': -2, 'mean_anomaly': 198.00000000000003, 'phase_zero_epoch': 97.5, 'eclipse_phase': 0.050000000000000044, 'phase_rate': 0.1}), ({'t': 21, 'P': 10, 'q': 0, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.10000000000000009, 'cycle_index': 2, 'mean_anomaly': 36.00000000000003, 'phase_zero_epoch': 100, 'eclipse_phase': 0.6000000000000001, 'phase_rate': 0.1}), ({'t': 14, 'P': 4, 'q': 0.25, 'eclipse': 0.5, 'epoch': 100}, {'phase': 0.75, 'cycle_index': 3, 'mean_anomaly': 270.0, 'phase_zero_epoch': 99.0, 'eclipse_phase': 0.25, 'phase_rate': 0.25}), ({'t': 21, 'P': 10, 'q': -0.25, 'eclipse': 0.25, 'epoch': 100}, {'phase': 0.8500000000000001, 'cycle_index': 1, 'mean_anomaly': 306.00000000000006, 'phase_zero_epoch': 102.5, 'eclipse_phase': 0.6000000000000001, 'phase_rate': 0.1})]}
for i, (record, expected) in enumerate(fixtures[N]):
    check('astronomical fixture %s' % i, solve(record), 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
astronomical fixture 0{'cycle_index': 1, 'eclipse_phase': 0.44999999999999996, 'mean_anomaly': 342.0, 'phase': 0.95, 'phase_rate': 0.1, 'phase_zero_epoch': 97.5}{'cycle_index': 1, 'eclipse_phase': 0.44999999999999996, 'mean_anomaly': 342.0, 'phase': 0.95, 'phase_rate': 0.1, 'phase_zero_epoch': 97.5}Passed
astronomical fixture 1{'cycle_index': 0, 'eclipse_phase': 0.75, 'mean_anomaly': 90.0, 'phase': 0.25, 'phase_rate': 0.1, 'phase_zero_epoch': 97.5}{'cycle_index': 0, 'eclipse_phase': 0.75, 'mean_anomaly': 90.0, 'phase': 0.25, 'phase_rate': 0.1, 'phase_zero_epoch': 97.5}Passed
astronomical fixture 2{'cycle_index': -2, 'eclipse_phase': 0.6499999999999999, 'mean_anomaly': 53.99999999999997, 'phase': 0.1499999999999999, 'phase_rate': 0.1, 'phase_zero_epoch': 97.5}{'cycle_index': -2, 'eclipse_phase': 0.6499999999999999, 'mean_anomaly': 53.99999999999997, 'phase': 0.1499999999999999, 'phase_rate': 0.1, 'phase_zero_epoch': 97.5}Passed
astronomical fixture 3{'cycle_index': 1, 'eclipse_phase': 0.19999999999999996, 'mean_anomaly': 251.99999999999997, 'phase': 0.7, 'phase_rate': 0.1, 'phase_zero_epoch': 100}{'cycle_index': 1, 'eclipse_phase': 0.19999999999999996, 'mean_anomaly': 251.99999999999997, 'phase': 0.7, 'phase_rate': 0.1, 'phase_zero_epoch': 100}Passed
astronomical fixture 4{'cycle_index': 2, 'eclipse_phase': 0.25, 'mean_anomaly': 270.0, 'phase': 0.75, 'phase_rate': 0.25, 'phase_zero_epoch': 99.0}{'cycle_index': 2, 'eclipse_phase': 0.25, 'mean_anomaly': 270.0, 'phase': 0.75, 'phase_rate': 0.25, 'phase_zero_epoch': 99.0}Passed
astronomical fixture 5{'cycle_index': 1, 'eclipse_phase': 0.19999999999999996, 'mean_anomaly': 161.99999999999997, 'phase': 0.44999999999999996, 'phase_rate': 0.1, 'phase_zero_epoch': 102.5}{'cycle_index': 1, 'eclipse_phase': 0.19999999999999996, 'mean_anomaly': 161.99999999999997, 'phase': 0.44999999999999996, 'phase_rate': 0.1, 'phase_zero_epoch': 102.5}Passed

SHA-256 / 2543cb1270eda2194fb4e4d51501afb6a5b47dfa9f4ef358d533afe4f8c81fad

Verification & scope

Explicitly stipulated finite algebraic adapter; no standards conformance, physical accuracy, or production-library claim. Inputs are the documented finite valid model domain. 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:45:57.251955+00:00.

Case digest / 4a527d54e45bbba4aaf4b99bb84e710edeb8941196c8bf9b17af386c8be9392e