mirror of
https://github.com/OpenSquawk/OpenSquawk
synced 2026-05-14 02:55:37 +08:00
586 lines
20 KiB
TypeScript
586 lines
20 KiB
TypeScript
const atcDecisionTree = {
|
|
"schema_version": "1.0",
|
|
"name": "icao_atc_decision_tree",
|
|
"description": "Machine-readable ICAO/FAA-style ATC flow for IFR, suited for LLM+Whisper+TTS loop.",
|
|
"start_state": "CD_CHECK_ATIS",
|
|
"end_states": ["FLOW_COMPLETE"],
|
|
"variables": {
|
|
"callsign": "DLH39A",
|
|
"acf_type": "A320",
|
|
"dep": "EDDF",
|
|
"dest": "EDDM",
|
|
"stand": "A12",
|
|
"runway": "25R",
|
|
"sid": "ANEKI 7S",
|
|
"transition": "ANEKI",
|
|
"squawk": "1234",
|
|
"initial_altitude_ft": 5000,
|
|
"climb_altitude_ft": 7000,
|
|
"cruise_flight_level": "FL360",
|
|
"star": "RNAV X",
|
|
"approach_type": "ILS Z",
|
|
"taxi_route": "V A",
|
|
"missed_approach": "as published",
|
|
"delivery_freq": "121.900",
|
|
"ground_freq": "121.700",
|
|
"tower_freq": "118.700",
|
|
"departure_freq": "125.350",
|
|
"approach_freq": "120.800",
|
|
"handoff_freq": "121.800",
|
|
"atis_freq": "118.025",
|
|
"atis_code": "K",
|
|
"gate": "B24",
|
|
"trans_level": "FL070",
|
|
"qnh_hpa": 1015,
|
|
"push_delay_min": 5,
|
|
"surface_wind": "220/05",
|
|
"speed_restriction": "210 knots",
|
|
"emergency_heading": "180",
|
|
"remarks": "standard",
|
|
"time_now": "ISO8601"
|
|
},
|
|
"flags": {
|
|
"in_air": false,
|
|
"emergency_active": false,
|
|
"current_unit": "DEL",
|
|
"stack": []
|
|
},
|
|
"policies": {
|
|
"timeouts": {
|
|
"pilot_readback_timeout_s": 8,
|
|
"controller_ack_timeout_s": 6,
|
|
"no_reply_retry_after_s": 5,
|
|
"no_reply_max_retries": 2,
|
|
"lost_comms_detect_after_s": 90
|
|
},
|
|
"no_reply_sequence": [
|
|
{"after_s": 5, "controller_say_tpl": "{callsign}, confirm last transmission."},
|
|
{"after_s": 10, "controller_say_tpl": "{callsign}, do you read?"},
|
|
{"after_s": 20, "controller_say_tpl": "{callsign}, if you read, ident."}
|
|
],
|
|
"interrupts_allowed_when": {
|
|
"MAYDAY": "flags.in_air === true",
|
|
"PANPAN": "flags.in_air === true",
|
|
"TCAS_RA": "flags.in_air === true",
|
|
"GO_AROUND": "true",
|
|
"LOST_COMMS": "true",
|
|
"UNABLE": "true",
|
|
"STANDBY": "true"
|
|
}
|
|
},
|
|
"hooks": {
|
|
"on_state_enter": true,
|
|
"on_state_exit": true,
|
|
"on_timeout": true,
|
|
"on_interrupt": true,
|
|
"on_handoff": true,
|
|
"on_readback_check": true,
|
|
"on_pilot_speech": true,
|
|
"router_note": "Given pilot utterance → detect intent → if valid in active flow, branch; else jump to flow start with matching intent."
|
|
},
|
|
"roles": ["pilot", "atc", "system"],
|
|
"phases": ["Preflight","Clearance","PushStart","TaxiOut","Departure","Climb","Enroute","Descent","Approach","Landing","TaxiIn","Postflight","Interrupt","LostComms","Missed"],
|
|
"states": {
|
|
"PREFLIGHT_START": {
|
|
"role": "pilot",
|
|
"phase": "Preflight",
|
|
"prompt_out": "Initial contact with Clearance Delivery.",
|
|
"next": [{"to": "CD_CHECK_ATIS"}]
|
|
},
|
|
"CD_CHECK_ATIS": {
|
|
"role": "pilot",
|
|
"phase": "Clearance",
|
|
"utterance_tpl": "{callsign} information {atis_code}, IFR to {dest}, stand {stand}, request clearance.",
|
|
"next": [{"to": "CD_ISSUE_CLR"}],
|
|
"on_timeout": [{"after_s": 5, "action": "remind", "say_tpl": "{callsign}, say request."}]
|
|
},
|
|
"CD_ISSUE_CLR": {
|
|
"role": "atc",
|
|
"phase": "Clearance",
|
|
"say_tpl": "{callsign}, cleared to {dest} via {sid} departure, runway {runway}, climb {initial_altitude_ft} feet, squawk {squawk}.",
|
|
"readback_required": ["dest","sid","runway","initial_altitude_ft","squawk"],
|
|
"next": [
|
|
{"to": "CD_VERIFY_READBACK"},
|
|
{"to": "CD_AMEND_CLR", "when": "pilot_requests_amendment === true"}
|
|
]
|
|
},
|
|
"CD_VERIFY_READBACK": {
|
|
"role": "pilot",
|
|
"phase": "Clearance",
|
|
"utterance_tpl": "{callsign} cleared {dest} via {sid}, runway {runway}, climb {initial_altitude_ft}, squawk {squawk}.",
|
|
"next": [{"to": "CD_READBACK_CHECK"}]
|
|
},
|
|
"CD_READBACK_CHECK": {
|
|
"role": "atc",
|
|
"phase": "Clearance",
|
|
"auto": "check_readback",
|
|
"readback_required": ["dest","sid","runway","initial_altitude_ft","squawk"],
|
|
"ok_next": [{"to": "CD_CLR_COMPLETE"}],
|
|
"bad_next": [{"to": "CD_READBACK_CORRECT"}],
|
|
"on_timeout": [{"after_s": 6, "action": "say", "say_tpl": "{callsign}, read back clearance."}]
|
|
},
|
|
"CD_READBACK_CORRECT": {
|
|
"role": "atc",
|
|
"phase": "Clearance",
|
|
"say_tpl": "{callsign}, negative; expect {sid}, runway {runway}, climb {initial_altitude_ft}, squawk {squawk}.",
|
|
"next": [{"to": "CD_VERIFY_READBACK"}]
|
|
},
|
|
"CD_AMEND_CLR": {
|
|
"role": "atc",
|
|
"phase": "Clearance",
|
|
"say_tpl": "{callsign}, amended clearance: {sid} {transition} departure, runway {runway}.",
|
|
"next": [{"to": "CD_VERIFY_READBACK"}]
|
|
},
|
|
"CD_CLR_COMPLETE": {
|
|
"role": "atc",
|
|
"phase": "Clearance",
|
|
"say_tpl": "{callsign}, readback correct. Start-up at own discretion. Contact Ground {ground_freq} when ready for push and start.",
|
|
"actions": [{"set": "flags.current_unit", "to": "DEL"}],
|
|
"handoff": {"to": "GROUND","freq": "{ground_freq}"},
|
|
"next": [{"to": "GRD_READY_FOR_PUSH"}]
|
|
},
|
|
|
|
"GRD_READY_FOR_PUSH": {
|
|
"role": "pilot",
|
|
"phase": "PushStart",
|
|
"utterance_tpl": "{callsign} stand {stand}, ready for push and start.",
|
|
"next": [
|
|
{"to": "GRD_PUSH_APPROVE", "when": "push_available === true"},
|
|
{"to": "GRD_PUSH_WAIT", "when": "push_available === false"}
|
|
]
|
|
},
|
|
"GRD_PUSH_WAIT": {
|
|
"role": "atc",
|
|
"phase": "PushStart",
|
|
"say_tpl": "{callsign}, push and start approved in {push_delay_min} minutes. Expect taxi via {taxi_route}.",
|
|
"timer_next": [{"after_s": 60, "to": "GRD_PUSH_APPROVE"}],
|
|
"next": [{"to": "GRD_PUSH_APPROVE"}]
|
|
},
|
|
"GRD_PUSH_APPROVE": {
|
|
"role": "atc",
|
|
"phase": "PushStart",
|
|
"say_tpl": "{callsign}, push and start approved, facing {runway}. QNH {qnh_hpa}.",
|
|
"next": [{"to": "GRD_TAXI_REQUEST"}]
|
|
},
|
|
|
|
"GRD_TAXI_REQUEST": {
|
|
"role": "pilot",
|
|
"phase": "TaxiOut",
|
|
"utterance_tpl": "{callsign}, request taxi.",
|
|
"next": [{"to": "GRD_TAXI_INSTR"}]
|
|
},
|
|
"GRD_TAXI_INSTR": {
|
|
"role": "atc",
|
|
"phase": "TaxiOut",
|
|
"say_tpl": "{callsign}, taxi to runway {runway} via {taxi_route}, hold short runway {runway}.",
|
|
"readback_required": ["runway","taxi_route","hold_short"],
|
|
"next": [{"to": "GRD_TAXI_READBACK"}]
|
|
},
|
|
"GRD_TAXI_READBACK": {
|
|
"role": "pilot",
|
|
"phase": "TaxiOut",
|
|
"utterance_tpl": "{callsign} taxi to {runway} via {taxi_route}, holding short {runway}.",
|
|
"next": [{"to": "GRD_TAXI_READBACK_CHECK"}]
|
|
},
|
|
"GRD_TAXI_READBACK_CHECK": {
|
|
"role": "atc",
|
|
"phase": "TaxiOut",
|
|
"auto": "check_readback",
|
|
"readback_required": ["runway","taxi_route","hold_short"],
|
|
"ok_next": [{"to": "TWR_CONTACT"}],
|
|
"bad_next": [{"to": "GRD_TAXI_READBACK_CORRECT"}]
|
|
},
|
|
"GRD_TAXI_READBACK_CORRECT": {
|
|
"role": "atc",
|
|
"phase": "TaxiOut",
|
|
"say_tpl": "{callsign}, negative; taxi to runway {runway} via {taxi_route}, hold short runway {runway}.",
|
|
"next": [{"to": "GRD_TAXI_READBACK"}]
|
|
},
|
|
|
|
"TWR_CONTACT": {
|
|
"role": "atc",
|
|
"phase": "TaxiOut",
|
|
"say_tpl": "{callsign}, contact Tower {tower_freq} when number one.",
|
|
"handoff": {"to": "TOWER","freq": "{tower_freq}"},
|
|
"next": [{"to": "TWR_LINEUP_REQ"}]
|
|
},
|
|
"TWR_LINEUP_REQ": {
|
|
"role": "pilot",
|
|
"phase": "Departure",
|
|
"utterance_tpl": "{callsign} holding short {runway}, ready for departure.",
|
|
"next": [
|
|
{"to": "TWR_LINEUP", "when": "runway_occupied === true"},
|
|
{"to": "TWR_TAKEOFF_CLR", "when": "runway_occupied === false"}
|
|
]
|
|
},
|
|
"TWR_LINEUP": {
|
|
"role": "atc",
|
|
"phase": "Departure",
|
|
"say_tpl": "{callsign}, line up and wait runway {runway}.",
|
|
"next": [{"to": "TWR_TAKEOFF_CLR"}]
|
|
},
|
|
"TWR_TAKEOFF_CLR": {
|
|
"role": "atc",
|
|
"phase": "Departure",
|
|
"say_tpl": "{callsign}, wind {surface_wind}, runway {runway} cleared for take-off.",
|
|
"readback_required": ["runway","cleared_takeoff"],
|
|
"actions": [{"set": "flags.in_air", "to": true}],
|
|
"next": [{"to": "TWR_TAKEOFF_READBACK"}]
|
|
},
|
|
"TWR_TAKEOFF_READBACK": {
|
|
"role": "pilot",
|
|
"phase": "Departure",
|
|
"utterance_tpl": "{callsign} cleared for take-off {runway}.",
|
|
"next": [{"to": "TWR_TAKEOFF_READBACK_CHECK"}]
|
|
},
|
|
"TWR_TAKEOFF_READBACK_CHECK": {
|
|
"role": "atc",
|
|
"phase": "Departure",
|
|
"auto": "check_readback",
|
|
"readback_required": ["runway","cleared_takeoff"],
|
|
"ok_next": [{"to": "DEP_CONTACT"}],
|
|
"bad_next": [{"to": "TWR_TAKEOFF_READBACK_CORRECT"}]
|
|
},
|
|
"TWR_TAKEOFF_READBACK_CORRECT": {
|
|
"role": "atc",
|
|
"phase": "Departure",
|
|
"say_tpl": "{callsign}, negative; runway {runway}, cleared for take-off.",
|
|
"next": [{"to": "TWR_TAKEOFF_READBACK"}]
|
|
},
|
|
|
|
"DEP_CONTACT": {
|
|
"role": "atc",
|
|
"phase": "Departure",
|
|
"say_tpl": "{callsign}, contact Departure {departure_freq}.",
|
|
"handoff": {"to": "DEPARTURE","freq": "{departure_freq}"},
|
|
"actions": [{"set": "flags.current_unit", "to": "DEP"}],
|
|
"next": [{"to": "DEP_IDENT"}]
|
|
},
|
|
"DEP_IDENT": {
|
|
"role": "pilot",
|
|
"phase": "Climb",
|
|
"utterance_tpl": "{callsign} passing {initial_altitude_ft}, on SID {sid}.",
|
|
"next": [{"to": "DEP_CLIMB_INSTR"}]
|
|
},
|
|
"DEP_CLIMB_INSTR": {
|
|
"role": "atc",
|
|
"phase": "Climb",
|
|
"say_tpl": "{callsign}, climb {climb_altitude_ft} feet, proceed direct {transition} if able.",
|
|
"next": [
|
|
{"to": "DEP_CLIMB_READBACK", "when": "pilot_able === true"},
|
|
{"to": "DEP_UNABLE_DIR", "when": "pilot_able === false"}
|
|
]
|
|
},
|
|
"DEP_UNABLE_DIR": {
|
|
"role": "pilot",
|
|
"phase": "Climb",
|
|
"utterance_tpl": "{callsign} unable direct {transition}.",
|
|
"next": [{"to": "DEP_ALT_RTE"}]
|
|
},
|
|
"DEP_ALT_RTE": {
|
|
"role": "atc",
|
|
"phase": "Climb",
|
|
"say_tpl": "{callsign}, continue SID, report passing {climb_altitude_ft}.",
|
|
"next": [{"to": "ENR_HANDOFF"}]
|
|
},
|
|
"DEP_CLIMB_READBACK": {
|
|
"role": "pilot",
|
|
"phase": "Climb",
|
|
"utterance_tpl": "{callsign} climb {climb_altitude_ft}, direct {transition}.",
|
|
"next": [{"to": "ENR_HANDOFF"}]
|
|
},
|
|
|
|
"ENR_HANDOFF": {
|
|
"role": "atc",
|
|
"phase": "Enroute",
|
|
"say_tpl": "{callsign}, contact Center {handoff_freq}.",
|
|
"handoff": {"to": "CENTER","freq": "{handoff_freq}"},
|
|
"actions": [{"set": "flags.current_unit", "to": "CTR"}],
|
|
"next": [{"to": "ENR_CRUISE"}]
|
|
},
|
|
"ENR_CRUISE": {
|
|
"role": "pilot",
|
|
"phase": "Enroute",
|
|
"auto": "monitor",
|
|
"next": [{"to": "DES_INITIATE"}]
|
|
},
|
|
|
|
"DES_INITIATE": {
|
|
"role": "atc",
|
|
"phase": "Descent",
|
|
"say_tpl": "{callsign}, descend via {star} {transition}, QNH {qnh_hpa}.",
|
|
"next": [{"to": "DES_READBACK"}]
|
|
},
|
|
"DES_READBACK": {
|
|
"role": "pilot",
|
|
"phase": "Descent",
|
|
"utterance_tpl": "{callsign} descend via {star} {transition}, QNH {qnh_hpa}.",
|
|
"next": [{"to": "APP_HANDOFF"}]
|
|
},
|
|
|
|
"APP_HANDOFF": {
|
|
"role": "atc",
|
|
"phase": "Descent",
|
|
"say_tpl": "{callsign}, contact Approach {approach_freq}.",
|
|
"handoff": {"to": "APPROACH","freq": "{approach_freq}"},
|
|
"actions": [{"set": "flags.current_unit", "to": "APP"}],
|
|
"next": [{"to": "APP_VECTORING"}]
|
|
},
|
|
"APP_VECTORING": {
|
|
"role": "atc",
|
|
"phase": "Approach",
|
|
"say_tpl": "{callsign}, turn left heading 220, descend to {initial_altitude_ft} feet, reduce speed {speed_restriction}.",
|
|
"next": [{"to": "APP_CLEARED_APP"}]
|
|
},
|
|
"APP_CLEARED_APP": {
|
|
"role": "atc",
|
|
"phase": "Approach",
|
|
"say_tpl": "{callsign}, cleared {approach_type} approach runway {runway}, report established.",
|
|
"next": [{"to": "APP_ESTABLISHED"}]
|
|
},
|
|
"APP_ESTABLISHED": {
|
|
"role": "pilot",
|
|
"phase": "Approach",
|
|
"utterance_tpl": "{callsign} established localizer {runway}.",
|
|
"next": [{"to": "TWR_LAND_CONTACT"}]
|
|
},
|
|
|
|
"TWR_LAND_CONTACT": {
|
|
"role": "atc",
|
|
"phase": "Approach",
|
|
"say_tpl": "{callsign}, contact Tower {tower_freq}.",
|
|
"handoff": {"to": "TOWER","freq": "{tower_freq}"},
|
|
"actions": [{"set": "flags.current_unit", "to": "TWR"}],
|
|
"next": [{"to": "TWR_LAND_CLEARABLE"}]
|
|
},
|
|
"TWR_LAND_CLEARABLE": {
|
|
"role": "atc",
|
|
"phase": "Landing",
|
|
"condition": "runway_available === true",
|
|
"say_tpl": "{callsign}, wind {surface_wind}, runway {runway} cleared to land.",
|
|
"else_say_tpl": "{callsign}, continue approach, expect late landing clearance.",
|
|
"next": [
|
|
{"to": "TWR_LAND_READBACK", "when": "runway_available === true"},
|
|
{"to": "TWR_CONTINUE_APPROACH", "when": "runway_available === false"}
|
|
]
|
|
},
|
|
"TWR_CONTINUE_APPROACH": {
|
|
"role": "atc",
|
|
"phase": "Landing",
|
|
"say_tpl": "{callsign}, continue approach.",
|
|
"next": [{"to": "TWR_LAND_CLEARABLE"}]
|
|
},
|
|
"TWR_LAND_READBACK": {
|
|
"role": "pilot",
|
|
"phase": "Landing",
|
|
"utterance_tpl": "{callsign} cleared to land {runway}.",
|
|
"next": [{"to": "TWR_VACATE"}]
|
|
},
|
|
"TWR_VACATE": {
|
|
"role": "atc",
|
|
"phase": "Landing",
|
|
"say_tpl": "{callsign}, vacate via {taxi_route}, contact Ground {ground_freq}.",
|
|
"actions": [{"set": "flags.in_air", "to": false}],
|
|
"handoff": {"to": "GROUND","freq": "{ground_freq}"},
|
|
"next": [{"to": "GRD_TAXI_IN_REQ"}]
|
|
},
|
|
|
|
"GRD_TAXI_IN_REQ": {
|
|
"role": "pilot",
|
|
"phase": "TaxiIn",
|
|
"utterance_tpl": "{callsign} runway vacated, request taxi to stand.",
|
|
"next": [{"to": "GRD_TAXI_INSTR_IN"}]
|
|
},
|
|
"GRD_TAXI_INSTR_IN": {
|
|
"role": "atc",
|
|
"phase": "TaxiIn",
|
|
"say_tpl": "{callsign}, taxi to stand {gate} via {taxi_route}.",
|
|
"readback_required": ["gate","taxi_route"],
|
|
"next": [{"to": "GRD_TAXI_IN_READBACK"}]
|
|
},
|
|
"GRD_TAXI_IN_READBACK": {
|
|
"role": "pilot",
|
|
"phase": "TaxiIn",
|
|
"utterance_tpl": "{callsign} taxi to stand {gate} via {taxi_route}.",
|
|
"next": [{"to": "GRD_TAXI_IN_READBACK_CHECK"}]
|
|
},
|
|
"GRD_TAXI_IN_READBACK_CHECK": {
|
|
"role": "atc",
|
|
"phase": "TaxiIn",
|
|
"auto": "check_readback",
|
|
"readback_required": ["gate","taxi_route"],
|
|
"ok_next": [{"to": "FLOW_COMPLETE"}],
|
|
"bad_next": [{"to": "GRD_TAXI_IN_READBACK_CORRECT"}]
|
|
},
|
|
"GRD_TAXI_IN_READBACK_CORRECT": {
|
|
"role": "atc",
|
|
"phase": "TaxiIn",
|
|
"say_tpl": "{callsign}, negative; taxi to stand {gate} via {taxi_route}.",
|
|
"next": [{"to": "GRD_TAXI_IN_READBACK"}]
|
|
},
|
|
"FLOW_COMPLETE": {
|
|
"role": "system",
|
|
"phase": "Postflight",
|
|
"auto": "end",
|
|
"next": []
|
|
},
|
|
|
|
/* ===== Interrupts (conditioned) ===== */
|
|
|
|
"INT_MAYDAY": {
|
|
"role": "pilot",
|
|
"phase": "Interrupt",
|
|
"guard": "flags.in_air === true",
|
|
"utterance_tpl": "MAYDAY MAYDAY MAYDAY, {callsign}, {problem}, intentions {intent}.",
|
|
"priority": "highest",
|
|
"actions": [{"set": "flags.emergency_active", "to": true}],
|
|
"next": [{"to": "ATC_MAYDAY_VECTOR"}]
|
|
},
|
|
"ATC_MAYDAY_VECTOR": {
|
|
"role": "atc",
|
|
"phase": "Interrupt",
|
|
"say_tpl": "{callsign}, roger MAYDAY, fly heading {emergency_heading}, climb/descend {initial_altitude_ft}, cleared direct {dest} when able, QNH {qnh_hpa}.",
|
|
"next": [{"to": "ATC_MAYDAY_COORD"}]
|
|
},
|
|
"ATC_MAYDAY_COORD": {
|
|
"role": "system",
|
|
"phase": "Interrupt",
|
|
"actions": ["alert_emergency_services","notify_adjacent_units"],
|
|
"next": [{"to": "RESUME_PRIOR_FLOW"}]
|
|
},
|
|
|
|
"INT_PANPAN": {
|
|
"role": "pilot",
|
|
"phase": "Interrupt",
|
|
"guard": "flags.in_air === true",
|
|
"utterance_tpl": "PAN PAN PAN, {callsign}, {problem}, request priority.",
|
|
"priority": "high",
|
|
"actions": [{"set": "flags.emergency_active", "to": true}],
|
|
"next": [{"to": "ATC_PAN_ACK"}]
|
|
},
|
|
"ATC_PAN_ACK": {
|
|
"role": "atc",
|
|
"phase": "Interrupt",
|
|
"say_tpl": "{callsign}, PAN acknowledged, priority granted, expect vectors direct {dest} or nearest suitable.",
|
|
"next": [{"to": "RESUME_PRIOR_FLOW"}]
|
|
},
|
|
|
|
"INT_TCAS_RA": {
|
|
"role": "pilot",
|
|
"phase": "Interrupt",
|
|
"guard": "flags.in_air === true",
|
|
"utterance_tpl": "{callsign} TCAS RA, deviating.",
|
|
"actions": ["suspend_clearances"],
|
|
"next": [{"to": "ATC_TCAS_ACK"}]
|
|
},
|
|
"ATC_TCAS_ACK": {
|
|
"role": "atc",
|
|
"phase": "Interrupt",
|
|
"say_tpl": "{callsign}, roger TCAS RA, report clear of conflict.",
|
|
"next": [{"to": "ATC_TCAS_RESUME"}]
|
|
},
|
|
"ATC_TCAS_RESUME": {
|
|
"role": "pilot",
|
|
"phase": "Interrupt",
|
|
"utterance_tpl": "{callsign} clear of conflict, returning to clearance.",
|
|
"actions": [{"set": "flags.emergency_active", "to": false}],
|
|
"next": [{"to": "RESUME_PRIOR_FLOW"}]
|
|
},
|
|
|
|
"INT_GOA": {
|
|
"role": "pilot",
|
|
"phase": "Missed",
|
|
"utterance_tpl": "{callsign} going around, {missed_approach}.",
|
|
"actions": [{"set": "flags.in_air", "to": true}],
|
|
"next": [{"to": "ATC_GOA_INSTR"}]
|
|
},
|
|
"ATC_GOA_INSTR": {
|
|
"role": "atc",
|
|
"phase": "Missed",
|
|
"say_tpl": "{callsign}, roger go-around, fly published missed approach, climb {initial_altitude_ft}, contact Approach {approach_freq}.",
|
|
"handoff": {"to": "APPROACH","freq": "{approach_freq}"},
|
|
"next": [{"to": "APP_VECTORING"}]
|
|
},
|
|
|
|
"INT_NORDO": {
|
|
"role": "system",
|
|
"phase": "LostComms",
|
|
"trigger": "no_reply > policies.timeouts.lost_comms_detect_after_s",
|
|
"actions": ["lost_comms_procedure"],
|
|
"next": [{"to": "ATC_NORDO_ACTION"}]
|
|
},
|
|
"ATC_NORDO_ACTION": {
|
|
"role": "atc",
|
|
"phase": "LostComms",
|
|
"say_tpl": "(Transmitted blind) {callsign}, if you read, squawk IDENT and continue per last clearance. Expect vectors.",
|
|
"next": [{"to": "SYSTEM_NORDO_COORD"}]
|
|
},
|
|
"SYSTEM_NORDO_COORD": {
|
|
"role": "system",
|
|
"phase": "LostComms",
|
|
"actions": ["notify_adjacent_units","monitor_light_gun","publish_ATIS_note"],
|
|
"next": [{"to": "RESUME_PRIOR_FLOW"}]
|
|
},
|
|
|
|
"INT_UNABLE": {
|
|
"role": "pilot",
|
|
"phase": "Interrupt",
|
|
"utterance_tpl": "{callsign} unable {instruction}.",
|
|
"next": [{"to": "ATC_ALT_PROPOSAL"}]
|
|
},
|
|
"ATC_ALT_PROPOSAL": {
|
|
"role": "atc",
|
|
"phase": "Interrupt",
|
|
"say_tpl": "{callsign}, alternative: {alt_instruction}.",
|
|
"next": [
|
|
{"to": "PILOT_ACCEPT_ALT"},
|
|
{"to": "PILOT_REJECT_ALT"}
|
|
]
|
|
},
|
|
"PILOT_ACCEPT_ALT": {
|
|
"role": "pilot",
|
|
"phase": "Interrupt",
|
|
"utterance_tpl": "{callsign} wilco.",
|
|
"next": [{"to": "RESUME_PRIOR_FLOW"}]
|
|
},
|
|
"PILOT_REJECT_ALT": {
|
|
"role": "pilot",
|
|
"phase": "Interrupt",
|
|
"utterance_tpl": "{callsign} negative, request {intent}.",
|
|
"next": [{"to": "ATC_ALT_PROPOSAL"}]
|
|
},
|
|
|
|
"INT_STANDBY": {
|
|
"role": "pilot",
|
|
"phase": "Interrupt",
|
|
"utterance_tpl": "{callsign} standby.",
|
|
"actions": ["pause_exchange"],
|
|
"next": [{"to": "RESUME_PRIOR_FLOW"}]
|
|
},
|
|
|
|
/* ===== Generic glue & router ===== */
|
|
|
|
"RESUME_PRIOR_FLOW": {
|
|
"role": "system",
|
|
"phase": "Interrupt",
|
|
"auto": "pop_stack_or_route_by_intent",
|
|
"actions": [
|
|
{"if": "flags.emergency_active === true && flags.in_air === true", "set": "flags.emergency_active", "to": false}
|
|
],
|
|
"next": []
|
|
},
|
|
|
|
"GEN_NO_REPLY": {
|
|
"role": "system",
|
|
"phase": "Interrupt",
|
|
"trigger": "no_reply",
|
|
"policy_ref": "policies.no_reply_sequence",
|
|
"escalate_to": "INT_NORDO",
|
|
"next": []
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
export default atcDecisionTree;
|