Add POST /runs/import for runs executed elsewhere

A history recorded before the move (MLflow experiments) had nowhere to
go, since runs were only made by running a flow. Each entry is stored as
it ended: parameters completed and checked like a submit, cause
"import", empty commit and code digest, metrics and artifacts written
as given, nothing queued or announced. Run.external_id (new migration)
makes a second import a no-op and is an export column so a row joins
back. The request is all or nothing and capped at 200 entries;
Client.import_runs pages a longer history.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QgG6TJw5qBZzaLghQSRVrq
This commit is contained in:
2026-09-16 17:01:07 +02:00
co-authored by Claude Opus 5
parent eeaa46d4ae
commit d9630f66f5
12 changed files with 848 additions and 32 deletions
+33
View File
@@ -383,6 +383,39 @@ path (`metric.final_metrics.train_loss`) and `metrics="final_metrics.train_loss"
selects one. Inputs work the same way, and are compared leaf by leaf, so two
configurations differing in one field give that field as the axis.
### Bringing in runs made elsewhere
Runs are made by running a flow, so a history recorded before the move (an
MLflow experiment, say) has to be imported instead. Each entry names the flow,
the id the run had where it ran, and what it ended with:
```python
Client().import_runs([
{
"flow": "train",
"external_id": "mlflow:study-1/3f2a…",
"params": {"lr": 0.01},
"seed": 1001,
"status": "ok",
"created_at": "2026-03-01T10:00:00Z",
"started_at": "2026-03-01T10:00:01Z",
"finished_at": "2026-03-01T10:40:12Z",
"result": {"final_metrics": {"train_loss": 0.08}},
"metrics": [{"name": "train.train_loss", "step": 0, "ts": 1772359201.0, "value": 2.3}],
"artifacts": [{"name": "weights", "filename": "model.txt",
"media_type": "text/plain", "content_base64": "…"}],
"labels": ["imported"],
"group_id": "mlflow:study-1",
},
])
```
The parameters are completed with the flow's declared values and checked the
way a submit checks them. The run is stored with the cause `import` and no
commit or code digest, since this engine never saw the code it ran. Importing
the same `external_id` again adds nothing, and `fluksio export runs` carries
it as a column, so an exported row joins back to where it came from.
### A dashboard, read against runs
A run records values under the same names a dashboard binds to (a run of