{"abstract":"Courses left of north come out negative or above 360.","category":"Tide and marine navigation tables","checks":7,"contract":"Input [track, boat_speed, set, drift] with degrees true (set is the direction the stream flows toward) and knots. Cross-track stream c=drift*sin(set-track); heading = track+asin(-c/boat); SOG=boat*cos(asin(-c/boat))+drift*cos(set-track). Return None when |c|>boat or SOG<=0, else [heading mod 360 rounded to 0.1, SOG rounded to 0.01].","evaluation_group":"w2-tide_and_marine_navigation_tables-course_to_steer","failed_approach":"Taking abs() of a negative heading reflects it about north.","family":"w2-tide_and_marine_navigation_tables-course_to_steer-heading-wrap","id":"FA-69021","implementations":{"attempt":{"sha256":"b887c1d6ab7abc51073dfa39ec2880728498613762750e4b2415e81484441abe","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    track,bs,setd,drift=x\n    rel=math.radians(setd-track)\n    cross=drift*math.sin(rel)\n    if abs(cross)>bs: return None\n    a=math.asin(-cross/bs)\n    sog=bs*math.cos(a)+drift*math.cos(rel)\n    if sog<=0: return None\n    return [round(abs(math.degrees(math.radians(track)+a)),1),round(sog,2)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [90, 6, 180, 1.5]', [90, 6, 180, 1.5], [75.5, 5.81]), ('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None)], [('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None)], [('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88])], [('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74]), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94])], [('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68]), ('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74]), ('course to steer across a stream [90, 4, 100, 4.5]', [90, 4, 100, 4.5], [78.7, 8.35])]]\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":"6a0d9cb63cf618273fcf6f4aef3fbc3a75450e0154f1f7371bbeb98129e02772","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    track,bs,setd,drift=x\n    rel=math.radians(setd-track)\n    cross=drift*math.sin(rel)\n    if abs(cross)>bs: return None\n    a=math.asin(-cross/bs)\n    sog=bs*math.cos(a)+drift*math.cos(rel)\n    if sog<=0: return None\n    return [round(math.degrees(math.radians(track)+a),1),round(sog,2)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [90, 6, 180, 1.5]', [90, 6, 180, 1.5], [75.5, 5.81]), ('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None)], [('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None)], [('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88])], [('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74]), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94])], [('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68]), ('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74]), ('course to steer across a stream [90, 4, 100, 4.5]', [90, 4, 100, 4.5], [78.7, 8.35])]]\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"},"fixed":{"sha256":"49bcdd87140b27bafd6b5521ae3ae73a109b6af3389bba7abd471eb8ab2674cb","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    track,bs,setd,drift=x\n    rel=math.radians(setd-track)\n    cross=drift*math.sin(rel)\n    if abs(cross)>bs: return None\n    a=math.asin(-cross/bs)\n    sog=bs*math.cos(a)+drift*math.cos(rel)\n    if sog<=0: return None\n    return [round(math.degrees(math.radians(track)+a)%360,1),round(sog,2)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [90, 6, 180, 1.5]', [90, 6, 180, 1.5], [75.5, 5.81]), ('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None)], [('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None)], [('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88])], [('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74]), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94])], [('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68]), ('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74]), ('course to steer across a stream [90, 4, 100, 4.5]', [90, 4, 100, 4.5], [78.7, 8.35])]]\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 model with stipulated rules and constants; not certified hydrographic software or a substitute for official tide tables. 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-tide_and_marine_navigation_tables-course_to_steer-heading-wrap","generated_at":"2026-09-29T14:48:07.605736+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Tide tables and passage plans turn published predictions into go/no-go decisions about depth, clearance and timing.","repair":"Reduce the heading modulo 360.","root_cause":"The heading is not reduced modulo 360.","sha256":"af89e8e154e2a551762abc6fde78ec61732f17c8f610955cc6c485b8384a8e18","title":"Course to steer across a stream: Headings near north are not wrapped · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":38.185,"exit_code":1,"observations":[{"actual":[13.6,4.58],"check":"course to steer across a stream [10, 5, 100, 2]","expected":[346.4,4.58],"passed":false},{"actual":[75.5,5.81],"check":"course to steer across a stream [90, 6, 180, 1.5]","expected":[75.5,5.81],"passed":true},{"actual":[104.5,5.81],"check":"course to steer across a stream [90, 6, 0, 1.5]","expected":[104.5,5.81],"passed":true},{"actual":[326.4,4.58],"check":"course to steer across a stream [350, 5, 80, 2]","expected":[326.4,4.58],"passed":true},{"actual":[200.0,7.0],"check":"course to steer across a stream [200, 4, 200, 3]","expected":[200.0,7.0],"passed":true},{"actual":[200.0,1.0],"check":"course to steer across a stream [200, 4, 20, 3]","expected":[200.0,1.0],"passed":true},{"actual":null,"check":"course to steer across a stream [45, 5, 135, 6]","expected":null,"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"course to steer across a stream [10, 5, 100, 2]\", \"actual\": [13.6, 4.58], \"expected\": [346.4, 4.58], \"passed\": false}, {\"check\": \"course to steer across a stream [90, 6, 180, 1.5]\", \"actual\": [75.5, 5.81], \"expected\": [75.5, 5.81], \"passed\": true}, {\"check\": \"course to steer across a stream [90, 6, 0, 1.5]\", \"actual\": [104.5, 5.81], \"expected\": [104.5, 5.81], \"passed\": true}, {\"check\": \"course to steer across a stream [350, 5, 80, 2]\", \"actual\": [326.4, 4.58], \"expected\": [326.4, 4.58], \"passed\": true}, {\"check\": \"course to steer across a stream [200, 4, 200, 3]\", \"actual\": [200.0, 7.0], \"expected\": [200.0, 7.0], \"passed\": true}, {\"check\": \"course to steer across a stream [200, 4, 20, 3]\", \"actual\": [200.0, 1.0], \"expected\": [200.0, 1.0], \"passed\": true}, {\"check\": \"course to steer across a stream [45, 5, 135, 6]\", \"actual\": null, \"expected\": null, \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":38.382,"exit_code":1,"observations":[{"actual":[-13.6,4.58],"check":"course to steer across a stream [10, 5, 100, 2]","expected":[346.4,4.58],"passed":false},{"actual":[75.5,5.81],"check":"course to steer across a stream [90, 6, 180, 1.5]","expected":[75.5,5.81],"passed":true},{"actual":[104.5,5.81],"check":"course to steer across a stream [90, 6, 0, 1.5]","expected":[104.5,5.81],"passed":true},{"actual":[326.4,4.58],"check":"course to steer across a stream [350, 5, 80, 2]","expected":[326.4,4.58],"passed":true},{"actual":[200.0,7.0],"check":"course to steer across a stream [200, 4, 200, 3]","expected":[200.0,7.0],"passed":true},{"actual":[200.0,1.0],"check":"course to steer across a stream [200, 4, 20, 3]","expected":[200.0,1.0],"passed":true},{"actual":null,"check":"course to steer across a stream [45, 5, 135, 6]","expected":null,"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"course to steer across a stream [10, 5, 100, 2]\", \"actual\": [-13.6, 4.58], \"expected\": [346.4, 4.58], \"passed\": false}, {\"check\": \"course to steer across a stream [90, 6, 180, 1.5]\", \"actual\": [75.5, 5.81], \"expected\": [75.5, 5.81], \"passed\": true}, {\"check\": \"course to steer across a stream [90, 6, 0, 1.5]\", \"actual\": [104.5, 5.81], \"expected\": [104.5, 5.81], \"passed\": true}, {\"check\": \"course to steer across a stream [350, 5, 80, 2]\", \"actual\": [326.4, 4.58], \"expected\": [326.4, 4.58], \"passed\": true}, {\"check\": \"course to steer across a stream [200, 4, 200, 3]\", \"actual\": [200.0, 7.0], \"expected\": [200.0, 7.0], \"passed\": true}, {\"check\": \"course to steer across a stream [200, 4, 20, 3]\", \"actual\": [200.0, 1.0], \"expected\": [200.0, 1.0], \"passed\": true}, {\"check\": \"course to steer across a stream [45, 5, 135, 6]\", \"actual\": null, \"expected\": null, \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":38.232,"exit_code":0,"observations":[{"actual":[346.4,4.58],"check":"course to steer across a stream [10, 5, 100, 2]","expected":[346.4,4.58],"passed":true},{"actual":[75.5,5.81],"check":"course to steer across a stream [90, 6, 180, 1.5]","expected":[75.5,5.81],"passed":true},{"actual":[104.5,5.81],"check":"course to steer across a stream [90, 6, 0, 1.5]","expected":[104.5,5.81],"passed":true},{"actual":[326.4,4.58],"check":"course to steer across a stream [350, 5, 80, 2]","expected":[326.4,4.58],"passed":true},{"actual":[200.0,7.0],"check":"course to steer across a stream [200, 4, 200, 3]","expected":[200.0,7.0],"passed":true},{"actual":[200.0,1.0],"check":"course to steer across a stream [200, 4, 20, 3]","expected":[200.0,1.0],"passed":true},{"actual":null,"check":"course to steer across a stream [45, 5, 135, 6]","expected":null,"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"course to steer across a stream [10, 5, 100, 2]\", \"actual\": [346.4, 4.58], \"expected\": [346.4, 4.58], \"passed\": true}, {\"check\": \"course to steer across a stream [90, 6, 180, 1.5]\", \"actual\": [75.5, 5.81], \"expected\": [75.5, 5.81], \"passed\": true}, {\"check\": \"course to steer across a stream [90, 6, 0, 1.5]\", \"actual\": [104.5, 5.81], \"expected\": [104.5, 5.81], \"passed\": true}, {\"check\": \"course to steer across a stream [350, 5, 80, 2]\", \"actual\": [326.4, 4.58], \"expected\": [326.4, 4.58], \"passed\": true}, {\"check\": \"course to steer across a stream [200, 4, 200, 3]\", \"actual\": [200.0, 7.0], \"expected\": [200.0, 7.0], \"passed\": true}, {\"check\": \"course to steer across a stream [200, 4, 20, 3]\", \"actual\": [200.0, 1.0], \"expected\": [200.0, 1.0], \"passed\": true}, {\"check\": \"course to steer across a stream [45, 5, 135, 6]\", \"actual\": null, \"expected\": null, \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}