Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
b743eb0
feat: follow experiment runs as they go
small-angel Nov 14, 2026
668f0c7
chore: add deliberately broken runs for run monitoring
small-angel Nov 14, 2026
f47144d
feat: declare the stages a run goes through
small-angel Nov 14, 2026
fc0d20a
feat: draw a run's declared stages
small-angel Nov 14, 2026
f1c5177
fix: keep a plan's stage totals as written
small-angel Nov 14, 2026
a955697
fix: a planned run that finished reads 100%
small-angel Nov 14, 2026
4a506c4
feat: let a view choose how a run meets its parent
small-angel Nov 14, 2026
3afde28
chore: test a view changed while its run goes
small-angel Nov 14, 2026
e22ba22
chore: read a run's line before its result lands
small-angel Nov 14, 2026
5336396
fix: keep one comparison map on the wire
small-angel Nov 14, 2026
e11bd95
fix: say No estimate once a floor runs out
small-angel Nov 14, 2026
19d2ffb
fix: time a run's stages from its earlier runs
small-angel Nov 14, 2026
d7935fa
fix: leave the whole run unknown without a plan
small-angel Nov 14, 2026
99bbfe3
fix: lead with a value that went wrong
small-angel Nov 14, 2026
dbd450d
feat: let progress() name its first stage
small-angel Nov 14, 2026
3fefeee
fix: read a stage's total from its plan
small-angel Nov 14, 2026
9fd0800
fix: say a silent run is late, not 0s left
small-angel Nov 14, 2026
db9bb6c
fix: say why a failed run failed
small-angel Nov 14, 2026
ddc01a0
fix: show the wake's log the way a person reads it
small-angel Nov 14, 2026
5c0bc0f
feat: say when a stage goes far slower than before
small-angel Nov 14, 2026
b26e61b
fix: draw a step chart from one stage's points
small-angel Nov 14, 2026
8b051dd
fix: place a stage's first report in time
small-angel Nov 14, 2026
cd8c933
fix: send a failed run's log error in its events
small-angel Nov 14, 2026
8cb05e3
feat: a skill for running an experiment
small-angel Nov 14, 2026
a2ad8ef
chore: tune the experiment-runs skill on real runs
small-angel Nov 14, 2026
1105e26
chore: teach progress() to name its stage
small-angel Nov 14, 2026
9eb0ad2
feat: declare stop rules on an experiment
small-angel Nov 14, 2026
592540b
feat: say who stopped a run
small-angel Nov 14, 2026
14f3fc9
feat: stop a run by its rules
small-angel Nov 14, 2026
fb2e80b
feat: show a stopped run as revising
small-angel Nov 14, 2026
2a85a5e
feat: show a run's rules and why it stopped
small-angel Nov 14, 2026
82957d1
chore: teach agents to declare stop rules
small-angel Nov 14, 2026
5ea37d3
fix: keep the revising note readable
small-angel Nov 14, 2026
1741c4f
fix: never act on a rule count orx cannot read
small-angel Nov 14, 2026
5bf90cf
chore: build a stop's record from who stopped it
small-angel Nov 14, 2026
e76e2c3
fix: say "no model" once in the rules list
small-angel Nov 14, 2026
0af936d
chore: run the broken runs with rules declared
small-angel Nov 14, 2026
78b3eed
feat: watch each chat's runs with a cheap model
small-angel Nov 14, 2026
f7b9e88
feat: show the watcher's journal and Look now
small-angel Nov 14, 2026
737ca5d
fix: hold the watcher to what real looks taught
small-angel Nov 14, 2026
4f7a8b2
chore: tidy the watcher and pin its contracts
small-angel Nov 14, 2026
4a9ea99
fix: read a run's watch once per change
small-angel Nov 14, 2026
4fa2502
fix: show the Watch section only with something to say
small-angel Nov 14, 2026
7ab6381
chore: say what each look said in the fault bed's shots
small-angel Nov 14, 2026
23bf268
fix: keep a flood of cited lines to its first twelve
small-angel Nov 14, 2026
01f83eb
fix: typecheck the run view e2e spec
small-angel Nov 14, 2026
1dd071b
feat: flag a run that may be going wrong
small-angel Nov 14, 2026
e34fba2
chore: teach agents the watch brief and flags
small-angel Nov 14, 2026
8eb8e25
fix: tell a silent log from a scan catching up
small-angel Nov 14, 2026
afe806e
fix: let a look name a past step and match its parent
small-angel Nov 14, 2026
a3d9d3b
fix: scan each field a look sends before encoding
small-angel Nov 14, 2026
f55651a
fix: compare a run with its parent in one stage
small-angel Nov 14, 2026
47919b8
fix: claim a flag's Stop before cancelling the run
small-angel Nov 14, 2026
ff37722
fix: take a failed last look of a run again
small-angel Nov 14, 2026
f9095cc
fix: note a look's flag under the one still open
small-angel Nov 14, 2026
7b56f58
fix: read a run's log only as far as its fold has
small-angel Nov 14, 2026
4a816aa
fix: back off when Codex's model list can't be read
small-angel Nov 14, 2026
baff264
fix: keep a Keep going to the run it was chosen on
small-angel Nov 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ repository = "https://github.com/alphaXiv/OpenResearch"
license = "MIT"

[workspace]
members = ["tests/support", "crates/orx-host-proto", "crates/orx-host"]
members = ["tests/support", "crates/orx-host-proto", "crates/orx-host", "crates/orx-signals"]
exclude = ["windows/launcher"]
default-members = [".", "tests/support", "crates/orx-host-proto", "crates/orx-host"]
default-members = [".", "tests/support", "crates/orx-host-proto", "crates/orx-host", "crates/orx-signals"]

[target.'cfg(unix)'.dev-dependencies]
orx-test-support = { path = "tests/support" }
Expand Down Expand Up @@ -55,6 +55,10 @@ semver = "1"
fd-lock = "4"
# Splits a pasted `ssh …` command (src/jobs/ssh/hosts.rs); already in the tree via portable-pty.
shell-words = "1"
# The watcher's count tokens and its sentence length (src/engine/watch); both already in the tree,
# regex through orx-signals and unicode-segmentation through the desktop window (tao).
regex = { version = "1", default-features = false, features = ["std", "unicode-perl", "perf"] }
unicode-segmentation = "1"
base64 = "0.22"
once_cell = "1"
# Uploaded skills (.zip of a SKILL.md folder) and shared projects (.orx). Lean:
Expand All @@ -77,6 +81,7 @@ portable-pty = "0.9"
# async fns in the Harness trait (object-safe `dyn Harness` in the registry).
async-trait = "0.1"
orx-host-proto = { path = "crates/orx-host-proto" }
orx-signals = { path = "crates/orx-signals" }
sha2 = "0.10"
hmac = "0.12"
# Import the Overleaf editor session cookie from a local browser store, so the
Expand Down
5 changes: 4 additions & 1 deletion SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,11 @@ group below has a module (`orx skill <name>`) with the full flags and rules.
| `orx compute instructions show --json` | Read the machine-wide custom recipe and its revision before configuring or launching. |
| `orx compute [--gpu <id>] [--count <n>] [--provider <name>]` / `orx compute --cpu` | List the GPU/CPU compute catalog. |
| `orx instance create <orgId> (--gpu <id> … \| --cpu <flavor> …)` | Spin up a standalone instance in an org; see `orx-instances`. |
| `orx exp status/run/cancel/wait/wake <localExpId>` | Inspect, run, cancel, wait on, or register a wake-up for a local experiment node. |
| `orx exp status/run/cancel/wait/wake <localExpId>` | Inspect (with the latest run's stage, estimate and measures), run, cancel, wait on, or register a wake-up for a local experiment node. |
| `orx exp flag <runId> --flag <flagId> (--keep \| --ask \| --stop) [--reason "<why>"]` | Settle a flag that woke you, after reading the run yourself: keep it going, leave the choice to the user, or stop it; see `orx-experiment-runs`. |
| `orx exp move/archive/unarchive/delete <localExpId>` | Re-parent, hide, restore, or permanently delete experiment nodes; see `orx-experiment-tree`. |
| `orx exp desc <expId> [--set "<text>" \| --stdin]` | Read or overwrite the experiment's description. |
| `orx exp view set <expId> [--file <view.xml>] [--pattern <patterns.json>] [--config <plan.json>]` / `view get <expId>` / `view check <runId>` | Set what an experiment's runs show and the stages they go through (copied into children), print it, or check it against a run's real log; see `orx-experiment-runs`. |

To **read or edit** a node's code—including diffing what a run changed—use plain
Git in the local session worktree. See the `orx-git` module.
Expand Down Expand Up @@ -134,6 +136,7 @@ The detail lives in focused modules — load one with `orx skill <name>` (the bu
list, with one-line descriptions, is printed at the end of `orx skill` output):

- **orx-experiment-tree** — the experiment-tree model, the auto-research loop, and `orx exp desc`.
- **orx-experiment-runs** — a run the user can follow: its stage plan, progress and measures, its view and comparisons, patterns, the first-minutes check, and changes mid-run.
- **orx-create** — initialize a local project and add local experiment nodes.
- **orx-compute** — launch and monitor runs; after resolving the backend, read its bundled reference.
- **orx-instances** — create persistent standalone machines for manual work.
Expand Down
7 changes: 7 additions & 0 deletions SYSTEM_PROMPT.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ When asked to run and summarize an experiment, load `orx-compute` and
`orx-results` before launching: execution and interpretation are separate skill
areas. Use `orx-logs` when retrieving supporting output.

Before a baseline's first launch, load `orx-experiment-runs` and make the run
followable without asking you: its stages declared, each stage's progress and
the measures that answer the question reported, a view that shows them, and
its first minutes checked. Children inherit these. Load it again whenever the
user asks to change what a run shows. Use `orx exp status <expId>` for a run's
live stage and numbers.

Use `orx` as the source of truth for the experiment tree, runs, and logs. Use
normal repository tools for code and file inspection. Use this project id
(`{id}`) for every `orx` command that takes one.
Expand Down
15 changes: 13 additions & 2 deletions agent-skills/orx-compute/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,24 @@ Remote backends receive that snapshot; Tinker extracts it for a local controller
whose SDK sends model operations remotely.

```sh
orx exp status <expId> # branch, parent, run command, latest run + commit
orx exp status <expId> # branch, parent, run command, latest run: stage, estimate, measures
orx compute # browse GPU offers across all providers
orx compute --gpu H100_SXM --count 1 # filter GPU offers
orx compute --cpu # browse CPU-only offers
orx exp run <expId> # launch on the configured default
orx exp cancel <expId> # cancel the in-flight run
orx exp cancel <expId> --reason '…' # cancel the in-flight run, saying why
```

## Follow a run

A baseline reports its stages and measures and has a view before its first
launch; children inherit them. How to write and change them: `orx-experiment-runs`.

`orx exp status <expId>` shows a run's stage, estimate and measures; `--run
<runId> --json` gives the stored checkpoint with its coverage and diagnostics.
Signals are advisory: confirm trouble in the raw log before changing the
experiment.

## Inspect configuration and custom instructions first

Before configuring compute or constructing a launch command:
Expand Down Expand Up @@ -164,3 +174,4 @@ session waiting for results.
- Escalate after a real OOM or hopelessly slow run instead of starting with the
largest accelerator.
- Raise the timeout only for genuinely long runs.

117 changes: 117 additions & 0 deletions agent-skills/orx-compute/assets/orx_run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
"""Advisory run signals. Vendor with `orx skill compute/assets/orx_run.py`."""

import atexit
import contextlib
import json
import math
import os
import sys
import threading
import time


_lock = threading.RLock()
# One clock per process, from its first progress(), so `t` restarts at zero only in a new process.
_origin = None


def _stage(total, unit):
"""A stage's total and unit, leaving out each one not given so the phase keeps what it has."""
return {key: value for key, value in (("of", total), ("unit", unit)) if value is not None}


def plan(stages, rank=None):
"""Declares every stage the run goes through, in order, replacing any plan declared before.

Each stage is a name, or a dict with "phase" and optionally "of" and "unit":
plan(["install", {"phase": "train", "of": 5000, "unit": "steps"}, "eval"]).
A stage that runs again is listed again where it recurs, never twice in a row.
"""
listed = []
for stage in stages:
stage = {"phase": stage} if isinstance(stage, str) else dict(stage)
name = stage.get("phase")
if not isinstance(name, str) or not name:
raise ValueError(f"each stage needs a phase name, got {stage!r}")
if listed and listed[-1]["phase"] == name:
raise ValueError(f"{name!r} is listed twice in a row; list it again only after another stage")
listed.append(stage)
if rank is None:
rank = int(os.environ.get("RANK") or os.environ.get("SLURM_PROCID") or "0")
if rank == 0:
with _lock:
sys.stdout.write("::orx:: " + json.dumps({"plan": listed}, separators=(",", ":")) + "\n")
sys.stdout.flush()


class progress:
def __init__(self, total=None, unit=None, rank=None, interval=1.0, start=0, phase=None):
if rank is None:
rank = int(os.environ.get("RANK") or os.environ.get("SLURM_PROCID") or "0")
self._enabled = rank == 0
self._interval = max(0.0, float(interval))
self._pending = None
self._lock = _lock
with self._lock:
global _origin
if _origin is None:
_origin = time.monotonic()
# Naming the phase here lets a script with no shell around it start in a named stage.
named = {} if phase is None else {"phase": phase}
self._write({**named, "step": start, **_stage(total, unit)})
atexit.register(self.flush)

@staticmethod
def _metrics(metrics):
result = {}
for key, value in metrics.items():
if not isinstance(value, (str, int, float, bool, type(None))) and hasattr(value, "item"):
value = value.item()
json.dumps(value, allow_nan=True)
result[key] = value
return result

def _write(self, record):
if self._enabled:
record = {**record, "t": time.monotonic() - _origin}
sys.stdout.write("::orx:: " + json.dumps(record, allow_nan=True, separators=(",", ":")) + "\n")
sys.stdout.flush()
self._last = time.monotonic()

def flush(self):
with self._lock:
if self._pending is not None:
self._write(self._pending)
self._pending = None

def step(self, step, **metrics):
with self._lock:
metrics = self._metrics(metrics)
merged = {} if self._pending is None else self._pending["m"].copy()
merged.update({key: value for key, value in metrics.items() if value is not None})
self._pending = {"step": step, "m": merged}
nonfinite = any(isinstance(v, float) and not math.isfinite(v) or
isinstance(v, str) and v in ("NaN", "Infinity", "-Infinity")
for v in metrics.values())
if nonfinite or time.monotonic() - self._last >= self._interval:
self.flush()

@contextlib.contextmanager
def phase(self, name, total=None, unit=None):
with self._lock:
self.flush()
self._write({"phase": name, "step": 0, **_stage(total, unit)})
try:
yield self
finally:
self.flush()

def row(self, name, **cells):
with self._lock:
self.flush()
self._write({"row": name, "m": self._metrics(cells)})

def spend(self, cumulative_usd):
with self._lock:
self.flush()
self._write({"spend": cumulative_usd})
4 changes: 4 additions & 0 deletions agent-skills/orx-create/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@ orx create-experiment <localProjectId> --title "Alternative baseline" --baseline
the oldest root unless `--baseline` explicitly requests another root.
- A child branches from its parent's Git branch and inherits its run
command. Vary code or configuration on the child; keep the command fixed.
- `--title` is what the user reads beside the node's progress among its
siblings: short, the setting that varies first ("Depth 4 at 2e15 FLOPs").
- `--description` should state the concrete change and measurement the node
owes.
- Before a baseline's first run, declare its stages, report its measures and
set its view (`orx-experiment-runs`).
- Commit the node's branch before launching. Runs use an immutable archive of
that local commit.
Loading
Loading