---
title: "Api Health Running Job"
method: GET
path: "/api/health/running-job"
---

# Api Health Running Job

`GET /api/health/running-job`

## Request

- Base URL: `https://www.oxfordledge.com` (the document declares no server; this is the origin it was published from)
- URL: `https://www.oxfordledge.com/api/health/running-job`
- Auth: none declared

Is a declared long-running shell job alive on this instance?

LIVENESS, added 2026-09-22. /persistent survives the container that wrote
the declaration, so a pid alone proves nothing: after the deploy that
killed the v49 fleet reparse, this endpoint still served `running: true`
for pid 4115 on a pod where that pid does not exist, and the pre-push hook
refused the RECOVERY push until an operator removed the file by hand.
services/running_job.py compares the declaration's recorded writer
(release, host, pid start) against THIS instance; a provably dead writer
reads dead=True / running=False / stale=True, so even a pre-2026-09-22
hook that only knows `running` and `stale` degrades to its warn path.
An UNPROVABLE liveness is never treated as dead — it falls back to the
TTL, and says which it did in `liveness`.

## Response `200`

Successful Response

- RunningJobResponse: `/api/health/running-job` — is a long shell job running on this instance? OBSERVER mechanism (2026-08-31) for the Render-shell-kills-long-jobs class (7 firings across 5 dates): a deploy replaces the instance and kills any shell job mid-flight. Long jobs declare themselves via tools/shell_job.py -> /persistent/RUNNING_JOB; the pre-push hook reads THIS endpoint before pushing to main (a green main push deploys) and refuses while a declared job is fresh. Public deliberately: the pre-push hook has no admin cookie. Exposes only operator-chosen job metadata (name/age/ttl) — never command lines, paths, or pids. LIVENESS (2026-09-22). /persistent outlives the container that wrote the declaration, so freshness alone once kept a DEAD job's sentinel blocking the recovery push for its full six-hour TTL. `dead` is the endpoint's proof that the writer is gone; `liveness`/`liveness_detail` say which evidence it had. The detail is categorical because this body is public.
  - `running` boolean, required: A declared job exists, is within its TTL, and is not provably dead. The pre-push hook refuses on True.
  - `stale` boolean, required: A sentinel exists but exceeded its TTL (crashed job / missing cleanup), was unparseable, or is provably dead. Hook warns, never refuses.
  - `name` string, nullable: Operator-chosen job name from the sentinel, when present.
  - `age_minutes` number, nullable: Minutes since the job declared itself.
  - `ttl_hours` number, nullable: The TTL the job declared at launch.
  - `dead` boolean: The declaring process is PROVABLY gone (a deploy replaced the instance, or the pid exited) — the sentinel is not protecting a job, regardless of its TTL.
  - `liveness` string, nullable: absent | alive | dead | unknown. 'unknown' means liveness could not be proven either way (a pre-v2 declaration, or a platform that cannot probe pids) and the TTL decided.
  - `liveness_detail` string, nullable: Why the liveness verdict came out that way, in categorical terms safe for a public body (no pids, paths or shas).

---

[API](https://skmtc.dev/oxfordledge/apis/oxford-ledge-api.md) · [All operations](https://skmtc.dev/oxfordledge/apis/oxford-ledge-api/llms.txt) · [OpenAPI document](https://skmtc.dev/oxfordledge/apis/oxford-ledge-api/revisions/e832a1260f0b?raw)
