Skip to content

orrery v0.5.0

Latest

Choose a tag to compare

@github-actions github-actions released this 17 Jul 07:37
474a571

Orrery v0.5.0 — Hardening release

A full-application review — five perspectives (Python engine, Svelte/TS frontend, Rust/Tauri layer, an adversarial pass over the seams between them, and a docs/CI sweep) — followed by fixes for everything it surfaced. No new features: this release is about correctness, crash-safety, security, and making the docs tell the truth. If you run loops unattended, this is a recommended upgrade.

All suites green: 679 engine pytest · 240 Vitest · 93 Rust unit + 10-case reducer golden-parity · 9 Playwright e2e (now gated in CI).

🛡️ Guardrail integrity (engine)

The whole premise of Orrery is that an external gate — not the model — decides green. This release closes several ways that promise could quietly break:

  • The test hash-lock now covers every configured lockGlobs pattern. Previously only the first pattern was locked, so in a multi-glob config (e.g. *.test.ts and *.spec.ts) an agent could rewrite the unlocked suite undetected. This is the most important fix in the release.
  • A judge that returns a string failingCriteria (instead of a list) no longer refutes a genuinely-green verdict character-by-character.
  • Quota survival can't spin forever. Non-probing runners (aider/codex) hitting a persistent rate limit are now capped at 4 blind waits, then surface as a real failure instead of an unbounded sleep-retry loop that bypassed maxIters and cost ceilings.
  • Crash-safe state: checkpoint.json and text writes are atomic (temp + os.replace), and the state-dir lockfile is acquired atomically (O_CREAT|O_EXCL) — closing a race where two simultaneous starts both "won" the lock.
  • A transient gh failure right after a BMAD merge degrades to the handoff path instead of crashing the driver mid-state-machine; all gh calls now carry a 120 s timeout.
  • A bad numeric value in loop.json (ceilingUsd, maxIters, …) warns and keeps the default instead of aborting the load with a traceback.

🖥️ Desktop app (Rust / Tauri)

  • LAN observe from your phone actually works now. The /ws path resolved a relative stateDir against the app's working directory instead of loops/<id>/, so a phone tailing any seeded loop saw an empty run forever. Fixed.
  • Finished loop processes are reaped — no more zombie accumulation over a long desktop session.
  • The log tailer is UTF-8-safe across read boundaries: a multibyte character flushed mid-write no longer corrupts (and silently drops) that event line.
  • Security hardening: a start.program allowlist (defense-in-depth against a hostile loop.json), the LAN token moved out of the WebSocket URL into a Sec-WebSocket-Protocol header (so it can't leak via logs/history), and a restrictive Content-Security-Policy replacing csp: null.
  • Blocking log reads and thread joins moved off the LAN server's async workers.

✨ App UI

Fast loop-switching can no longer flash the previous loop's state into the new view; a repeat verifier refutation re-surfaces the Verdict panel; the settings scope switcher is keyboard-navigable and external settings edits aren't clobbered by a focused field; the command palette keeps its selection across live ticks and surfaces run-control errors as a toast; a gate stage now requires a command; and several slow leaks (Observatory tracking maps, the alert chime's AudioContext) are fixed.

🧪 Tests, CI & docs

  • CI now runs the Playwright e2e suite alongside the engine, unit, and Rust jobs.
  • New golden case (guardrails) pins cross-reducer parity for the gate / handoff / plateau / parse_error events, which had zero coverage before.
  • The README now states the default guardrail posture honestly (held-out verify + mutation audit are opt-in), with corrected test counts and fixed doc links; PROTOCOL documents the metrics field.
  • The engine sources its version from __init__.py so app and package versions can't drift again. Dropped unused deps (@tauri-apps/plugin-opener, regex).

⚠️ Before you trust the bundles

The new CSP and the LAN subprotocol-token handshake are not exercisable by cargo test (Tauri hashes the inline bootstrap script only at bundle time). Give a built desktop bundle a quick manual smoke test — open a system, toggle theme, connect a phone over LAN — before relying on these binaries.

📦 Install

Grab a bundle from the assets below (orrery_0.5.0_*), or pip install orrery-loop for the engine alone. See the README for platform notes.

Full changelog: v0.4.0...v0.5.0