EMRY-015: RunSession + Engine API — Emry runs end-to-end #60

Merged
vxfemboy merged 2 commits from emry-015-run-session into main 2026-06-25 04:06:10 +00:00
vxfemboy commented 2026-06-25 03:32:00 +00:00 (Migrated from github.com)

Closes EMRY-015 (#13). Branched off main. Emry is now runnable end-to-end.

What

crates/emry-engine/src/session.rsEngine::start(RunConfig) -> RunHandle assembles every M0/M1 piece into a live run:

  • ring (producer on training thread / consumer on worker thread)
  • bounded EventBus for observers
  • AnomalyDetector per metric → Event::Alert
  • JsonlSink writing events.jsonl (audit) + metrics.jsonl (wide rows)

RunHandle: emit(&[(MetricId,f64)]) (fast, lock-free ring push), emit_dynamic (slow, name-resolving), set_phase, set_epoch, finish. The worker drains the ring, persists, publishes, and runs anomaly detection. finish() drains+flushes everything; Drop marks the run interrupted.

examples/synthetic_run.rs is the runnable demo — confirmed locally: a 200-step loop produced RunStarted → 200 batches → a spike Alert at step 120 (z=147) → RunFinished, plus a 200-row metrics.jsonl with resolved names.

Architecture note

emry-engine now depends on emry-store (engine orchestrates persistence). No cycle (store depends only on core). This corrects the core→engine→store flow I'd noted earlier — the real direction is engine→store.

Verification

  • ./scripts/pre-commit-rust.sh green: clippy -D warnings, 41 engine tests, session.rs 95% lines, total 97.68%
  • Ran the demo binary; inspected both JSONL files
  • Tests: synthetic run file contents, NaN→alert, emit_dynamic, set_phase, Drop-interrupted, missing-dir error, bus observer

Self-review fix (review agent hit a session limit)

Found and fixed a hang: if the ring is full at finish(), the RunFinished push is dropped and the worker would never terminate → join() hangs forever. finish_with now also raises the stop flag, so the worker always exits (then drains the ring; a pushed RunFinished is still written).

Deferred

EMA/Welford/throughput processor wiring into the session → EMRY-022 (their DerivedMetrics need a DerivedState/TUI consumer). Anomaly is wired now because Event::Alert has a home.

Closes EMRY-015 (#13). Branched off `main`. **Emry is now runnable end-to-end.** ## What `crates/emry-engine/src/session.rs` — `Engine::start(RunConfig) -> RunHandle` assembles every M0/M1 piece into a live run: - ring (producer on training thread / consumer on worker thread) - bounded `EventBus` for observers - `AnomalyDetector` per metric → `Event::Alert` - `JsonlSink` writing `events.jsonl` (audit) + `metrics.jsonl` (wide rows) `RunHandle`: `emit(&[(MetricId,f64)])` (fast, **lock-free** ring push), `emit_dynamic` (slow, name-resolving), `set_phase`, `set_epoch`, `finish`. The worker drains the ring, persists, publishes, and runs anomaly detection. `finish()` drains+flushes everything; `Drop` marks the run interrupted. `examples/synthetic_run.rs` is the runnable demo — confirmed locally: a 200-step loop produced RunStarted → 200 batches → a spike `Alert` at step 120 (z=147) → RunFinished, plus a 200-row `metrics.jsonl` with resolved names. ## Architecture note `emry-engine` now depends on `emry-store` (engine orchestrates persistence). No cycle (store depends only on core). This corrects the `core→engine→store` flow I'd noted earlier — the real direction is engine→store. ## Verification - `./scripts/pre-commit-rust.sh` green: clippy `-D warnings`, 41 engine tests, session.rs 95% lines, total 97.68% - Ran the demo binary; inspected both JSONL files - Tests: synthetic run file contents, NaN→alert, emit_dynamic, set_phase, Drop-interrupted, missing-dir error, bus observer ## Self-review fix (review agent hit a session limit) Found and fixed a **hang**: if the ring is full at `finish()`, the `RunFinished` push is dropped and the worker would never terminate → `join()` hangs forever. `finish_with` now also raises the stop flag, so the worker always exits (then drains the ring; a pushed RunFinished is still written). ## Deferred EMA/Welford/throughput processor wiring into the session → EMRY-022 (their `DerivedMetric`s need a `DerivedState`/TUI consumer). Anomaly is wired now because `Event::Alert` has a home.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
femboy/emry!60
No description provided.