v0.41.3
v0.41.3
Patch release. Cache-stability and startup fixes on every harness, Pi/OMP parity work, and OMP as a first-class harness.
Fixed
Startup could hang with a second OpenCode instance on the same project (#420). A current-schema migration check took a write lock merely to confirm nothing was pending, so a second instance booting while the first was writing queued silently, and the SQLite busy timeout was installed only after the schema fence's first read. Both are fixed; the conflict detector's host config lookup is now bounded and fails open to the file check; the whole plugin boot runs under one 15-second budget with per-phase timings in the log, a boot that runs long installs the runtime when it settles instead of staying fail-closed, and the first log line (boot: entering) is written before anything can block. The same discipline now applies to the Pi and OMP plugin boot.
Background status notices could start an agent turn (#415). A notice appended while a run was in flight could become the newest user row at the moment OpenCode evaluated its loop-exit check, producing an assistant turn that replied to nothing. Notices are now held while a real prompt is unanswered or a generation is in flight, and rolled back if a run starts between the check and the append; Desktop startup notices go through the same guard.
Two double cache misses on the pass after a compaction fold. On OpenCode, a legacy whitespace-only assistant part carrying a tag was classified as non-blank by the absorbing strip, so a frozen decision applied one pass late after a marker advance. The classifier now strips well-formed tags before testing emptiness. On Pi, /ctx-wrapup followed by /ctx-flush served the covered raw span one pass longer than the compartment that replaced it; the busting pass now trims it itself, and a native compaction marker that cannot resolve its first kept entry falls back to the next resolvable one instead of being dropped silently.
Pi: the ctx_reduce reminder could not reach a long tool-running turn. Channel 2 was queued until the user's next message; it now delivers mid-run at the next model call (steer), after the current step's tool results and without cancelling any tool, on Pi and OMP.
Pi: a transient SQLite lock served the raw history. Pi now replays the previous pass's served bytes plus the raw tail on transient storage failures (the same Last-Known-Good mechanism OpenCode has), survives a process restart, and logs the reason and raw message count when no replay is available.
Pi: model-switch events could re-pin the previous model's cache TTL when a late assistant event arrived after a newer one; only the newest assistant now moves the model pin.
Fable 5.1 thinking-binding recovery on Pi (previously OpenCode-only): a 400 for a modified thinking block strips the bound block on the retry and drops stale replay state.
A provider-proven emergency no longer falls back to the raw array when storage fails during the fold; OpenCode, Pi, and the Rust engine all refuse instead, as the design always specified.
Rust engine: the supersession reclaim keeps the newest-20 owner floor (a review pin that had only reached the TypeScript engine); whitespace-only assistant framing is never tagged; store failures are visible in session.status and health even when trace persistence is also busy; ck-mc --version reports its build sha.
Added
OMP (oh-my-pi) is a first-class harness. historian.omp, dreamer.omp, and profile omp blocks configure models on OMP, falling back to the pi blocks when absent; the dashboard scopes model lists per harness; OMP hosts are detected through the host's own module graph, so plain Pi installs are unaffected.
Pi cache-bust instrument. A per-pass served-array digest ledger (on by default, sub-millisecond, bodies opt-in via MAGIC_CONTEXT_PI_SERVED_BODY_CAPTURE) and packages/pi-plugin/scripts/analyze-pi-cache-busts.ts, the Pi twin of the OpenCode analyzer.
Changed
Boot-phase timings and the SQLite boot busy timeout line are logged on every start. Pi ctx_expand rejects fractional ordinals. Pi routine cleanup is priced once per pressure episode, matching OpenCode.