# Runs

Source: https://mostlyright.md/docs/reference/cli/run/

Start one run with `run`, follow it with `watch`, and read the result with `status`, `checks`, `receipt`, `diff` and `verify`.

A run moves through seven states: `queued`, `running`, `awaiting_confirmation`, `awaiting_sample_approval`, `succeeded`, `failed` and `cancelled`. It stops in three of them, `succeeded`, `failed` and `cancelled`. There is no `released` state. A succeeded run's version is a workspace candidate the moment it exists. The first succeeded run of a table makes that table live.

Every failed run carries a failure triple: `failure_code`, `failure_detail` and `failed_stage`. The triple sits on the run record, in the terminal event and in every refusal built from it. This client refuses a record whose triple is incomplete.

## run

```bash
mr-data run --recipe RECIPE_ID --digest HEX (--sample | --full | --refresh | --backfill | --mode MODE)
            [--max-rows N] [--max-source-bytes N] [--window START END]
            [--sources-from RUN_ID] [--resource-class CLASS] [--confirm]
            [--no-activity] [--json]
mr-data run --cancel RUN_ID [--json]
```

`mr-data run` starts one run against a registered recipe under stated ceilings. The digest names which bytes of the recipe to run. This client states it and Studio checks it, never derives it. A digest that does not match the registered recipe refuses the run.

Start with `--full`. Full builds use progressive acquisition by default: an inspection checkpoint becomes available after about five minutes, then the same acquisition continues automatically. It needs no second approval or full run. Over the projection threshold Studio holds the run for confirmation before acquisition. Use `--sample` with a ceiling only for a deliberately bounded experiment; row limits do not bound acquisition time.

The client settles every argument before it resolves a credential. A command line it cannot accept never reaches the network.

| Flag | Argument | Required | Meaning | Default |
| --- | --- | --- | --- | --- |
| `--recipe` | `RECIPE_ID` | yes | The registered recipe to run. | none |
| `--digest` | `HEX` | yes | The recipe digest those bytes carry, bare lowercase hex. Checked, never derived. | none |
| `--mode` | `sample\|full\|refresh\|backfill\|compact\|replay` | one of these or a shorthand | The run mode to request. | none |
| `--sample` | none | see `--mode` | Shorthand for `--mode sample`. Run an explicit bounded experiment with a ceiling; row limits do not limit acquisition time. A source with a request window is read only for its latest lookback span. | none |
| `--full` | none | see `--mode` | Shorthand for `--mode full`. Full builds use progressive acquisition automatically. Over the projection threshold it is held for confirmation first. | none |
| `--refresh` | none | see `--mode` | Shorthand for `--mode refresh`. Run forward from where the last successful run reached. | none |
| `--backfill` | none | see `--mode` | Shorthand for `--mode backfill`. Run one exact window, stated with `--window`. | none |
| `--max-rows` | `N` | no | Stop at this many rows from each source. A recipe with eight sources can deliver eight times this many rows. | server ceiling |
| `--max-source-bytes` | `N` | no | Stop before fetching more than this from the sources. The run fails in every mode if it exceeds this limit because bytes already transferred cannot be truncated. | server ceiling |
| `--window` | `START END` | with `--backfill` | The half-open time range to cover. The start is included and the end is not. | none |
| `--sources-from` | `RUN_ID` | with `--mode replay` | Replay the retained raw inputs of this successful run. A replay never becomes live. Refused on any other mode. | none |
| `--resource-class` | `CLASS` | no | The capacity class to ask for. Studio refuses one it cannot satisfy. | server default |
| `--confirm` | none | no | Authorize the run if it is held for a confirmation, instead of printing the projection. | off |
| `--cancel` | `RUN_ID` | no | Cancel this run instead of starting one. Legal while it is queued, held or running. | none |
| `--no-activity` | none | no | Accepted, and has no effect from 0.27.1: this command tells the dataset page nothing. | off |
| `--json` | none | no | One JSON object instead of human lines. | off |

`--sample` with no ceiling at all is refused. A sample with no ceiling is a full run, dispatched and billed as one.

```json title="mr-data run --recipe … --digest … --sample --max-rows 500 --json"
{
  "schema_version": "mostlyright-thin-client-v4-run.v1",
  "status": "run_queued",
  "lane": "hosted",
  "dashboard_url": "https://mostlyright.md/datasets/d31017e0/runs/7c9e1d34-8b52-4f61-9a03-2e5d6f7a8b90",
  "watch_command": "mr-data watch 7c9e1d34-8b52-4f61-9a03-2e5d6f7a8b90",
  "run": {
    "run_id": "7c9e1d34-8b52-4f61-9a03-2e5d6f7a8b90",
    "workspace_id": "39ffafde-…",
    "recipe_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
    "recipe_digest": "9f3c…",
    "dataset_id": "d31017e0",
    "table_id": "3f8c2d10-6a4b-4c8e-9d1f-5b7a0c2e4d68",
    "mode": "sample",
    "status": "queued",
    "clamps": { "max_rows": 500 },
    "resource_class": null,
    "created_at": "2026-09-12T09:00:00Z",
    "completed_at": null,
    "coverage": null,
    "table_version_id": null,
    "candidate_digest": null,
    "sample_run_id": null,
    "full_run_id": null
  }
}
```

Values are illustrative. `status` is `run_queued` when the returned run is queued, `run_returned` when submission returns a run already in another state, `run_cancelled` under `--cancel`, and `run_confirmed` when `--confirm` settled the confirmation gate. The `run_confirmed` payload also carries `confirmed_from_status` and the three projection numbers.

```json title="held at the confirmation gate (exit 2)"
{
  "schema_version": "mostlyright-thin-client-v4-run.v1",
  "status": "run_awaiting_confirmation",
  "lane": "hosted",
  "run_id": "7c9e1d34-8b52-4f61-9a03-2e5d6f7a8b90",
  "projected_bytes": 41000000000,
  "projected_runtime_s": 3600,
  "projected_cost": "12.40",
  "confirm_command": "mr-data run --recipe 1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d --digest 9f3c… --mode full --confirm"
}
```

The run already exists, persisted `awaiting_confirmation`. `confirm_command` re-states the request that was sent, always spelled `--mode MODE` for every mode. `--confirm` authorizes the projection on it. This payload exits `2`.

Errors:

| Code | When |
| --- | --- |
| `THIN_REQUEST_INVALID` | No `--recipe`. No `--digest`. No mode. A `--sample` with no ceiling. A `--backfill` with no `--window`. |
| `THIN_ARGUMENT_INVALID` | `--mode replay` with no `--sources-from`. `--sources-from` on a mode that acquires its own inputs. A `--sources-from` that is not a run identifier. |
| `THIN_STUDIO_CONFIRM_REQUIRED` | Studio raises it and this client handles it. Without `--confirm` it becomes the `run_awaiting_confirmation` payload. |
| `THIN_RESPONSE_INVALID` | Studio held the run for a confirmation without saying what it projected. |
| `THIN_STUDIO_*` | A digest that does not match the registered recipe, a resource class Studio cannot satisfy, a cancel of a run that already finished, and the rest of Studio's refusals. |

```bash title="one full build, followed and verified"
mr-data run --recipe "$RECIPE_ID" --digest "$DIGEST" --full --json
mr-data watch "$RUN_ID"
mr-data checks "$RUN_ID" --json
```

## runs

```bash
mr-data runs [--status STATUS] [--mode MODE] [--limit N] [--json]
```

`mr-data runs` reports this workspace's own runs, newest first, narrowed by status and by mode. Use it to find a run identifier, or to see what has been happening.

| Flag | Argument | Required | Meaning | Default |
| --- | --- | --- | --- | --- |
| `--status` | one of seven | no | `queued`, `running`, `awaiting_confirmation`, `awaiting_sample_approval`, `succeeded`, `failed`, `cancelled`. A word outside this list is refused before the network. | every status |
| `--mode` | one of six | no | `sample`, `full`, `refresh`, `backfill`, `compact`, `replay`. | every mode |
| `--limit` | `N` | no | How many runs to report. The command follows the workspace's own pages until it has that many or there are no more, up to 200 pages. | `20` |
| `--json` | none | no | One JSON object instead of human lines. | off |

```json title="mr-data runs --status failed --json"
{
  "schema_version": "mostlyright-thin-client-v4-runs.v1",
  "status": "runs_listed",
  "lane": "hosted",
  "count": 2,
  "runs": {
    "run 1": { "run_id": "7c9e1d34-8b52-4f61-9a03-2e5d6f7a8b90", "mode": "refresh", "status": "failed", "created_at": "2026-09-12T08:00:00Z",
               "failure": { "failure_code": "CONTENT_LENGTH", "failure_detail": "…", "failed_stage": "acquire" } }
  },
  "next_cursor": null,
  "filters": { "status": "failed", "mode": null }
}
```

Values are illustrative. Every listed row carries those four members. A row carries `failure`, the nested triple, only on a run that failed. It carries `pages`, one sentence about page coverage, only on a run whose record holds a page-collection block.

Errors: `THIN_ARGUMENT_INVALID` for a `--status` or `--mode` naming a word this contract does not have.

```bash
mr-data runs --limit 5 --json | jq -r '.runs[] | "\(.run_id) \(.mode) \(.status)"'
```

## status

```bash
mr-data status RUN_ID [--receipts] [--json]
```

`mr-data status` reports which of the seven states one run is in, what it delivered, and why it failed. Studio refuses a run in another workspace the same way it refuses one that does not exist.

| Flag | Argument | Required | Meaning | Default |
| --- | --- | --- | --- | --- |
| `RUN_ID` | id | yes | The run to report, by the identifier the start printed. | none |
| `--receipts` | none | no | No effect here. The run record this command reads already carries the digests, sources, timings, checks and causes. The payload reports the flag under `flags_without_effect`. | off |
| `--json` | none | no | One JSON object instead of human lines. | off |

```json title="mr-data status RUN_ID --json"
{
  "schema_version": "mostlyright-thin-client-v4-run-status.v1",
  "status": "run_status_reported",
  "lane": "hosted",
  "terminal": true,
  "run": { "run_id": "7c9e1d34-8b52-4f61-9a03-2e5d6f7a8b90", "mode": "full", "status": "failed", "failed_stage": "acquire", "…": "…" },
  "pages": "…",
  "failure": { "failure_code": "CONTENT_LENGTH", "failure_detail": "…", "failed_stage": "acquire" },
  "refusal": { "code": "CONTENT_LENGTH", "detail": "…" }
}
```

Values are illustrative. `run` includes the full run record projected onto the same members `mr-data run` prints. `failure` and `refusal` appear only on a failed run. `projection` appears only on one held at the confirmation gate. `pages` is a sentence about page coverage when the run has one. The command exits `2` when `run.status` is `failed`.

Errors: `THIN_ARGUMENT_INVALID` for a positional that is not a run identifier. `THIN_NOT_FOUND`. `THIN_RESPONSE_INVALID` when a failed run's triple is incomplete.

```bash
mr-data status "$RUN_ID" --json | jq '{state: .run.status, why: .failure}'
```

## watch

```bash
mr-data watch RUN_ID [--from-seq N] [--last-event-id CURSOR] [--json]
```

`mr-data watch` follows one run's live progress and prints what it stopped on. The stream resumes across cuts on its own. `--last-event-id` resumes a watch that ended on this side. The run keeps going when nothing is watching it.

| Flag | Argument | Required | Meaning | Default |
| --- | --- | --- | --- | --- |
| `RUN_ID` | id | yes | The run to follow, by the identifier the start printed. | none |
| `--from-seq` | `N` | no | Replay from after this log position. Ignored once a cursor is known. | none |
| `--last-event-id` | `CURSOR` | no | Resume from this cursor, as a previous watch reported it. | none |
| `--json` | none | no | One JSON object instead of human lines. | off |

```json title="mr-data watch RUN_ID --json"
{
  "schema_version": "mostlyright-thin-client-v4-watch.v1",
  "status": "run_terminal",
  "lane": "hosted",
  "run_id": "7c9e1d34-8b52-4f61-9a03-2e5d6f7a8b90",
  "dashboard_url": "https://mostlyright.md/datasets/d31017e0/runs/7c9e1d34-8b52-4f61-9a03-2e5d6f7a8b90",
  "terminal_event": "run_succeeded",
  "stream": {
    "last_event_id": "88-…",
    "last_sequence": 88,
    "events_seen": 88,
    "progress_seen": 41,
    "stage": "persist",
    "stage_index": 5,
    "stage_total": 5,
    "status": "succeeded",
    "end_reason": "run_succeeded",
    "reconnects": 1,
    "halted": false,
    "expired": false,
    "failure": null,
    "diagnostic": null
  }
}
```

Values are illustrative. `terminal_event` is `run_succeeded`, `run_failed` or `null`. On `run_failed` the payload also includes `failure` and `refusal` built from the same triple, and the command exits `2`. Progress events are narration. Nothing in `stream` is evidence about the build.

Errors: `THIN_STREAM_UNAVAILABLE`, `THIN_STREAM_FRAME_INVALID`, `THIN_STREAM_LINE_TOO_LONG`, `THIN_STREAM_REFUSED`, `THIN_NOT_FOUND`.

```bash
mr-data watch "$RUN_ID" || echo "the run failed; mr-data status $RUN_ID says why"
```

## checks

```bash
mr-data checks RUN_ID [--no-activity] [--json]
```

`mr-data checks` reports how each check the recipe declared came out for one run. It exits `2` when any declared check failed.

The command reads the run record first, to learn whether the run has finished. It reads no version, no promotion and no approval.

| Flag | Argument | Required | Meaning | Default |
| --- | --- | --- | --- | --- |
| `RUN_ID` | id | yes | The run to read. | none |
| `--no-activity` | none | no | Accepted, and has no effect from 0.27.1: this command tells the dataset page nothing. | off |
| `--json` | none | no | One JSON object instead of human lines. | off |

```json title="mr-data checks RUN_ID --json"
{
  "schema_version": "mostlyright-thin-client-v4-checks.v1",
  "status": "checks_reported",
  "lane": "hosted",
  "run_id": "7c9e1d34-8b52-4f61-9a03-2e5d6f7a8b90",
  "dashboard_url": "https://mostlyright.md/datasets/d31017e0/runs/7c9e1d34-8b52-4f61-9a03-2e5d6f7a8b90",
  "run_status": "succeeded",
  "checks_scope": "version",
  "checks": {
    "check 1": { "check_id": "max_temp_within_range", "passed": true, "detail": null, "scope": "version" }
  },
  "check_count": 4,
  "checks_passed": 4,
  "checks_failed": 0
}
```

Values are illustrative. `checks_scope` comes off the run's own receipt, and is `null` when that receipt could not be read. On any scope but `version`, the payload carries a `note`. The checks ran over the rows this run added, not over every row of the version it composed.

On a failed run the payload includes empty `checks`, zero counts and the `failure` and `refusal` blocks. A required check that fails terminalizes the run, so the failure names the failed check. The command exits `2` when `checks_failed` is non-zero or the run failed.

Errors: `THIN_NO_CHECK_RESULTS` in three cases. The run has not finished, and the message names the state and points at `mr-data watch`. The run was cancelled before its checks ran. Studio has the run as succeeded and its log carries no terminal record.

```bash
mr-data checks "$RUN_ID" --json && echo "safe to publish"
```

## receipt

```bash
mr-data receipt RUN_ID [--no-activity] [--json]
```

`mr-data receipt` prints the receipt, the record of how one run was built: the sources it fetched, their digests, the timings, the checks and the causes. The document arrives verbatim under `receipt`.

| Flag | Argument | Required | Meaning | Default |
| --- | --- | --- | --- | --- |
| `RUN_ID` | id | yes | The run to read. | none |
| `--no-activity` | none | no | Accepted, and has no effect from 0.27.1: this command tells the dataset page nothing. | off |
| `--json` | none | no | One JSON object instead of human lines. | off |

```json title="mr-data receipt RUN_ID --json"
{
  "schema_version": "mostlyright-thin-client-v4-receipt.v1",
  "status": "receipt_reported",
  "lane": "hosted",
  "run_id": "7c9e1d34-8b52-4f61-9a03-2e5d6f7a8b90",
  "dashboard_url": "https://mostlyright.md/datasets",
  "artifact_id": "5e2a9c74-1d6b-4308-b9c5-8f0a3d7e2b41",
  "digest": "9f3c…",
  "size_bytes": 18422,
  "receipt": {}
}
```

Studio caps a run at one artifact per kind per attempt. A run that never retried wrote one receipt. A run that retried wrote one per attempt, and this command reads the first listed. `artifact_id` says which one.

Errors: `THIN_NO_MATCHING_ARTIFACT` when the run wrote no receipt. `THIN_ARTIFACT_TOO_LARGE`, `THIN_NOT_FOUND`.

```bash
mr-data receipt "$RUN_ID" --json | jq '.receipt'
```

## note

```bash
mr-data note --run RUN [--heading TEXT] [--cell-id ID] [--markdown-file FILE]
             [--blocks-file FILE] [--phase {acquire,parse,transform,check,persist}]
             [--checkpoint N] [--revise CELL_ID] [--list] [--json]
```

`mr-data note` writes one cell of the decision record into a run's log while the run is going. A cell is one heading and a markdown body, with typed blocks beside it. The dataset page lays out the blocks.

Writing the same cell identifier again revises that cell in place, and the superseded version stays in the log. A run's log closes when the run reaches a terminal state. Research a person will read next week goes on the [dataset](/docs/reference/cli/dataset/) instead.

A cell is not sealed. No receipt quotes it, and it is not evidence about the build.

| Flag | Argument | Required | Meaning | Default |
| --- | --- | --- | --- | --- |
| `--run` | `RUN` | yes | The run this cell is about. | none |
| `--list` | none | no | List the cells this run holds instead of writing one, superseded ones flagged. | off |
| `--heading` | `TEXT` | to write | The cell's one outcome-led line. At most 200 characters. | none |
| `--cell-id` | `ID` | no | A stable identifier. Writing it again revises the cell in place. Letters, digits, dot, dash and underscore, opening on a letter or digit, at most 64 characters. | derived from the heading |
| `--markdown-file` | `FILE` | no | The cell body as UTF-8 markdown. At most 65536 bytes. | standard input |
| `--blocks-file` | `FILE` | no | The cell's typed blocks as a JSON array of at most 64 `source`, `decision` or `clarification` objects. | none |
| `--phase` | one of five | no | `acquire`, `parse`, `transform`, `check`, `persist`, the worker protocol's own stages, so the cell lands in a bucket the log already has. | none |
| `--checkpoint` | `N` or cursor | no | The run-event sequence this cell is about, as the number or as the cursor `mr-data watch` printed beside it. | the cell's own append sequence |
| `--revise` | `CELL_ID` | no | The identifier of a different cell this one supersedes. Revising a cell under its own identifier needs no flag. | none |
| `--json` | none | no | One JSON object instead of human lines. | off |

Block fields, by kind:

| Kind | Required | Optional |
| --- | --- | --- |
| `source` | `name`, `provides`, `status` (`using`, `considered` or `rejected`) | `host`, `grain`, `coverage`, `reason` |
| `decision` | `chose`, `because` | `over` |
| `clarification` | `question` | `answer`, `answered_at` (only beside an `answer`) |

Labels are at most 200 characters, hosts 255, text 1024. A key the kind does not declare refuses rather than going unread.

```json title="mr-data note --run RUN --heading '…' --json"
{
  "schema_version": "mostlyright-thin-client-v4-narrative.v1",
  "status": "narrative_cell_appended",
  "lane": "hosted",
  "run_id": "7c9e1d34-8b52-4f61-9a03-2e5d6f7a8b90",
  "workspace_id": "39ffafde-…",
  "cell": {
    "cell_id": "dropped-station-kbos",
    "heading": "Dropped KBOS: the feed stopped in 2023",
    "checkpoint_seq": 41,
    "revision_of": null,
    "sequence": 3,
    "cursor": "3-…",
    "appended_at": "2026-09-12T09:00:00Z",
    "payload_digest": "9f3c…",
    "superseded": null,
    "markdown_bytes": 420,
    "block_count": 1,
    "phase": "acquire"
  },
  "sealed": false,
  "not_evidence": "…",
  "flags_without_effect": {}
}
```

`--list` answers `status: "narrative_listed"` with `cell_count`, `rendered_count`, `source_truncated` and `cells`.

Errors: `THIN_NARRATIVE_CELL_TOO_LARGE`, `THIN_NARRATIVE_CELL_CONTROL_CHARACTER` and `THIN_NARRATIVE_REVISION_INVALID`. `THIN_REQUEST_INVALID` for a bad `--cell-id`, a `--blocks-file` over its ceiling or holding more than 64 blocks, or a block field the kind does not declare. `THIN_RESPONSE_INVALID` when Studio does not describe the cell as unsealed.

```bash title="record why a source was dropped"
mr-data note --run "$RUN_ID" \
  --heading "Dropped KBOS: the feed stopped in 2023" \
  --phase acquire \
  --blocks-file blocks.json < body.md
```

## diff

```bash
mr-data diff LEFT RIGHT [--columns-only] [--json]
```

`mr-data diff` compares two runs and says what changed. Without `--columns-only` it compares the row count, the window covered and the data's own fingerprint as well as the columns. A run that failed at `acquire` wrote no column profile. That side reads as unknown.

| Flag | Argument | Required | Meaning | Default |
| --- | --- | --- | --- | --- |
| `LEFT` | run id | yes | The first run. | none |
| `RIGHT` | run id | yes | The second run. | none |
| `--columns-only` | none | no | Compare the columns alone, out of each run's column profile. | off |
| `--json` | none | no | One JSON object instead of human lines. | off |

```json title="mr-data diff RUN_A RUN_B --json"
{
  "schema_version": "mostlyright-thin-client-v4-comparison.v1",
  "status": "builds_differ",
  "lane": "hosted",
  "summary": "…",
  "change count": 2,
  "changes": { "change 1": "…", "change 2": "…" },
  "first run": { "run_id": "7c9e1d34-8b52-4f61-9a03-2e5d6f7a8b90", "row_count": 4100000, "columns": {}, "columns_known": true, "column_profile": "5e2a9c74-1d6b-4308-b9c5-8f0a3d7e2b41", "candidate_digest": "9f3c…" },
  "second run": { "run_id": "run_02J…", "row_count": 4210000, "columns": {}, "columns_known": true, "column_profile": "art_02J…", "candidate_digest": "a1b2…" },
  "columns not compared": [],
  "columns only": false
}
```

Values are illustrative. `status` is `builds_identical` or `builds_differ`. `columns not compared` appears only when a side wrote no column profile. `columns only` appears only under the flag.

Errors: `THIN_NO_FINGERPRINT`, `THIN_NOT_FOUND`, `THIN_ARGUMENT_INVALID`.

```bash
mr-data diff "$YESTERDAY_RUN" "$TODAY_RUN" --json | jq '.summary, .changes'
```

## verify

```bash
mr-data verify RUN_ID [--deep] [--json]
```

`mr-data verify` holds this run's table manifest against the parts it names. Without `--deep` it fetches no part, so a clean answer does not prove every part's bytes still match the manifest. With `--deep` it fetches every part this run wrote and re-hashes it against the digest the manifest states.

| Flag | Argument | Required | Meaning | Default |
| --- | --- | --- | --- | --- |
| `RUN_ID` | id | yes | The run to read. | none |
| `--deep` | none | no | Fetch every part and re-hash its bytes. | off |
| `--json` | none | no | One JSON object instead of human lines. | off |

```json title="mr-data verify RUN_ID --deep --json"
{
  "schema_version": "mostlyright-thin-client-v4-table-verification.v1",
  "lane": "hosted",
  "run_id": "7c9e1d34-8b52-4f61-9a03-2e5d6f7a8b90",
  "dashboard_url": "https://mostlyright.md/datasets",
  "deep": true,
  "status": "table_verified",
  "layout_format_version": 2,
  "manifest_digest": "9f3c…",
  "part_count": 128,
  "row_count": 4100000,
  "total_bytes": 811000000,
  "parts_read": 128,
  "findings": []
}
```

Values are illustrative. `status` is `table_verified` or `table_disagrees`. `findings` names each disagreement, and a non-empty `findings` exits `2`. `parts_read` is `0` without `--deep`.

Errors: `THIN_VERSION_PART_UNREACHABLE`, `THIN_NO_SEALED_RESULT`, `THIN_RESULT_DIGEST_MISMATCH`, `THIN_NOT_FOUND`.

```bash
mr-data verify "$RUN_ID" --deep --json | jq '{status, part_count, findings}'
```

## See also

- [CLI reference](/docs/reference/cli/): conventions, exit codes, environment variables
- [Reading a table](/docs/reference/cli/read/): `peek`, `query`, `download`, `parts`
- [Tables](/docs/reference/cli/table/): what a succeeded run makes live

## When the same run is returned

Identical submissions are idempotent. A returned failed or completed run is not a new attempt. Read `run.status`; `run_returned` does not mean queued. Failed runs return exit code 2 with the recorded failure. For recognized execution failures, the CLI supplies the existing `--retry` command. A deterministic source or recipe failure needs a corrected recipe.

## Follow several runs

```sh
mr-data watch RUN_ID_A RUN_ID_B --json
```

Watch accepts up to 16 runs and returns once all have finished, with one receipt per run. It exits 2 when any failed. Resume a single run's stream with `--last-event-id`; use the cursor returned by the previous watch rather than inventing one.
