# Guided Example: A Small Pipeline, End to End

> A complete walkthrough of a roar + GLaaS pipeline — from installation to tracked lineage across a real ML run.

This guided example walks through a complete **roar + GLaaS** workflow, starting from a clean checkout and ending with a globally reproducible artifact whose lineage you can inspect in a browser.

The goal here is not to explain *everything* roar and GLaaS can do—you’ll find that elsewhere in the docs—but to show, concretely, what it feels like to use them.

We’ll:

1. Generate a few small binary artifacts
2. Combine them through a short, multi‑step pipeline
3. Inspect the inferred DAG locally
4. Register the final artifact with GLaaS
5. Navigate the lineage in the GLaaS UI
6. Reproduce the artifact from its hash and verify the result

## What we’re building

This example uses the `simple_treqs_demo` repository, which contains two tiny Python scripts:

- `produce.py` — generates a deterministic binary file of a given length
- `binary_op.py` — performs a binary operation (`--mul` or `--add`) on two inputs to produce a third output

The pipeline looks like this:

- Produce three independent input files
- Multiply them pairwise (two intermediate outputs)
- Add the intermediate outputs to produce a final artifact

There are **six steps total**, and no pipelines, configs, or annotations are declared up front. roar infers everything by observing what happens.

## Setup

### Clone the demo repository

```bash
git clone https://github.com/treqs/simple_treqs_demo.git
cd simple_treqs_demo
```

### Install roar

We recommend [**uv**](https://docs.astral.sh/uv/getting-started/installation/) for Python tooling. It’s fast, reproducible, and is what `roar reproduce` uses under the hood.

```bash
uv tool install roar-cli
```

### Initialize roar

```bash
roar init
```

This creates a local `.roar/` directory that stores job records, artifacts, and the inferred DAG.

## Running the pipeline (six steps)

We’ll run each command exactly as we normally would—just prefixed with `roar run`.

To make the example deterministic, we’ll set a seed. Put in your own random number:

```bash
export SEED=<insert a random number here>
```

### Step 1–3: produce three inputs

```bash
roar run python src/produce.py --seed $(($SEED+1)) --n 10240 data/input1.bin
roar run python src/produce.py --seed $(($SEED+2)) --n 10240 data/input2.bin
roar run python src/produce.py --seed $(($SEED+3)) --n 10240 data/input3.bin
```

Each run:

- executes the command
- records which files were written
- hashes the resulting artifact
- creates a job record

### Step 4–5: multiply inputs pairwise

```bash
roar run python src/binary_op.py --mul data/input1.bin data/input2.bin data/output1.bin
roar run python src/binary_op.py --mul data/input2.bin data/input3.bin data/output2.bin
```

Here roar observes both **reads** and **writes**, allowing it to infer dependencies automatically.

### Step 6: add the intermediate results

```bash
roar run python src/binary_op.py --add data/output1.bin data/output2.bin data/output3.bin
```

`data/output3.bin` is our final artifact.

## Inspecting the inferred DAG locally

At this point, roar has enough information to infer the pipeline structure.

```bash
roar dag
```

You’ll see a six‑step DAG showing:

- which jobs depended on which artifacts
- how intermediate outputs flowed into downstream steps
- which artifact is the final output

You can also inspect the jobs using any of the aliases @1 through @6 directly. For instance:

```bash
roar show @6
```

This shows:

- the exact command
- git repository, branch, and commit
- runtime environment (OS, Python, CPU/GPU when available)
- input and output artifacts, identified by content hash

## Registering the result with GLaaS

Now we’ll make the final artifact **globally dereferenceable**.

> **Note:** If this is your first time running roar, you'll need to set up an account with GLaaS. See [authentication docs](/docs/roar-guide#setting-up-authentication-with-glaasai-roar-auth) for more information.

```bash
roar register data/output3.bin
```

roar uploads the lineage information (not the file contents) and prints a reproduction hint:

```text
To reproduce this artifact:
  roar reproduce <artifact-hash>
```

From this point on, anyone with the hash can look up how this artifact was produced.

## Exploring lineage in GLaaS

Open [**glaas.ai**](https://glaas.ai) and paste the artifact hash into the search bar.

To see an example that we've made check on [this artifact page](https://glaas.ai/artifact/57211199e09dd60b92698b7f0bb3ee1fd854c38adcaf82c266f34e95565bb473).

### Artifact → DAG navigation

- The **artifact page** shows size, registration time, and associated jobs
- Clicking the producing job reveals execution details
- From there, you can jump to the **DAG view** showing the full lineage

This navigation is intentionally simple: follow links from result → job → DAG → other artifacts.

## Reproducing from a hash

To prove this is real, we’ll reproduce the artifact in a **fresh directory**.

```bash
mkdir ~/tmp
cd ~/tmp
```

Now reproduce using only the hash:

```bash
roar reproduce <artifact-hash>
```

roar will:

- fetch the repository at the recorded commit
- create a clean environment
- show a preview of the six planned steps

To actually run them:

```bash
roar reproduce --run <artifact-hash>
```

You’ll be prompted step‑by‑step before execution.

## Final verification (checksum)

To confirm the reproduced artifact is **bit‑for‑bit identical**, compute its hash and compare it to the original:

```bash
b3sum ~/simple_treqs_demo/data/output3.bin reproduce/simple_treqs_demo/data/output3.bin
```

You should see the same BLAKE3 hash printed twice.

This is the moment where everything clicks:

- no pipeline definition was written
- no outputs were manually logged
- no conventions were required

Yet the result is reproducible, inspectable, and globally referenceable.

## What you just saw

- roar inferred a DAG from real executions
- Artifacts were identified by content, not filenames
- GLaaS made the lineage navigable by hash
- Reproduction worked starting from the *result*, not the recipe
