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,46 @@
1
+ # Airworthiness Compliance Matrix
2
+
3
+ **Item:** Autopilot flight guidance system retrofit (STC)
4
+ **Aircraft type:** transport (jurisdiction FAA)
5
+ **Certification basis:** FAR-25
6
+ **Certification path:** STC
7
+ **Applicable regulations (proposed):** 25.1301, 25.1309, 25.1329, 25.671, 25.683
8
+ **Special conditions:** none identified
9
+ **Equivalent level of safety (ELOS) findings:** none proposed
10
+ **Status:** draft-for-review
11
+ **Coverage:** 100% of applicable regulations have a proposed means of compliance and compliance document
12
+
13
+ ## Certification basis
14
+
15
+ - Aircraft/system: Autopilot flight guidance system retrofit (STC)
16
+ - Certification basis reference (TC/STC/amendment level): FAR-25, STC
17
+ - Applicable regulations (list with amendment): 25.1301, 25.1309, 25.1329, 25.671, 25.683 (amendment level per the basis)
18
+ - Special conditions: none identified
19
+ - Equivalent level of safety findings: none proposed
20
+
21
+ ## Compliance matrix
22
+
23
+ | Reg | Applicable? | Means of compliance | Compliance document | Status (proposed/open) | Owner |
24
+ |---|---|---|---|---|---|
25
+ | 25.1301 (Subpart F - Equipment) | YES | ground test + engineering/analysis | Equipment installation inspection records and qualification test report (installation conformity) | proposed (severity n/a / DAL n/a) | equipment engineer |
26
+ | 25.1309 (Subpart F - Equipment) | YES | engineering/analysis + safety assessment (safety assessment required) | System safety assessment (SSA) per 25.1309 with failure condition classification | proposed (severity hazardous / DAL B) | systems safety engineer |
27
+ | 25.1329 (Subpart F - Equipment) | YES | engineering/analysis + safety assessment + ground test + flight test (safety assessment required) | Autopilot ground/flight test report and SSA input for the flight guidance system | proposed (severity hazardous / DAL B) | systems safety engineer |
28
+ | 25.671 (Subpart D - Design and Construction) | YES | engineering/analysis + safety assessment (safety assessment required) | Flight control integration analysis and test report (control system failure assessment) | proposed (severity hazardous / DAL B) | flight controls engineer |
29
+ | 25.683 (Subpart D - Design and Construction) | YES | engineering/analysis + ground test | Control system operation test report | proposed (severity n/a / DAL n/a) | flight controls engineer |
30
+ | 25.301 (Subpart C - Structure) | NO | n/a | not required (screened out: not applicable to this change: 25.301 covers the structure area but the change scope is limited to equipment, flight-controls, systems; screened out unless the change also touches the structure area - confirm with the certification authority) | proposed (n/a) | - |
31
+ | 25.571 (Subpart C - Structure) | NO | n/a | not required (screened out: not applicable to this change: 25.571 covers the structure area but the change scope is limited to equipment, flight-controls, systems; screened out unless the change also touches the structure area - confirm with the certification authority) | proposed (n/a) | - |
32
+ | 25.607 (Subpart D - Design and Construction) | NO | n/a | not required (screened out: not applicable to this change: 25.607 covers the design-and-construction area but the change scope is limited to equipment, flight-controls, systems; screened out unless the change also touches the design-and-construction area - confirm with the certification authority) | proposed (n/a) | - |
33
+
34
+ ## Notes
35
+
36
+ - Status vocabulary: proposed | open | in-work | evidence-available.
37
+ - Every row above is a PROPOSED determination by the compliance engineer (this role). The certification authority makes the binding applicability and compliance findings.
38
+ - NEVER mark a row "compliant/found" without evidence - that is the authority's finding, not ours.
39
+ - Severity and DAL context are proposed inputs to the 25.1309 safety assessment, subject to the system safety process.
40
+
41
+ ## Open items (gap report)
42
+
43
+ - No open gaps in this draft; confirm every row with the certification authority before submission.
44
+
45
+ ---
46
+ *Generated by Aero Agent Roles airworthiness-compliance-engineer core (2026-09-05). DRAFT - for human compliance engineer review. Not a compliance finding or an approval.*
@@ -0,0 +1,224 @@
1
+ #!/usr/bin/env python3
2
+ """Test airworthiness_core: the executable engine of the
3
+ airworthiness-compliance-engineer role.
4
+
5
+ Proves the role can DO its job standalone (no AeroSkills needed):
6
+ applicability determination, means-of-compliance selection, compliance
7
+ matrix generation, and evidence-gate checks.
8
+
9
+ Author: ashfordeOU
10
+ """
11
+ import os
12
+ import sys
13
+ import unittest
14
+
15
+ sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
16
+ "..", "core"))
17
+ from airworthiness_core import ( # noqa: E402
18
+ MOC_IDS, MOC_NAMES, REGS, SEVERITY_TO_DAL,
19
+ build_matrix, check_matrix, check_matrix_markdown,
20
+ compliance_row, determine_applicability, example_item,
21
+ example_matrix_markdown, moc_is_valid, moc_suitability,
22
+ render_matrix_markdown, safety_assessment_required, select_moc,
23
+ severity_to_dal,
24
+ )
25
+
26
+
27
+ class TestCoreDomainRules(unittest.TestCase):
28
+
29
+ def test_severity_to_dal_mapping(self):
30
+ self.assertEqual(SEVERITY_TO_DAL["catastrophic"], "A")
31
+ self.assertEqual(SEVERITY_TO_DAL["hazardous"], "B")
32
+ self.assertEqual(SEVERITY_TO_DAL["major"], "C")
33
+ self.assertEqual(SEVERITY_TO_DAL["minor"], "D")
34
+ self.assertEqual(severity_to_dal("hazardous"), "B")
35
+
36
+ def test_safety_assessment_rule(self):
37
+ # 25.1309 practice: catastrophic/hazardous/major need the SSA.
38
+ self.assertTrue(safety_assessment_required("catastrophic"))
39
+ self.assertTrue(safety_assessment_required("hazardous"))
40
+ self.assertTrue(safety_assessment_required("major"))
41
+ self.assertFalse(safety_assessment_required("minor"))
42
+ self.assertFalse(safety_assessment_required("no-safety-effect"))
43
+ with self.assertRaises(ValueError):
44
+ safety_assessment_required("very-bad")
45
+
46
+ def test_moc_suitability_rules(self):
47
+ # Structure: analysis primary, static/ground test evidence.
48
+ self.assertEqual(moc_suitability("structure", "n/a", "n/a"), [1, 2])
49
+ # Novel structure adds flight test.
50
+ self.assertEqual(
51
+ moc_suitability("structure", "n/a", "n/a", novel=True), [1, 2, 3])
52
+ # Hazardous systems: analysis + MOC 6 safety assessment.
53
+ self.assertEqual(
54
+ moc_suitability("systems", "hazardous", "B"), [1, 6])
55
+ # Equipment: qualification ground test with analysis support.
56
+ self.assertEqual(moc_suitability("equipment"), [2, 1])
57
+ with self.assertRaises(ValueError):
58
+ moc_suitability("quantum", "n/a", "n/a")
59
+
60
+ def test_real_regs_are_real(self):
61
+ # Regs in the register must be real FAR-25 paragraphs (public
62
+ # domain; register verified against the public eCFR titles).
63
+ for number, rec in REGS.items():
64
+ self.assertRegex(number, r"^25\.\d{3,4}$")
65
+ self.assertTrue(rec["title"])
66
+ self.assertIn(rec["subpart"], "ABCDEFGH")
67
+ for num in ("25.1309", "25.1329", "25.301", "25.571",
68
+ "25.607", "25.683", "25.671", "25.1301"):
69
+ self.assertIn(num, REGS)
70
+
71
+ def test_applicability_transport(self):
72
+ verdict = determine_applicability("25.1309", "transport")
73
+ self.assertTrue(verdict["applicable"])
74
+ verdict2 = determine_applicability("25.1329", "transport-category")
75
+ self.assertTrue(verdict2["applicable"])
76
+
77
+ def test_applicability_not_transport(self):
78
+ # Part 25 paragraphs do not apply to a normal-category airplane
79
+ # (that certifies under Part 23 / CS-23).
80
+ verdict = determine_applicability("25.1309", "normal")
81
+ self.assertFalse(verdict["applicable"])
82
+ self.assertIn("Part 23", verdict["reason"])
83
+ with self.assertRaises(ValueError):
84
+ determine_applicability("25.1309", "airship")
85
+ with self.assertRaises(ValueError):
86
+ determine_applicability("99.9999", "transport")
87
+ with self.assertRaises(ValueError):
88
+ determine_applicability("25.9999", "transport")
89
+
90
+ def test_applicability_change_scope(self):
91
+ # Structure paragraphs screen out when the STC touches only
92
+ # systems/flight-controls/equipment.
93
+ scope = ["systems", "flight-controls", "equipment"]
94
+ self.assertTrue(
95
+ determine_applicability("25.1309", "transport", scope)["applicable"])
96
+ self.assertFalse(
97
+ determine_applicability("25.571", "transport", scope)["applicable"])
98
+ self.assertFalse(
99
+ determine_applicability("25.301", "transport", scope)["applicable"])
100
+
101
+
102
+ class TestMocSelection(unittest.TestCase):
103
+
104
+ def test_select_moc_far25_vocabulary(self):
105
+ moc = select_moc("25.1309", "FAR-25")
106
+ self.assertEqual(moc["reg"], "25.1309")
107
+ self.assertEqual(moc["item_kind"], "systems")
108
+ self.assertEqual(moc["dal"], "B") # hazardous context
109
+ self.assertTrue(moc["safety_assessment"])
110
+ # Real vocabulary words only.
111
+ for m in moc["methods"]:
112
+ self.assertTrue(moc_is_valid(m))
113
+ self.assertIn("analysis", moc["moc_display"])
114
+ self.assertIn("safety assessment", moc["moc_display"])
115
+
116
+ def test_select_moc_cs25_scheme(self):
117
+ moc = select_moc("25.1309", "CS-25")
118
+ self.assertIn("MOC", moc["moc_display"])
119
+ self.assertIn("MOC 6 safety assessment", moc["moc_display"])
120
+ # ids must all be real MOC class ids
121
+ for i in moc["moc_ids"]:
122
+ self.assertIn(i, MOC_IDS)
123
+
124
+ def test_select_moc_extras_and_novelty(self):
125
+ # Autopilot flight guidance is novel on the type: ground test is
126
+ # added; the reg carries flight test from demonstration practice.
127
+ moc = select_moc("25.1329", "FAR-25", novel=True)
128
+ self.assertIn("flight test", moc["methods"])
129
+ self.assertIn(2, moc["moc_ids"]) # test MOC present for novel item
130
+ # 25.683 operation tests carries a ground test MOC.
131
+ moc683 = select_moc("25.683", "FAR-25")
132
+ self.assertIn("ground test", moc683["methods"])
133
+
134
+ def test_moc_names_real(self):
135
+ self.assertEqual(MOC_NAMES[1], "engineering/analysis")
136
+ self.assertEqual(MOC_NAMES[5], "certification by similarity")
137
+ self.assertEqual(MOC_NAMES[6], "safety assessment")
138
+ self.assertFalse(moc_is_valid("quantum compliance"))
139
+ with self.assertRaises(ValueError):
140
+ select_moc("25.9999", "FAR-25")
141
+
142
+
143
+ class TestMatrixBuilder(unittest.TestCase):
144
+
145
+ def test_build_matrix_example(self):
146
+ model = build_matrix(example_item())
147
+ self.assertEqual(model["certification_basis"], "FAR-25")
148
+ self.assertEqual(model["status"], "draft-for-review")
149
+ # 8 candidate regs: 5 applicable, 3 screened out.
150
+ self.assertEqual(model["row_count"], 8)
151
+ self.assertEqual(model["applicable_count"], 5)
152
+ self.assertEqual(model["coverage"], 1.0)
153
+ self.assertEqual(model["issues"], [])
154
+ # The applicable autopilot regs are present.
155
+ regs_app = {r["reg"] for r in model["rows"] if r["applicable"]}
156
+ self.assertEqual(regs_app,
157
+ {"25.1301", "25.1309", "25.1329", "25.671", "25.683"})
158
+
159
+ def test_compliance_row_fields(self):
160
+ row = compliance_row("25.1309", example_item())
161
+ self.assertTrue(row["applicable"])
162
+ self.assertEqual(row["status"], "proposed")
163
+ self.assertEqual(row["dal"], "B")
164
+ self.assertTrue(row["safety_assessment"])
165
+ self.assertIn("System safety assessment", row["compliance_document"])
166
+ self.assertTrue(row["owner"])
167
+ # No blank fields anywhere in the row.
168
+ for v in row.values():
169
+ self.assertNotIn("___", str(v))
170
+
171
+ def test_matrix_has_no_blanks(self):
172
+ md = example_matrix_markdown()
173
+ self.assertNotIn("___", md)
174
+ self.assertGreater(len(md), 1500)
175
+
176
+
177
+ class TestGates(unittest.TestCase):
178
+
179
+ def test_core_gates_all_pass(self):
180
+ model = build_matrix(example_item())
181
+ gates = check_matrix(model)
182
+ self.assertTrue(gates["all_pass"], gates)
183
+
184
+ def test_core_gates_fail_on_missing_doc(self):
185
+ model = build_matrix(example_item())
186
+ # Break a row: applicable reg without a compliance document.
187
+ row = next(r for r in model["rows"] if r["applicable"])
188
+ row["compliance_document"] = ""
189
+ gates = check_matrix(model)
190
+ self.assertFalse(gates["all_pass"])
191
+ self.assertFalse(gates["all_applicable_have_doc"])
192
+
193
+ def test_core_gates_fail_on_found_status(self):
194
+ model = build_matrix(example_item())
195
+ model["rows"][0]["status"] = "compliant"
196
+ gates = check_matrix(model)
197
+ self.assertFalse(gates["all_pass"])
198
+ self.assertFalse(gates["statuses_honest"])
199
+
200
+ def test_markdown_gates_all_pass(self):
201
+ md = example_matrix_markdown()
202
+ gates = check_matrix_markdown(md)
203
+ self.assertTrue(gates["all_pass"], gates)
204
+
205
+ def test_markdown_gates_fail_on_blank(self):
206
+ md = example_matrix_markdown().replace("## Compliance matrix",
207
+ "## Compliance ___ matrix")
208
+ gates = check_matrix_markdown(md)
209
+ self.assertFalse(gates["all_pass"])
210
+ self.assertFalse(gates["no_blank_fields"])
211
+
212
+ def test_standalone_no_skills_repo(self):
213
+ # Core must work with no AeroSkills present.
214
+ os.environ["AEROSKILLS_DEV"] = "/nonexistent"
215
+ model = build_matrix(example_item())
216
+ self.assertTrue(model["row_count"] >= 5)
217
+ self.assertTrue(model["coverage"] >= 0.5)
218
+ md = render_matrix_markdown(model)
219
+ self.assertGreater(len(md), 1500)
220
+ self.assertTrue(check_matrix_markdown(md)["all_pass"])
221
+
222
+
223
+ if __name__ == "__main__":
224
+ unittest.main()
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env python3
2
+ """Role test: Airworthiness Compliance Engineer.
3
+
4
+ Offline verification:
5
+ 1. Every bound skill resolves in aero-agent-skills.
6
+ 2. Workflow stage order deterministic + complete.
7
+ 3. Compliance matrix template has the required columns/rows.
8
+ 4. Boundaries + sign-off present.
9
+ """
10
+ import os
11
+ import re
12
+ import unittest
13
+
14
+ ROLES_REPO = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(
15
+ os.path.abspath(__file__)))))
16
+ AEROSKILLS = os.environ.get("AEROSKILLS_DEV", os.path.expanduser("~/AeroSkills"))
17
+ # Bound-skill resolution requires the Aero Agent Skills checkout (cross-repo
18
+ # dev check); skip when absent so fresh public clones can still run make validate.
19
+ HAS_SKILLS = os.path.isdir(os.path.join(AEROSKILLS, "skills"))
20
+ ROLE_DIR = os.path.join(ROLES_REPO, "roles", "airworthiness-compliance-engineer")
21
+ MATRIX = os.path.join(ROLE_DIR, "templates", "compliance-matrix-template.md")
22
+
23
+ EXPECTED_BOUND = [
24
+ "avionics/far-cs25/airworthiness",
25
+ "avionics/far-cs25/special-conditions",
26
+ "systems-engineering-safety/certification/certification-basis",
27
+ "systems-engineering-safety/certification/equivalent-level-of-safety",
28
+ "systems-engineering-safety/certification/means-of-compliance",
29
+ "systems-engineering-safety/certification/mmel-development",
30
+ "systems-engineering-safety/continued-airworthiness/airworthiness-directive-compliance",
31
+ "systems-engineering-safety/continued-airworthiness/type-certificate-data-sheet",
32
+ "systems-engineering-safety/continued-airworthiness/in-service-safety-assessment",
33
+ ]
34
+
35
+ STAGES = ["Certification basis", "Special conditions", "ELOS",
36
+ "Means of compliance", "Airworthiness mapping", "MMEL",
37
+ "Continued airworthiness", "Compliance matrix"]
38
+
39
+
40
+ def role_text():
41
+ p = os.path.join(ROLE_DIR, "ROLE.md")
42
+ return open(p).read() if os.path.exists(p) else None
43
+
44
+
45
+ class TestAirworthinessRole(unittest.TestCase):
46
+
47
+ def test_bound_skills_resolve(self):
48
+ if not HAS_SKILLS:
49
+ self.skipTest("Aero Agent Skills checkout not present (cross-repo dev check)")
50
+ for leaf in EXPECTED_BOUND:
51
+ self.assertTrue(
52
+ os.path.exists(os.path.join(AEROSKILLS, "skills", leaf, "SKILL.md")),
53
+ f"bound skill missing: {leaf}")
54
+
55
+ def test_stages_ordered(self):
56
+ role = role_text()
57
+ self.assertIsNotNone(role)
58
+ idx = [role.find(s) for s in STAGES]
59
+ self.assertTrue(all(i >= 0 for i in idx))
60
+ self.assertEqual(idx, sorted(idx), "stage order not deterministic")
61
+
62
+ def test_matrix_columns_present(self):
63
+ if not os.path.exists(MATRIX):
64
+ self.fail("compliance-matrix-template.md missing")
65
+ text = open(MATRIX).read()
66
+ for col in ["Reg", "Applicable?", "Means of compliance",
67
+ "Compliance document", "Status", "Owner"]:
68
+ self.assertIn(col, text, f"column missing: {col}")
69
+ self.assertIn("proposed", text.lower())
70
+
71
+ def test_boundaries(self):
72
+ role = role_text()
73
+ self.assertIsNotNone(role)
74
+ for phrase in ["declare a compliance finding", "claim certification approval",
75
+ "sign_off_required: true"]:
76
+ self.assertIn(phrase, role)
77
+
78
+ def test_sources_register(self):
79
+ self.assertTrue(
80
+ os.path.exists(os.path.join(ROLE_DIR, "SOURCES.md")),
81
+ "SOURCES.md missing")
82
+
83
+
84
+ if __name__ == "__main__":
85
+ unittest.main()
@@ -0,0 +1,128 @@
1
+ ---
2
+ type: role
3
+ name: as9100-quality-auditor
4
+ title: "AS9100 Quality / Internal Auditor"
5
+ status: draft
6
+ domain: manufacturing-quality
7
+ deliverable_type: "audit plan + findings report + corrective-action follow-up"
8
+ standards_bound:
9
+ - id: as9100
10
+ tier: TIER-2
11
+ reference-only: true
12
+ skills_bound:
13
+ - manufacturing-quality/as9100/internal-quality-audit
14
+ - manufacturing-quality/as9100/document-control
15
+ - manufacturing-quality/as9100/management-review
16
+ - manufacturing-quality/as9100/nonconformance-control
17
+ - manufacturing-quality/as9100/corrective-action
18
+ - manufacturing-quality/as9100/risk-management
19
+ - manufacturing-quality/as9100/supplier-control
20
+ - manufacturing-quality/as9100/order-requirements-review
21
+ - manufacturing-quality/as9100/calibration-control
22
+ - manufacturing-quality/as9100/counterfeit-prevention
23
+ - manufacturing-quality/as9100/fod-control
24
+ - manufacturing-quality/as9100/quality
25
+ - manufacturing-quality/as9102/first-article-inspection
26
+ - manufacturing-quality/as9102/delta-fai
27
+ - manufacturing-quality/as9102/fai-revalidation
28
+ tools_allowed: [stdlib, offline-file-processing]
29
+ forbidden:
30
+ - "issue certification"
31
+ - "claim audit closure"
32
+ - "recommend supplier approval"
33
+ sign_off_required: true
34
+ license: Apache-2.0
35
+ compatibility: "agentskills.io ROLE.md; any SKILL.md host"
36
+ metadata:
37
+ version: 0.1.0
38
+ author: Aero Agent Roles
39
+ skills_release: "v1.3.0+"
40
+ ---
41
+
42
+ # AS9100 Quality / Internal Auditor
43
+
44
+ ## Role identity
45
+
46
+ Plans and executes an AS9100 quality-management-system internal audit:
47
+ scope, criteria, evidence collection against the standard's clauses,
48
+ findings classification, and corrective-action follow-up. Use when a
49
+ manufacturing/supplier site must demonstrate QMS conformity (internal
50
+ audit, supplier audit prep, management-review input). Do NOT use for
51
+ design/engineering work, or for external certification audits (that is a
52
+ certification body's role).
53
+
54
+ ## Deliverable contract
55
+
56
+ 1. **Audit plan** — scope, criteria (AS9100 clauses + customer/supplier
57
+ requirements), schedule, auditee areas.
58
+ 2. **Findings report** — nonconformities classified (major/minor/
59
+ observation) with objective evidence + clause references.
60
+ 3. **Corrective-action follow-up** — root-cause verification, action
61
+ tracking, closure recommendation (for human QA sign-off).
62
+
63
+ ## Workflow (stages → bound skills)
64
+
65
+ | Stage | Loads skill | Produces |
66
+ |---|---|---|
67
+ | 1. Audit planning | as9100/internal-quality-audit | audit plan, criteria, scope |
68
+ | 2. Document control check | as9100/document-control | doc-control evidence review |
69
+ | 3. Management review check | as9100/management-review | MR input/output evidence |
70
+ | 4. Risk + ops review | as9100/risk-management + quality | operational risk evidence |
71
+ | 5. Nonconformance + corrective action | as9100/nonconformance-control + corrective-action | NC handling evidence, CA effectiveness |
72
+ | 6. Supplier + purchasing | as9100/supplier-control + order-requirements-review | supplier control evidence |
73
+ | 7. Calibration + counterfeit + FOD | as9100/calibration-control + counterfeit-prevention + fod-control | special-process evidence |
74
+ | 8. FAI (AS9102) | as9102/first-article-inspection + delta-fai + fai-revalidation | FAI evidence for product audit |
75
+ | 9. Findings + report | (all above) | findings report + CA follow-up |
76
+
77
+ ## Evidence gates
78
+
79
+ - Stage 1 done = audit plan states scope + criteria + schedule.
80
+ - Stage 5 done = every NC has clause ref + objective evidence.
81
+ - FINAL = findings classified; closure recommendation is PROPOSED (the
82
+ QA manager/auditor signs closure).
83
+
84
+ ## Boundary / forbidden
85
+
86
+ - NEVER issue certification (external cert bodies do that).
87
+ - NEVER claim audit closure without human sign-off.
88
+ - NEVER recommend supplier approval/disapproval — report evidence only.
89
+ - AS9100 is proprietary (IAQG) — TIER-2 reference-only, no verbatim.
90
+
91
+ ## Verification
92
+
93
+ The role runs STANDALONE: `core/as9100_core.py` is an executable engine
94
+ that classifies each nonconformity on the finding ladder (major/minor/
95
+ observation with systemic and detection/containment escalation),
96
+ scores corrective-action records on the closure chain (containment ->
97
+ root cause -> corrective action -> effectiveness), sizes the record
98
+ sample, computes the next audit due date from the process risk
99
+ category, BUILDS the findings report, and gate-checks deliverables. No
100
+ AeroSkills checkout required.
101
+
102
+ Run the role:
103
+ ```bash
104
+ python3 cli.py build --out findings.md # example supplier audit
105
+ python3 cli.py build --risk-category low --out f.md # low-risk variant
106
+ python3 cli.py check --file findings.md # gate-check a report
107
+ ```
108
+
109
+ Tests:
110
+ - tests/test_as9100_core.py (22 tests): classification ladder +
111
+ corrective-action chain + audit program numbers + findings builder +
112
+ gates + no-blanks render + standalone (no skills repo)
113
+ - tests/test_role_as9100.py: bound-skill resolution (skips if the
114
+ skills repo is absent) + workflow + filled template fields +
115
+ boundaries
116
+
117
+ `templates/findings-report-template.md` is the FILLED, generated
118
+ deliverable for the example audit (2 major, 2 minor, 1 observation,
119
+ zero blanks) — produced by `cli.py build --out`.
120
+
121
+ Bound skills in Aero Agent Skills deepen individual stages when the
122
+ library is present (audit scheduling, disposition, calibration,
123
+ corrective action); the core engine does not depend on them.
124
+
125
+ ## Compliance
126
+
127
+ - as9100 TIER-2 reference-only; as9102 same family.
128
+ - SOURCES.md records acquisition/extraction/verification status.
@@ -0,0 +1,16 @@
1
+ # SOURCES.md - AS9100 Quality / Internal Auditor
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
+ | AS9100D | QMS requirements (the audit criteria) | true |
9
+ | AS9102 | First Article Inspection (product audit) | true |
10
+ | ISO 19011 | audit program and evidence discipline | true |
11
+ | ISO 9001:2015 | QMS baseline that AS9100 extends | true |
12
+ | IAQG public guides | supplier guidance and FAQs | false |
13
+
14
+ The findings report template in `templates/` cites clause numbers, not
15
+ standard text - the same practice real audit reports follow. Clause
16
+ references are identifiers, not reproduction.
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env python3
2
+ """cli.py - run the AS9100 Quality / Internal Auditor role.
3
+
4
+ Usage:
5
+ python3 cli.py build --out <file.md> # build the findings report for the example audit
6
+ python3 cli.py build --out <file.md> --bundle # + evidence/{model,gates,provenance}.json
7
+ python3 cli.py build --out <file.md> --bundle --profile <profile.json>
8
+ # + program profile (audited supplier context,
9
+ # docs/PROFILE-SCHEMA.md)
10
+ python3 cli.py check --file <file.md> # gate-check an existing findings report
11
+
12
+ The role ENGINE (core/as9100_core.py) does the work standalone; bound
13
+ skills in Aero Agent Skills deepen individual stages when present.
14
+ """
15
+ import argparse
16
+ import os
17
+ import sys
18
+
19
+ sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "core"))
20
+ sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
21
+ "..", "..", "scripts"))
22
+ import as9100_core as core
23
+ import evidence # noqa: E402
24
+
25
+ ROLE_SLUG = "as9100-quality-auditor"
26
+
27
+
28
+ def _provenance():
29
+ """Provenance for the evidence bundle: role core functions used."""
30
+ return {
31
+ "role": ROLE_SLUG,
32
+ "core": {
33
+ "file": "core/as9100_core.py",
34
+ "functions": ["classify_nc", "corrective_action_status",
35
+ "audit_sample_size", "audit_due_date",
36
+ "audit_findings", "check_findings"],
37
+ "version": "0.1.0",
38
+ },
39
+ "skills": [],
40
+ "cross_checked": False,
41
+ "disclaimer": "DRAFT for human review. Not an approval document.",
42
+ }
43
+
44
+
45
+ def cmd_build(args):
46
+ item = core.example_item()
47
+ if args.risk_category:
48
+ item.process_risk = args.risk_category
49
+ if args.audit_date:
50
+ item.audit_date = args.audit_date
51
+ model = core.audit_findings(item)
52
+ md = core.render_findings_markdown(model)
53
+
54
+ # program profile (audited supplier context): load + apply context header
55
+ profile = None
56
+ try:
57
+ profile = evidence.load_profile(args.profile)
58
+ except ValueError as e:
59
+ print(f"error: bad profile: {e}")
60
+ return 1
61
+ if profile:
62
+ model["profile"] = {
63
+ "customer": profile.get("customer"),
64
+ "program": profile.get("program"),
65
+ "basis": profile.get("basis"),
66
+ "authority": profile.get("authority"),
67
+ "der": profile.get("der"),
68
+ "document_prefix": profile.get("document_prefix"),
69
+ "revision": profile.get("revision"),
70
+ }
71
+ md = evidence.profile_header_block(profile) + md
72
+
73
+ gates = core.check_findings(model)
74
+ if args.out:
75
+ with open(args.out, "w") as f:
76
+ f.write(md)
77
+ print("built findings report for %s -> %s" % (model["supplier"],
78
+ args.out))
79
+ if profile:
80
+ print("profile: %s / %s" % (profile.get("customer"),
81
+ profile.get("program")))
82
+ print("counts: %s" % model["counts"])
83
+ print("gates: all_pass=%s %s" % (gates["all_pass"], gates))
84
+ if args.bundle:
85
+ paths = evidence.write_bundle(
86
+ args.out, ROLE_SLUG,
87
+ "AS9100 internal audit findings report", model, gates,
88
+ _provenance())
89
+ print("bundle: model=%s" % paths["model"])
90
+ print(" gates=%s" % paths["gates"])
91
+ print(" provenance=%s" % paths["provenance"])
92
+ else:
93
+ print(md)
94
+ return 0 if gates["all_pass"] else 1
95
+
96
+
97
+ def cmd_check(args):
98
+ if not os.path.exists(args.file):
99
+ print("file not found: %s" % args.file)
100
+ return 1
101
+ md = open(args.file).read()
102
+ gates = core.check_findings_markdown(md)
103
+ for name, ok in gates.items():
104
+ if name != "all_pass":
105
+ print("%s %s" % ("PASS" if ok else "FAIL", name))
106
+ print("RESULT: %s" % ("PASS" if gates["all_pass"] else "FAIL"))
107
+ return 0 if gates["all_pass"] else 1
108
+
109
+
110
+ def main():
111
+ p = argparse.ArgumentParser(description="AS9100 Quality / Internal Auditor role")
112
+ sub = p.add_subparsers(dest="cmd", required=True)
113
+
114
+ b = sub.add_parser("build")
115
+ b.add_argument("--out", default="", help="output file (default: stdout)")
116
+ b.add_argument("--risk-category", default="",
117
+ help="low/medium/high process risk")
118
+ b.add_argument("--audit-date", default="", help="audit date ISO YYYY-MM-DD")
119
+ b.add_argument("--bundle", action="store_true",
120
+ help="emit evidence/{model,gates,provenance}.json")
121
+ b.add_argument("--profile", default="",
122
+ help="program profile JSON (audited supplier context, "
123
+ "docs/PROFILE-SCHEMA.md)")
124
+ b.set_defaults(fn=cmd_build)
125
+
126
+ c = sub.add_parser("check")
127
+ c.add_argument("--file", required=True,
128
+ help="findings report markdown file to gate-check")
129
+ c.set_defaults(fn=cmd_check)
130
+
131
+ args = p.parse_args()
132
+ sys.exit(args.fn(args))
133
+
134
+
135
+ if __name__ == "__main__":
136
+ main()