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