- Updated run-summary test mocks to track tool completion and only surface steering messages after the first task finishes.
- Reworked steering message retrieval from call counts to completion-and-drain state so pre-chat polls no longer block tool execution.
- Revised task prompt guidance to require batching multiple `tasks[]` in one call when subagents share context.
- Added optional `hasSteeringMessages` config hook and limited steering checks to boundaries.
- Fixed interrupted tool-batch steering by keeping queued messages until boundary handling.
- Added idle text and image submissions to steer queueing when no input waiter exists.
- Auto-continued resumable sessions after queued steering and preserved submit metadata.
- Fixed deep insert-after-block landing by retreating inward corrections across trailing closers.
- Added blockStart tracking and warning diagnostics for inward correction of block inserts.
- Clarified insert-after-block prompt and changelog guidance to require opener-based landing rules.
- Added regression tests for nested, empty, and conflicted inward landing scenarios.
- Added a `personality` enum to `settings-schema.ts` and new `Personality` type alias.
- Replaced inline reply guidelines with a templated `<personality>` block in `system-prompt.md`.
- Added markdown personality specs and wired them into `system-prompt.ts` rendering.
- Updated `sdk.ts` and `selector-controller.ts` to apply personality changes and refresh prompts.
- Set sub-agent sessions to use `personality: none` to suppress personality rendering.
- Added `partialHoldTimeout` to `StdinBufferOptions` to configure extra wait for dangling partial escapes.
- Reworked `StdinBuffer` flush scheduling to defer emits and avoid stale partials merging with new escapes.
- Held SGR mouse and kitty partial escapes until cap expiry to prevent tail bytes leaking as typed text.
- Added `SettingsList` section-focus state with `sectionFocused`, `hasSectionFocusTargets`, and `toggleSectionFocus()`.
- Implemented section-heading navigation with Tab/Shift+Tab, Up/Down focus jumps, and Enter/Escape exits.
- Updated `/settings` input hints and fallback routing to tab-bar keys when section focus is unavailable.
- Added tests for section-focus navigation, mouse parsing, and tab-bar behavior coverage.
- Added mouse hover, wheel, and click routing for `/settings` rows and tabs.
- Changed `/settings` to open as a fullscreen alternate-screen overlay.
- Added hover, hit-testing, and wheel APIs across TabBar, SelectList, and SettingsList.
- Added SGR mouse parsing plus `routeMouse` dispatch and exported it from the `tui` entrypoint.
- Renamed all functions, types, and constants in @oh-my-pi/snapcompact to namespace-relative names (`snapcompactCompact` → `compact`, `renderSnapcompactFrames` → `renderMany`, `snapcompactFrameCount` → `frames`, `SnapcompactShape` → `Shape`, `SNAPCOMPACT_SHAPES` → `SHAPES`, …).
- Converted every consumer to `import * as snapcompact` member access: `agent/compaction.ts`, `coding-agent` `agent-session.ts`/`session-manager.ts`/`snapcompact-inline.ts`, and all affected tests.
- Renamed internal `geometry` locals to `geo` in `snapcompact.ts` to avoid TDZ collisions with the new `geometry` export.
- Updated `docs/compaction.md` prose and added a Breaking Changes entry to the snapcompact changelog documenting the full rename map.
- Added `renderSnapcompactFrames()` and `snapcompactFrameCount()` to @oh-my-pi/snapcompact for paging arbitrary text into PNG image blocks without dim-marker bookkeeping.
- Widened the agent loop's `transformProviderContext` hook to `(context, model) => Context` so per-request transforms can gate on the dispatch model's capabilities.
- Added `SnapcompactInlineTransformer` rendering the system prompt and large historical tool results as snapcompact frames on vision models: vision gate, per-provider image budgets, 3k-token floor, savings-margin gate, skip-last rule, and hash-keyed render caches swept to live tool calls.
- Added default-off `snapcompact.systemPrompt` and `snapcompact.toolResults` settings under a new Context → Experimental group, composed after secret obfuscation in `sdk.ts` so frames are built per-request and never persisted to session.jsonl.
- Added prompt stubs (`snapcompact-system-stub.md`, `snapcompact-system-frames-note.md`, `snapcompact-toolresult-note.md`) and unit tests covering frame paging, no-mutate guarantees, budget caps, gates, and render caching.
Dropped `mapReasoningEffort` and `resolveActiveEffortMap` in both
`openai-completions.ts` and `openai-responses.ts`. Each callsite now chains
two ?? lookups: `compat.reasoningEffortMap?.[k] ?? model.thinking?.effortMap?.[k] ?? k`.
No `Object.keys`, no spread-merged object per request — same precedence
(post-`whenThinking` compat overrides win over catalog-baked thinking map).
Fixes#2315
blockRangeAt inferred no language for files like `zshrc`/`.zshrc`/`.bashrc`
because `Path::extension` returns `None` for bare and dotfile names alike,
so the edit tool's `replace block` / `insert after block` ops were
permanently unresolvable on them — an agent retrying the block op would
loop on the same "could not resolve a syntactic block" error.
from_extension now maps known shell rc/profile basenames (zshrc, zshenv,
zprofile, zlogin, zlogout, zsh_aliases, bashrc, bash_profile, bash_login,
bash_logout, bash_aliases, profile, kshrc, mkshrc, shrc; with or without a
leading dot) to the bash grammar, alongside the existing Makefile/Dockerfile
basename handling. Adds a block-resolution regression test over a zsh
`if [[ … ]]; then … fi` block in `zshrc`/`.zshrc`/`.bashrc`.
- Updated `settings-selector-memory-refresh.test.ts` to assert the cross-tab search banner's cursor rendering (`b▌`) instead of the old `Search: b` label when verifying Escape clears the search before closing the selector.
- Replaced the fixed `CALL_PREVIEW_MAX_LINES` cap in `render-utils.ts` with a dynamic `previewWindowRows()` (terminal rows minus a chrome reserve); `capPreviewLines` now returns lines untouched when expanded and windows them otherwise.
- Applied the cap in every render state for bash and ssh command previews — streaming and final render identically instead of snapping fully open on completion — and included the preview window in bash's render cache key so terminal resizes invalidate it.
- Capped eval cell code previews via the same window; previously cell code was never capped at all, with `ctrl+o` remaining the only way to uncap.
- Added stream-vs-final parity coverage in `bash-sixel-render.test.ts`, `ssh-render.test.ts`, and the new `eval-code-preview.test.ts`, and a changelog entry.
- Fixed `/dump` output (`session-dump-format.ts`) and the RPC `get_state` `dumpTools` payload (`rpc-mode.ts`) serializing Zod schema instances — leaking `def`/`shape` internals and stringified methods — by converting parameters through `zodToWireSchema` like providers receive.
- Fixed context-usage token estimation stringifying the Zod `def` tree, which overcounted tool schema tokens in the status line.
- Fixed tool-discovery indexing (`tool-index.ts`) returning empty `schemaKeys` for Zod tools, weakening BM25 ranking; keys are now recovered via wire conversion.
- Fixed the extension inspector panel rendering "(no arguments)" for Zod tools by reading properties off the converted wire schema.
- Added coverage in `tool-index.test.ts` plus new `context-usage.test.ts` and `session-dump-format.test.ts`, and a changelog entry.
- Added a `SettingsSearchHeader` banner to `SettingsSelectorComponent`, permanently mounted under the top border and rendering only while a cross-tab search is active.
- Typing now filters settings across every tab via `getSettingItemFilterText` + `fuzzyFilter`, with per-tab first-match ids so Tab jumps between tabs that have matches; non-matching tabs render muted and the pre-search tab is restored on exit.
- Moved the tab bar below the tab content, disabled `SettingsList`'s own type-to-search in favor of the selector-owned global search, and only advertised PgUp/PgDn in the hint when multiple sections exist.
- Wired the new `mutedTab` style into `getTabBarTheme` in `modes/shared.ts`.
- Added `SettingsListOptions` to `SettingsList` with a `layout` override ("auto" sidebar vs "flat" inline headings) and a `typeToSearch: false` switch for hosts that own filtering globally.
- Added `getSelectedItem()` and an `onSelectionChange` callback to `SettingsList`, replaced index-based submenu selection restore with id-based item resolution, and exported `getSettingItemFilterText` for external filtering.
- Padded short section panes to the full viewport in `SettingsList` so the panel height stays constant across sections.
- Added `muted` tabs to `TabBar` (skipped during keyboard navigation, styled via the new `TabBarTheme.mutedTab`), a `setTabs()` replace API that preserves the active tab by id without firing `onTabChange`, a `showHint` toggle for the trailing "(tab to cycle)" hint, and omission of the label prefix when the label is empty.
Also normalizes setting labels/descriptions and carries the package changelog entries for this batch (adjacent unreleased bullets are not splittable per commit), restoring section placement disturbed by the two prior changelog hunks.
- Caught and logged npm `PluginManager.list()` rejections in `PluginSettingsComponent`, returning an empty plugin list so the settings tab no longer stays blank when plugin listing fails.
- Added tests covering Escape handling while lists are loading and marketplace rendering when npm listing rejects.
- Added `responsesLite`, `reasoningContext`, `clientMetadata`, and `onModerationMetadata` options.
- Changed Lite request transformation to default `reasoning.context` to `all_turns`.
- Changed request shaping to strip image `detail` fields and force `parallel_tool_calls` off in Lite mode.
- Fixed streaming behavior by excluding `client_metadata` from websocket append diffs and swallowing moderation metadata errors.
- AuthStorage now synchronizes the selected OAuth row from SQLite before returning or force-refreshing credentials.
- Credential preparation was updated to resync the selected credential after invoking `prepareForRequest`, so peer-updated tokens are observed.
- Added an OAuth refresh race test that confirmed peer-updated SQLite rows are returned without extra refresh calls.
- Mapped Codex `end_turn:false` terminal events to `pause_turn` stop details in response stream parsing.
- Updated `agent-loop` to re-sample `pause_turn` turns, reset on tool calls, and cap continuations at 8.
- Added coverage for pause-turn mapping and continuation-capping in agent and AI stream tests.
After PR #2317 moved detected effort maps into model.thinking.effortMap,
the request builders stopped reading the active compat's reasoningEffortMap
at all. That dropped two surfaces:
1) compat.whenThinking variants whose reasoningEffortMap was applied at
buildModel time were silently ignored on thinking turns.
2) Custom raw Model configs that author reasoningEffortMap on compat (no
buildModel pass) had no path onto the wire.
Introduce a single resolveActiveEffortMap helper in both openai-completions
and openai-responses that overlays the active compat's reasoningEffortMap on
top of model.thinking.effortMap. Default catalog path is unchanged because
the resolved compat.reasoningEffortMap is empty.
Fixes#2315