Skip to content

v0.5.7 — Instrument-flow: 10Hz cockpit + dual-curve canvas

Choose a tag to compare

@zzallirog zzallirog released this 13 May 05:20

Daemon tick rate raised from 1 Hz to 10 Hz on the same hardware after caching synchronous chroma stats off the hot path. Cockpit gains a horizon toggle (+5s / +15s / +30s, default +5s) plus a second forecast line — pure hardware-current Newton trajectory laid over the KNN-anchored archive envelope, so the operator reads the gap between the two curves as installed cooling margin instead of one ambiguous prediction.

New surface

  • Multi-horizon toggle in the cockpit — segmented control [ +5s | +15s | +30s ] with a meta-led / balanced / archive-led weight label. Backend ships forecasts: {h5, h15, h30} sampled from the same meta-anchored saturation curve; UI picks which point to render. Selection persisted in localStorage. The Δ block, canvas span, and forecast curve endpoint all respect the active horizon.
  • Dual-curve canvas — hardware-current Newton τ=4s trajectory drawn alongside the existing KNN-anchored saturation curve. Solid teal reads as «now», dashed teal as «remembered»; the gap is the installed cooling margin.
  • Signed ±err pills — negative median residual reads as «cooling outperforms historical envelope» (teal/cooling tint) instead of an alarming red. Red is reserved for positive median (real under-prediction warning). Backend exports median_signed_err_c alongside median_abs_err_c.
  • spike_detector predictor-margin exit gate — a spike that opens on a real residual but then stays open because the predictor systematically over-predicts (signed residual ≤ −N°C for M ticks) now closes with closure_reason=\"predictor_margin_exceeded\". Distinguishes «predictor was right, cooling caught up» from «real interactive burst calmed» in the incident journal.

Changed

  • Daemon tick rate 1 Hz → 10 Hz (DEFAULT_PERIOD = 0.1). Hot path is sample → cached predict → cached decision → store → ml-state dump → out (~25 ms steady-state). Periodic ops (backfill_labels, drift history, chroma stats refresh) keep their wall-clock cadence via ticks_per_sec scaling.
  • Chroma writes moved to a background drain worker (bounded queue, single consumer — chroma client is not thread-safe for concurrent writes). Per-tick chroma.add no longer blocks the tick loop on HNSW index rebuild.
  • Chroma stats cached. chroma.count(), count_labeled(), dir_size_bytes() previously walked the 42k-vector HNSW index on every _dump_ml_state (~6-25 s). Refreshed every 30 s off the hot path.
  • Cockpit canvas repaint is signature-gated — repaints only when data has materially changed, eliminating per-poll flicker at 10 Hz refresh.
  • Cockpit refresh chain is exception-safe. A transient fetch failure no longer breaks the poll loop and freezes the tile.

Fixed

  • chromadb 0.6.3 posthog telemetry wrapper silenced via monkey-patch in ChromaStore.discover() — the wrapper's capture() signature mismatch raised a TypeError on every chroma operation and blocked the tick loop indirectly.
  • Test isolation — daemon_factory monkeypatch.setenv's COOLSTEP_HOME to the test's tmp_path, so throttle-FSM tests no longer inherit state from the live daemon's runtime-state.json.

Tests

715+ tests pass. Suite extends test_spike_detector (margin-exceeded exit cases), test_routes (forecasts + signed median fields), and test_embedding (stats save/load roundtrip).