Goal
Add Mission.validate(path) — a parse-only classmethod that loads a script through GMAT, captures the engine's log, and returns structured diagnostics. Today Mission.load exposes only the bool from gmat.LoadScript; the actual error / warning text is written into the GMAT log file and never reaches the caller. Downstream consumers that want to surface what GMAT thinks of a script without committing to a run() (LLM authoring loops, CI lint gates, batch screening) currently have to re-implement the load-with-log-capture pattern by hand.
Interface
@dataclass(frozen=True)
class ParseDiagnostic:
line: int | None # populated when GMAT's message carries `in line: "<N>: …"`
message: str # cleaned Interpreter Exception / warning text
raw: str # original log line, for fallback when scraping misses something
@dataclass(frozen=True)
class LoadDiagnostics:
ok: bool # LoadScript returned True AND post-load init didn't raise
errors: list[ParseDiagnostic]
warnings: list[ParseDiagnostic]
summary: MissionSummary | None # populated on ok=True; None on parse failure
raw_log: str # verbatim GMAT log, escape hatch
class Mission:
@classmethod
def validate(cls, path, *, gmat_root=None) -> LoadDiagnostics: ...
Semantics:
- Bypasses
LoadScript's bool-only contract by redirecting UseLogFile to a temp file across the load, scraping *** ERROR *** / Interpreter Exception: / *** WARNING *** markers, then resetting the log handle.
- Runs the same
_initialize_spacecraft step Mission.load does — an APIException there sets ok=False and lands in errors. Does not call sandbox-wide gmat.Initialize() (breaks EventLocator scripts; see the existing comment in Mission.load).
summary is built via build_mission_summary on success so callers get the resource + command inventory for free.
- Known false-negative: GMAT's interpreter silently accepts missing semicolons and similar lenient-syntax cases. Document in the docstring.
Error / warning format anchors
Three patterns observed in R2026a logs:
**** ERROR **** Interpreter Exception: <message> in line:
"<line_number>: <line_text>"
Interpreter Exception: <path>: <message> # no line context
*** WARNING *** <message>
Out of scope
- Static analysis beyond what GMAT itself emits.
- Applying field overrides before the validate.
- Reformatting / pretty-printing scripts.
Acceptance
Mission.validate(<valid>) → ok=True, empty errors/warnings, populated summary.
Mission.validate(<unknown-field>) → ok=False, ≥1 error with line+message, summary is None.
Mission.validate(<missing-BeginMissionSequence>) → ok=True, ≥1 warning, populated summary.
- Integration test against a stock GMAT sample plus a handcrafted bad script.
- Docstring carries the known-lenient-syntax callout.
Goal
Add
Mission.validate(path)— a parse-only classmethod that loads a script through GMAT, captures the engine's log, and returns structured diagnostics. TodayMission.loadexposes only the bool fromgmat.LoadScript; the actual error / warning text is written into the GMAT log file and never reaches the caller. Downstream consumers that want to surface what GMAT thinks of a script without committing to arun()(LLM authoring loops, CI lint gates, batch screening) currently have to re-implement the load-with-log-capture pattern by hand.Interface
Semantics:
LoadScript's bool-only contract by redirectingUseLogFileto a temp file across the load, scraping*** ERROR ***/Interpreter Exception:/*** WARNING ***markers, then resetting the log handle._initialize_spacecraftstepMission.loaddoes — anAPIExceptionthere setsok=Falseand lands inerrors. Does not call sandbox-widegmat.Initialize()(breaks EventLocator scripts; see the existing comment inMission.load).summaryis built viabuild_mission_summaryon success so callers get the resource + command inventory for free.Error / warning format anchors
Three patterns observed in R2026a logs:
Out of scope
Acceptance
Mission.validate(<valid>)→ok=True, empty errors/warnings, populatedsummary.Mission.validate(<unknown-field>)→ok=False, ≥1 error with line+message,summary is None.Mission.validate(<missing-BeginMissionSequence>)→ok=True, ≥1 warning, populatedsummary.