Expose retained runs through service API

This commit is contained in:
2026-05-16 03:04:17 +02:00
parent 2412f30975
commit 2a1a53c140
8 changed files with 378 additions and 21 deletions

View File

@@ -164,6 +164,15 @@ Fetch reports after the job status is `succeeded`:
curl -sf http://127.0.0.1:8080/runs/JOB_ID/reports | python3 -m json.tool
```
Inspect retained run history, including runs produced before the current
service process started:
```sh
curl -sf "http://127.0.0.1:8080/retained-runs?runs_dir=runs" | python3 -m json.tool
curl -sf "http://127.0.0.1:8080/retained-runs/latest?runs_dir=runs" | python3 -m json.tool
curl -sf "http://127.0.0.1:8080/retained-runs/RUN_ID/artifact-manifest?runs_dir=runs" | python3 -m json.tool
```
Service job state is currently in memory for the running service process. Run
artifacts are durable in the output directory and can still be inspected after a
service restart. See `docs/SERVICE-JOB-DURABILITY.md` for the restart and

View File

@@ -144,4 +144,9 @@ podman run --rm -p 8080:8080 \
The service layer adds in-memory job tracking and HTTP transport. Execution
semantics remain the CLI/core semantics documented in
`docs/LOCAL-SERVICE-API.md`.
`docs/LOCAL-SERVICE-API.md`. Mounted run directories remain discoverable through
the retained-run endpoints, for example:
```sh
curl -sf "http://127.0.0.1:8080/retained-runs?runs_dir=/runs" | python3 -m json.tool
```

View File

@@ -98,7 +98,41 @@ errors.
### `GET /runs/{job_id}/reports`
Returns the Markdown report content, assessment package JSON, retention summary,
and their filesystem paths after a job has succeeded.
submission package JSON when present, and their filesystem paths after a job has
succeeded.
### `GET /retained-runs`
Lists durable retained run summaries by scanning a runs directory. Without a
query parameter, the service scans `<root>/runs`.
```text
GET /retained-runs?runs_dir=/runs
```
### `GET /retained-runs/latest`
Selects the latest retained run, optionally filtered by target and assessment
profile refs.
```text
GET /retained-runs/latest?runs_dir=/runs&target=sample-repository&assessment=sample-noop-assessment
```
### `GET /retained-runs/{run_id}/reports`
Returns the retained summary plus safe report paths for a durable run. This
works after a service restart because it reads `retention-summary.json` from
disk instead of in-memory job records.
### `GET /retained-runs/{run_id}/artifact-manifest`
Returns the assessment package `artifact_manifest` for a retained run. If the
run predates assessment packages, the response is compatible and returns an
empty manifest with `compatibility: "assessment-package-missing"`.
Retained-run endpoints validate report and artifact paths before returning
them. A path that escapes the selected run directory is rejected.
## Container Mode
@@ -112,5 +146,6 @@ podman run --rm -p 8080:8080 \
```
The service keeps job state in memory. Durable run evidence remains in the
mounted output directory. See `docs/SERVICE-JOB-DURABILITY.md` for the explicit
restart and recovery contract.
mounted output directory and can be discovered through `GET /retained-runs`
after restart. See `docs/SERVICE-JOB-DURABILITY.md` for the explicit recovery
contract.

View File

@@ -13,16 +13,19 @@ Durable state lives in run directories:
- `run.json`
- `plan.json`
- `sources.lock.json`
- `retention-summary.json`
- `normalized/evidence.json`
- `normalized/findings.json`
- `normalized/mappings.json`
- `reports/assessment-package.json`
- `reports/report.md`
- `reports/submission-package.json`
- `artifacts/`
The durable recovery index is the set of `retention-summary.json` files under a
runs directory.
runs directory. No separate durable service index is required for the baseline;
the service reconstructs retained-run views by scanning those summaries.
## Why In-Memory Jobs Stay The Baseline
@@ -47,9 +50,14 @@ After a service restart:
- old `job_id` values are invalid,
- `GET /runs/{job_id}` cannot recover pre-restart job metadata,
- `GET /runs/{job_id}/reports` only works for jobs known to the current process,
- run artifacts from earlier service processes remain available on disk.
- run artifacts from earlier service processes remain available on disk,
- `GET /retained-runs`, `GET /retained-runs/latest`,
`GET /retained-runs/{run_id}/reports`, and
`GET /retained-runs/{run_id}/artifact-manifest` can expose completed retained
runs after restart.
Operators should recover previous results with the CLI run-history commands:
Operators can recover previous results with either the CLI run-history commands
or the retained-run service endpoints:
```sh
PYTHONPATH=src python3 -m guide_board runs list --runs-dir runs
@@ -57,6 +65,12 @@ PYTHONPATH=src python3 -m guide_board runs latest --runs-dir runs
PYTHONPATH=src python3 -m guide_board runs report --runs-dir runs --run-id RUN_ID
```
```sh
curl -sf "http://127.0.0.1:8080/retained-runs?runs_dir=runs" | python3 -m json.tool
curl -sf "http://127.0.0.1:8080/retained-runs/RUN_ID/reports?runs_dir=runs" | python3 -m json.tool
curl -sf "http://127.0.0.1:8080/retained-runs/RUN_ID/artifact-manifest?runs_dir=runs" | python3 -m json.tool
```
## Recovery Flow
Use this flow when the service process restarted or a browser/UI lost its job
@@ -64,8 +78,9 @@ state:
1. Identify the output directory passed to `POST /runs`.
2. Confirm whether `retention-summary.json` exists.
3. If it exists, use `guide-board runs report --runs-dir <parent>` to retrieve
report paths.
3. If it exists, use `guide-board runs report --runs-dir <parent>` or
`GET /retained-runs/{run_id}/reports?runs_dir=<parent>` to retrieve report
paths.
4. If only partial files exist, inspect `run.json`, `plan.json`, and artifacts
before rerunning.
5. Rerun into a fresh output directory when the prior status is unclear.
@@ -73,8 +88,8 @@ state:
## Future Durable Index Option
A future durable service index may be added if UI or automation workflows need
cross-restart job lookup. If added, it should remain reconstructable from run
directories and should not become the authority for assessment results.
cross-restart transport job lookup. If added, it should remain reconstructable
from run directories and should not become the authority for assessment results.
The minimum acceptable durable index would contain: