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,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()
|