- 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
- Make over-context models selectable in the model picker by graying them instead of disabling them.
- Trigger automatic session compaction with the current model prior to switching when an over-context model is chosen.
The Agent Hub kill path called AgentLifecycleManager.release(), which
disposes the session and then unregisters the ref while leaving the
on-disk <id>.jsonl intact. On the next hub open, registerPersistedSubagents
rescans the transcript tree and its `if (!registry.get(id))` guard cannot
distinguish an explicit kill from a normally-parked agent, so it re-adopts
the killed id as a fresh `parked` row.
Add a `tombstone` option to release() that mirrors finalizeSubagentLifecycle's
genuine-kill path: dispose and detach the session but keep the ref registered
as terminal `aborted` instead of removing it. The kept-registered id makes the
rescan guard skip it, and the transcript stays on disk (still reachable via
history://<id>, per #5261). The hub kill button now passes tombstone: true.
Fixes#7250
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
Track entry into tool.execute separately from tool event emission. Never-started skips retain SyntheticToolResultDetails with executed:false; in-flight aborts now use distinct interrupted metadata with execution:started so consumers do not assume no partial work occurred.
Keep both interrupt states neutral in the TUI and cover the agent metadata boundary plus rendering behavior.
Fixes#7199
A tool call aborted mid-batch to service queued steering/peer input emits a synthetic placeholder result with isError:true so the model retries it. The TUI keyed all error styling (red ✘, red frame/text) off that flag, so a normal steering skip rendered identically to a real tool failure.
Mark the skip placeholder with the existing SyntheticToolResultDetails discriminator (source: "interrupt_skipped", executed:false) and render benign skips through the neutral generic card (info glyph, dim text, neutral background), bypassing any bespoke error frame. Genuine failures keep their error styling.
Fixes#7199
- Centralized PNG conversion behind an async boundary so constructor and encoder throws become promise rejections.
- Kept live and restored Kitty image rendering interactive by omitting failed conversions.
- Added regressions for both tool-result render paths.
Fixes#7160
macOS Terminal.app consumes Option for character composition, so Alt+Up
never reaches the app and the dequeue is unreachable there. Bind Shift+Up
alongside it -- Shift is not intercepted, and the key was unbound in the
input path.
The three overlay handlers that already use shift+up for fast scroll
(scroll-view, model-hub, log-viewer) match keys directly rather than
through the manager, so they never see this binding.
Both default tables move together: the registry in config/keybindings.ts
and DEFAULT_ACTION_KEYS in custom-editor.ts, which silently shadows the
registry when they disagree.
- Wrap status line path segment labels and worktree names in file hyperlinks.
- Apply hyperlink generation using the project directory and rendered path text.
- 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.
- Implemented clipboard register management, parsing, and execution rules for CUT, COPY, and PASTE operations in the hashline engine.
- Added session-persistent clipboard state and integration across agent session execution, diff previews, and streaming tools.
- Added comprehensive validation, error messages, recovery handling, and test coverage for clipboard and block operations.
- Updated task tool execution to pin live regions and drop partial snapshots once rows commit.
- Tracked background task frozen styled rows and render timestamps to prevent clock drift on committed history.
- Added tests verifying detached and blocking task progress do not duplicate rows in scrollback.
- Implemented session stores and metadata converters to import Claude and Codex sessions into OMP.
- Added `--from-claude` and `--from-codex` CLI flags and `/resume` command arguments for foreign session resolution.
- Updated session selector components and controllers to support listing and picking external agent sessions.
- Added comprehensive unit tests and documentation covering foreign session import functionality.
GitHub Copilot's call_id|id transport (and any stream that delivers a tool's name/args before its id) makes a streamed tool-call block appear with an empty or partial id, then rewrites it in a later delta. The transcript keyed the live card by that mutable content.id, so the changed id passed the creation guard and spawned a second card: the old-id card orphaned as a blue pending preview while the new-id card took the result.
Track the streamed id per tool-call block position (reset per assistant message) and migrate the live card's id-keyed trackers (pendingTools, tool timeline, args reveal, read tracking, and the shared read group's entry) when the id changes, so the populated id reuses the existing card.
Fixes#6879