StoredRun, LocalExperiment, and LocalProject Types in orx: A Complete Guide

The orx CLI relies on three distinct Rust types—StoredRun for SQLite persistence, LocalExperiment for runtime experiment metadata, and LocalProject for workspace organization—to manage research artefacts locally without requiring remote services.

The alphaXiv/OpenResearch repository provides a local-first research execution framework where StoredRun, LocalExperiment, and LocalProject types form the backbone of state management. These structs separate persisted database records from in-memory workspace representations, enabling the CLI to query, create, and manipulate experiments consistently across local and synced environments.

StoredRun: The SQLite Persistence Layer

Definition and Location

The StoredRun struct is defined in src/store.rs at approximately line 202 and serves as the canonical database representation of an experiment execution. This type maps directly to SQLite rows and contains all fields necessary to reconstruct a run's state across CLI sessions.

Core Fields

According to the source analysis, StoredRun includes the following fields:

pub struct StoredRun {
    pub id: String,
    pub experiment_id: String,
    pub project_id: String,
    pub status: String,
    pub start_ms: i64,
    pub end_ms: Option<i64>,
    pub backend_json: Option<String>,
    // ... additional optional fields
}

Database Row Conversion

When fetching data from the SQLite store, orx uses the row_to_run helper function located around line 2960 in src/store.rs. This function transforms database rows into StoredRun instances, handling the conversion of SQL types to Rust String and i64 primitives. The store module also provides upsert_run, get_run, and list_runs methods for database operations.

LocalExperiment: Lightweight In-Memory Views

Purpose and Structure

LocalExperiment (commonly aliased as Experiment in the codebase) lives in src/local/mod.rs and provides a lightweight, in-memory view of experiment metadata tailored for CLI operations. Unlike StoredRun, which focuses on execution state, LocalExperiment focuses on experiment configuration and metadata.

Conversion from Persisted State

The bridge between the database layer and the local workspace is implemented through conversion traits. The impl From<&StoredRun> for Run (approximately line 16 in src/local/mod.rs) extracts relevant fields from a StoredRun to populate the local Run struct. A similar pattern exists for experiments, allowing the CLI to enrich workspace file data with persisted execution history from the store.

LocalProject: Workspace Project Organization

Project Structure Definition

LocalProject (aliased as Project) is defined in src/local/projects.rs and represents a project that groups related experiments and runs. In local mode, orx reads project definitions from workspace files (such as project.toml) and instantiates LocalProject structs to organize the CLI's view of the research workspace.

Key Utility Functions

The src/local/projects.rs module exposes several critical functions for project management:

  • list_projects – Enumerates all projects in the local workspace
  • resolve_project – Locates a specific project by identifier
  • run_duration_secs – Computes execution durations using the start_ms and end_ms fields from associated runs

Type Relationships and Data Flow

Understanding how these types interact requires examining the conversion pipeline implemented across the codebase:

  1. Persistence Layer – StoredRun, StoredExperiment, and StoredProject reside in the SQLite database (src/store.rs) and serve as the source of truth for execution history
  2. Local Layer – Conversion helpers in src/local/mod.rs transform &StoredRun references into Run instances (public API types), while src/local/projects.rs handles analogous transformations for projects
  3. API Layer – The impl From<&StoredRun> for ApiRun conversion located around line 800 in src/commands/up.rs prepares data for serialization, with src/plane.rs containing the Run struct that bridges stored and API representations

Practical Usage Examples

Creating and Storing a New Run

use orx::store::Store;

let store = Store::open()?;
let new_run = StoredRun {
    id: uuid::Uuid::new_v4().to_string(),
    experiment_id: "exp-42".into(),
    project_id: "proj-alpha".into(),
    status: "pending".into(),
    start_ms: chrono::Utc::now().timestamp_millis(),
    end_ms: None,
    backend_json: None,
    // ... other optional fields
};
store.upsert_run(&new_run)?;

Resolving Local Workspace Entities

// Resolve a specific run from the local workspace
let run_handle = orx::local::resolve::resolve_run(&store, "run-123")?;
println!("Run {} has status {} ", run_handle.id, run_handle.status);

// List all projects with their experiment counts
let projects = orx::local::projects::list_projects(&store)?;
for project in projects {
    println!("Project {} contains {} experiments", 
             project.name, 
             project.experiments.len());
}

Command-Line Interface Operations


# Display run details (triggers StoredRun → Run conversion)

orx runs show <run-id>

# List experiments within a specific project

orx exp list --project <project-id>

# Create a new run (internally constructs StoredRun)

orx run create --experiment <exp-id> --backend docker

Summary

  • StoredRun is the authoritative database representation in src/store.rs, containing execution state, timestamps, and backend configuration JSON for SQLite persistence
  • LocalExperiment provides lightweight, in-memory experiment metadata in src/local/mod.rs, built from workspace files and enriched with stored execution data via From trait implementations
  • LocalProject organizes experiments and runs in src/local/projects.rs, offering workspace-aware project resolution and duration calculations
  • Conversion helpers in src/local/mod.rs (line 16) and src/commands/up.rs (line 800) bridge the gap between SQLite storage and API serialization

Frequently Asked Questions

What is the difference between StoredRun and LocalExperiment?

StoredRun represents a single execution instance persisted in SQLite with fields like status, start_ms, and backend_json, while LocalExperiment represents the experiment definition itself—containing metadata such as name and description—typically loaded from workspace configuration files and held in memory during CLI operations.

Where does orx store the LocalProject configuration?

LocalProject configuration originates from workspace definition files (such as project.toml) in the user's working directory, then gets enriched with execution data from the SQLite store via the resolution functions in src/local/projects.rs.

How does orx convert database rows into runtime types?

The row_to_run helper function in src/store.rs (around line 2960) converts SQLite rows into StoredRun structs, while conversion traits like impl From<&StoredRun> for Run in src/local/mod.rs transform these stored types into local workspace representations used by the CLI.

Can I access StoredRun directly without using the local type wrappers?

Yes, you can interact directly with StoredRun through the store module's public methods such as upsert_run, get_run, and list_runs defined in src/store.rs, though the CLI typically prefers the LocalExperiment and LocalProject wrappers for workspace-aware operations that combine file-based configuration with database state.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →