{"abstract":"Sun-synchronous retrograde orbits regress instead of precess.","category":"Orbital propagation","checks":7,"contract":"Input [a km, e, i deg, days]. With mu=398600.4418, Re=6378.137, J2=1.08263e-3, n=sqrt(mu/a^3), p=a(1-e^2): dRAAN/dt=-1.5 n J2 (Re/p)^2 cos i, dargp/dt=0.75 n J2 (Re/p)^2 (5cos^2 i-1). Return [RAAN drift deg, argp drift deg over the interval (rounded 4), sun-synchronous flag: |RAAN rate in deg/day - 0.9856|<0.01].","contract_signature":"x","evaluation_group":"w2-orbital_propagation-j2_secular","failed_approach":"Using sin i instead of cos i swaps polar and equatorial behaviour.","family":"w2-orbital_propagation-j2_secular-retrograde-node-sign","id":"FA-69576","implementations":{"attempt":{"sha256":"5995691a1c6dc8208ea351385fbc148eb3803e2fbed81c1a39cb3d5647fbe138","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    a,e,i,days=x\n    mu,Re,J2=398600.4418,6378.137,1.08263e-3\n    n=math.sqrt(mu/a**3)\n    p=a*(1-e*e)\n    ci=math.cos(math.radians(i))\n    fac=n*J2*(Re/p)**2\n    dO=-1.5*fac*math.sin(math.radians(i))\n    dw=0.75*fac*(5*ci*ci-1)\n    t=days*86400\n    sso=abs(math.degrees(dO)*86400-0.9856)<0.01\n    return [round(math.degrees(dO*t),4),round(math.degrees(dw*t),4),sso]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('j2 secular node and perigee drift [7078.0, 0.001, 98.19, 1]', [7078.0, 0.001, 98.19, 1], [0.986, -3.1094, True]), ('j2 secular node and perigee drift [7078.0, 0.001, 51.6, 1]', [7078.0, 0.001, 51.6, 1], [-4.2991, 3.2153, False]), ('j2 secular node and perigee drift [26560.0, 0.74, 63.4, 10]', [26560.0, 0.74, 63.4, 10], [-1.4793, 0.004, False]), ('j2 secular node and perigee drift [7000.0, 0.2, 28.5, 3]', [7000.0, 0.2, 28.5, 3], [-20.5825, 33.5103, False]), ('j2 secular node and perigee drift [6878.0, 0.0, 97.4, 2]', [6878.0, 0.0, 97.4, 2], [1.971, -7.0169, True]), ('j2 secular node and perigee drift [7500.0, 0.05, 82.0, 5]', [7500.0, 0.05, 82.0, 5], [-3.9523, -12.8241, False]), ('j2 secular node and perigee drift [12000.0, 0.3, 120.0, 7]', [12000.0, 0.3, 120.0, 7], [4.6102, 1.1525, False])], [('j2 secular node and perigee drift [6878.0, 0.0, 97.4, 2]', [6878.0, 0.0, 97.4, 2], [1.971, -7.0169, True]), ('j2 secular node and perigee drift [7078.0, 0.001, 51.6, 1]', [7078.0, 0.001, 51.6, 1], [-4.2991, 3.2153, False]), ('j2 secular node and perigee drift [7000.0, 0.2, 28.5, 3]', [7000.0, 0.2, 28.5, 3], [-20.5825, 33.5103, False]), ('j2 secular node and perigee drift [7500.0, 0.05, 82.0, 5]', [7500.0, 0.05, 82.0, 5], [-3.9523, -12.8241, False]), ('j2 secular node and perigee drift [12000.0, 0.3, 120.0, 7]', [12000.0, 0.3, 120.0, 7], [4.6102, 1.1525, False]), ('j2 secular node and perigee drift [42164.0, 0.0, 0.1, 30]', [42164.0, 0.0, 0.1, 30], [-0.4024, 0.8049, False]), ('j2 secular node and perigee drift [7078.0, 0.001, 81.81, 1]', [7078.0, 0.001, 81.81, 1], [-0.986, -3.1094, False])], [('j2 secular node and perigee drift [12000.0, 0.3, 120.0, 7]', [12000.0, 0.3, 120.0, 7], [4.6102, 1.1525, False]), ('j2 secular node and perigee drift [26560.0, 0.74, 63.4, 10]', [26560.0, 0.74, 63.4, 10], [-1.4793, 0.004, False]), ('j2 secular node and perigee drift [42164.0, 0.0, 0.1, 30]', [42164.0, 0.0, 0.1, 30], [-0.4024, 0.8049, False]), ('j2 secular node and perigee drift [7078.0, 0.001, 81.81, 1]', [7078.0, 0.001, 81.81, 1], [-0.986, -3.1094, False]), ('j2 secular node and perigee drift [8000.0, 0.1, 45.0, 0.5]', [8000.0, 0.1, 45.0, 0.5], [-1.6264, 1.7251, False]), ('j2 secular node and perigee drift [7078.0, 0.001, 98.19, 1]', [7078.0, 0.001, 98.19, 1], [0.986, -3.1094, True]), ('j2 secular node and perigee drift [7078.0, 0.001, 51.6, 1]', [7078.0, 0.001, 51.6, 1], [-4.2991, 3.2153, False])], [('j2 secular node and perigee drift [7078.0, 0.001, 98.19, 1]', [7078.0, 0.001, 98.19, 1], [0.986, -3.1094, True]), ('j2 secular node and perigee drift [7000.0, 0.2, 28.5, 3]', [7000.0, 0.2, 28.5, 3], [-20.5825, 33.5103, False]), ('j2 secular node and perigee drift [8000.0, 0.1, 45.0, 0.5]', [8000.0, 0.1, 45.0, 0.5], [-1.6264, 1.7251, False]), ('j2 secular node and perigee drift [7078.0, 0.001, 51.6, 1]', [7078.0, 0.001, 51.6, 1], [-4.2991, 3.2153, False]), ('j2 secular node and perigee drift [26560.0, 0.74, 63.4, 10]', [26560.0, 0.74, 63.4, 10], [-1.4793, 0.004, False]), ('j2 secular node and perigee drift [6878.0, 0.0, 97.4, 2]', [6878.0, 0.0, 97.4, 2], [1.971, -7.0169, True]), ('j2 secular node and perigee drift [7500.0, 0.05, 82.0, 5]', [7500.0, 0.05, 82.0, 5], [-3.9523, -12.8241, False])], [('j2 secular node and perigee drift [6878.0, 0.0, 97.4, 2]', [6878.0, 0.0, 97.4, 2], [1.971, -7.0169, True]), ('j2 secular node and perigee drift [26560.0, 0.74, 63.4, 10]', [26560.0, 0.74, 63.4, 10], [-1.4793, 0.004, False]), ('j2 secular node and perigee drift [7000.0, 0.2, 28.5, 3]', [7000.0, 0.2, 28.5, 3], [-20.5825, 33.5103, False]), ('j2 secular node and perigee drift [7500.0, 0.05, 82.0, 5]', [7500.0, 0.05, 82.0, 5], [-3.9523, -12.8241, False]), ('j2 secular node and perigee drift [12000.0, 0.3, 120.0, 7]', [12000.0, 0.3, 120.0, 7], [4.6102, 1.1525, False]), ('j2 secular node and perigee drift [42164.0, 0.0, 0.1, 30]', [42164.0, 0.0, 0.1, 30], [-0.4024, 0.8049, False]), ('j2 secular node and perigee drift [7078.0, 0.001, 81.81, 1]', [7078.0, 0.001, 81.81, 1], [-0.986, -3.1094, False])]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"f424e7de8c931992793b23f7229dda56dffc3f43ebe2b9f556bc01ccc6bccb83","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    a,e,i,days=x\n    mu,Re,J2=398600.4418,6378.137,1.08263e-3\n    n=math.sqrt(mu/a**3)\n    p=a*(1-e*e)\n    ci=math.cos(math.radians(i))\n    fac=n*J2*(Re/p)**2\n    dO=-1.5*fac*abs(ci)\n    dw=0.75*fac*(5*ci*ci-1)\n    t=days*86400\n    sso=abs(math.degrees(dO)*86400-0.9856)<0.01\n    return [round(math.degrees(dO*t),4),round(math.degrees(dw*t),4),sso]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('j2 secular node and perigee drift [7078.0, 0.001, 98.19, 1]', [7078.0, 0.001, 98.19, 1], [0.986, -3.1094, True]), ('j2 secular node and perigee drift [7078.0, 0.001, 51.6, 1]', [7078.0, 0.001, 51.6, 1], [-4.2991, 3.2153, False]), ('j2 secular node and perigee drift [26560.0, 0.74, 63.4, 10]', [26560.0, 0.74, 63.4, 10], [-1.4793, 0.004, False]), ('j2 secular node and perigee drift [7000.0, 0.2, 28.5, 3]', [7000.0, 0.2, 28.5, 3], [-20.5825, 33.5103, False]), ('j2 secular node and perigee drift [6878.0, 0.0, 97.4, 2]', [6878.0, 0.0, 97.4, 2], [1.971, -7.0169, True]), ('j2 secular node and perigee drift [7500.0, 0.05, 82.0, 5]', [7500.0, 0.05, 82.0, 5], [-3.9523, -12.8241, False]), ('j2 secular node and perigee drift [12000.0, 0.3, 120.0, 7]', [12000.0, 0.3, 120.0, 7], [4.6102, 1.1525, False])], [('j2 secular node and perigee drift [6878.0, 0.0, 97.4, 2]', [6878.0, 0.0, 97.4, 2], [1.971, -7.0169, True]), ('j2 secular node and perigee drift [7078.0, 0.001, 51.6, 1]', [7078.0, 0.001, 51.6, 1], [-4.2991, 3.2153, False]), ('j2 secular node and perigee drift [7000.0, 0.2, 28.5, 3]', [7000.0, 0.2, 28.5, 3], [-20.5825, 33.5103, False]), ('j2 secular node and perigee drift [7500.0, 0.05, 82.0, 5]', [7500.0, 0.05, 82.0, 5], [-3.9523, -12.8241, False]), ('j2 secular node and perigee drift [12000.0, 0.3, 120.0, 7]', [12000.0, 0.3, 120.0, 7], [4.6102, 1.1525, False]), ('j2 secular node and perigee drift [42164.0, 0.0, 0.1, 30]', [42164.0, 0.0, 0.1, 30], [-0.4024, 0.8049, False]), ('j2 secular node and perigee drift [7078.0, 0.001, 81.81, 1]', [7078.0, 0.001, 81.81, 1], [-0.986, -3.1094, False])], [('j2 secular node and perigee drift [12000.0, 0.3, 120.0, 7]', [12000.0, 0.3, 120.0, 7], [4.6102, 1.1525, False]), ('j2 secular node and perigee drift [26560.0, 0.74, 63.4, 10]', [26560.0, 0.74, 63.4, 10], [-1.4793, 0.004, False]), ('j2 secular node and perigee drift [42164.0, 0.0, 0.1, 30]', [42164.0, 0.0, 0.1, 30], [-0.4024, 0.8049, False]), ('j2 secular node and perigee drift [7078.0, 0.001, 81.81, 1]', [7078.0, 0.001, 81.81, 1], [-0.986, -3.1094, False]), ('j2 secular node and perigee drift [8000.0, 0.1, 45.0, 0.5]', [8000.0, 0.1, 45.0, 0.5], [-1.6264, 1.7251, False]), ('j2 secular node and perigee drift [7078.0, 0.001, 98.19, 1]', [7078.0, 0.001, 98.19, 1], [0.986, -3.1094, True]), ('j2 secular node and perigee drift [7078.0, 0.001, 51.6, 1]', [7078.0, 0.001, 51.6, 1], [-4.2991, 3.2153, False])], [('j2 secular node and perigee drift [7078.0, 0.001, 98.19, 1]', [7078.0, 0.001, 98.19, 1], [0.986, -3.1094, True]), ('j2 secular node and perigee drift [7000.0, 0.2, 28.5, 3]', [7000.0, 0.2, 28.5, 3], [-20.5825, 33.5103, False]), ('j2 secular node and perigee drift [8000.0, 0.1, 45.0, 0.5]', [8000.0, 0.1, 45.0, 0.5], [-1.6264, 1.7251, False]), ('j2 secular node and perigee drift [7078.0, 0.001, 51.6, 1]', [7078.0, 0.001, 51.6, 1], [-4.2991, 3.2153, False]), ('j2 secular node and perigee drift [26560.0, 0.74, 63.4, 10]', [26560.0, 0.74, 63.4, 10], [-1.4793, 0.004, False]), ('j2 secular node and perigee drift [6878.0, 0.0, 97.4, 2]', [6878.0, 0.0, 97.4, 2], [1.971, -7.0169, True]), ('j2 secular node and perigee drift [7500.0, 0.05, 82.0, 5]', [7500.0, 0.05, 82.0, 5], [-3.9523, -12.8241, False])], [('j2 secular node and perigee drift [6878.0, 0.0, 97.4, 2]', [6878.0, 0.0, 97.4, 2], [1.971, -7.0169, True]), ('j2 secular node and perigee drift [26560.0, 0.74, 63.4, 10]', [26560.0, 0.74, 63.4, 10], [-1.4793, 0.004, False]), ('j2 secular node and perigee drift [7000.0, 0.2, 28.5, 3]', [7000.0, 0.2, 28.5, 3], [-20.5825, 33.5103, False]), ('j2 secular node and perigee drift [7500.0, 0.05, 82.0, 5]', [7500.0, 0.05, 82.0, 5], [-3.9523, -12.8241, False]), ('j2 secular node and perigee drift [12000.0, 0.3, 120.0, 7]', [12000.0, 0.3, 120.0, 7], [4.6102, 1.1525, False]), ('j2 secular node and perigee drift [42164.0, 0.0, 0.1, 30]', [42164.0, 0.0, 0.1, 30], [-0.4024, 0.8049, False]), ('j2 secular node and perigee drift [7078.0, 0.001, 81.81, 1]', [7078.0, 0.001, 81.81, 1], [-0.986, -3.1094, False])]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"A deterministic toy two-body model with stipulated constants and conventions; not flight dynamics software or a validated SGP4 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.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-orbital_propagation-j2_secular-retrograde-node-sign","generated_at":"2026-09-29T14:48:12.640127+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Orbit determination and mission planning chain many small conversions; one wrong branch or unit silently moves a spacecraft by kilometres.","root_cause":"The nodal rate uses |cos i|, so retrograde orbits keep the prograde sign.","sha256":"fb4dd22d44d55948e8967e630c561570c2b29bf5013e2a4b6e4436c0f9aad48f","title":"J2 secular node and perigee drift: Nodal rate sign ignores retrograde inclinations · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verified":true,"visibility":"public","verification":{"attempt":{"elapsed_ms":41.232,"exit_code":1,"observations":[{"actual":[-6.8506,-3.1094,false],"check":"j2 secular node and perigee drift [7078.0, 0.001, 98.19, 1]","expected":[0.986,-3.1094,true],"passed":false},{"actual":[-5.4241,3.2153,false],"check":"j2 secular node and perigee drift [7078.0, 0.001, 51.6, 1]","expected":[-4.2991,3.2153,false],"passed":false},{"actual":[-2.9542,0.004,false],"check":"j2 secular node and perigee drift [26560.0, 0.74, 63.4, 10]","expected":[-1.4793,0.004,false],"passed":false},{"actual":[-11.1754,33.5103,false],"check":"j2 secular node and perigee drift [7000.0, 0.2, 28.5, 3]","expected":[-20.5825,33.5103,false],"passed":false},{"actual":[-15.1755,-7.0169,false],"check":"j2 secular node and perigee drift [6878.0, 0.0, 97.4, 2]","expected":[1.971,-7.0169,true],"passed":false},{"actual":[-28.122,-12.8241,false],"check":"j2 secular node and perigee drift [7500.0, 0.05, 82.0, 5]","expected":[-3.9523,-12.8241,false],"passed":false},{"actual":[-7.985,1.1525,false],"check":"j2 secular node and perigee drift [12000.0, 0.3, 120.0, 7]","expected":[4.6102,1.1525,false],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"j2 secular node and perigee drift [7078.0, 0.001, 98.19, 1]\", \"actual\": [-6.8506, -3.1094, false], \"expected\": [0.986, -3.1094, true], \"passed\": false}, {\"check\": \"j2 secular node and perigee drift [7078.0, 0.001, 51.6, 1]\", \"actual\": [-5.4241, 3.2153, false], \"expected\": [-4.2991, 3.2153, false], \"passed\": false}, {\"check\": \"j2 secular node and perigee drift [26560.0, 0.74, 63.4, 10]\", \"actual\": [-2.9542, 0.004, false], \"expected\": [-1.4793, 0.004, false], \"passed\": false}, {\"check\": \"j2 secular node and perigee drift [7000.0, 0.2, 28.5, 3]\", \"actual\": [-11.1754, 33.5103, false], \"expected\": [-20.5825, 33.5103, false], \"passed\": false}, {\"check\": \"j2 secular node and perigee drift [6878.0, 0.0, 97.4, 2]\", \"actual\": [-15.1755, -7.0169, false], \"expected\": [1.971, -7.0169, true], \"passed\": false}, {\"check\": \"j2 secular node and perigee drift [7500.0, 0.05, 82.0, 5]\", \"actual\": [-28.122, -12.8241, false], \"expected\": [-3.9523, -12.8241, false], \"passed\": false}, {\"check\": \"j2 secular node and perigee drift [12000.0, 0.3, 120.0, 7]\", \"actual\": [-7.985, 1.1525, false], \"expected\": [4.6102, 1.1525, false], \"passed\": false}], \"passed\": false}\n"},"broken":{"elapsed_ms":41.278,"exit_code":1,"observations":[{"actual":[-0.986,-3.1094,false],"check":"j2 secular node and perigee drift [7078.0, 0.001, 98.19, 1]","expected":[0.986,-3.1094,true],"passed":false},{"actual":[-4.2991,3.2153,false],"check":"j2 secular node and perigee drift [7078.0, 0.001, 51.6, 1]","expected":[-4.2991,3.2153,false],"passed":true},{"actual":[-1.4793,0.004,false],"check":"j2 secular node and perigee drift [26560.0, 0.74, 63.4, 10]","expected":[-1.4793,0.004,false],"passed":true},{"actual":[-20.5825,33.5103,false],"check":"j2 secular node and perigee drift [7000.0, 0.2, 28.5, 3]","expected":[-20.5825,33.5103,false],"passed":true},{"actual":[-1.971,-7.0169,false],"check":"j2 secular node and perigee drift [6878.0, 0.0, 97.4, 2]","expected":[1.971,-7.0169,true],"passed":false},{"actual":[-3.9523,-12.8241,false],"check":"j2 secular node and perigee drift [7500.0, 0.05, 82.0, 5]","expected":[-3.9523,-12.8241,false],"passed":true},{"actual":[-4.6102,1.1525,false],"check":"j2 secular node and perigee drift [12000.0, 0.3, 120.0, 7]","expected":[4.6102,1.1525,false],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"j2 secular node and perigee drift [7078.0, 0.001, 98.19, 1]\", \"actual\": [-0.986, -3.1094, false], \"expected\": [0.986, -3.1094, true], \"passed\": false}, {\"check\": \"j2 secular node and perigee drift [7078.0, 0.001, 51.6, 1]\", \"actual\": [-4.2991, 3.2153, false], \"expected\": [-4.2991, 3.2153, false], \"passed\": true}, {\"check\": \"j2 secular node and perigee drift [26560.0, 0.74, 63.4, 10]\", \"actual\": [-1.4793, 0.004, false], \"expected\": [-1.4793, 0.004, false], \"passed\": true}, {\"check\": \"j2 secular node and perigee drift [7000.0, 0.2, 28.5, 3]\", \"actual\": [-20.5825, 33.5103, false], \"expected\": [-20.5825, 33.5103, false], \"passed\": true}, {\"check\": \"j2 secular node and perigee drift [6878.0, 0.0, 97.4, 2]\", \"actual\": [-1.971, -7.0169, false], \"expected\": [1.971, -7.0169, true], \"passed\": false}, {\"check\": \"j2 secular node and perigee drift [7500.0, 0.05, 82.0, 5]\", \"actual\": [-3.9523, -12.8241, false], \"expected\": [-3.9523, -12.8241, false], \"passed\": true}, {\"check\": \"j2 secular node and perigee drift [12000.0, 0.3, 120.0, 7]\", \"actual\": [-4.6102, 1.1525, false], \"expected\": [4.6102, 1.1525, false], \"passed\": false}], \"passed\": false}\n"}},"member_only":{"stages":["fixed"],"fields":["implementations.fixed","verification.fixed","harness","repair"],"note":"The verified repair, its recorded checks, the repair description, and the scoring harness are available to members."}}