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 workspaceresolve_project– Locates a specific project by identifierrun_duration_secs– Computes execution durations using thestart_msandend_msfields from associated runs
Type Relationships and Data Flow
Understanding how these types interact requires examining the conversion pipeline implemented across the codebase:
- Persistence Layer –
StoredRun,StoredExperiment, andStoredProjectreside in the SQLite database (src/store.rs) and serve as the source of truth for execution history - Local Layer – Conversion helpers in
src/local/mod.rstransform&StoredRunreferences intoRuninstances (public API types), whilesrc/local/projects.rshandles analogous transformations for projects - API Layer – The
impl From<&StoredRun> for ApiRunconversion located around line 800 insrc/commands/up.rsprepares data for serialization, withsrc/plane.rscontaining theRunstruct 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
StoredRunis the authoritative database representation insrc/store.rs, containing execution state, timestamps, and backend configuration JSON for SQLite persistenceLocalExperimentprovides lightweight, in-memory experiment metadata insrc/local/mod.rs, built from workspace files and enriched with stored execution data viaFromtrait implementationsLocalProjectorganizes experiments and runs insrc/local/projects.rs, offering workspace-aware project resolution and duration calculations- Conversion helpers in
src/local/mod.rs(line 16) andsrc/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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →