`get_job_status` returns YARN state + the raw response blob, so the
terminal fields (finalStatus, diagnostics, trackingUrl, startedTime,
finishedTime) are buried inside `raw` and not surfaced in a structured
form. Add a new tool that parses them.
`get_job_result(job_id)` reuses `yarn_client.get_application_status` and
extracts:
- finalStatus (SUCCEEDED / FAILED / KILLED / UNDEFINED)
- diagnostics (YARN final message)
- tracking_url (Spark Web UI)
- started_time / finished_time (epoch ms)
All five fields are optional: running jobs have no `finishedTime`, and
older YARN versions (CDH 5 / H2) may omit some fields. Missing fields
stay None — never raise.
Coexistence with `get_job_status` is intentional: the latter is for
polling the running YARN state, the former is the terminal view.
Tests: 4 cases — happy path, running job (no finishedTime), bare-minimum
raw (all optionals None), unknown job_id raises KeyError. uv run pytest
-> 171 passed.