Release BJ — stage-379 — 4-PR review-bypass batch
Four already-approved contributor fixes spanning four runtime surfaces.
Fixed
- #2461 by @starship-s — Add a WebUI-side memory-provider session lifecycle for batch-extraction providers (OpenViking, etc.). The new
api/session_lifecycle.pymodule tracks per-session generation, segment ownership, and anin_flightflag with athreading.Condition, so a late-finishing commit can only advancecommitted_generationagainst its captured generation without erasing newer turns marked during the commit.mark_turn_completedruns post-turn after save/cancel/completed-journal guards;commit_session_memoryruns at session boundaries (new session, eviction, shutdown) outside cache locks.drain_all_on_shutdownflushes every registered session with uncommitted work at process exit. - #2473 by @ts2111 —
/model <alias>now correctly routes cross-provider custom-model aliases to theircustom_providers[].namerather than falling through to the active provider'sconfig_base_urlbranch. Adds a custom-providers prefix check inresolve_model_provider()between the explicit early-return carve-outs and theconfig_base_urlcatch-all, and exposes a top-levelaliaseskey in/api/modelsso the frontend can resolve/model <alias>shortcuts.cmdModel()fetches the aliases list, fuzzy-matches the dropdown, and falls back to a directPOST /api/session/updatewhen no dropdown match exists. - #2480 by @Michaelyklam (closes #2472) — Make "Fork from here" use the same merged messaging-session transcript coordinate space that
/api/sessionexposes, so forking an older message no longer silently copies the full sidecar when CLI/Gateway history inflated the visible message offset. Extracts the merge logic into_merged_session_messages_for_display()and routes bothGET /api/sessionandPOST /api/session/branchthrough it. The frontend snapshots the source session id across the async full-history load and reloads the forked transcript fully after creation.
Changed
- #2479 by @Michaelyklam (refs #1925) — Route Stop Generation through the default-off
RuntimeAdapter.cancel_run(...)seam whenHERMES_WEBUI_RUNTIME_ADAPTER=legacy-journalis enabled. Implements the first code slice of the Slice 3a cancel-control gate accepted in #2469 / v0.51.85. The defaultlegacy-directpath still callscancel_stream(...)directly; the adapter branch preserves the existing{ok, cancelled, stream_id}JSON response contract. No new cancellation registry, runner, sidecar, approval/clarify, queue/goal, or cached-agent state is introduced — the adapter remains a pure protocol translator.
Verification
- pytest: 5889 passed, 6 skipped, 3 xpassed, 0 failed
- Opus advisor: STAGE-FIX-FIRST (one CHANGELOG hygiene issue found and applied as stage commit) → SHIP; verified late-commit safety on the new lifecycle module, disjoint cross-PR handler interactions in
api/routes.py,cmdModel()XSS surface safe (showToastusestextContent), 20+ existingresolve_model_providertests still passing - Agent self-verify on
api/session_lifecycle.py: late-commit safety invariant, segment-merge correctness, drain_all_on_shutdown, unregister_agent cleanup — all PASS via direct unmocked execution - Browser API sanity: all 11 endpoint checks PASS on isolated port-8789 stage server
- CI: 3.11 / 3.12 / 3.13 all green
- Tag SHA verified against merge commit