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,23 @@
1
+ # SOURCES.md - Data Bus / Avionics Network Engineer
2
+
3
+ Standards and documents this role references. Summary-not-copy: see
4
+ [STANDARDS.md](../../STANDARDS.md) for the full rule and purchase links.
5
+
6
+ | Source | Role use | Gated |
7
+ |---|---|---|
8
+ | ARINC 429 (Mark 33 DITS) | 32-bit word format, octal label, SDI, SSM, parity, BNR/BCD coding, 12.5/100 kbps topology, 36 bit-times per word loading model | true (TIER-2, reference-only) |
9
+ | ARINC 664 Part 7 (AFDX) | virtual link definition, BAG sizing, 100 Mbps link budget, redundancy, jitter/latency margins | true (TIER-2, reference-only) |
10
+ | MIL-STD-1553B | 20-bit command/status/data words, BC/RT operation, dual redundant bus, 1 Mbps command/response protocol | false (TIER-1, US public domain) |
11
+ | MIL-STD-1553 bus loading practice | minor-frame schedule, wire-word counting, 24 us word slot, 80% loading guideline | false (derived practice) |
12
+ | ARINC 429 loading practice | label-rate schedule budgets, word-per-second capacity (~2778 wps @ 100 kbps), 80% design guideline | false (derived practice) |
13
+
14
+ The AeroSkills data-bus leaves (avionics/data-bus/arinc429-protocol,
15
+ arinc429-bus-loading, arinc664-afdx, mil-std-1553,
16
+ mil-std-1553-bus-loading) encode the protocol/loading rules this role
17
+ computes with; their SKILL.md files and scripts are the field-level
18
+ reference, and each standards-map entry above marks the ARINC family as
19
+ summary-only.
20
+
21
+ The assessment and loading templates in `templates/` are original
22
+ structures informed by common-knowledge protocol summaries and the
23
+ leaf logic files. No proprietary standard text is reproduced.
@@ -0,0 +1,311 @@
1
+ #!/usr/bin/env python3
2
+ """cli.py - run the Data Bus / Avionics Network Engineer role.
3
+
4
+ Usage:
5
+ python3 cli.py build [--out <file.md>] [--bundle] [--profile <file.json>]
6
+ [--no-dispatch]
7
+ # build the Avionics Data Bus Loading and Protocol Assessment for the
8
+ # example aircraft bus architecture
9
+ # --bundle also emit evidence/{model,gates,provenance}.json (PROTOCOL.md)
10
+ # --profile program profile JSON for customer tailoring
11
+ # (docs/PROFILE-SCHEMA.md) -> prepended context header
12
+ # --no-dispatch skip dispatching bound AeroSkills data-bus logic
13
+ python3 cli.py check --file <file.md> # gate-check an existing assessment
14
+
15
+ The role ENGINE (core/data_bus_avionics_core.py) does the work standalone:
16
+ ARINC 429 word decode + bus loading, MIL-STD-1553 word decode + BC schedule
17
+ loading, ARINC 664 AFDX VL bandwidth checks, and the evidence gates. When
18
+ AeroSkills is present (AEROSKILLS_DEV or ~/AeroSkills), the CLI dispatches
19
+ the five bound avionics/data-bus leaf logic modules and cross-checks their
20
+ numbers against the core's — two independent implementations agreeing is
21
+ recorded in provenance.json.
22
+ """
23
+ import argparse
24
+ import importlib.util
25
+ import os
26
+ import sys
27
+
28
+ sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
29
+ "core"))
30
+ sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
31
+ "..", "..", "scripts"))
32
+ import data_bus_avionics_core as core # noqa: E402
33
+ import evidence # noqa: E402
34
+
35
+ AEROSKILLS = os.environ.get("AEROSKILLS_DEV", os.path.expanduser("~/AeroSkills"))
36
+ SKILLS_ROOT = os.path.join(AEROSKILLS, "skills", "avionics", "data-bus")
37
+ ROLE_SLUG = "data-bus-avionics-engineer"
38
+ SKILLS_RELEASE = "v1.3.0+"
39
+
40
+ # Bound leaves and their dispatch points (leaf module names as on disk).
41
+ BOUND_LEAVES = [
42
+ ("arinc429-protocol", "arinc429_logic.py"),
43
+ ("arinc429-bus-loading", "arinc429_bus_loading_logic.py"),
44
+ ("arinc664-afdx", "arinc664_afdx_logic.py"),
45
+ ("mil-std-1553", "mil_std_1553_logic.py"),
46
+ ("mil-std-1553-bus-loading", "mil_std_1553_bus_loading_logic.py"),
47
+ ]
48
+
49
+
50
+ def _load_leaf(leaf, logic_file):
51
+ """Import a bound leaf's *_logic.py module, or None when unavailable."""
52
+ path = os.path.join(SKILLS_ROOT, leaf, "scripts", logic_file)
53
+ if not os.path.exists(path):
54
+ return None
55
+ spec = importlib.util.spec_from_file_location("data_bus_leaf_" + leaf
56
+ .replace("-", "_"), path)
57
+ mod = importlib.util.module_from_spec(spec)
58
+ try:
59
+ spec.loader.exec_module(mod)
60
+ return mod
61
+ except Exception:
62
+ return None
63
+
64
+
65
+ def _run_crosschecks(model):
66
+ """Cross-check the core's numbers against the five bound leaf modules.
67
+
68
+ Each row compares the same quantity computed two independent ways:
69
+ the core implementation and the AeroSkills leaf logic. Returns a list
70
+ of provenance rows (empty when the skills library is absent) with
71
+ leaf, logic_file, function, dispatched, core_value, skill_value,
72
+ delta, agrees, and the cross-check point description.
73
+ """
74
+ rows = []
75
+ a429_lines = model.get("arinc429") or []
76
+
77
+ # 1. arinc429-protocol: word build anchor label 010/SDI1/data 1234/SSM3
78
+ mod = _load_leaf("arinc429-protocol", "arinc429_logic.py")
79
+ if mod is not None and hasattr(mod, "build_word"):
80
+ try:
81
+ core_val = core.a429_build_word(8, 1, 1234, 3)
82
+ skill_val = mod.build_word(8, 1, 1234, 3)
83
+ rows.append(_row("arinc429-protocol", "arinc429_logic.py",
84
+ "build_word", core_val, skill_val,
85
+ "32-bit word label 010 SDI1 data 1234 SSM3"))
86
+ except Exception as e: # pragma: no cover
87
+ rows.append(_row_err("arinc429-protocol", "arinc429_logic.py",
88
+ "build_word", e))
89
+
90
+ # 2. arinc429-bus-loading: utilization of the first example TX line
91
+ mod = _load_leaf("arinc429-bus-loading", "arinc429_bus_loading_logic.py")
92
+ if mod is not None and a429_lines and hasattr(mod, "bus_loading_summary"):
93
+ try:
94
+ rates = a429_lines[0]["label_rates"]
95
+ link = a429_lines[0]["link_rate_bps"]
96
+ core_val = core.a429_loading_summary(rates, link)["utilization_pct"]
97
+ skill_val = mod.bus_loading_summary(rates, link)["utilization_pct"]
98
+ rows.append(_row("arinc429-bus-loading",
99
+ "arinc429_bus_loading_logic.py",
100
+ "bus_loading_summary", core_val, skill_val,
101
+ "%s utilization" % a429_lines[0]["name"]))
102
+ except Exception as e: # pragma: no cover
103
+ rows.append(_row_err("arinc429-bus-loading",
104
+ "arinc429_bus_loading_logic.py",
105
+ "bus_loading_summary", e))
106
+
107
+ # 3. arinc664-afdx: VL bandwidth anchor (BAG 4 ms, 1518 bytes)
108
+ mod = _load_leaf("arinc664-afdx", "arinc664_afdx_logic.py")
109
+ if mod is not None and hasattr(mod, "vl_bandwidth"):
110
+ try:
111
+ core_val = core.afdx_vl_bandwidth(4, 1518)
112
+ skill_val = mod.vl_bandwidth(4, 1518)
113
+ rows.append(_row("arinc664-afdx", "arinc664_afdx_logic.py",
114
+ "vl_bandwidth", core_val, skill_val,
115
+ "VL bandwidth BAG 4 ms frame 1518 bytes"))
116
+ except Exception as e: # pragma: no cover
117
+ rows.append(_row_err("arinc664-afdx", "arinc664_afdx_logic.py",
118
+ "vl_bandwidth", e))
119
+
120
+ # 4. mil-std-1553: command word anchor RT5 SA12 WC16 RT-to-BC
121
+ mod = _load_leaf("mil-std-1553", "mil_std_1553_logic.py")
122
+ if mod is not None and hasattr(mod, "encode_command_word"):
123
+ try:
124
+ core_val = core.m1553_encode_command_word(5, 12, 16, 1)
125
+ skill_val = mod.encode_command_word(5, 12, 16, 1)
126
+ rows.append(_row("mil-std-1553", "mil_std_1553_logic.py",
127
+ "encode_command_word", core_val, skill_val,
128
+ "20-bit command word RT5 SA12 WC16 T/R 1"))
129
+ except Exception as e: # pragma: no cover
130
+ rows.append(_row_err("mil-std-1553", "mil_std_1553_logic.py",
131
+ "encode_command_word", e))
132
+
133
+ # 5. mil-std-1553-bus-loading: example BC minor-frame schedule loading
134
+ mod = _load_leaf("mil-std-1553-bus-loading",
135
+ "mil_std_1553_bus_loading_logic.py")
136
+ if mod is not None and hasattr(mod, "schedule_utilization"):
137
+ try:
138
+ item = core.example_item()
139
+ messages = [(k, w) for k, w in item.m1553_bus.messages]
140
+ frame_us = item.m1553_bus.frame_us
141
+ core_val = core.m1553_schedule_utilization(
142
+ messages, frame_us)["utilization_pct"]
143
+ skill_val = mod.schedule_utilization(messages, frame_us)[
144
+ "utilization_pct"]
145
+ rows.append(_row("mil-std-1553-bus-loading",
146
+ "mil_std_1553_bus_loading_logic.py",
147
+ "schedule_utilization", core_val, skill_val,
148
+ "%s minor-frame utilization" %
149
+ item.m1553_bus.name))
150
+ except Exception as e: # pragma: no cover
151
+ rows.append(_row_err("mil-std-1553-bus-loading",
152
+ "mil_std_1553_bus_loading_logic.py",
153
+ "schedule_utilization", e))
154
+ return rows
155
+
156
+
157
+ def _row(leaf, logic_file, fn, core_val, skill_val, point, tol=1e-6):
158
+ delta = abs(float(core_val) - float(skill_val))
159
+ return {
160
+ "leaf": "avionics/data-bus/" + leaf,
161
+ "skill_md": "SKILL.md",
162
+ "logic_file": "scripts/" + logic_file,
163
+ "function": fn,
164
+ "dispatched": True,
165
+ "cross_check_point": point,
166
+ "core_value": round(float(core_val), 6),
167
+ "skill_value": round(float(skill_val), 6),
168
+ "delta": round(delta, 9),
169
+ "agrees": delta <= tol,
170
+ "tolerance": tol,
171
+ "skills_release": SKILLS_RELEASE,
172
+ }
173
+
174
+
175
+ def _row_err(leaf, logic_file, fn, exc):
176
+ return {"leaf": "avionics/data-bus/" + leaf,
177
+ "logic_file": "scripts/" + logic_file,
178
+ "function": fn, "dispatched": True,
179
+ "error": str(exc), "agrees": False}
180
+
181
+
182
+ def _provenance(rows):
183
+ ok_rows = [r for r in rows if r.get("dispatched") and not r.get("error")]
184
+ return {
185
+ "role": ROLE_SLUG,
186
+ "core": {
187
+ "file": "core/data_bus_avionics_core.py",
188
+ "functions": ["a429_build_word", "a429_loading_summary",
189
+ "afdx_vl_bandwidth", "m1553_encode_command_word",
190
+ "m1553_schedule_utilization"],
191
+ "version": "0.1.0",
192
+ },
193
+ "skills": rows,
194
+ "cross_checked": bool(ok_rows) and all(r.get("agrees")
195
+ for r in ok_rows),
196
+ "disclaimer": "DRAFT for human review. Not an approval document.",
197
+ }
198
+
199
+
200
+ def cmd_build(args):
201
+ item = core.example_item()
202
+ results = core.analyze_architecture(item)
203
+ model = core.build_assessment(item, results)
204
+ md = core.render_assessment_markdown(model)
205
+
206
+ # program profile (customer tailoring): load + apply context header
207
+ profile = None
208
+ try:
209
+ profile = evidence.load_profile(args.profile)
210
+ except ValueError as e:
211
+ print(f"error: bad profile: {e}")
212
+ return 1
213
+ if profile:
214
+ model["profile"] = {
215
+ "customer": profile.get("customer"),
216
+ "program": profile.get("program"),
217
+ "basis": profile.get("basis"),
218
+ "authority": profile.get("authority"),
219
+ "der": profile.get("der"),
220
+ "document_prefix": profile.get("document_prefix"),
221
+ "revision": profile.get("revision"),
222
+ }
223
+ md = evidence.profile_header_block(profile) + md
224
+
225
+ gates = core.check_assessment(model)
226
+
227
+ rows = []
228
+ if not args.no_dispatch:
229
+ rows = _run_crosschecks(model)
230
+
231
+ if args.out:
232
+ with open(args.out, "w") as f:
233
+ f.write(md if md.endswith("\n") else md + "\n")
234
+ a429_max = max(b["summary"]["utilization_pct"]
235
+ for b in model["arinc429"])
236
+ print("built Avionics Data Bus Loading and Protocol Assessment "
237
+ "-> %s" % args.out)
238
+ print("ARINC 429 max line utilization: %.2f%%" % a429_max)
239
+ print("MIL-STD-1553 bus utilization: %.2f%%"
240
+ % model["m1553"]["schedule"]["utilization_pct"])
241
+ print("AFDX link utilization: %.2f%%"
242
+ % model["afdx"]["utilization_pct"])
243
+ print("gates: all_pass=%s %s" % (gates["all_pass"], gates))
244
+ if profile:
245
+ print("profile: %s / %s" % (profile.get("customer"),
246
+ profile.get("program")))
247
+ if args.bundle:
248
+ prov = _provenance(rows)
249
+ paths = evidence.write_bundle(
250
+ args.out, ROLE_SLUG,
251
+ "Avionics Data Bus Loading and Protocol Assessment",
252
+ model, gates, prov)
253
+ print("bundle: model=%s" % paths["model"])
254
+ print(" gates=%s" % paths["gates"])
255
+ print(" provenance=%s" % paths["provenance"])
256
+ if rows:
257
+ for r in rows:
258
+ if r.get("dispatched") and not r.get("error"):
259
+ print("cross-check: %-28s core=%-12s skill=%-12s "
260
+ "delta=%s agrees=%s"
261
+ % (r["function"], r["core_value"],
262
+ r["skill_value"], r["delta"], r["agrees"]))
263
+ else:
264
+ print("cross-check: not dispatched (no AeroSkills logic)")
265
+ else:
266
+ print(md)
267
+ return 0 if gates["all_pass"] else 1
268
+
269
+
270
+ def cmd_check(args):
271
+ if not os.path.exists(args.file):
272
+ print(f"file not found: {args.file}")
273
+ return 1
274
+ md = open(args.file).read()
275
+ gates = core.check_assessment_markdown(md)
276
+ for name, ok in gates.items():
277
+ if name != "all_pass":
278
+ print(f"{'PASS' if ok else 'FAIL'} {name}")
279
+ print(f"RESULT: {'PASS' if gates['all_pass'] else 'FAIL'}")
280
+ return 0 if gates["all_pass"] else 1
281
+
282
+
283
+ def main():
284
+ p = argparse.ArgumentParser(
285
+ description="Data Bus / Avionics Network Engineer role: avionics "
286
+ "data bus loading + protocol assessment")
287
+ sub = p.add_subparsers(dest="cmd", required=True)
288
+
289
+ b = sub.add_parser("build")
290
+ b.add_argument("--out", default="",
291
+ help="output file (default: stdout)")
292
+ b.add_argument("--bundle", action="store_true",
293
+ help="emit evidence/{model,gates,provenance}.json")
294
+ b.add_argument("--profile", default="",
295
+ help="program profile JSON (customer tailoring, "
296
+ "docs/PROFILE-SCHEMA.md)")
297
+ b.add_argument("--no-dispatch", action="store_true",
298
+ help="skip dispatching bound AeroSkills logic")
299
+ b.set_defaults(fn=cmd_build)
300
+
301
+ c = sub.add_parser("check")
302
+ c.add_argument("--file", required=True,
303
+ help="assessment markdown to gate-check")
304
+ c.set_defaults(fn=cmd_check)
305
+
306
+ args = p.parse_args()
307
+ sys.exit(args.fn(args))
308
+
309
+
310
+ if __name__ == "__main__":
311
+ main()