aero-agent-roles 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/NOTICE +18 -0
  2. package/README.md +49 -0
  3. package/bin/aero-agent-roles.js +127 -0
  4. package/lib/catalog.js +97 -0
  5. package/lib/install.js +48 -0
  6. package/lib/mcp.js +199 -0
  7. package/manifest.json +516 -0
  8. package/package.json +44 -0
  9. package/roles/aerodynamics-engineer/ROLE.md +153 -0
  10. package/roles/aerodynamics-engineer/SOURCES.md +12 -0
  11. package/roles/aerodynamics-engineer/cli.py +143 -0
  12. package/roles/aerodynamics-engineer/core/aerodynamics_core.py +1218 -0
  13. package/roles/aerodynamics-engineer/templates/aero-design-report-template.md +72 -0
  14. package/roles/aerodynamics-engineer/tests/test_aerodynamics_core.py +227 -0
  15. package/roles/aerodynamics-engineer/tests/test_role_aerodynamics.py +94 -0
  16. package/roles/aircraft-design-engineer/ROLE.md +138 -0
  17. package/roles/aircraft-design-engineer/SOURCES.md +12 -0
  18. package/roles/aircraft-design-engineer/cli.py +152 -0
  19. package/roles/aircraft-design-engineer/core/aircraft_design_core.py +1278 -0
  20. package/roles/aircraft-design-engineer/templates/concept-design-template.md +99 -0
  21. package/roles/aircraft-design-engineer/tests/test_aircraft_design_core.py +269 -0
  22. package/roles/aircraft-design-engineer/tests/test_role_aircraft_design_engineer.py +106 -0
  23. package/roles/airworthiness-compliance-engineer/ROLE.md +122 -0
  24. package/roles/airworthiness-compliance-engineer/SOURCES.md +16 -0
  25. package/roles/airworthiness-compliance-engineer/cli.py +146 -0
  26. package/roles/airworthiness-compliance-engineer/core/airworthiness_core.py +894 -0
  27. package/roles/airworthiness-compliance-engineer/templates/compliance-matrix-template.md +46 -0
  28. package/roles/airworthiness-compliance-engineer/tests/test_airworthiness_core.py +224 -0
  29. package/roles/airworthiness-compliance-engineer/tests/test_role_airworthiness.py +85 -0
  30. package/roles/as9100-quality-auditor/ROLE.md +128 -0
  31. package/roles/as9100-quality-auditor/SOURCES.md +16 -0
  32. package/roles/as9100-quality-auditor/cli.py +136 -0
  33. package/roles/as9100-quality-auditor/core/as9100_core.py +857 -0
  34. package/roles/as9100-quality-auditor/templates/findings-report-template.md +119 -0
  35. package/roles/as9100-quality-auditor/tests/test_as9100_cli_profile.py +105 -0
  36. package/roles/as9100-quality-auditor/tests/test_as9100_core.py +204 -0
  37. package/roles/as9100-quality-auditor/tests/test_role_as9100.py +90 -0
  38. package/roles/data-bus-avionics-engineer/ROLE.md +146 -0
  39. package/roles/data-bus-avionics-engineer/SOURCES.md +23 -0
  40. package/roles/data-bus-avionics-engineer/cli.py +311 -0
  41. package/roles/data-bus-avionics-engineer/core/data_bus_avionics_core.py +1121 -0
  42. package/roles/data-bus-avionics-engineer/templates/bus-assessment-template.md +134 -0
  43. package/roles/data-bus-avionics-engineer/tests/test_bundle_protocol.py +137 -0
  44. package/roles/data-bus-avionics-engineer/tests/test_data_bus_avionics_core.py +261 -0
  45. package/roles/data-bus-avionics-engineer/tests/test_role_data_bus_avionics_engineer.py +121 -0
  46. package/roles/do160-environmental-engineer/ROLE.md +136 -0
  47. package/roles/do160-environmental-engineer/SOURCES.md +30 -0
  48. package/roles/do160-environmental-engineer/cli.py +147 -0
  49. package/roles/do160-environmental-engineer/core/do160_environmental_core.py +1246 -0
  50. package/roles/do160-environmental-engineer/templates/environmental-qualification-plan-template.md +114 -0
  51. package/roles/do160-environmental-engineer/tests/test_do160_environmental_core.py +312 -0
  52. package/roles/do160-environmental-engineer/tests/test_role_do160_environmental_engineer.py +281 -0
  53. package/roles/do178c-cert-engineer/ROLE.md +120 -0
  54. package/roles/do178c-cert-engineer/SOURCES.md +16 -0
  55. package/roles/do178c-cert-engineer/cli.py +129 -0
  56. package/roles/do178c-cert-engineer/core/do178c_core.py +411 -0
  57. package/roles/do178c-cert-engineer/templates/psac-template.md +74 -0
  58. package/roles/do178c-cert-engineer/tests/test_do178c_cert_engineer_core.py +91 -0
  59. package/roles/do178c-cert-engineer/tests/test_role_do178c.py +109 -0
  60. package/roles/do254-hardware-engineer/ROLE.md +127 -0
  61. package/roles/do254-hardware-engineer/SOURCES.md +19 -0
  62. package/roles/do254-hardware-engineer/cli.py +308 -0
  63. package/roles/do254-hardware-engineer/core/do254_hardware_core.py +761 -0
  64. package/roles/do254-hardware-engineer/templates/phac-template.md +87 -0
  65. package/roles/do254-hardware-engineer/tests/test_do254_bundle_profile.py +152 -0
  66. package/roles/do254-hardware-engineer/tests/test_do254_hardware_core.py +200 -0
  67. package/roles/do254-hardware-engineer/tests/test_role_do254_hardware.py +108 -0
  68. package/roles/engineering-analysis-engineer/ROLE.md +154 -0
  69. package/roles/engineering-analysis-engineer/SOURCES.md +15 -0
  70. package/roles/engineering-analysis-engineer/cli.py +151 -0
  71. package/roles/engineering-analysis-engineer/core/engineering_analysis_engineer_core.py +866 -0
  72. package/roles/engineering-analysis-engineer/templates/analysis-memo-template.md +73 -0
  73. package/roles/engineering-analysis-engineer/tests/test_engineering_analysis_engineer_core.py +367 -0
  74. package/roles/engineering-analysis-engineer/tests/test_role_engineering_analysis_engineer.py +113 -0
  75. package/roles/flight-management-engineer/ROLE.md +160 -0
  76. package/roles/flight-management-engineer/SOURCES.md +30 -0
  77. package/roles/flight-management-engineer/cli.py +258 -0
  78. package/roles/flight-management-engineer/core/flight_management_core.py +1473 -0
  79. package/roles/flight-management-engineer/templates/route-assessment-template.md +94 -0
  80. package/roles/flight-management-engineer/tests/test_flight_management_core.py +437 -0
  81. package/roles/flight-management-engineer/tests/test_role_flight_management_engineer.py +123 -0
  82. package/roles/flight-mechanics-engineer/ROLE.md +162 -0
  83. package/roles/flight-mechanics-engineer/SOURCES.md +51 -0
  84. package/roles/flight-mechanics-engineer/cli.py +149 -0
  85. package/roles/flight-mechanics-engineer/core/flight_mechanics_core.py +1507 -0
  86. package/roles/flight-mechanics-engineer/templates/perf-sc-report-template.md +82 -0
  87. package/roles/flight-mechanics-engineer/tests/test_flight_mechanics_core.py +277 -0
  88. package/roles/flight-mechanics-engineer/tests/test_role_flight_mechanics_engineer.py +141 -0
  89. package/roles/flight-test-engineer/ROLE.md +137 -0
  90. package/roles/flight-test-engineer/SOURCES.md +24 -0
  91. package/roles/flight-test-engineer/cli.py +135 -0
  92. package/roles/flight-test-engineer/core/flight_test_core.py +931 -0
  93. package/roles/flight-test-engineer/templates/flight-test-template.md +143 -0
  94. package/roles/flight-test-engineer/tests/test_flight_test_engineer_core.py +227 -0
  95. package/roles/flight-test-engineer/tests/test_role_flight_test_engineer.py +150 -0
  96. package/roles/flight-test-performance-engineer/ROLE.md +165 -0
  97. package/roles/flight-test-performance-engineer/SOURCES.md +20 -0
  98. package/roles/flight-test-performance-engineer/cli.py +319 -0
  99. package/roles/flight-test-performance-engineer/core/flight_test_performance_core.py +1398 -0
  100. package/roles/flight-test-performance-engineer/templates/performance-report-template.md +105 -0
  101. package/roles/flight-test-performance-engineer/tests/test_flight_test_performance_engineer_core.py +308 -0
  102. package/roles/flight-test-performance-engineer/tests/test_role_flight_test_performance_engineer.py +165 -0
  103. package/roles/gnc-engineer/ROLE.md +141 -0
  104. package/roles/gnc-engineer/SOURCES.md +35 -0
  105. package/roles/gnc-engineer/cli.py +141 -0
  106. package/roles/gnc-engineer/core/gnc_core.py +1074 -0
  107. package/roles/gnc-engineer/templates/gnc-report-template.md +105 -0
  108. package/roles/gnc-engineer/tests/test_gnc_engineer_core.py +238 -0
  109. package/roles/gnc-engineer/tests/test_role_gnc_engineer.py +142 -0
  110. package/roles/guidance-engineer/ROLE.md +156 -0
  111. package/roles/guidance-engineer/SOURCES.md +43 -0
  112. package/roles/guidance-engineer/cli.py +280 -0
  113. package/roles/guidance-engineer/core/guidance_core.py +820 -0
  114. package/roles/guidance-engineer/templates/guidance-report-template.md +70 -0
  115. package/roles/guidance-engineer/tests/test_guidance_engineer_core.py +269 -0
  116. package/roles/guidance-engineer/tests/test_role_guidance_engineer.py +146 -0
  117. package/roles/high-speed-aerodynamics-engineer/ROLE.md +161 -0
  118. package/roles/high-speed-aerodynamics-engineer/SOURCES.md +18 -0
  119. package/roles/high-speed-aerodynamics-engineer/cli.py +282 -0
  120. package/roles/high-speed-aerodynamics-engineer/core/high_speed_aero_core.py +1566 -0
  121. package/roles/high-speed-aerodynamics-engineer/templates/high-speed-memo-template.md +75 -0
  122. package/roles/high-speed-aerodynamics-engineer/tests/test_bundle_protocol.py +103 -0
  123. package/roles/high-speed-aerodynamics-engineer/tests/test_high_speed_aero_core.py +280 -0
  124. package/roles/high-speed-aerodynamics-engineer/tests/test_role_high_speed_aerodynamics.py +125 -0
  125. package/roles/ndt-engineer/ROLE.md +157 -0
  126. package/roles/ndt-engineer/SOURCES.md +18 -0
  127. package/roles/ndt-engineer/cli.py +316 -0
  128. package/roles/ndt-engineer/core/ndt_core.py +1590 -0
  129. package/roles/ndt-engineer/templates/ndt-plan-template.md +109 -0
  130. package/roles/ndt-engineer/tests/test_ndt_cli_bundle.py +183 -0
  131. package/roles/ndt-engineer/tests/test_ndt_core.py +437 -0
  132. package/roles/ndt-engineer/tests/test_role_ndt_engineer.py +148 -0
  133. package/roles/numerical-analysis-engineer/ROLE.md +158 -0
  134. package/roles/numerical-analysis-engineer/SOURCES.md +19 -0
  135. package/roles/numerical-analysis-engineer/cli.py +414 -0
  136. package/roles/numerical-analysis-engineer/core/numerical_analysis_core.py +1220 -0
  137. package/roles/numerical-analysis-engineer/templates/verification-memo-template.md +120 -0
  138. package/roles/numerical-analysis-engineer/tests/test_bundle_protocol.py +157 -0
  139. package/roles/numerical-analysis-engineer/tests/test_numerical_analysis_core.py +337 -0
  140. package/roles/numerical-analysis-engineer/tests/test_role_numerical_analysis_engineer.py +117 -0
  141. package/roles/propulsion-engineer/ROLE.md +163 -0
  142. package/roles/propulsion-engineer/SOURCES.md +15 -0
  143. package/roles/propulsion-engineer/cli.py +168 -0
  144. package/roles/propulsion-engineer/core/propulsion_core.py +1291 -0
  145. package/roles/propulsion-engineer/templates/propulsion-report-template.md +92 -0
  146. package/roles/propulsion-engineer/tests/test_propulsion_engineer_core.py +294 -0
  147. package/roles/propulsion-engineer/tests/test_role_propulsion_engineer.py +106 -0
  148. package/roles/space-systems-engineer/ROLE.md +161 -0
  149. package/roles/space-systems-engineer/SOURCES.md +49 -0
  150. package/roles/space-systems-engineer/cli.py +173 -0
  151. package/roles/space-systems-engineer/core/space_systems_core.py +980 -0
  152. package/roles/space-systems-engineer/templates/space-systems-template.md +88 -0
  153. package/roles/space-systems-engineer/tests/test_role_space_systems_engineer.py +117 -0
  154. package/roles/space-systems-engineer/tests/test_space_systems_engineer_core.py +247 -0
  155. package/roles/state-estimation-engineer/ROLE.md +154 -0
  156. package/roles/state-estimation-engineer/SOURCES.md +27 -0
  157. package/roles/state-estimation-engineer/cli.py +326 -0
  158. package/roles/state-estimation-engineer/core/state_estimation_core.py +958 -0
  159. package/roles/state-estimation-engineer/templates/nav-state-estimator-design-template.md +76 -0
  160. package/roles/state-estimation-engineer/tests/test_bundle_protocol.py +110 -0
  161. package/roles/state-estimation-engineer/tests/test_role_state_estimation_engineer.py +127 -0
  162. package/roles/state-estimation-engineer/tests/test_state_estimation_engineer_core.py +231 -0
  163. package/roles/structures-loads-engineer/ROLE.md +171 -0
  164. package/roles/structures-loads-engineer/SOURCES.md +44 -0
  165. package/roles/structures-loads-engineer/cli.py +219 -0
  166. package/roles/structures-loads-engineer/core/structures_loads_core.py +1112 -0
  167. package/roles/structures-loads-engineer/templates/loads-strength-report-template.md +96 -0
  168. package/roles/structures-loads-engineer/tests/test_bundle_protocol.py +101 -0
  169. package/roles/structures-loads-engineer/tests/test_role_structures_loads_engineer.py +147 -0
  170. package/roles/structures-loads-engineer/tests/test_structures_loads_core.py +261 -0
@@ -0,0 +1,160 @@
1
+ ---
2
+ type: role
3
+ name: flight-management-engineer
4
+ title: "Flight Management Engineer"
5
+ status: draft
6
+ domain: avionics
7
+ deliverable_type: "flight plan and RNAV/RNP route assessment"
8
+ standards_bound:
9
+ - id: do-236c
10
+ tier: TIER-2
11
+ reference-only: true
12
+ - id: do-283a
13
+ tier: TIER-2
14
+ reference-only: true
15
+ - id: ac-90-105a
16
+ tier: TIER-1
17
+ reference-only: false
18
+ skills_bound:
19
+ - avionics/flight-management/flight-planning
20
+ - avionics/flight-management/lateral-navigation
21
+ - avionics/flight-management/vertical-navigation
22
+ - avionics/flight-management/holding-pattern-entry
23
+ - avionics/flight-management/dme-arc-leg
24
+ - avionics/flight-management/radius-to-fix-leg
25
+ - avionics/flight-management/rhumb-line-leg
26
+ - avionics/flight-management/radio-navigation-aids
27
+ - avionics/flight-management/rnp-anp-containment
28
+ - avionics/flight-management/performance-computation
29
+ - avionics/flight-management/rta-time-control
30
+ tools_allowed: [stdlib, offline-file-processing]
31
+ forbidden:
32
+ - "approve the flight plan or issue a clearance"
33
+ - "claim route eligibility without computed ANP evidence"
34
+ - "reproduce proprietary RTCA/ICAO text"
35
+ - "pass the assessment off as an approved filing"
36
+ sign_off_required: true
37
+ license: Apache-2.0
38
+ compatibility: "agentskills.io ROLE.md; any SKILL.md host"
39
+ metadata:
40
+ version: 0.1.0
41
+ author: ashfordeOU
42
+ skills_release: "v1.3.0+"
43
+ ---
44
+
45
+ # Flight Management Engineer
46
+
47
+ ## Role identity
48
+
49
+ This role is the flight management engineer for an aircraft program or
50
+ flight operations analysis: it takes a candidate route and produces a
51
+ Flight Plan and RNAV/RNP Route Assessment with computed geometry and
52
+ verdicts - great-circle leg tracks and distances, radius-to-fix (RF)
53
+ leg construction, DME arc checks, RNP/ANP containment, holding pattern
54
+ entry classification, RTA time-control feasibility, vertical (VNAV)
55
+ profile compliance, ECON cruise performance, and radio navaid geometry.
56
+ Use when a route must be checked for RNAV/RNP flyability and navigation
57
+ performance containment before operational dispatch review. Do NOT use
58
+ for general route "shortest path" travel planning (non-avionics), for
59
+ aircraft performance certification (see flight-mechanics roles), or
60
+ when no route facts (waypoints, RNP value, procedure legs) exist.
61
+
62
+ ## Deliverable contract
63
+
64
+ The role produces:
65
+
66
+ 1. **Flight Plan and RNAV/RNP Route Assessment** - per the filled
67
+ `templates/route-assessment-template.md`: waypoint/leg inventory with
68
+ computed tracks and distances, RF arc geometry, the ANP-versus-RNP
69
+ verdict with margin, the hold entry result, RTA verdict,
70
+ VNAV/performance numbers, and a findings list. The example route in
71
+ the template is a synthetic 4-leg illustration (waypoints are not
72
+ from a published navigation database and the flight is not a filed
73
+ plan).
74
+ 2. **Evidence bundle** (with `--bundle`) - model/gates/provenance JSON
75
+ per `docs/PROTOCOL.md`, including cross-check rows when the bound
76
+ AeroSkills leaves are present.
77
+ 3. **Findings** - constraint violations and required corrections for
78
+ the human dispatcher/flight operations reviewer.
79
+
80
+ ## Workflow (stages → bound skills)
81
+
82
+ | Stage | Loads skill | Produces |
83
+ |---|---|---|
84
+ | 1. Route structure & constraints | avionics/flight-management/flight-planning | waypoint/leg inventory, total track distance, vertical band constraint checks |
85
+ | 2. Lateral track geometry | avionics/flight-management/lateral-navigation | great-circle TF leg tracks and distances |
86
+ | 3. RF leg construction | avionics/flight-management/radius-to-fix-leg | RF turn centre, swept angle, arc length, exit track, chord, validity |
87
+ | 4. Rhumb line legs | avionics/flight-management/rhumb-line-leg | rhumb vs great-circle distance delta for the track-distance method |
88
+ | 5. RNP containment | avionics/flight-management/rnp-anp-containment | ANP (95% = 2 x sigma), required margin, PASS/FAIL containment verdict |
89
+ | 6. Holding entry | avionics/flight-management/holding-pattern-entry | 70/110 sector entry type, outbound timing, 1-in-60 wind-corrected heading |
90
+ | 7. DME arc legs | avionics/flight-management/dme-arc-leg | arc length, chord, bank angle to hold the arc, turn radius |
91
+ | 8. Navaid geometry | avionics/flight-management/radio-navigation-aids | DME slant range, VOR bearing/radial conversions |
92
+ | 9. RTA control | avionics/flight-management/rta-time-control | ETA, achievable window, required Mach, feasibility verdict |
93
+ | 10. VNAV & performance | avionics/flight-management/vertical-navigation + performance-computation | top of descent, gradient/FPA, crossing altitudes, ECON cruise Mach |
94
+ | 11. Findings & sign-off | all bound leaves | findings list, DRAFT assessment for dispatch review |
95
+
96
+ ## Evidence gates
97
+
98
+ Every produced assessment is gate-checked (`check_report`):
99
+
100
+ | Gate | Meaning |
101
+ |---|---|
102
+ | route_stated | the route has >= 2 waypoints and >= 1 leg with computed geometry |
103
+ | rnp_present | an RNP value > 0 is stated for the assessed segment |
104
+ | containment_checked | ANP-vs-RNP verdict computed (ANP = 2 x sigma, 95% containment) |
105
+ | entries_correct | holding entry classified as direct/teardrop/parallel by the 70/110 rule |
106
+ | sign_off_honest | document marked draft-for-review, never an approval |
107
+
108
+ - A stage is done when its computed numbers are in the model and
109
+ rendered in the deliverable.
110
+ - FINAL = every gate passes AND every finding is recorded; the route
111
+ may still carry open findings (the assessment surfaces them).
112
+
113
+ ## Boundary / forbidden
114
+
115
+ - NEVER approve the flight plan and NEVER issue a clearance - the
116
+ dispatcher, flight crew, and operator retain operational authority.
117
+ - NEVER claim RNP/route eligibility without the computed ANP
118
+ containment evidence trail.
119
+ - NEVER reproduce proprietary RTCA (DO-236C/DO-283A) or ICAO text.
120
+ Summaries and original structure only; public FAA advisory circulars
121
+ (AC 90-105A) are quotable with citation but paraphrase is preferred.
122
+ - The assessment is a DRAFT for human review, not a filed plan and not
123
+ an approval document.
124
+
125
+ ## Verification
126
+
127
+ The role runs STANDALONE: `core/flight_management_core.py` is an
128
+ executable engine that computes route geometry (great-circle, RF, DME
129
+ arc, rhumb), RNP containment, holding entry, RTA control, VNAV, ECON
130
+ performance, navaid geometry, BUILDS the assessment, and gate-checks
131
+ deliverables. No AeroSkills checkout required.
132
+
133
+ Run the role:
134
+ ```bash
135
+ python3 cli.py build --out assessment.md # example route
136
+ python3 cli.py build --out assessment.md --bundle # + evidence JSON
137
+ python3 cli.py build --rnp-nm 0.5 --sigma 250 --bundle # other facts
138
+ python3 cli.py build --profile program-profile.json # customer context
139
+ python3 cli.py check --file assessment.md # gate-check a doc
140
+ ```
141
+
142
+ With `--bundle`, `cli.py` dispatches the bound rnp-anp-containment and
143
+ holding-pattern-entry leaf logic when the AeroSkills checkout is
144
+ present (AEROSKILLS_DEV or ~/AeroSkills) and records the cross-check
145
+ (agrees/delta) in `evidence/provenance.json`; absent the library the
146
+ role core still produces the complete assessment.
147
+
148
+ Tests:
149
+ - tests/test_flight_management_core.py (offline): domain rules with
150
+ real anchors (2-sigma ANP, 70/110 boundaries, RF geometry, DME arc,
151
+ RTA law, VNAV, ECON), builder + gates + standalone (no skills repo).
152
+ - tests/test_role_flight_management_engineer.py: bound-skill
153
+ resolution (skips when the skills repo is absent) + workflow order +
154
+ filled template + boundaries + SOURCES presence.
155
+
156
+ ## Compliance
157
+
158
+ - do-236c / do-283a TIER-2 reference-only per standards-map; summaries
159
+ only, never verbatim. ac-90-105a is public FAA guidance (TIER-1).
160
+ - SOURCES.md records acquisition/extraction/verification status.
@@ -0,0 +1,30 @@
1
+ # SOURCES.md - Flight Management Engineer
2
+
3
+ Standards and documents this role references. Summary-not-copy: see
4
+ [STANDARDS.md](../../STANDARDS.md) for the full rule and purchase links.
5
+
6
+ | Source | Role use | Gated |
7
+ |---|---|---|
8
+ | RTCA DO-236C | RNAV/RNP system and FMS functional requirements, RNP containment and alerting concepts (95% containment basis) | true |
9
+ | RTCA DO-283A | RNP AR procedure design criteria (RF leg context) | true |
10
+ | FAA AC 90-105A | public approval guidance for RNP operations and baro-VNAV in the U.S. NAS, oceanic and remote airspace | false |
11
+ | FAA AC 90-101A | public approval guidance for RNP AR procedures (RF legs, containment) | false |
12
+ | FAA AIM / Instrument Flying Handbook | holding pattern entry sectors and timing (operational procedure, paraphrased) | false |
13
+ | 14 CFR Part 25 | airworthiness context for the FMS procedure function | false |
14
+ | ICAO Doc 9613 (PBN Manual) | performance-based navigation framework (reference only) | true |
15
+
16
+ Acquisition status: DO-236C/DO-283A are purchased RTCA documents -
17
+ referenced summary-only, never quoted. AC 90-105A, AC 90-101A, the AIM
18
+ and 14 CFR Part 25 are public FAA documents (available from faa.gov);
19
+ paraphrase preferred, short attributed quotes allowed.
20
+
21
+ The role's numeric rules are public geometric/physical equations
22
+ (spherical great-circle geometry, coordinated-turn radius
23
+ V^2/(g tan(bank)), the 1-in-60 rule, ISA atmosphere) and the documented
24
+ leaf models of the bound AeroSkills avionics/flight-management leaves:
25
+ RNP containment (ANP = 2 x 1-sigma, 95% containment), the 70/110
26
+ holding-entry sector rule, outbound leg timing (60 s at or below
27
+ 14000 ft, 90 s above), DME arc/radius-to-fix geometry, and the
28
+ documented simplified mid-size-transport drag/fuel model (calibrate per
29
+ aircraft against the FMS performance manual). No proprietary table or
30
+ standard text is reproduced anywhere in this role.
@@ -0,0 +1,258 @@
1
+ #!/usr/bin/env python3
2
+ """cli.py - run the Flight Management Engineer role.
3
+
4
+ Usage:
5
+ python3 cli.py build [--out <file.md>] [--rnp-nm <nm>] [--sigma <m>]
6
+ [--bundle] [--profile <p.json>]
7
+ # build the flight plan + RNAV/RNP route assessment for the example
8
+ # route; --rnp-nm / --sigma re-run the containment check with other
9
+ # facts; --bundle emits evidence/{model,gates,provenance}.json
10
+ python3 cli.py check --file <file.md>
11
+ # gate-check an existing assessment document
12
+
13
+ The role ENGINE (core/flight_management_core.py) does the work standalone:
14
+ route structure (great-circle/RF/DME-arc/rhumb geometry), RNP containment,
15
+ holding entry, RTA speed control, VNAV profile, ECON performance, radio
16
+ navaid checks, and the evidence gates. When AeroSkills is present
17
+ (AEROSKILLS_DEV or ~/AeroSkills), the CLI dispatches the bound
18
+ rnp-anp-containment and holding-pattern-entry leaf logic and cross-checks
19
+ it against the core's computation - two independent implementations
20
+ agreeing is recorded in provenance.json.
21
+ """
22
+ import argparse
23
+ import importlib.util
24
+ import os
25
+ import sys
26
+
27
+ sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
28
+ "core"))
29
+ sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
30
+ "..", "..", "scripts"))
31
+ import flight_management_core as core # noqa: E402
32
+ import evidence # noqa: E402
33
+
34
+ ROLE_SLUG = "flight-management-engineer"
35
+ AEROSKILLS = os.environ.get("AEROSKILLS_DEV", os.path.expanduser("~/AeroSkills"))
36
+ _LEAF_PREFIX = os.path.join(AEROSKILLS, "skills", "avionics",
37
+ "flight-management")
38
+
39
+
40
+ def _load_leaf_logic(leaf, logic_name):
41
+ """Import a bound leaf's *logic.py if present; else None."""
42
+ path = os.path.join(_LEAF_PREFIX, leaf, "scripts", logic_name)
43
+ if not os.path.exists(path):
44
+ return None
45
+ spec = importlib.util.spec_from_file_location("aeroskills_" + leaf.replace("-", "_"),
46
+ path)
47
+ mod = importlib.util.module_from_spec(spec)
48
+ try:
49
+ spec.loader.exec_module(mod)
50
+ return mod
51
+ except Exception:
52
+ return None
53
+
54
+
55
+ def _dispatch_crosschecks(model):
56
+ """Cross-check core numbers against the bound AeroSkills leaf logic.
57
+
58
+ Row 1: RNP containment margin (rnp-anp-containment leaf
59
+ margin_available_m vs core margin_available_m).
60
+ Row 2: holding entry lap time (holding-pattern-entry leaf
61
+ entry_lap_time_seconds vs core holding_entry_lap_seconds).
62
+ Rows are None when the skills checkout (or a leaf) is absent; the
63
+ role then simply ran standalone.
64
+ """
65
+ rows = []
66
+ rnp = model.get("rnp", {}).get("containment", {})
67
+ rnp_mod = _load_leaf_logic("rnp-anp-containment",
68
+ "rnp_anp_containment_logic.py")
69
+ if rnp_mod is not None and rnp.get("anp_m") is not None:
70
+ try:
71
+ core_margin = core.margin_available_m(
72
+ rnp["anp_m"], rnp["rnp_m"], 0.0)
73
+ skill_margin = rnp_mod.margin_available_m(
74
+ anp_m=rnp["anp_m"], rnp_m=rnp["rnp_m"], margin_fraction=0.0)
75
+ delta = abs(core_margin - skill_margin)
76
+ rows.append({
77
+ "leaf": "avionics/flight-management/rnp-anp-containment",
78
+ "skill_md": "SKILL.md",
79
+ "logic_file": "scripts/rnp_anp_containment_logic.py",
80
+ "function": "margin_available_m",
81
+ "dispatched": True,
82
+ "cross_check_point": "ANP %.1f m vs RNP %.1f m, margin %.0f %%"
83
+ % (rnp["anp_m"], rnp["rnp_m"],
84
+ model["rnp"].get("rnp_margin_fraction",
85
+ 0.0) * 100),
86
+ "core_value": round(float(core_margin), 6),
87
+ "skill_value": round(float(skill_margin), 6),
88
+ "delta": round(delta, 9),
89
+ "agrees": delta <= 1e-6,
90
+ "tolerance": 1e-6,
91
+ "skills_release": "v1.3.0+",
92
+ })
93
+ except Exception as e:
94
+ rows.append({"leaf": "avionics/flight-management/"
95
+ "rnp-anp-containment",
96
+ "dispatched": True, "error": str(e), "agrees": False})
97
+ hold = model.get("hold", {})
98
+ hold_mod = _load_leaf_logic("holding-pattern-entry",
99
+ "holding_pattern_entry_logic.py")
100
+ if hold_mod is not None and hold.get("entry"):
101
+ try:
102
+ core_lap = core.holding_entry_lap_seconds(hold["entry"],
103
+ hold["outbound_leg_s"])
104
+ skill_lap = hold_mod.entry_lap_time_seconds(hold["entry"],
105
+ hold["outbound_leg_s"])
106
+ delta = abs(core_lap - skill_lap)
107
+ rows.append({
108
+ "leaf": "avionics/flight-management/holding-pattern-entry",
109
+ "skill_md": "SKILL.md",
110
+ "logic_file": "scripts/holding_pattern_entry_logic.py",
111
+ "function": "entry_lap_time_seconds",
112
+ "dispatched": True,
113
+ "cross_check_point": ("%s entry, %.0f s outbound leg"
114
+ % (hold["entry"], hold["outbound_leg_s"])),
115
+ "core_value": round(float(core_lap), 6),
116
+ "skill_value": round(float(skill_lap), 6),
117
+ "delta": round(delta, 9),
118
+ "agrees": delta <= 1e-6,
119
+ "tolerance": 1e-6,
120
+ "skills_release": "v1.3.0+",
121
+ })
122
+ except Exception as e:
123
+ rows.append({"leaf": "avionics/flight-management/"
124
+ "holding-pattern-entry",
125
+ "dispatched": True, "error": str(e), "agrees": False})
126
+ return rows
127
+
128
+
129
+ def _provenance(model, dispatch_rows):
130
+ return {
131
+ "role": ROLE_SLUG,
132
+ "core": {
133
+ "file": "core/flight_management_core.py",
134
+ "functions": ["containment_analysis", "hold_entry_analysis",
135
+ "rf_leg_geometry", "rhumb_vs_great_circle",
136
+ "dme_arc_geometry", "rta_speed_command",
137
+ "vnav_tod_distance_nm", "perf_econ_summary"],
138
+ "version": "0.1.0",
139
+ },
140
+ "skills": dispatch_rows,
141
+ "cross_checked": bool(dispatch_rows),
142
+ "disclaimer": "DRAFT for human review. Not an approval document.",
143
+ }
144
+
145
+
146
+ def cmd_build(args):
147
+ item = core.example_item()
148
+ if args.rnp_nm:
149
+ item.rnp_nm = float(args.rnp_nm)
150
+ if args.sigma:
151
+ item.sigma_lateral_m = float(args.sigma)
152
+ model = core.build_report(item)
153
+ md = core.render_report_markdown(model)
154
+
155
+ # program profile (customer tailoring): load + apply context header
156
+ profile = None
157
+ try:
158
+ profile = evidence.load_profile(args.profile)
159
+ except ValueError as e:
160
+ print("error: bad profile: %s" % e)
161
+ return 1
162
+ if profile:
163
+ model["profile"] = {
164
+ "customer": profile.get("customer"),
165
+ "program": profile.get("program"),
166
+ "basis": profile.get("basis"),
167
+ "authority": profile.get("authority"),
168
+ "der": profile.get("der"),
169
+ "document_prefix": profile.get("document_prefix"),
170
+ "revision": profile.get("revision"),
171
+ }
172
+ md = evidence.profile_header_block(profile) + md
173
+
174
+ gates = core.check_report(model)
175
+ dispatch_rows = [] if args.no_dispatch else _dispatch_crosschecks(model)
176
+ if args.out:
177
+ with open(args.out, "w") as f:
178
+ f.write(md if md.endswith("\n") else md + "\n")
179
+ print("built flight plan + RNAV/RNP route assessment -> %s" % args.out)
180
+ print("route: %s" % model["route_id"])
181
+ print("total distance: %.2f NM | RNP %.1f | containment: %s | "
182
+ "hold entry: %s | RTA: %s"
183
+ % (model["total_distance_nm"], model["rnp"]["rnp_nm"],
184
+ model["rnp"]["containment"]["verdict"], model["hold"]["entry"],
185
+ model["rta"]["verdict"]))
186
+ print("gates: all_pass=%s %s" % (gates["all_pass"], gates))
187
+ if args.bundle:
188
+ prov = _provenance(model, dispatch_rows)
189
+ paths = evidence.write_bundle(
190
+ args.out, ROLE_SLUG,
191
+ "flight plan and RNAV/RNP route assessment",
192
+ model, gates, prov)
193
+ print("bundle: model=%s" % paths["model"])
194
+ print(" gates=%s" % paths["gates"])
195
+ print(" provenance=%s" % paths["provenance"])
196
+ if dispatch_rows:
197
+ for row in dispatch_rows:
198
+ if "error" in row:
199
+ print("cross-check: %s error: %s"
200
+ % (row["leaf"], row["error"]))
201
+ else:
202
+ print("cross-check: %s core=%.6f skill=%.6f "
203
+ "delta=%.9f agrees=%s"
204
+ % (row["leaf"], row["core_value"],
205
+ row["skill_value"], row["delta"],
206
+ row["agrees"]))
207
+ else:
208
+ print("cross-check: not dispatched (no AeroSkills logic)")
209
+ else:
210
+ print(md)
211
+ return 0 if gates["all_pass"] else 1
212
+
213
+
214
+ def cmd_check(args):
215
+ if not os.path.exists(args.file):
216
+ print("file not found: %s" % args.file)
217
+ return 1
218
+ md = open(args.file).read()
219
+ gates = core.check_report_markdown(md)
220
+ for name, ok in gates.items():
221
+ if name != "all_pass":
222
+ print("%s %s" % ("PASS" if ok else "FAIL", name))
223
+ print("RESULT: %s" % ("PASS" if gates["all_pass"] else "FAIL"))
224
+ return 0 if gates["all_pass"] else 1
225
+
226
+
227
+ def main():
228
+ p = argparse.ArgumentParser(
229
+ description="Flight Management Engineer role")
230
+ sub = p.add_subparsers(dest="cmd", required=True)
231
+
232
+ b = sub.add_parser("build")
233
+ b.add_argument("--out", default="",
234
+ help="output file (default: stdout)")
235
+ b.add_argument("--rnp-nm", default="",
236
+ help="RNP for the segment in NM (default: example 0.3)")
237
+ b.add_argument("--sigma", default="",
238
+ help="1-sigma lateral position error in m (default: example)")
239
+ b.add_argument("--bundle", action="store_true",
240
+ help="emit evidence/{model,gates,provenance}.json")
241
+ b.add_argument("--no-dispatch", action="store_true",
242
+ help="skip dispatching bound AeroSkills logic")
243
+ b.add_argument("--profile", default="",
244
+ help="program profile JSON (customer tailoring, "
245
+ "docs/PROFILE-SCHEMA.md)")
246
+ b.set_defaults(fn=cmd_build)
247
+
248
+ c = sub.add_parser("check")
249
+ c.add_argument("--file", required=True,
250
+ help="route assessment markdown to gate-check")
251
+ c.set_defaults(fn=cmd_check)
252
+
253
+ args = p.parse_args()
254
+ sys.exit(args.fn(args))
255
+
256
+
257
+ if __name__ == "__main__":
258
+ main()