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.
- package/NOTICE +18 -0
- package/README.md +49 -0
- package/bin/aero-agent-roles.js +127 -0
- package/lib/catalog.js +97 -0
- package/lib/install.js +48 -0
- package/lib/mcp.js +199 -0
- package/manifest.json +516 -0
- package/package.json +44 -0
- package/roles/aerodynamics-engineer/ROLE.md +153 -0
- package/roles/aerodynamics-engineer/SOURCES.md +12 -0
- package/roles/aerodynamics-engineer/cli.py +143 -0
- package/roles/aerodynamics-engineer/core/aerodynamics_core.py +1218 -0
- package/roles/aerodynamics-engineer/templates/aero-design-report-template.md +72 -0
- package/roles/aerodynamics-engineer/tests/test_aerodynamics_core.py +227 -0
- package/roles/aerodynamics-engineer/tests/test_role_aerodynamics.py +94 -0
- package/roles/aircraft-design-engineer/ROLE.md +138 -0
- package/roles/aircraft-design-engineer/SOURCES.md +12 -0
- package/roles/aircraft-design-engineer/cli.py +152 -0
- package/roles/aircraft-design-engineer/core/aircraft_design_core.py +1278 -0
- package/roles/aircraft-design-engineer/templates/concept-design-template.md +99 -0
- package/roles/aircraft-design-engineer/tests/test_aircraft_design_core.py +269 -0
- package/roles/aircraft-design-engineer/tests/test_role_aircraft_design_engineer.py +106 -0
- package/roles/airworthiness-compliance-engineer/ROLE.md +122 -0
- package/roles/airworthiness-compliance-engineer/SOURCES.md +16 -0
- package/roles/airworthiness-compliance-engineer/cli.py +146 -0
- package/roles/airworthiness-compliance-engineer/core/airworthiness_core.py +894 -0
- package/roles/airworthiness-compliance-engineer/templates/compliance-matrix-template.md +46 -0
- package/roles/airworthiness-compliance-engineer/tests/test_airworthiness_core.py +224 -0
- package/roles/airworthiness-compliance-engineer/tests/test_role_airworthiness.py +85 -0
- package/roles/as9100-quality-auditor/ROLE.md +128 -0
- package/roles/as9100-quality-auditor/SOURCES.md +16 -0
- package/roles/as9100-quality-auditor/cli.py +136 -0
- package/roles/as9100-quality-auditor/core/as9100_core.py +857 -0
- package/roles/as9100-quality-auditor/templates/findings-report-template.md +119 -0
- package/roles/as9100-quality-auditor/tests/test_as9100_cli_profile.py +105 -0
- package/roles/as9100-quality-auditor/tests/test_as9100_core.py +204 -0
- package/roles/as9100-quality-auditor/tests/test_role_as9100.py +90 -0
- package/roles/data-bus-avionics-engineer/ROLE.md +146 -0
- package/roles/data-bus-avionics-engineer/SOURCES.md +23 -0
- package/roles/data-bus-avionics-engineer/cli.py +311 -0
- package/roles/data-bus-avionics-engineer/core/data_bus_avionics_core.py +1121 -0
- package/roles/data-bus-avionics-engineer/templates/bus-assessment-template.md +134 -0
- package/roles/data-bus-avionics-engineer/tests/test_bundle_protocol.py +137 -0
- package/roles/data-bus-avionics-engineer/tests/test_data_bus_avionics_core.py +261 -0
- package/roles/data-bus-avionics-engineer/tests/test_role_data_bus_avionics_engineer.py +121 -0
- package/roles/do160-environmental-engineer/ROLE.md +136 -0
- package/roles/do160-environmental-engineer/SOURCES.md +30 -0
- package/roles/do160-environmental-engineer/cli.py +147 -0
- package/roles/do160-environmental-engineer/core/do160_environmental_core.py +1246 -0
- package/roles/do160-environmental-engineer/templates/environmental-qualification-plan-template.md +114 -0
- package/roles/do160-environmental-engineer/tests/test_do160_environmental_core.py +312 -0
- package/roles/do160-environmental-engineer/tests/test_role_do160_environmental_engineer.py +281 -0
- package/roles/do178c-cert-engineer/ROLE.md +120 -0
- package/roles/do178c-cert-engineer/SOURCES.md +16 -0
- package/roles/do178c-cert-engineer/cli.py +129 -0
- package/roles/do178c-cert-engineer/core/do178c_core.py +411 -0
- package/roles/do178c-cert-engineer/templates/psac-template.md +74 -0
- package/roles/do178c-cert-engineer/tests/test_do178c_cert_engineer_core.py +91 -0
- package/roles/do178c-cert-engineer/tests/test_role_do178c.py +109 -0
- package/roles/do254-hardware-engineer/ROLE.md +127 -0
- package/roles/do254-hardware-engineer/SOURCES.md +19 -0
- package/roles/do254-hardware-engineer/cli.py +308 -0
- package/roles/do254-hardware-engineer/core/do254_hardware_core.py +761 -0
- package/roles/do254-hardware-engineer/templates/phac-template.md +87 -0
- package/roles/do254-hardware-engineer/tests/test_do254_bundle_profile.py +152 -0
- package/roles/do254-hardware-engineer/tests/test_do254_hardware_core.py +200 -0
- package/roles/do254-hardware-engineer/tests/test_role_do254_hardware.py +108 -0
- package/roles/engineering-analysis-engineer/ROLE.md +154 -0
- package/roles/engineering-analysis-engineer/SOURCES.md +15 -0
- package/roles/engineering-analysis-engineer/cli.py +151 -0
- package/roles/engineering-analysis-engineer/core/engineering_analysis_engineer_core.py +866 -0
- package/roles/engineering-analysis-engineer/templates/analysis-memo-template.md +73 -0
- package/roles/engineering-analysis-engineer/tests/test_engineering_analysis_engineer_core.py +367 -0
- package/roles/engineering-analysis-engineer/tests/test_role_engineering_analysis_engineer.py +113 -0
- package/roles/flight-management-engineer/ROLE.md +160 -0
- package/roles/flight-management-engineer/SOURCES.md +30 -0
- package/roles/flight-management-engineer/cli.py +258 -0
- package/roles/flight-management-engineer/core/flight_management_core.py +1473 -0
- package/roles/flight-management-engineer/templates/route-assessment-template.md +94 -0
- package/roles/flight-management-engineer/tests/test_flight_management_core.py +437 -0
- package/roles/flight-management-engineer/tests/test_role_flight_management_engineer.py +123 -0
- package/roles/flight-mechanics-engineer/ROLE.md +162 -0
- package/roles/flight-mechanics-engineer/SOURCES.md +51 -0
- package/roles/flight-mechanics-engineer/cli.py +149 -0
- package/roles/flight-mechanics-engineer/core/flight_mechanics_core.py +1507 -0
- package/roles/flight-mechanics-engineer/templates/perf-sc-report-template.md +82 -0
- package/roles/flight-mechanics-engineer/tests/test_flight_mechanics_core.py +277 -0
- package/roles/flight-mechanics-engineer/tests/test_role_flight_mechanics_engineer.py +141 -0
- package/roles/flight-test-engineer/ROLE.md +137 -0
- package/roles/flight-test-engineer/SOURCES.md +24 -0
- package/roles/flight-test-engineer/cli.py +135 -0
- package/roles/flight-test-engineer/core/flight_test_core.py +931 -0
- package/roles/flight-test-engineer/templates/flight-test-template.md +143 -0
- package/roles/flight-test-engineer/tests/test_flight_test_engineer_core.py +227 -0
- package/roles/flight-test-engineer/tests/test_role_flight_test_engineer.py +150 -0
- package/roles/flight-test-performance-engineer/ROLE.md +165 -0
- package/roles/flight-test-performance-engineer/SOURCES.md +20 -0
- package/roles/flight-test-performance-engineer/cli.py +319 -0
- package/roles/flight-test-performance-engineer/core/flight_test_performance_core.py +1398 -0
- package/roles/flight-test-performance-engineer/templates/performance-report-template.md +105 -0
- package/roles/flight-test-performance-engineer/tests/test_flight_test_performance_engineer_core.py +308 -0
- package/roles/flight-test-performance-engineer/tests/test_role_flight_test_performance_engineer.py +165 -0
- package/roles/gnc-engineer/ROLE.md +141 -0
- package/roles/gnc-engineer/SOURCES.md +35 -0
- package/roles/gnc-engineer/cli.py +141 -0
- package/roles/gnc-engineer/core/gnc_core.py +1074 -0
- package/roles/gnc-engineer/templates/gnc-report-template.md +105 -0
- package/roles/gnc-engineer/tests/test_gnc_engineer_core.py +238 -0
- package/roles/gnc-engineer/tests/test_role_gnc_engineer.py +142 -0
- package/roles/guidance-engineer/ROLE.md +156 -0
- package/roles/guidance-engineer/SOURCES.md +43 -0
- package/roles/guidance-engineer/cli.py +280 -0
- package/roles/guidance-engineer/core/guidance_core.py +820 -0
- package/roles/guidance-engineer/templates/guidance-report-template.md +70 -0
- package/roles/guidance-engineer/tests/test_guidance_engineer_core.py +269 -0
- package/roles/guidance-engineer/tests/test_role_guidance_engineer.py +146 -0
- package/roles/high-speed-aerodynamics-engineer/ROLE.md +161 -0
- package/roles/high-speed-aerodynamics-engineer/SOURCES.md +18 -0
- package/roles/high-speed-aerodynamics-engineer/cli.py +282 -0
- package/roles/high-speed-aerodynamics-engineer/core/high_speed_aero_core.py +1566 -0
- package/roles/high-speed-aerodynamics-engineer/templates/high-speed-memo-template.md +75 -0
- package/roles/high-speed-aerodynamics-engineer/tests/test_bundle_protocol.py +103 -0
- package/roles/high-speed-aerodynamics-engineer/tests/test_high_speed_aero_core.py +280 -0
- package/roles/high-speed-aerodynamics-engineer/tests/test_role_high_speed_aerodynamics.py +125 -0
- package/roles/ndt-engineer/ROLE.md +157 -0
- package/roles/ndt-engineer/SOURCES.md +18 -0
- package/roles/ndt-engineer/cli.py +316 -0
- package/roles/ndt-engineer/core/ndt_core.py +1590 -0
- package/roles/ndt-engineer/templates/ndt-plan-template.md +109 -0
- package/roles/ndt-engineer/tests/test_ndt_cli_bundle.py +183 -0
- package/roles/ndt-engineer/tests/test_ndt_core.py +437 -0
- package/roles/ndt-engineer/tests/test_role_ndt_engineer.py +148 -0
- package/roles/numerical-analysis-engineer/ROLE.md +158 -0
- package/roles/numerical-analysis-engineer/SOURCES.md +19 -0
- package/roles/numerical-analysis-engineer/cli.py +414 -0
- package/roles/numerical-analysis-engineer/core/numerical_analysis_core.py +1220 -0
- package/roles/numerical-analysis-engineer/templates/verification-memo-template.md +120 -0
- package/roles/numerical-analysis-engineer/tests/test_bundle_protocol.py +157 -0
- package/roles/numerical-analysis-engineer/tests/test_numerical_analysis_core.py +337 -0
- package/roles/numerical-analysis-engineer/tests/test_role_numerical_analysis_engineer.py +117 -0
- package/roles/propulsion-engineer/ROLE.md +163 -0
- package/roles/propulsion-engineer/SOURCES.md +15 -0
- package/roles/propulsion-engineer/cli.py +168 -0
- package/roles/propulsion-engineer/core/propulsion_core.py +1291 -0
- package/roles/propulsion-engineer/templates/propulsion-report-template.md +92 -0
- package/roles/propulsion-engineer/tests/test_propulsion_engineer_core.py +294 -0
- package/roles/propulsion-engineer/tests/test_role_propulsion_engineer.py +106 -0
- package/roles/space-systems-engineer/ROLE.md +161 -0
- package/roles/space-systems-engineer/SOURCES.md +49 -0
- package/roles/space-systems-engineer/cli.py +173 -0
- package/roles/space-systems-engineer/core/space_systems_core.py +980 -0
- package/roles/space-systems-engineer/templates/space-systems-template.md +88 -0
- package/roles/space-systems-engineer/tests/test_role_space_systems_engineer.py +117 -0
- package/roles/space-systems-engineer/tests/test_space_systems_engineer_core.py +247 -0
- package/roles/state-estimation-engineer/ROLE.md +154 -0
- package/roles/state-estimation-engineer/SOURCES.md +27 -0
- package/roles/state-estimation-engineer/cli.py +326 -0
- package/roles/state-estimation-engineer/core/state_estimation_core.py +958 -0
- package/roles/state-estimation-engineer/templates/nav-state-estimator-design-template.md +76 -0
- package/roles/state-estimation-engineer/tests/test_bundle_protocol.py +110 -0
- package/roles/state-estimation-engineer/tests/test_role_state_estimation_engineer.py +127 -0
- package/roles/state-estimation-engineer/tests/test_state_estimation_engineer_core.py +231 -0
- package/roles/structures-loads-engineer/ROLE.md +171 -0
- package/roles/structures-loads-engineer/SOURCES.md +44 -0
- package/roles/structures-loads-engineer/cli.py +219 -0
- package/roles/structures-loads-engineer/core/structures_loads_core.py +1112 -0
- package/roles/structures-loads-engineer/templates/loads-strength-report-template.md +96 -0
- package/roles/structures-loads-engineer/tests/test_bundle_protocol.py +101 -0
- package/roles/structures-loads-engineer/tests/test_role_structures_loads_engineer.py +147 -0
- 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()
|