Every test run, in one queryable record.
Orrery is Cthonica’s analysis backend. Astrolabe sends it every run from the bench. Orrery checks each one against rules you write, explains what changed, and keeps a record your QA, firmware, and release teams can search months later.
Channel 3 temperature during soak, from run-20251014-140311 on DEV-00391, firmware v2.3.1.
- Shaded band
- Two standard deviations either side of the golden run for plan-thermal-v4.
- At 812 seconds
- Channel 3 reads 74.1 °C, 4.2 °C over baseline. The drift rule fires.
- On the same run
- Stall recovery takes 312 ms against a 180 ms baseline. Orrery links the two.
What happens to that run
The bench finished at 14:18 on 14 October. Here is everything Orrery did with the run, in order, with the files it read and wrote along the way.
-
Astrolabe uploads the run
Astrolabe asks for presigned URLs, then streams the manifest and NDJSON artifacts straight to storage. Uploads are idempotent by
run_idand resume where they stopped, so a dropped bench connection never makes a duplicate.POST /api/v1/runs/upload { "run_id": "run-20251014-140311", "project": "prod-validation", "plan": "plan-thermal-v4", "manifest_sha256": "a7b3…" }
-
Checksums and schema are verified
Every file is checked against its SHA-256 from the bench. The manifest is checked against the schema before anything else reads it, so a malformed run is rejected at the door instead of surfacing later as a strange chart.
Verification results File Size Result manifest.json 4.1 KB sha256 matches channels.ndjson 10,840 rows sha256 matches events.ndjson 212 rows sha256 matches schema v3 valid -
A rule fires
Rules are YAML files versioned with your test plan: thresholds, regressions against a golden run, schema checks, and signal shape. Each rule is pinned to the plan version that ran it, so re-checking an old run gives the same answer it gave then.
# rules/thermal/temp_drift.yaml id: temp_drift_exceeds_2σ kind: regression severity: critical plan: plan-thermal-v4 match: channel: "channels.ndjson:temp_c" where: "phase == 'soak'" assert: type: band baseline: plan.golden_run tolerance: 2 # σ duration_ms: 500
-
Claude writes the analysis
Claude Sonnet reads the run’s artifacts next to the golden run and writes down what changed, which rules fired, and the likely cause. Every claim points at the rows it came from, so an engineer can check it in one click.
{ "verdict": "failed", "rules_fired": ["temp_drift_exceeds_2σ", "stall_recovery_slow"], "likely_cause": "thermal protection is throttling the stall recovery loop", "evidence": [ { "artifact": "channels.ndjson", "lines": "8144-8210", "value": 74.1 }, { "artifact": "channels.ndjson", "line": 9002, "stall_recovery_ms": 312 } ], "compared_to": "run-20251013-174501" } -
CI hears about it
The
run.analyzedwebhook fires as soon as the analysis is saved. CI, Slack, or a release script can act on the verdict without polling.{ "event": "run.analyzed", "run_id": "run-20251014-140311", "verdict": "failed", "permalink": "https://orrery…/r/…140311" } -
The device’s history grows by one
Every serial number has a record: firmware history, calibration events, and every run it has produced. DEV-00391’s lifetime pass rate now includes this failure.
- Device
- DEV-00391
- Runs
- 238
- Lifetime pass rate
- 94.1%
- Firmware
- v2.2.8, v2.2.9, v2.3.1
- Last calibrated
- 2025-09-30
-
Someone finds it again
Two days later a firmware engineer asks which v2.3 runs tripped the drift rule. Filter by project, device, firmware, status, rule, plan version, or any manifest field, then share the URL or export the results as CSV or JSONL.
GET /api/v1/runs?project=prod-validation &fw=v2.3.* &rule=temp_drift_exceeds_2σ &status=failed # 3 runs, newest first
-
The release report is signed
Sign-off produces a PDF and JSON record that can’t be edited. It links to the exact manifests, artifacts, and rules behind it, including this failure and its fix. Re-running the analysis later will not change the signed record.
- Report
- release-2.3.1
- Runs included
- 214
- Failures, each linked
- 3
- Signed by
- QA lead
- pdf_sha256
- 9c1e…f04a
What your team opens each morning
One project: the runs that landed, the rules that fired, and links to each analysis. Open a run or filter the list. The line above the tabs is the link you would share, and it uses the same filters as the API.
Link to this view
Recent runs
| Run | Device | Firmware | Plan | Status |
|---|
Rules fired today
- Critical
- Warning
- Info
Pick a rule to see every recent run it fired on.
What Orrery stores
Seven entities. Every screen, API call, and report is a view over them.
- Run
- id project device_id firmware plan_id status started_at finished_at manifest_sha256
- Manifest
- run_id env inputs capture_source astrolabe_version schema_version
- Artifact
- run_id kind s3_uri sha256 bytes rows
- Device
- id serial model firmware_history first_seen runs_total
- Plan
- id version rules golden_run channels
- Rule
- id kind severity spec plan_version
- Report
- id scope runs signed_by signed_at pdf_sha256
Three endpoints carry the whole product
Astrolabe calls these so you don’t have to. The dashboard, rules engine, and reports are all built on the same three.
| Method | Path or event | What it does |
|---|---|---|
| POST | /api/v1/runs/upload | Returns presigned URLs for the manifest and artifacts. Idempotent on run_id. |
| GET | /api/v1/runs | Queries runs by any manifest field, with cursor pagination. Uses the same filters as dashboard URLs. |
| Webhook | run.analyzed | Sent when an analysis is saved, with the verdict, rules fired, and a permalink. |
Before and after a shared backend
Shared drives and tribal knowledge
- Each engineer has their own folder layout, and the schema lives in someone’s head.
- A failed run is a screenshot in Slack and a CSV nobody can find a week later.
- Regressions are caught when a customer files a ticket, not when the bench produces them.
- Release sign-off is a meeting, and the evidence is whatever was on screen at the time.
One backend, one schema, one URL per run
- Every run arrives with its manifest, checksums, and plan version, and the schema is enforced on upload.
- A failed run has a permalink, its artifacts, the rules that fired, and a written analysis.
- Regressions show up when the rule fires, and the webhook tells CI before anyone opens the dashboard.
- Release sign-off is a signed report that traces back to the exact files behind it.
Tour Orrery with your own data
A 30-minute walkthrough with your test data, your devices, and one of your plans set up. No slides.
Hosted, or single-tenant on request. Analysis by Claude Sonnet. Runs stored in S3 and Postgres.