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,49 @@
1
+ # SOURCES.md - Space Systems 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
+ ## Standards / references
7
+
8
+ | Source | Role use | Gated |
9
+ |---|---|---|
10
+ | ECSS-E-ST-10, E-ST-32, E-ST-33, E-ST-40, Q-ST-80 | systems/software engineering + product assurance context | true |
11
+ | Wertz et al., Space Mission Analysis and Design (SMAD) | mission design, margin policy, disturbance model (book) | true |
12
+ | Vallado, Fundamentals of Astrodynamics and Applications | astrodynamics methods: vis-viva, Hohmann, Kepler (book) | true |
13
+ | Larson & Wertz, Space Mission Analysis and Design | subsystem sizing conventions (book) | true |
14
+ | NASA GEVS / NPR | environment and test practice (informational) | false |
15
+
16
+ ## Domain rules encoded in core/space_systems_core.py
17
+
18
+ Every number the engine produces follows a REAL relation exercised by
19
+ the bound AeroSkills space-systems leaves (same formulas, reimplemented
20
+ stdlib-only so the role is standalone). Anchor values in
21
+ tests/test_space_systems_engineer_core.py are the leaves' own worked
22
+ examples.
23
+
24
+ | Rule | Formula | Source leaf |
25
+ |---|---|---|
26
+ | Circular orbit velocity | v = sqrt(mu/r) | space-systems/orbit-mechanics/hohmann-transfer |
27
+ | Orbit period | T = 2*pi*sqrt(r^3/mu) | hohmann-transfer / kepler-orbit-propagation |
28
+ | Hohmann transfer delta-v | dv = dv1 + dv2 (two burns, vis-viva) | hohmann-transfer |
29
+ | Disposal perigee-lowering burn | single retrograde burn, vis-viva | hohmann-transfer pattern, ECSS-E-ST-33 disposal practice |
30
+ | Delta-v budget + margin | sum contributions; dv*(1+margin) | mission-design/mission-delta-v-budget |
31
+ | Propellant mass (rocket equation) | m_prop = m_dry*(exp(dv/(Isp*g0)) - 1) | mission-delta-v-budget |
32
+ | Eclipse fraction/time (beta = 0) | f = asin(Re/r)/pi; t = f*T | orbit-mechanics/eclipse-time |
33
+ | Battery capacity | C = P*T_ecl/(DoD*efficiency) | subsystems/power-thermal-budget, spacecraft-battery-sizing |
34
+ | Solar array daylight power | P/(eff*(1-f))*(1+margin) | power-thermal-budget |
35
+ | Array EOL specific power + area | p_eol = G*eta*PF*(1-r)^n; A = P/p_eol | subsystems/solar-array-sizing |
36
+ | Radiator area | A = Q/(eps*sigma*(T^4 - T_sink^4)) | subsystems/thermal-design |
37
+ | Reaction wheel momentum sizing | h_slew = J*omega; h_wheel = J_w*omega_max | adcs/reaction-wheel-control, attitude-control-sizing |
38
+ | Pointing error budget | RSS of 3-sigma contributors vs requirement | adcs/pointing-error-budget |
39
+ | Link budget (Friis) | L_fs, EIRP, C/N0, Eb/N0 margin | subsystems/communication-link-budget |
40
+ | Tank sizing | V = m/rho, ullage, t = p*r/(2*sigma) | subsystems/propellant-tank-sizing |
41
+
42
+ Conservative stated inputs (margin 15% on delta-v, 20% array margin, 30%
43
+ battery DoD, 3 dB link requirement, 0.1 deg 3-sigma pointing) follow SMAD
44
+ margin practice and are cited as design inputs in the report; the engine
45
+ does not invent an allowable or a factor.
46
+
47
+ The template in `templates/space-systems-template.md` is the generated
48
+ worked example (Aurora-1, 600 km SSO): REAL delta-v, propellant, wheel,
49
+ array, battery, radiator, and link numbers - zero blanks.
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env python3
2
+ """cli.py - run the Space Systems Engineer role.
3
+
4
+ Usage:
5
+ python3 cli.py build --out <file.md> # build the mission +
6
+ # subsystem design report
7
+ python3 cli.py build --out alt.md --altitude 500 # variant orbit
8
+ python3 cli.py build --out r.md --bundle # also write
9
+ # evidence/{model,gates,
10
+ # provenance}.json
11
+ # (docs/PROTOCOL.md v1)
12
+ python3 cli.py build --out r.md --bundle \
13
+ --profile profiles/example-airframer.json # program profile context
14
+ # header (customer
15
+ # tailoring, docs/
16
+ # PROFILE-SCHEMA.md)
17
+ python3 cli.py check --file <file.md> # gate-check a report
18
+
19
+ The role ENGINE (core/space_systems_core.py) does the work standalone;
20
+ bound AeroSkills space-systems leaves deepen individual stages when
21
+ present, but the core never depends on them.
22
+ """
23
+ import argparse
24
+ import os
25
+ import sys
26
+
27
+ sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "core"))
28
+ sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
29
+ "..", "..", "scripts"))
30
+ import space_systems_core as core # noqa: E402
31
+ import evidence # noqa: E402
32
+
33
+ ROLE_SLUG = "space-systems-engineer"
34
+
35
+
36
+ def cmd_build(args):
37
+ mission = core.example_mission()
38
+ if args.altitude:
39
+ mission.altitude_km = args.altitude
40
+ if args.name:
41
+ mission.name = args.name
42
+ if args.dry_mass:
43
+ mission.dry_mass_kg = args.dry_mass
44
+ if args.isp:
45
+ mission.isp_s = args.isp
46
+ if args.dv_margin:
47
+ mission.dv_margin_fraction = args.dv_margin
48
+ model = core.build_report(mission)
49
+ md = core.render_report_markdown(model)
50
+
51
+ # program profile (customer tailoring): load + apply context header
52
+ profile = None
53
+ try:
54
+ profile = evidence.load_profile(args.profile)
55
+ except ValueError as e:
56
+ print(f"error: bad profile: {e}")
57
+ return 1
58
+ if profile:
59
+ model["profile"] = {
60
+ "customer": profile.get("customer"),
61
+ "program": profile.get("program"),
62
+ "basis": profile.get("basis"),
63
+ "authority": profile.get("authority"),
64
+ "der": profile.get("der"),
65
+ "document_prefix": profile.get("document_prefix"),
66
+ "revision": profile.get("revision"),
67
+ }
68
+ md = evidence.profile_header_block(profile) + md
69
+
70
+ gates = core.check_report(model)
71
+ if args.out:
72
+ with open(args.out, "w") as f:
73
+ f.write(md)
74
+ dv = model["delta_v"]
75
+ print(f"built report -> {args.out}")
76
+ if profile:
77
+ print(f"profile: {profile.get('customer')} / "
78
+ f"{profile.get('program')}")
79
+ print(f" orbit: {mission.altitude_km:.0f} km circular, "
80
+ f"period {model['power']['eclipse']['period_min']:.1f} min")
81
+ print(f" delta-v: {dv['nominal_dv_m_s']:.1f} m/s nominal / "
82
+ f"{dv['budgeted_dv_m_s']:.1f} m/s budgeted; "
83
+ f"propellant {dv['propellant_mass_kg']:.1f} kg")
84
+ print(f" wheel: {model['adcs']['wheel_momentum_capacity_nms']:.1f} N m s "
85
+ f"at {model['adcs']['wheel_speed_max_rpm']:.0f} rpm; "
86
+ f"array {model['power']['array_area_m2']:.2f} m^2; "
87
+ f"battery {model['power']['battery_sized_wh']:.0f} Wh")
88
+ print(f" pointing {model['pointing']['rss_deg']:.3f} deg; "
89
+ f"link down {model['comms']['downlink']['margin_db']:.1f} dB / "
90
+ f"up {model['comms']['uplink']['margin_db']:.1f} dB")
91
+ print(f" gates: all_pass={gates['all_pass']}")
92
+ if args.bundle:
93
+ paths = evidence.write_bundle(
94
+ args.out, ROLE_SLUG,
95
+ "Spacecraft Mission and Subsystem Design Report",
96
+ model, gates, _provenance())
97
+ print(f" bundle: model={paths['model']}")
98
+ print(f" gates={paths['gates']}")
99
+ print(f" provenance={paths['provenance']}")
100
+ else:
101
+ print(md)
102
+ return 0 if gates["all_pass"] else 1
103
+
104
+
105
+ def _provenance():
106
+ """PROTOCOL.md v1 provenance row.
107
+
108
+ The role core computed every number in the model standalone; no
109
+ bound-skill logic file was dispatched, so skills is honestly empty
110
+ and cross_checked is False.
111
+ """
112
+ return {
113
+ "role": ROLE_SLUG,
114
+ "core": {
115
+ "file": "core/space_systems_core.py",
116
+ "functions": ["build_report", "mission_delta_v_budget",
117
+ "power_and_thermal", "reaction_wheel_sizing",
118
+ "comms_link_budget", "check_report"],
119
+ "version": "0.1.0",
120
+ },
121
+ "skills": [],
122
+ "cross_checked": False,
123
+ "disclaimer": "DRAFT for human review. Not an approval document.",
124
+ }
125
+
126
+
127
+ def cmd_check(args):
128
+ if not os.path.exists(args.file):
129
+ print(f"file not found: {args.file}")
130
+ return 1
131
+ md = open(args.file).read()
132
+ gates = core.check_report_markdown(md)
133
+ for name, ok in gates.items():
134
+ if name != "all_pass":
135
+ print(f"{'PASS' if ok else 'FAIL'} {name}")
136
+ print(f"RESULT: {'PASS' if gates['all_pass'] else 'FAIL'}")
137
+ return 0 if gates["all_pass"] else 1
138
+
139
+
140
+ def main():
141
+ p = argparse.ArgumentParser(description="Space Systems Engineer role")
142
+ sub = p.add_subparsers(dest="cmd", required=True)
143
+
144
+ b = sub.add_parser("build")
145
+ b.add_argument("--out", default="", help="output file (default: stdout)")
146
+ b.add_argument("--name", default="", help="spacecraft/mission name")
147
+ b.add_argument("--altitude", type=float, default=0.0,
148
+ help="circular orbit altitude in km (default 600)")
149
+ b.add_argument("--dry-mass", type=float, default=0.0,
150
+ help="spacecraft dry mass in kg (default 150)")
151
+ b.add_argument("--isp", type=float, default=0.0,
152
+ help="propulsion specific impulse in s (default 220)")
153
+ b.add_argument("--dv-margin", type=float, default=0.0,
154
+ help="delta-v margin fraction (default 0.15)")
155
+ b.add_argument("--bundle", action="store_true",
156
+ help="also write evidence/{model,gates,provenance}.json "
157
+ "(docs/PROTOCOL.md v1)")
158
+ b.add_argument("--profile", default="",
159
+ help="program profile JSON (customer tailoring, "
160
+ "docs/PROFILE-SCHEMA.md)")
161
+ b.set_defaults(fn=cmd_build)
162
+
163
+ c = sub.add_parser("check")
164
+ c.add_argument("--file", required=True,
165
+ help="report markdown file to gate-check")
166
+ c.set_defaults(fn=cmd_check)
167
+
168
+ args = p.parse_args()
169
+ sys.exit(args.fn(args))
170
+
171
+
172
+ if __name__ == "__main__":
173
+ main()