Reserve the plain b shortcut only after /btw has a completed answer or a branch is already pending. Running, empty, aborted, and failed panels now leave the key for the composer, while completed-but-refused branches still consume it with an explanation.
Fixes#7474
Branched session files preserve entry ids, so leaf-id equality alone let a stale /btw answer promote into a different loaded session. Capture the originating session id at /btw start and require it to match at both the controller gate and every branchFromBtw checkpoint.
Fixes#7474
- Passed the authorized leaf through the branch executor and revalidated it before rewriting history.
- Refused promotion during active turns and bounded post-prompt drains.
- Consumed unavailable branch keys while showing pending and refusal state in the panel.
Fixes#7474
- The 'N tool calls elided' replay placeholder leaked tool activity while
display.hideToolActivity was on; it is now a visibility-aware component
wired into both the hotkey and /settings toggle paths.
- Added replay + live-reveal regression coverage.
The isTerminal:false early-return skipped #finishAgentEnd, the only site
that flushes a deferred plan-mode model switch, so an automatic continuation
(async wake) ran on the old model/thinking level until the terminal settle.
Flush the pending switch on the non-terminal branch before returning; the
title/loader teardown stays deferred to the terminal agent_end.
EventController.#handleAgentEnd guarded only on session.isStreaming, so a
non-terminal agent_end (isTerminal:false, emitted while an async job will
re-wake the loop) flipped the terminal title to idle and tore down the
working loader while a /vibe worker or async bash job was still running.
Early-return on event.isTerminal === false, matching the guard every other
agent_end consumer already applies; the later terminal agent_end performs
the normal teardown.
Fixes#7386
- Advanced indentation for a virtual root's direct children so single-child roots no longer collapse to the shared column-0 root.
- Mirrored the fix in the HTML export renderer and added a multi-root regression.
Fixes#7332
- Kept single-child chains aligned with their branch head while preserving real branch depth.
- Removed disconnected terminal-branch anchors from TUI and HTML tree renderers.
- Updated nested tree regressions for compact connector alignment.
Fixes#7332
/memory stats and /memory diagnose fall back to a generic
'Memory <action> is not available for the <backend.id> backend.'
message whenever the active backend's stats/diagnose hook is
undefined. For every real backend (hindsight, mnemopi, local) this
reads fine, but the off backend isn't a backend a user picked among
several stats-capable options - it's the no-op state memory falls
back to by default - so the same template renders as 'Memory stats
is not available for the off backend.', which reads as an odd,
almost self-contradictory warning.
Special-case backend.id === "off" with wording that matches the
phrasing offBackend.status() already uses elsewhere ('Memory backend
is off.'), and add a unit test covering both the off-backend wording
and the unchanged generic fallback for a real backend (local) that
simply has no stats hook.
The regression test only asserts on a mocked showWarning call and
never renders Markdown, so it doesn't need a real theme instance;
drop the global dark-theme setup/teardown to avoid leaving the
process-wide theme singleton mutated for later suites in the same
Bun process.
The live AskDialog trusted question.question while its render helpers
(replaceTabs, renderQuestionTitle, questionTabLabel) assume a string. A
question reaching AskDialogComponent without a string question field threw
an uncaught TypeError that escaped the TUI render loop and killed the
session. The transcript renderer already normalizes the same malformed
data via normalizeRenderQuestions; the live path did not.
Normalize the questions array at dialog entry (new normalizeDialogQuestions),
coercing question/id/label to strings and options to a well-formed array,
matching the transcript path.
Fixes#7211
- Add the `app.live.toggle` keybinding defaulted to `Ctrl+L` to start or stop live voice mode.
- Remap the default display-reset action (`app.display.reset`) from `Ctrl+L` to `Alt+L`.
- Update the live visualizer to listen for stop keys so the toggle chord terminates active sessions.
Snapshot this.ctx.sessionManager.getSessionId() for the tan clone's local://
mapping instead of session.sessionId. The two diverge after /fresh or a
provider session override, and the Windows short-root fallback keys
%TEMP%/omp-local/<id> off the session-manager id used by the parent's
large-paste writes and '/data/workspaces/can1357__oh-my-pi__6971/.omp-session/2026-07-29T06-08-45-283Z_019fac7d-5ee3-7000-a7aa-16fe9394fdc9/local' reads, so the mismatched id left attachments
unreachable.
Diverge the mocked session id from the manager id in the regression test so
it pins the session-manager id.
Fixes#6971
(cherry picked from commit 1efcd22326d76fdb8b50c0977a836c892e80ab76)
Capture the parent artifacts directory and session ID when /tan dispatches
instead of resolving them through the mutable interactive SessionManager.
This keeps background tan '/data/workspaces/can1357__oh-my-pi__6971/.omp-session/2026-07-29T06-08-45-283Z_019fac7d-5ee3-7000-a7aa-16fe9394fdc9/local' reads pinned to the dispatching transcript
after the user switches or resumes another session.
Extend the regression test to switch the mocked interactive session before
the background job starts and assert the original local mapping is retained.
Fixes#6971
(cherry picked from commit e05db428eabd5087e4b2b4a462f47927c0628e72)
TanCommandController.start nests the tan clone at
<parent-artifacts>/Tan-<id>.jsonl, so the clone's session manager derived
its own artifacts dir and hence local root <parent-artifacts>/Tan-<id>/local.
Its sdk.createAgentSession call omitted localProtocolOptions, unlike the
task-subagent path which inherits the parent's mapping, so parent-session
'/data/workspaces/can1357__oh-my-pi__6971/.omp-session/2026-07-29T06-08-45-283Z_019fac7d-5ee3-7000-a7aa-16fe9394fdc9/local' attachments (pasted files, generated references) were unreadable.
Thread the parent session manager's localProtocolOptions into the tan clone
so local:// resolves against <parent-artifacts>/local.
Fixes#6971
(cherry picked from commit 1ded46e182fc24f9f57d8e9a907aaad58f790783)
- branch() and navigateTree() now return the selected user message's image
parts (selectedImages/editorImages) alongside the text, extracted in marker
order by #extractUserMessageImages.
- CustomEditor.setDraft() replaces the composer draft with text plus its
pending images, so restored [Image #N] markers resolve on resubmit instead
of degrading to literal text.
- Wired all six restore call sites (selector-controller, extension-ui-controller)
through setDraft; updated rpc-subagents mocks for the new branch shape.
- Added offline regression tests for branch/navigateTree image restitution,
multi-image marker order, and text-only prompts.
/usage, /session, /advisor status, /jobs, /changelog, /context, and
/memory view mounted their finalized panel immediately via ctx.present()
instead of ctx.presentCommandOutput(), the streaming-deferral path added in
#5427 for /tools and /mcp. When invoked mid-turn, the panel landed above a
still-growing live block and the append-only scrollback contract recommitted
it lower down, so it appeared twice in native scrollback.
Route all six large command panels through presentCommandOutput() so they
defer until agent_end, matching /tools and /mcp.
Fixes#6767
computeNonMessageBreakdown estimated Skills tokens from the unfiltered
session.skills registry and subtracted that from the first system-prompt
block, which only ever contained the rendered (filtered) skills. Hidden
explicit-only skills (hide/disable-model-invocation) and all skills when
the read tool was absent inflated Skills and clamped System prompt to 0.
Add a renderedSkills helper mirroring buildSystemPrompt's filter and use
it for the Skills estimate so the category split matches the provider
prompt.
Fixes#6498
- Add `pinSessionOAuthAccount` storage method and active account flag to the auth storage API.
- Introduce session account selector component, controller logic, and interactive mode delegation.
- Implement the `/session pin` builtin slash command with text listing and account pinning capabilities.
- Add unit tests covering session account selection, component navigation, and command handling.