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,117 @@
1
+ #!/usr/bin/env python3
2
+ """Role test: Numerical Analysis Engineer.
3
+
4
+ Verifies (offline, no network):
5
+ 1. Every skill bound in ROLE.md frontmatter RESOLVES to a real leaf in
6
+ the aero-agent-skills repo (the pinned skills_release band).
7
+ 2. The workflow stage order is deterministic and complete.
8
+ 3. The filled deliverable template is present with no blanks and the
9
+ boundary markers.
10
+ """
11
+ import os
12
+ import re
13
+ import unittest
14
+
15
+ ROLES_REPO = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(
16
+ os.path.abspath(__file__))))) # repo root (4 up from tests/)
17
+ # Bound-skill resolution requires the Aero Agent Skills checkout. It is a
18
+ # cross-repo dev check: when the skills repo is absent (fresh public clone),
19
+ # skip resolution rather than fail - the role's bound list is verified in CI.
20
+ AEROSKILLS = os.environ.get("AEROSKILLS_DEV", os.path.expanduser("~/AeroSkills"))
21
+ HAS_SKILLS = os.path.isdir(os.path.join(AEROSKILLS, "skills"))
22
+ ROLE_DIR = os.path.join(ROLES_REPO, "roles", "numerical-analysis-engineer")
23
+ TEMPLATE = os.path.join(ROLE_DIR, "templates", "verification-memo-template.md")
24
+
25
+ EXPECTED_BOUND = [
26
+ "cross-cutting/numerics/numerical-integration",
27
+ "cross-cutting/numerics/root-finding",
28
+ "cross-cutting/numerics/convergence-verification",
29
+ "cross-cutting/numerics/finite-difference-derivatives",
30
+ "cross-cutting/numerics/ode-solvers",
31
+ "cross-cutting/numerics/interpolation",
32
+ "cross-cutting/numerics/least-squares-regression",
33
+ "cross-cutting/numerics/matrix-operations",
34
+ "cross-cutting/numerics/singular-value-decomposition",
35
+ "cross-cutting/numerics/uncertainty-propagation",
36
+ ]
37
+
38
+ EXPECTED_STAGES = [
39
+ "Integration", "Root finding", "Derivatives", "ODE paths",
40
+ "Interpolation paths", "Regression paths", "Linear solve",
41
+ "Convergence", "Error budget", "Memo build",
42
+ ]
43
+
44
+
45
+ def read_role_md():
46
+ p = os.path.join(ROLE_DIR, "ROLE.md")
47
+ if not os.path.exists(p):
48
+ return None
49
+ return open(p).read()
50
+
51
+
52
+ class TestNumericalAnalysisEngineerRole(unittest.TestCase):
53
+
54
+ def test_bound_skills_resolve_in_aeroskills(self):
55
+ if not HAS_SKILLS:
56
+ self.skipTest("Aero Agent Skills checkout not present "
57
+ "(cross-repo dev check)")
58
+ for leaf in EXPECTED_BOUND:
59
+ sk = os.path.join(AEROSKILLS, "skills", leaf, "SKILL.md")
60
+ self.assertTrue(
61
+ os.path.exists(sk),
62
+ f"bound skill not found in aero-agent-skills: {leaf}")
63
+ logic = os.path.join(AEROSKILLS, "skills", leaf, "scripts")
64
+ self.assertTrue(
65
+ any(f.endswith("_logic.py")
66
+ for f in os.listdir(logic)),
67
+ f"bound leaf ships no logic file: {leaf}")
68
+
69
+ def test_bound_skills_listed_in_frontmatter(self):
70
+ role = read_role_md()
71
+ self.assertIsNotNone(role)
72
+ for leaf in EXPECTED_BOUND:
73
+ self.assertIn(leaf, role,
74
+ f"missing in ROLE.md skills_bound: {leaf}")
75
+
76
+ def test_workflow_stages_deterministic(self):
77
+ role = read_role_md()
78
+ # every expected stage appears in order (indexes ascending)
79
+ idx = [role.find(stage) for stage in EXPECTED_STAGES]
80
+ self.assertTrue(all(i >= 0 for i in idx), "a stage is missing")
81
+ self.assertEqual(idx, sorted(idx), "stage order not deterministic")
82
+
83
+ def test_deliverable_template_complete(self):
84
+ if not os.path.exists(TEMPLATE):
85
+ self.fail("verification-memo-template.md missing")
86
+ with open(TEMPLATE) as fh:
87
+ text = fh.read()
88
+ # all 6 numbered sections present
89
+ for n in range(1, 7):
90
+ self.assertTrue(
91
+ re.search(rf"^## {n}\. ", text, re.M),
92
+ f"section {n} missing")
93
+ self.assertIn("DRAFT", text)
94
+ low = text.lower()
95
+ self.assertIn("not an approval", low)
96
+ self.assertIn("Numerical Methods Verification Memo", text)
97
+ self.assertNotIn("___", text) # filled deliverable, zero blanks
98
+
99
+ def test_forbidden_lines_present(self):
100
+ role = read_role_md()
101
+ for phrase in ["issue engineering approval", "declare compliance",
102
+ "sign_off_required: true", "reproduce proprietary"]:
103
+ self.assertIn(phrase, role, f"missing boundary: {phrase}")
104
+
105
+ def test_sources_register_exists(self):
106
+ p = os.path.join(ROLE_DIR, "SOURCES.md")
107
+ self.assertTrue(os.path.exists(p), "SOURCES.md missing for role")
108
+
109
+ def test_core_engine_exists(self):
110
+ """100% standard: every role ships an executable core + cli."""
111
+ for f in ["core", "cli.py"]:
112
+ self.assertTrue(os.path.exists(os.path.join(ROLE_DIR, f)),
113
+ f"{f} missing - role is not executable")
114
+
115
+
116
+ if __name__ == "__main__":
117
+ unittest.main()
@@ -0,0 +1,163 @@
1
+ ---
2
+ type: role
3
+ name: propulsion-engineer
4
+ title: "Propulsion Engineer"
5
+ status: draft
6
+ domain: propulsion
7
+ deliverable_type: "propulsion system design + cycle analysis report"
8
+ standards_bound:
9
+ - id: far-33
10
+ tier: TIER-1
11
+ reference-only: false
12
+ skills_bound:
13
+ - propulsion/gas-turbine-cycle/gas-turbine-cycle
14
+ - propulsion/gas-turbine-cycle/real-cycle-effects
15
+ - propulsion/gas-turbine-cycle/afterburner-cycle
16
+ - propulsion/gas-turbine-cycle/regenerative-cycle
17
+ - propulsion/gas-turbine-cycle/propelling-nozzle
18
+ - propulsion/gas-turbine-cycle/subsonic-inlet-recovery
19
+ - propulsion/gas-turbine-cycle/combustor-design
20
+ - propulsion/turbofan/turbofan-cycle
21
+ - propulsion/turbofan/bypass-ratio-trade
22
+ - propulsion/turbofan/turbofan-off-design
23
+ - propulsion/turboprop/turboprop-cycle
24
+ - propulsion/turboprop/free-turbine
25
+ - propulsion/axial-compressor/axial-compressor-stage
26
+ - propulsion/axial-compressor/compressor-map
27
+ - propulsion/axial-compressor/multi-stage-compressor
28
+ - propulsion/axial-compressor/turbine-stage
29
+ - propulsion/axial-compressor/turbine-blade-cooling
30
+ - propulsion/engine-airframe/engine-airframe-integration
31
+ - propulsion/rocket/rocket-engine-cycle
32
+ - propulsion/rocket/nozzle-design
33
+ - propulsion/rocket/combustion-chamber-design
34
+ - propulsion/rocket/injector-design
35
+ - propulsion/rocket/propellant-selection
36
+ - propulsion/rocket/solid-rocket-motor
37
+ - propulsion/rocket/hybrid-rocket-motor
38
+ - propulsion/rocket/thrust-chamber-cooling
39
+ - propulsion/rocket/thrust-vector-control
40
+ - propulsion/rocket/cold-gas-thruster
41
+ - propulsion/combustion/cea-rocket-combustion
42
+ - propulsion/electric/hall-thruster
43
+ - propulsion/electric/gridded-ion-thruster
44
+ - propulsion/electric/electrothermal-thruster
45
+ - propulsion/ramjet/ramjet-cycle
46
+ - propulsion/ramjet/ramjet-inlet
47
+ tools_allowed: [stdlib, offline-file-processing, cea-cli]
48
+ forbidden:
49
+ - "claim certification approval"
50
+ - "release an engine for production"
51
+ - "reproduce proprietary standard text"
52
+ sign_off_required: true
53
+ license: Apache-2.0
54
+ compatibility: "agentskills.io ROLE.md; any SKILL.md host"
55
+ metadata:
56
+ version: 1.0.0
57
+ author: Aero Agent Roles
58
+ skills_release: "v1.3.0+"
59
+ ---
60
+
61
+ # Propulsion Engineer
62
+
63
+ ## Role identity
64
+
65
+ Owns propulsion system selection and cycle design: gas turbine cycle
66
+ analysis (turbofan/turboprop/turbojet), component matching (compressor,
67
+ turbine, combustor, nozzle), engine-airframe integration, and the rocket
68
+ or electric propulsion trades for non-airbreathing applications. Use
69
+ when a vehicle needs a propulsion solution with a defensible cycle,
70
+ specific fuel consumption, thrust, and integration answer. Do NOT use
71
+ for structural or certification workflow (separate roles).
72
+
73
+ ## Deliverable contract
74
+
75
+ 1. **Propulsion design report** - selected cycle + rationale, on-design
76
+ and off-design performance, component choices, fuel burn, integration
77
+ notes (inlet, nozzle, nacelle), or rocket/electric trade for space.
78
+ 2. **Cycle analysis evidence** - the thermodynamic calculations,
79
+ component maps, and trade studies supporting the selection.
80
+
81
+ The filled deliverable for the reference item (a BPR-8 / OPR-30 /
82
+ TIT-1650 K high-bypass turbofan at M0.78 / FL350) is
83
+ `templates/propulsion-report-template.md` - generated by the core,
84
+ zero blanks: station state table, net thrust, TSFC/SFC, efficiencies,
85
+ off-design envelope, component table, integration, and the bypass
86
+ trade. Rocket-cycle evidence for space items is generated the same way
87
+ with the `--engine rocket` variant.
88
+
89
+ ## Workflow (stages -> bound skills)
90
+
91
+ | Stage | Loads skill | Produces |
92
+ |---|---|---|
93
+ | 1. Airbreathing cycle | gas-turbine-cycle + real-cycle-effects + turbofan-cycle + turboprop-cycle | cycle on-design: thrust, SFC, thermal efficiency |
94
+ | 2. Bypass/regenerative/AB trades | bypass-ratio-trade + regenerative-cycle + afterburner-cycle | configuration trade |
95
+ | 3. Off-design | turbofan-off-design | performance across envelope |
96
+ | 4. Components | compressor-map + multi-stage-compressor + turbine-stage + combustor-design + propelling-nozzle + subsonic-inlet-recovery + free-turbine | component maps + matching |
97
+ | 5. Turbine cooling | turbine-blade-cooling | cooling flow requirement |
98
+ | 6. Integration | engine-airframe-integration | installation + ram drag + bleed |
99
+ | 7. Rocket cycle | rocket-engine-cycle + nozzle-design + combustion-chamber-design + injector-design + propellant-selection | rocket cycle, Isp, chamber conditions |
100
+ | 8. Solid/hybrid | solid-rocket-motor + hybrid-rocket-motor | motor option |
101
+ | 9. Cooling/TVC | thrust-chamber-cooling + thrust-vector-control + cold-gas-thruster | cooling + control solution |
102
+ | 10. Combustion | cea-rocket-combustion | equilibrium products |
103
+ | 11. Electric | hall-thruster + gridded-ion-thruster + electrothermal-thruster | electric propulsion trade |
104
+ | 12. Ramjet | ramjet-cycle + ramjet-inlet | ramjet option |
105
+ | 13. Report | (all above) | the propulsion design report |
106
+
107
+ ## Evidence gates
108
+
109
+ - Stage 1 done = cycle state points complete (T, p, efficiency), SFC +
110
+ thrust with the input assumptions stated.
111
+ - Stage 3 done = off-design map covers the operating envelope.
112
+ - Stage 7 done = Isp and chamber conditions from an equilibrium or
113
+ accepted method; propellant choice has a rationale.
114
+ - FINAL = every performance claim traces to a calculation.
115
+
116
+ The core's `check_report` gate applies these: requirement present,
117
+ cycle identified, station state points complete, net thrust computed,
118
+ TSFC/SFC computed, assumptions stated, and the document marked
119
+ draft-for-review.
120
+
121
+ ## Boundary / forbidden
122
+
123
+ - NEVER claim certification approval or release an engine.
124
+ - Component maps are representative input, not vendor data unless the
125
+ vendor source is cited.
126
+ - Electric/rocket performance assumes stated inputs (Isp, efficiency,
127
+ chamber Tc/gamma/R to be confirmed by equilibrium CEA); never assert a
128
+ vendor product spec without a source.
129
+ - Output is a DRAFT for human review - mark it draft.
130
+
131
+ ## Verification
132
+
133
+ The role runs STANDALONE: `core/propulsion_core.py` is an executable
134
+ engine that computes the ISA atmosphere, the ideal/real gas-turbine
135
+ relations, the separate-stream turbofan on-design cycle (station state
136
+ table, net thrust F = sum mdot*(V9-V0) + (P9-P0)*A9, TSFC, efficiency
137
+ decomposition), the off-design envelope with corrected-flow matching
138
+ and compressor-map verdicts, the bypass-ratio trade, and the rocket
139
+ feed-cycle/nozzle analysis. No AeroSkills checkout required.
140
+
141
+ Run the role:
142
+ ```bash
143
+ python3 cli.py build --out report.md # turbofan report
144
+ python3 cli.py build --engine rocket --out rocket.md # rocket option
145
+ python3 cli.py build --bpr 6 --opr 25 --tit 1600 # cycle variants
146
+ python3 cli.py check --file report.md # gate-check
147
+ ```
148
+
149
+ Tests:
150
+ - tests/test_propulsion_engineer_core.py (26 tests): domain rules +
151
+ on-design builder + off-design + rocket + gates + standalone (no
152
+ skills repo)
153
+ - tests/test_role_propulsion_engineer.py: bound-skill resolution
154
+ (skips if the skills repo is absent) + workflow + template + boundaries
155
+
156
+ Bound skills in Aero Agent Skills deepen individual stages when the
157
+ library is present (component maps, CEA equilibrium, turbine cooling,
158
+ TVC); the core engine does not depend on them.
159
+
160
+ ## Compliance
161
+
162
+ - far-33 TIER-1 context. Data references summary-not-copy.
163
+ - SOURCES.md records standards referenced.
@@ -0,0 +1,15 @@
1
+ # SOURCES.md - Propulsion Engineer
2
+
3
+ | Source | Role use | Gated |
4
+ |---|---|---|
5
+ | 14 CFR Part 33 | engine certification context | false |
6
+ | Mattingly, Aircraft Engine Design | cycle analysis methodology (book) | true |
7
+ | Hill & Peterson, Mechanics and Thermodynamics of Propulsion | propulsion fundamentals (book) | true |
8
+ | Sutton, Rocket Propulsion Elements | rocket propulsion reference (book) | true |
9
+ | NASA CEA documentation | equilibrium combustion tooling | false |
10
+ | AeroSkills propulsion leaves (gas-turbine-cycle, real-cycle-effects, turbofan-cycle, bypass-ratio-trade, turbofan-off-design, compressor-map, propelling-nozzle, rocket-engine-cycle, nozzle-design) | domain rules and reference-typical values encoded in core/propulsion_core.py: Brayton/real-cycle relations and anchors, choked-flow and area-Mach relations, standard-day corrections, surge-margin definitions, throttle bands, rocket propellant table (LOX/RP-1, LOX/LH2, N2O4/MMH, hydrazine) and feed-cycle chamber-pressure bounds | false (offline mirrors) |
11
+
12
+ Summary-not-copy per STANDARDS.md. The core encodes the *relations*
13
+ (summary of common propulsion methodology) with reference-typical
14
+ values used in the bound leaves; no leaf script is imported and no
15
+ proprietary text is reproduced.
@@ -0,0 +1,168 @@
1
+ #!/usr/bin/env python3
2
+ """cli.py - run the Propulsion Engineer role.
3
+
4
+ Usage:
5
+ python3 cli.py build --out <file.md> # turbofan design report
6
+ python3 cli.py build --engine rocket --out r.md # rocket option report
7
+ python3 cli.py build --engine turbofan --bpr 6 --opr 25 # parameter sweep
8
+ python3 cli.py build --out <file.md> --bundle # + evidence/{model,gates,provenance}.json
9
+ python3 cli.py build --out <file.md> --profile profiles/example-airframer.json --bundle
10
+ python3 cli.py check --file <file.md> # gate-check a report
11
+
12
+ The role ENGINE (core/propulsion_core.py) does the work standalone; bound
13
+ skills in Aero Agent Skills deepen individual stages when present. With
14
+ --bundle the CLI also writes the PROTOCOL.md v1 evidence bundle
15
+ (evidence/{model,gates,provenance}.json) next to the deliverable. With
16
+ --profile <profile.json> the program context header
17
+ (docs/PROFILE-SCHEMA.md) is prepended to the report and profile.* is
18
+ recorded in the bundle model.
19
+ """
20
+ import argparse
21
+ import os
22
+ import sys
23
+
24
+ sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "core"))
25
+ sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
26
+ "..", "..", "scripts"))
27
+ import propulsion_core as core # noqa: E402
28
+ import evidence # noqa: E402
29
+
30
+ ROLE_SLUG = "propulsion-engineer"
31
+
32
+
33
+ def _provenance(model):
34
+ """Provenance for the evidence bundle (PROTOCOL.md v1).
35
+
36
+ The propulsion role core computes every number standalone (cycle,
37
+ envelope, trade, rocket sizing); no bound skill logic is dispatched,
38
+ so the skills list is empty and the bundle is not cross-checked.
39
+ """
40
+ return {
41
+ "role": ROLE_SLUG,
42
+ "core": {
43
+ "file": "core/propulsion_core.py",
44
+ "functions": ["turbofan_design_point", "off_design_envelope",
45
+ "bpr_trend", "rocket_engine_cycle_analysis",
46
+ "rocket_nozzle_sizing"],
47
+ "version": "0.1.0",
48
+ },
49
+ "skills": [],
50
+ "cross_checked": False,
51
+ "disclaimer": "DRAFT for human review. Not an approval document.",
52
+ }
53
+
54
+
55
+ def _apply_overrides(item, args):
56
+ if args.bpr is not None:
57
+ item.bpr = args.bpr
58
+ if args.opr is not None:
59
+ item.opr = args.opr
60
+ if args.tit is not None:
61
+ item.tit_k = args.tit
62
+ if args.fpr is not None:
63
+ item.fpr = args.fpr
64
+ if args.thrust is not None:
65
+ item.thrust_requirement_n = args.thrust * 1000.0
66
+ if args.engine == "rocket":
67
+ if args.thrust is not None:
68
+ item.thrust_vac_n = args.thrust * 1000.0
69
+ return item
70
+
71
+
72
+ def cmd_build(args):
73
+ if args.engine == "rocket":
74
+ item = core.example_rocket_item()
75
+ else:
76
+ item = core.example_turbofan_item()
77
+ item = _apply_overrides(item, args)
78
+ model = core.build_report(item)
79
+ md = core.render_report_markdown(model)
80
+
81
+ # program profile (customer tailoring): load + apply context header
82
+ profile = None
83
+ try:
84
+ profile = evidence.load_profile(args.profile)
85
+ except ValueError as e:
86
+ print(f"error: bad profile: {e}")
87
+ return 1
88
+ if profile:
89
+ model["profile"] = {
90
+ "customer": profile.get("customer"),
91
+ "program": profile.get("program"),
92
+ "basis": profile.get("basis"),
93
+ "authority": profile.get("authority"),
94
+ "der": profile.get("der"),
95
+ "document_prefix": profile.get("document_prefix"),
96
+ "revision": profile.get("revision"),
97
+ }
98
+ md = evidence.profile_header_block(profile) + md
99
+
100
+ gates = core.check_report(model)
101
+ if args.out:
102
+ with open(args.out, "w") as f:
103
+ f.write(md)
104
+ kind = model["engine_kind"]
105
+ print(f"built {kind} design report -> {args.out}")
106
+ if profile:
107
+ print(f"profile: {profile.get('customer')} / "
108
+ f"{profile.get('program')}")
109
+ print(f"gates: all_pass={gates['all_pass']} {gates}")
110
+ if args.bundle:
111
+ prov = _provenance(model)
112
+ paths = evidence.write_bundle(
113
+ args.out, ROLE_SLUG, "propulsion design report",
114
+ model, dict(gates, checker="check_report"), prov)
115
+ print(f"bundle: model={paths['model']}")
116
+ print(f" gates={paths['gates']}")
117
+ print(f" provenance={paths['provenance']}")
118
+ else:
119
+ print(md)
120
+ return 0 if gates["all_pass"] else 1
121
+
122
+
123
+ def cmd_check(args):
124
+ if not os.path.exists(args.file):
125
+ print(f"file not found: {args.file}")
126
+ return 1
127
+ md = open(args.file).read()
128
+ gates = core.check_report_markdown(md)
129
+ for name, ok in gates.items():
130
+ if name != "all_pass":
131
+ print(f"{'PASS' if ok else 'FAIL'} {name}")
132
+ print(f"RESULT: {'PASS' if gates['all_pass'] else 'FAIL'}")
133
+ return 0 if gates["all_pass"] else 1
134
+
135
+
136
+ def main():
137
+ p = argparse.ArgumentParser(description="Propulsion Engineer role")
138
+ sub = p.add_subparsers(dest="cmd", required=True)
139
+
140
+ b = sub.add_parser("build")
141
+ b.add_argument("--out", default="", help="output file (default: stdout)")
142
+ b.add_argument("--engine", default="turbofan",
143
+ choices=["turbofan", "rocket"],
144
+ help="engine class for the reference item")
145
+ b.add_argument("--bpr", type=float, default=None, help="bypass ratio")
146
+ b.add_argument("--opr", type=float, default=None, help="overall pressure ratio")
147
+ b.add_argument("--tit", type=float, default=None, help="turbine inlet temp (K)")
148
+ b.add_argument("--fpr", type=float, default=None, help="fan pressure ratio")
149
+ b.add_argument("--thrust", type=float, default=None,
150
+ help="thrust requirement (kN)")
151
+ b.add_argument("--bundle", action="store_true",
152
+ help="emit evidence/{model,gates,provenance}.json "
153
+ "(PROTOCOL.md v1, requires --out)")
154
+ b.add_argument("--profile", default="",
155
+ help="program profile JSON (customer tailoring, "
156
+ "docs/PROFILE-SCHEMA.md)")
157
+ b.set_defaults(fn=cmd_build)
158
+
159
+ c = sub.add_parser("check")
160
+ c.add_argument("--file", required=True, help="report markdown to gate-check")
161
+ c.set_defaults(fn=cmd_check)
162
+
163
+ args = p.parse_args()
164
+ sys.exit(args.fn(args))
165
+
166
+
167
+ if __name__ == "__main__":
168
+ main()