> ## Documentation Index
> Fetch the complete documentation index at: https://docs.doomberg.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Artifacts

> The 8-file backtest artifact bundle — schemas, content hashing, storage backends, and the REST API for retrieval.

Every backtest run produces a **bundle of 8 artifacts**. Together they form a complete, reproducible record of the run: what was computed, what the result was, what data and environment were used, and how to view it. Each file is content-hashed with SHA-256 for tamper detection and reproducibility verification.

## The 8-file bundle

| # | File                    | Format | Purpose                                                          |
| - | ----------------------- | ------ | ---------------------------------------------------------------- |
| 1 | `summary.json`          | JSON   | One-line overview: run id, spec ref, result hash, status.        |
| 2 | `metrics.json`          | JSON   | Full stats block (sharpe, sortino, cagr, vol, maxDD, ...).       |
| 3 | `equity_curve.json`     | JSON   | Daily equity values + dates.                                     |
| 4 | `positions.json`        | JSON   | Per-bar per-name weights and exposures.                          |
| 5 | `data_manifest.json`    | JSON   | Price panel provenance: source, symbols, date range, panel hash. |
| 6 | `environment_lock.json` | JSON   | Pinned deps: numpy version, kernel version, seed.                |
| 7 | `run_trace.json`        | JSON   | The full trace event stream for the run.                         |
| 8 | `report.html`           | HTML   | Human-readable rendered report (charts + tables).                |

### `summary.json`

```json theme={null}
{
  "run_id": "run_abc123",
  "spec_id": "spec_xyz",
  "spec_version": 3,
  "status": "succeeded",
  "result_hash": "sha256:9f2c...",
  "created_at": "2025-01-15T12:00:00Z"
}
```

### `metrics.json`

The full `stats` block from the backtest kernel. See [Backtest system](/strategy/backtest#stats-block) for the field reference.

### `equity_curve.json`

```json theme={null}
{
  "dates": ["2024-01-02", "2024-01-03"],
  "equity": [1.0, 1.0023]
}
```

### `positions.json`

Per-bar weights keyed by date, then by symbol. Used by the web UI to render position charts.

### `data_manifest.json`

```json theme={null}
{
  "source": "polygon",
  "symbols": ["NVDA", "AMD", "INTC"],
  "start": "2023-01-03",
  "end": "2024-12-31",
  "panel_hash": "sha256:1a2b..."
}
```

### `environment_lock.json`

```json theme={null}
{
  "numpy_version": "1.26.4",
  "kernel_version": "doomberg-backtest==0.4.2",
  "seed": 42,
  "python_version": "3.11.7"
}
```

### `run_trace.json`

The complete ordered list of `TraceEvent` records for the run. See [Trace events](/api/runs).

### `report.html`

A self-contained HTML file with embedded charts (equity curve, drawdown, positions) and the metrics table. Openable in any browser; no external dependencies.

## Content hashing

Every artifact file is hashed with **SHA-256** over its exact byte content. The hashes are recorded in `summary.json` (and in the run record). This gives you two guarantees:

1. **Tamper detection.** If a file is modified after the run, its hash no longer matches.
2. **Reproducibility verification.** Re-run the same spec; if the new `result_hash` matches the old one, the run is bit-identical.

<Tip>
  The `result_hash` in `summary.json` is a hash over the `metrics.json` + `equity_curve.json` + `positions.json` hashes. It's the single fingerprint of the run's numeric output.
</Tip>

## Storage backends

Ithaca supports two artifact storage backends, selected by environment:

| Backend     | When used           | Location                          |
| ----------- | ------------------- | --------------------------------- |
| `memory://` | Development / local | In-process dict; lost on restart. |
| `file://`   | Production          | `DOOMBERG_ARTIFACT_DIR` on disk.  |

<Callout type="info">
  Set `DOOMBERG_ARTIFACT_DIR` in production to a persistent, backed-up volume. Artifacts are written as individual files under `<dir>/<run_id>/<filename>`.
</Callout>

The backend is chosen at startup; runs do not pick their own backend.

## REST API

| Method | Path                  | Description                                                 |
| ------ | --------------------- | ----------------------------------------------------------- |
| `GET`  | `/api/artifacts`      | List artifact bundles for the tenant (optional `?run_id=`). |
| `GET`  | `/api/artifacts/{id}` | Fetch a single artifact bundle (all 8 files).               |

### Example: list artifacts

```http theme={null}
GET /api/artifacts?run_id=run_abc123
Authorization: Bearer dmbg_prod_...
```

```json theme={null}
{
  "artifacts": [
    { "run_id": "run_abc123", "files": ["summary.json", "metrics.json", "..."], "result_hash": "sha256:9f2c..." }
  ]
}
```

### Example: fetch a bundle

```http theme={null}
GET /api/artifacts/run_abc123
Authorization: Bearer dmbg_prod_...
```

Returns a JSON object with each file's content and hash. The `report.html` is returned as a string; the rest are parsed JSON.

## Related

* [Backtest system](/strategy/backtest) — how the bundle is produced
* [StrategySpec](/strategy/spec) — the input to a backtest
* [Trace events](/api/runs) — the `run_trace.json` contract
* [Artifacts MCP tool](/tools/artifacts) — retrieving artifacts via MCP
