Production fixes (Tamaz-sujashvili, reviewed sound by maintainer):
- loadSession clears S.busy/S.activeStreamId as soon as metadata confirms no active_stream_id, before the async message-load gap (idle session no longer shows streaming chrome).
- Snapshots the live turn before wiping msgInner + seeds INFLIGHT, restores on the active-stream return path (timer/trace survive switch-back).
Re-anchored the 2 brittle regression tests per maintainer review: test_..snapshots.. now anchors on the unique 'Loading conversation...' marker (was matching the no-space 'Session not available' error path); test_..restores.. now asserts the LIVE Phase 2a restore (after loadInflightState) instead of the unreachable Phase-2b/1184 branch. CHANGELOG stamped v0.51.384 (MW).
The update-check payload now carries a `dirty: bool` reflecting the
working-tree state vs HEAD, computed via the same `git diff-index
--quiet HEAD --` primitive already used by `_dirty_suffix()`. A dirty
install at-or-past the latest release tag used to silently report
"Up to date" with no remediation affordance; the Settings panel
can now read this flag to offer `apply_force_update` (which already
does `git checkout .` + `git reset --hard` to reset to a clean
latest).
The probe is conservatively clean on real errors (timeout, missing
git, fatal) so a transient probe failure never produces a false-
positive "local changes" alert.
Closes#4085
Per maintainer decision, auto_scroll_follow defaults TRUE (sticky-bottom: follow
new output while streaming, scroll-up unpins and is respected) — matching Codex
CLI / Claude Code. The PR shipped it default-False.
Default-mismatch bug fixed (would have shown the True default as OFF for existing
users with no saved value):
- boot.js settings path: !!s.auto_scroll_follow -> s.auto_scroll_follow!==false
- boot.js no-settings fallback: false -> true
- panels.js checkbox render: !!settings.auto_scroll_follow -> !==false
Resolved the config.py + panels.js merge conflicts (kept both the Transparent
Stream setting and auto_scroll_follow). Added test_issue4006_auto_scroll_follow_default.py
pinning the True default across config/boot/panels + the follow-gate references.
3 maintainer-review items the contributor hadn't addressed:
1. (blocking) restored .session-list overflow-anchor:none — the PR accidentally reverted the deliberate Firefox sidebar fix (2dfe765b); only the on-topic .messages removal is kept.
2/3. _settleFinalScroll was dead code + the promised 2s static-content safety timeout was missing — wired _settleFinalScroll(token) via a single 2s top-level fallback after _settleRO.observe(el), declared _settleFinalTimer + cleared it in _cancelBottomSettle and at settle re-entry.
Opus advisor found a key-space asymmetry: _pruneLineageReportCacheToVisibleSessions
built visibleKeys from RAW rows via _sidebarLineageKeyForRow, but the render loop
keys the lineage-report cache by _sidebarLineageKeyForRow on the COLLAPSED row,
which can differ when collapse merges segments. On a malformed/edge chain the
expanded row's cache could be evicted every payload and re-fetched ~every 5s
(partial regression of the bug #4020 fixes). Fold the collapsed rows' cache keys
into the visible set too, mirroring the _resolveSessionIdFromSidebarLineage
precedent, behind a defensive try/catch.
docs(changelog): stamp #4020+#4055 as v0.51.373 (Release ML)
The richer static-catalog builder's group-building loop used a strict item["id"]
extraction that would KeyError (caught → degrade to the minimal one-model catalog)
for legal config shapes where providers.<id>.models is a list of dicts keyed by
"model"/"name" rather than "id". Mirror the tolerant id-or-model-or-name resolution
the detection loop already uses, skip entries with nothing usable, and add a
regression test. No behavior change for the common list-of-strings / list-of-id-dicts
shapes.
docs(changelog): stamp #4052 model-picker budget fallback as v0.51.370 (Release MI)
Resolve custom provider API keys from the matched config snapshot and pass them through session hydration plus streaming fallback context-length probes. This prevents authenticated /v1/models endpoints from falling back to the default 256K window and clobbering larger persisted session metadata.