Unreleased
next release
Breaking
- Agent settings use agent.*, tier.agent, advisor.agents, and argot.agents; legacy keys migrate on load, while historical runtime export names, custom-theme color tokens, session records, and RPC spellings remain unchanged.
- Account formatting helpers are exported from @veyyon/coding-agent/session/account-format instead of @veyyon/coding-agent/slash-commands/helpers/format.
- Screen takeover moved off ExtensionUIContext and HookUIContext onto an optional ui.terminal capability: custom() and setEditorComponent() are now ctx.ui.terminal?.custom(...) and ctx.ui.terminal?.setEditorComponent(...), and a component widget goes through ctx.ui.terminal?.setWidgetComponent(key, factory) while setWidget(key, lines) keeps the text form every host draws. A host that is not a terminal omits ui.terminal rather than declaring members with empty bodies.
- Removed ui.setHeader() and ui.setFooter(), which every host implemented as an empty function, interactive mode included.
- Session spine, plugin loader and contribution registry modules moved from src/session/ and src/extensibility/ to @veyyon/kernel: affected subpath imports now use @veyyon/kernel/session/*, @veyyon/kernel/loader/* and @veyyon/kernel/registry/*; edit-specific event normalization remains at @veyyon/coding-agent/extensibility/tool-event-input.
- The 152 modules under src/tools/ moved into one directory per domain — core/ for the plumbing every domain reads, then fs/, search/, shell/, web/ and agent/ — so a subpath import previously resolved through @veyyon/coding-agent/tools/<name> is now @veyyon/coding-agent/tools/<domain>/<name>.
- sanitizeStatusText is @veyyon/utils/sanitize-status-text, so a subpath import previously resolved through @veyyon/coding-agent/modes/sanitize-status-text names the utils module: the function is text-only and every host reduces a value to one line the same way.
- The 81 site scrapers, the page loader and the Parallel extraction client moved to @veyyon/web: a subpath import previously resolved through @veyyon/coding-agent/web/scrapers/* or @veyyon/coding-agent/web/parallel is now @veyyon/web/scrapers/* and @veyyon/web/parallel, and the search providers' withHardTimeout is @veyyon/web/hard-timeout.
- escapeMarkdownTableCell and the Turndown helpers are @veyyon/utils/markdown-table and @veyyon/utils/turndown, and htmlToBasicMarkdown is @veyyon/utils/html-markdown, so a subpath import previously resolved through @veyyon/coding-agent/utils/markdown-table, @veyyon/coding-agent/utils/turndown or the scrapers barrel names the utils module.
- CliUsageError is @veyyon/utils/cli-usage-error; @veyyon/coding-agent/cli/usage-error is removed, so a flag the root parser rejects and one the command framework rejects are the same class.
- @veyyon/coding-agent/session/auth-storage is removed; the credential types and AuthStorage it re-exported are imported from @veyyon/ai/auth-storage, the module that defines them.
- The setting declaration vocabulary — SettingDef and its definition kinds, SettingType, SETTING_TYPES, isSettingType, SettingTab, AnyUiMetadata and SubmenuOption — moved from @veyyon/coding-agent/config/settings-schema to @veyyon/settings; the schema, its readers, the tab metadata and the tab groups stay where they were.
- URL target parsing is exported from tools/web/read-url-target instead of tools/web/fetch.
- Setting-change signals are exported from config/settings-signals instead of config/settings.
- fgOrPlain is exported from theme/theme-binding instead of theme/theme.
- Diagnostic cards use diagnosticsSection from tools/core/diagnostics instead of formatDiagnostics from tools/core/render-utils; diagnostic parsing and sanitisation helpers are imported directly from tools/core/diagnostics.
- Read selector helpers parseSel and isRawSelector are exported from tools/core/path-utils instead of tools/fs/read.
- readSourceFsPath is exported from tools/fs/read-view instead of tools/fs/read and remains available from the package root.
- metadataLine is exported from tools/core/render-utils instead of tools/web/search/view.
- Removed the unused inheritedAgentDir keybinding option and ohMyPiXAIUserAgent alias; xAI requests continue to use veyyonXAIUserAgent.
- @veyyon/coding-agent/extensibility/hooks no longer exports HookRunner, HookToolWrapper, discoverAndLoadHooks, loadHooks and execCommand: the legacy hook runtime is removed, a plugin's hooks entry loads through the extension runner, and the subpath keeps the hook types.
- UNICODE_SYMBOLS is @veyyon/view's; theme/symbols re-exports it and keeps the terminal-only Nerd Font and ASCII presets, the spinner frames and the bar ramps.
Added
- Exported projectToolDisplay from presentation/web-tool-display.ts, projecting canonical tool execution displays for collab live sessions and HTML export.
- tools/view-registry.ts exports toolViewDefinitions, the host-agnostic ToolViewDefinition for every tool card the terminal drew, and tools/renderers.ts derives the terminal adapters from it; the set of cards and their chrome are unchanged.
- A tool card value-imports no tool: the search card limits are tools/search/search-card-limits.ts, the web search provider label is tools/web/search/types.ts, and the launch card owns callMeta and readyPendingSummary; each name is exported from that one module only. Print mode and the HTML export load a card without the tool behind it, and no output changes.
- presentation/transcript-builder.ts is split into content-text.ts, custom-display.ts and session-projection-engine.ts, each under the presentation module size ceiling; no output changes.
- src/presentation/ builds the @veyyon/wire/presentation view-models from session state, and PresentationEventBridge turns session events into transcript updates, so a renderer draws a session without importing one.
- src/modes/terminal/driver.ts implements PresentationContext on @veyyon/tui: it renders every transcript block kind, the status line, the composer and the dialogs from view-models alone, and reports operator input back as UIEvents.
- InteractiveMode.presentation applies transcript, status, composer and overlay updates to the existing terminal surface without constructing a second terminal or composer.
- /process-manager opens the Agent Control Center across every conversation this process is running rather than only the one on screen, and a switches the roster, the comms stream and the transcript guard between the two scopes together.
- read accepts a semicolon-delimited list of internal resources (skill://demo/one.md;skill://demo/two.md), the same list form grep and glob take, and returns one section per entry.
- @veyyon/coding-agent/session/facade exposes AgentSessionFacade, a thirteen-member session API a front end drives — start, stop, submit, interrupt, retry, per-call tool approval, six event streams and the model, provider and context-usage readings — over a live AgentSession; the facade owns the permission prompt while it is started, and refuses a session another host already routes through.
- setImageDisplayProbe lets a front end state whether it draws pictures, which is what the session reports to the model about an image a tool returned; a client that installs nothing draws nothing, so a host embedding the engine no longer inherits a terminal's answer.
- ToolDefinition.view lets an extension describe its tool's call and result cards as a ToolView instead of building a terminal component, and re-exports the @veyyon/view vocabulary (ToolView, StatusRowView, TextBlockView, ViewSpan, ViewTone, ViewStatus) so a plugin can construct one; the terminal draws it, and a tool that also declares renderCall/renderResult keeps those.
- src/modes/terminal/draw/draw-tool-view.ts draws a ToolView as terminal bytes through exhaustive tone-to-colour and status-to-icon records, so a tone added to the contract fails the type check until the terminal states how it looks.
- A ToolView span carries file for a filesystem path a host opens however it can, separate from the link a URL rides on, and the tone vocabulary adds diffAdded and diffRemoved for the two sides of a change; the terminal wraps a file run in an OSC 8 link to its file:// URI.
- Tool domains declare lazy factories in manifest.ts, while tools/view-registry.ts defines their views and policies and tools/renderers.ts derives terminal adapters with shared identities for provider aliases.
- CustomTool.view lets a tool authored as a custom tool describe its call and result cards as a ToolView, the member ToolDefinition.view already offered an extension, and both adapters forward it to the host.
- The ask tool emits a host-agnostic HostNotification through ToolSession.notify instead of calling the terminal, and the running host installs its delivery through setToolNotifier; a host that cannot reach an operator outside its own window installs nothing and the capability reads as absent.
- Source-path comments in modes/terminal/controllers/input-controller.ts, tools/render-utils.ts, utils/block-context.ts and utils/shell-snapshot.ts name the Rust modules they cite at their new paths under natives/. No user-visible behavior changes.
- A commit whose changes all sit under a grouping directory named natives proposes the directory below it as the scope, the way crates, packages and tests already do, instead of proposing natives.
- The set_cwd renderer drops name, renderArguments and renderPending: no host reads any of the three, and the tool-renderer contract declares none of them. No user-visible behavior changes.
- showHookInput's inputOptions.mask is a boolean rather than the character to draw, so the host that paints the field owns the glyph and /secret add no longer names the terminal engine to ask for a hidden field; the masked prompt draws the same • it drew before.
- The todo tool states where a closed task's completion strike has reached with todoStrikeSplit and writes no SGR escape itself: the terminal draws the struck run with the theme's strikethrough attribute, so a session with terminal attributes off receives the task text without the \x1b[9m bytes it cannot render, and the transcript card sweeps the strike exactly as it did before.
- runCommitAgentSession reports its run through a CommitAgentReporter instead of writing to stdout itself, and commit/agentic/agent-render.ts is the only module that draws it, so the commit domain names neither the terminal engine nor chalk; veyyon commit prints the same thinking line, markdown, tool tree and totals it printed before.
- The /collab QR block draws its own leading blank row instead of being presented behind a spacer, so the slash-command registry no longer imports the terminal engine; the transcript shows the same blank row above the code and above the too-narrow hint.
- The compaction policy vocabulary (check outcomes, the bar a pass is measured against, the truncation edge budget, the prune cache window and idle flush, and the recovery band) lives in @veyyon/kernel/session/agent-session-compaction-policy rather than interleaved with shutdown timeouts and credential backoffs in agent-session.ts, with no behavior change.
- resolveSlashCommand in slash-commands/helpers/parse resolves a parsed invocation against a command set, joining the first argument token back onto a namespaced plugin command name.
- SingleResult.isolationFallback records the requested and actual isolation backends and the reason when an explicit mode was not honoured; isolationModeName in task/worktree states a backend's setting spelling.
- TruncationMeta.totalLinesUnknown states that a read's scan stopped after the shown window, so the notice omits a total it does not have.
- PLUGIN_MANIFEST_ENTRY_KEYS and PluginManifestEntryKey in extensibility/plugins/loader state the four manifest entry keys a plugin contributes through.
- cli/stdout-drain exports awaitStdoutDrain and exitAfterStdoutDrain, the one way a non-interactive mode exits after its last frame is written.
Changed
- A running tool card animates one mark: the "… (streaming)" spinner row is drawn only under a header that carries no running spinner of its own, and an agent an eval cell spawned shows the task card's static accent mark instead of a second spinner.
- The read and write cards parse their arguments and details through @veyyon/utils/fs-tool-args, so a terminal launch no longer evaluates @veyyon/tool-render; the cards draw the same rows.
- The legacy memories.enabled key is no longer a declared or host-defaulted setting: a config that still holds it migrates to memory.backend on load, the key is dropped on the next rewrite, and the local memory pipeline is enabled by memory.backend: local only. The presentation module's error messages, read-target parsing and cursor clamping use the @veyyon/utils helpers; no behavior change.
- Reworded the Include Model in Prompt, Max Retry Delay, Hindsight Bank ID, Subagents and Subagent Delegation setting descriptions shown in /settings.
- The HTML export attaches sub-sessions, redacts and writes the file through one finishExport for the session-manager and file entry points, a stage-1 memory job is completed under its ownership token through one completeOwnedStage1Job for the with-output and no-output paths and the global phase-2 claim reads its row through one readGlobalJobRow, the JavaScript eval cell builds its success, cancelled and failed results through one finish, the GitHub commit watch reports each poll and its grace and confirm notes through one reportWatching, and a capability scope splits (, [ and { groups through one keyed depth table so a closer of another kind never ends the open group; no behavior change.
- The token-rate helpers are presentation/token-rate.ts, moved from modes/components/status-line/token-rate.ts without a forwarding module, and the status view-model is presentation/status-producer.ts with no presentation/status-builder.ts beside it; the search card limits are exported from tools/search/search-card-limits.ts only, and callMeta and readyPendingSummary from tools/shell/launch-view.ts only.
- The propose-commit and split-commit tools state the summary and detail limits in their verdict through one verdictWithLimits, Enter and Ctrl+Enter run a builtin slash command and recall the line as typed through one #consumeBuiltinSlashCommand, and a read records its hashline snapshot through one recordFullHashlineContext and renders an over-long first line through one oversizedFirstLineText on the ranged and whole-file paths; no behavior change.
- Tool-argument repair parses a stringified payload and a parse-sentinel payload through one repairJsonObjectArguments, the launch path resolves the prewalk strong, prewalk cheap and plan-yolo models through one resolveLaunchModel, --resume relocates a session whose recorded directory is gone through one block for local and cross-project matches, and the vault key scans staging entries through one bounded stagedKeyEntries for orphan recovery and crash-stage cleanup; no behavior change.
- The models-config schema rejects an empty id, name, baseUrl, apiKey, contextPromotionTarget or compactionModel through one narrow helper, the URL fetcher assembles every render result through one buildRenderResult, the patch mode resolves a space-separated outer inner context through one resolveInnerAfterOuter, and the clipboard reads images and text from Windows through one runPowerShell bridge; no behavior change.
- The plugin manager runs every bun install, bun update, bun uninstall and dry-run through one #runBun, the marketplace manager resolves where a plugin is installed and which scope a verb applies to through one lookup and one #scopeFor, the microphone recorder and its streaming twin walk the detected recorders through one fallback loop, the ZIP64 locator and end-of-central-directory record are parsed by one reader for the in-memory and ranged paths, and head and tail truncation build their single-line results through one helper each; no behavior change.
- The profile bootstrap reads --profile and --alias through one flag reader, the vault's Linux and macOS atomic exchange share one rollback builder, the eval tool builds its cancelled, failed and completed results through one finishCell, and the lexical bracket scanner opens quote modes from one table; no behavior change.
- ToolExecutionComponent rebuilds its block through one #syncBlock whenever the spinner frame, the expansion or the freeze changes, including when the spinner starts and stops, so a card that reads context.frame in its view (the vibe composer caret) blinks from its first paint and holds still once stopped.
- The terminal tool card keeps four behaviors the producer split had dropped: a settled streaming diff preview is drawn without waiting for the next spinner tick, a live-widget call that never ran (ask) falls back to its label, a background task result finalizes its block while the job runs, and the write card coerces non-string content to text; EventController.attachTo seeds the projection engine from the engine's own message source.
- DapSessionManager.launch and attach share one start sequence, and each breakpoint kind (source, function, instruction, data) replaces its list through one helper for both set and remove; no behavior change.
- CustomEditor dispatches its twenty app-level shortcuts through one ordered table with the same precedence, deferral during early startup, bash-background fall-through and retry-yields-to-extension rules; no behavior change.
- Every ModalShell host (tree, session, settings, model hub and model picker selectors, the agent dashboard and transcript viewer, the plan review, login, ask and MCP wizard dialogs, the extension dashboard) routes its close glyph, outside click, breadcrumb and footer chips through one routeModalChrome prelude instead of a hand-typed hitTestModalChrome sequence; no behavior change.
- Goal and vibe mode context reach the model through one delivery step that keeps the hidden display, the agent attribution and the requested channel; plan-mode context is unchanged.
- The /btw and /omfg panels settle every outcome (complete, saved, rejected, aborted, error) through one step per panel that clears a previous error and ignores a dismissed panel; the painted rows are unchanged.
- The reftable ref readers answer null for a missing ref and rethrow an abort through one read-only git query, and the github ops raise the same "unavailable" ToolError for a missing repository root, primary root, branch or head through one check; no behavior change.
- The legacy extension resolver's six promise caches (package root, manifest, bare dependency, native addon, addon-require scan, realpath) share one memoizer and one importer-scoped key; each result is cached once per key, as before.
- veyyon setup speech picks the speech-to-text and text-to-speech models through one step that persists only a value the setting declares and flushes it before the next pick; no behavior change.
- The SearXNG endpoint, token and Basic-auth readers share one settings-then-environment lookup, with an empty endpoint or token still read as unset, and the tool result builder records match, result and head limits through one setter; no behavior change.
- ACP session/resume opens a stored session through the same step as session/load (same cwd check, same MCP configuration, same not-found error) without replaying history, and the symbolPreset and colorBlindMode settings apply to the theme through one signal hook that logs a fallback or a failed setter under the setting's name; no behavior change.
- Single-range and multi-range read clip long lines to tools.outputMaxColumns through one display-only clipper that records each clipped line, including a block-context line outside the window, out of the seen-lines record and reports the column cap once; no behavior change.
- /btw, /tan and /omfg read their argument and clear the composer through one handler; the composer's locked and awaitingApproval flags enter and leave their modes through one step; an agent's extension sendMessage and sendUserMessage are tracked and error-logged through one step; the b, c and down-arrow empty-composer keys install through one listener; and the token_in, token_out, cache_read and cache_write status segments render through one counter; no behavior change.
- Async job deliveries and in-flight deliveries filter by owner and suppression through one step; the projection engine's running and background-task marks toggle set membership through one step; and skill loading resolves authored and managed skill real paths through one helper, so one SKILL.md reached through two paths loads once without a collision warning; no behavior change.
- RPC agent and session events pass one typed-set check; every streaming edit mode recovers its matcher paths and entries through one non-empty and one single-path step; and skill, rule, context-file, prompt-template, slash-command and custom-command discovery resolve their project and agent roots through one step; no behavior change.
- Streamed text and thinking segments reveal through one generic step; both Gemini search request paths build their per-attempt body through one transform step; and the cmux tab's waitForSelector is waitFor; no behavior change.
- The theme.dark and theme.light setting hooks republish their slot through one factory; the RPC host_tool_result and host_tool_update frames pass one guard parameterised on the frame type and payload key; and the Hindsight retainMode, recallBudget and scoping env and settings values are accepted through one listed-value picker; no behavior change.
- Built-in model discovery selects its standard and special providers through one predicate (disabled set, configured discovery rows, provider filter) and resolves each provider's discovery endpoint through one lookup (runtime override, models.yml, catalog); the ! and % shortcuts present, stream into, settle and release their transcript block through one step with their own failure labels; no behavior change.
- The agent executor reads a message's or event's content and usage through one field reader, and a symbol-preset or colour-blind change re-renders the committed theme through one ephemeral re-apply step; no behavior change.
- The legacy pi-coding-agent read, bash, grep, find and ls tool definitions draw their call card through one step (title, then the call's own summary), with the same bytes as before; no behavior change.
- Grouped read displays and path expansion share delimiter scanning while preserving escaped separators, glob braces and selector ranges.
- Learn and Memory Edit result views share text projection while preserving titles, empty results and error formatting.
- Collab and HTML tool previews build display data without serializing discarded transcript input.
- Tab expansion imports @veyyon/utils/tab-width; no user-facing effect.
- The speech-to-text, tiny-model and TTS worker clients share one request lifecycle (subprocess/worker-request-client) and one progress-event shape; a worker error or client shutdown settles every pending request the same way in all three, with no user-facing effect.
- Collab link formatting and parsing (formatCollabLink, parseCollabLink, generateRoomId) are @veyyon/wire's, re-exported from collab/protocol; a link the host mints and the browser guest parses read one grammar, with no user-facing effect.
- Claude plugin hooks, tools, skills, slash commands and MCP servers resolve their plugin roots through one pluginRootsFor step, and no loader can mutate the cached root warnings; no user-facing effect.
- Terminal and presentation event handling share tool-argument correlation and retry traces, with stable block identities across streaming snapshots and session resets.
- Standalone and adopted terminal drivers share transcript updates and composer bindings with unchanged read-card presentation.
- Grouped read projections preserve per-call status, paths, previews and line numbers across serialization.
- Live and rebuilt tool cards share single-card rendering while preserving renderer precedence, streamed arguments and failure notices.
- Status-line usage fields use the shared presentation contract without changing rendered output.
- Bash and job cards load shared presentation helpers without importing their execution modules.
- Plugin discovery shares installed-registry validation and root collection without changing scope precedence or warnings.
- Runtime initialization no longer waits for first-frame replay cache publication.
- Eval bridge options share field declarations while preserving exported interfaces and runtime behavior.
- Settings selectors share list initialization, model-picker attachment and inline updates without changing input routing or persistence.
- Extension API instances no longer allocate unused flag maps and provider-registration arrays; flags and registrations remain in the shared session runtime.
- MCP commands share argument parsing without changing terminal and CLI option policies or interpreting argument text as a second command.
- DAP and LSP configuration discovery share source ordering, and Gemini and OpenCode share user-context loading, without changing precedence or warnings.
- Editor keybinding matching shares default key sets while preserving remap isolation and fallback chords.
- Autoresearch experiment tools share active-branch session resolution without changing errors or session selection.
- Autoresearch session updates share optional-column assembly without changing stored values, omitted-field handling, or database errors.
- Extension dashboard loading shares disable and shadow precedence across capability kinds without changing state or metadata.
- settings-selector.ts writes its escape comparison as \x1b instead of a raw control byte. No user-visible behavior changes.
- Output minimizer tool filters collapse repetitive line filtering, table formatting and subcommand routing into declarative specs with unchanged output behavior.
- GitHub search operations in the web domain and vibe mode tools use shared parameterized dispatch tables; behavior is unchanged.
- Terminal selector cards and command controllers share modal select delegation, mouse routing, subcommand dispatch, and markdown panel presentation without changing TUI behavior.
- Settings selectors share model-chain summaries, heading rows, picker targeting and candidate deletion without changing display or persistence behavior.
- Parity ledger schema validation, module specifier resolution, and workspace traversal logic are consolidated into shared script helpers without changing validation verdicts.
- Custom and legacy hook messages use the agent-core type definitions without changing message conversion or public type signatures.
- Filesystem reads and writes share range calculations, candidate probing and result assembly while preserving SQLite row-operation exports.
- Terminal code cells and tool views share row splitting, truncation summaries and text sanitization without changing rendered output.
- Image inspection, Mnemopi initialization and search-provider loading use AI subpath imports while preserving usage-provider and credential-ranking registration.
- Launch and live status rows share configuration reads, and launch redraws avoid enumerating the settings schema.
- Settings group reads reuse declaration-path membership without caching setting values.
- Filesystem and goal previews load without their tool execution modules.
- Task cards share row construction, nested traversal, finding normalization and yield labels without changing rendered output.
- Web-search providers share credential resolution and HTTP error handling, and discovery providers share equivalent scanners without changing provider behavior.
- Tool cards share hidden-count formatting and symbol presets share identical glyph definitions without changing rendered output.
- Tool cards share error rows, metadata and empty-result construction without changing rendered output.
- Python, Ruby and Julia kernels share runtime probing and subprocess initialization while preserving language-specific environment and execution behavior.
- First-frame replay recordings are written asynchronously so filesystem operations do not block editor input.
- Launch status rendering reuses repository discovery when reading branch and worktree metadata.
- Launch layout measures the fixed-height status footline without rendering it.
- Every setting in every domain states what it does and what each value selects in one to three sentences, with no design history or internal vocabulary; the idle timeout row is labelled "Park Idle Agents After", the Park and Prune groups are one "Idle Agents" group, the artifact rows are "Artifact Threshold", "Artifact Head Size" and "Artifact Tail Size" with the unit on their options, and the MCP debounce row is "MCP Notification Delay".
- AgentRegistry.setStatus consults AGENT_TRANSITIONS and throws AgentTransitionError for a status move the lifecycle does not perform, so a turn event that arrives after a kill or a park no longer revives the agent; a collab guest mirrors the host's roster through mirrorStatus.
- An agent adopted at hand-over, revived from disk or listed from a previous run receives its idle and prune budgets through one builder, so a zero quiet budget disables pruning and a waiting budget is never shorter than the quiet one on every path; no behaviour changes on the paths that already agreed.
- A retired agent.* setting is retired in one place: rejectedAgentModelSettings sweeps the keys the schema itself marks retiredBy instead of a second hardcoded list, and a retired key with no page hint is reported against the replacement the schema declares rather than being named as undefined; agentsEnabled is the one predicate for whether agents exist, replacing the delegationEnabled alias that returned it unchanged. No setting changes what it does.
- Interactive chat and the transcript viewer use one replay implementation without changing displayed content or live-tool lifecycle.
- Transcript rebuilds and live updates share tool-text projection without changing displayed content.
- Settings group types derive from the settings schema while preserving their existing optional fields and value types.
- JSON tree projections share bounded traversal, and code and Markdown cells share output assembly, with unchanged rendering.
- Plugin discovery, import rewriting, MCP configuration toggles, Exa responses, secret-preserving text transforms, todo state cloning and projection, and session-file discovery use shared implementations without behavioral changes.
- Tool views share progress rows, diff statistics, disclosure metadata, and task separators without changing rendered output.
- Extension kind labels use a shared function without changing list or sidebar text.
- Handbook HTML and search assets are generated during documentation and website builds instead of being tracked in Git.
- Startup reads setting-change signals and terminal formatting without constructing the settings store or unrelated tool modules.
- The terminal host constructs autoresearch screens and styled slash-command reports; headless command execution no longer imports those terminal components.
- Subagent statistics and output sanitization are shared across the task tool's view and dashboard through host-independent presentation helpers in task/agent-stats.ts without terminal imports. No user-visible behavior changes.
- Account inventory formatting no longer imports terminal progress-bar or theme helpers; displayed values are unchanged.
- Terminal mode initialization overlaps session discovery instead of loading during sequential runtime warmup.
- Interactive startup begins background model discovery after terminal initialization.
- Model registry initialization defers unused provider records until lookup or enumeration while preserving runtime provider updates and model overrides.
- Startup reads provider caches without constructing unrelated discovery options or their bundled reference maps.
- Model discovery snapshots from earlier host-classification rules rebuild before model selection.
- Resolved model snapshots no longer duplicate the bundled catalog; model selection and provider overrides are unchanged.
- Resolved model snapshots use shared byte-integrity checks and atomic replacement without durability flushes; obsolete snapshots rebuild before model selection.
- Startup imports AI streaming helpers and usage registration without evaluating the AI package barrel; usage providers and credential ranking remain available.
- Evaluator implementations load on the first enabled request instead of session or tool construction, and loaded runtimes register their own process-exit cleanup.
- URL reader initialization is deferred until an enabled URL read or search; local tools and transcript previews no longer initialize it.
- Vibe tools load on /vibe activation rather than during startup, and failed loading preserves the session toolset.
- The settings schema registry is @veyyon/kernel/settings/schema and config/optional-number is @veyyon/kernel/settings/optional-number; config/settings-schema composes the domain tables through declareSettings and still exports the queries (getDefault, getType, getUi, hasUi, getPathsForTab, retiredBy, isSettingPath, getEnumValues, isUnsetNumberPath, describeSettingTypeMismatch), the SettingPath and SettingValue types, SETTINGS_SCHEMA, the tab metadata and the typed groups, so importing a query loads the tables it reads. No setting, default or config file changes.
- Settings (config/settings) extends SettingsStore from @veyyon/kernel/settings/store and passes the product's hook set (the global setting bindings, the SETTING_HOOKS table, the config migrations, the settings.json and agent.db legacy read, the changelog-marker seed and the per-directory resolution of enabledModels); config/settings re-exports the store's vocabulary and SettingSignal under the same names, so every import resolves. No setting, default, config file or write order changes.
- Settings.getGroup delegates prefix path lookup to groupSettingPaths from the kernel store; model role dictionary normalization is consolidated across layer accessors.
- The tool session, the terminal mode and the SDK read HostNotifier from @veyyon/host instead of @veyyon/utils/host-notification; behavior is unchanged.
- session/messages.ts registers its message kinds on @veyyon/session's CustomAgentMessages rather than @veyyon/agent-core's; behavior is unchanged.
- SessionManager, buildSessionContext, the session file loader and AgentStorage are @veyyon/kernel/session/*; session/messages.ts re-exports the custom-message payload helpers and the rehydration sanitiser from @veyyon/kernel/session/custom-message-payload under the same names. appendMessage accepts every AgentMessage but a branch or compaction summary, the set it accepted before. Behavior is unchanged.
- BashExecutionMessage, PythonExecutionMessage, bashExecutionToText and pythonExecutionToText are @veyyon/coding-agent/tools/shell/execution-messages, declared on the shell domain's manifest as message kinds; session/messages.ts no longer exports them, and convertToLlm converts the two roles through the kind table the tool registry fills. formatGroupedDiagnosticMessages is tools/core/grouped-file-output, which lsp/utils re-exports. Behavior is unchanged.
- The plugin loader, the plugin manager, the plugin settings dialog and the extensibility/plugins barrel read the manifest vocabulary from @veyyon/plugin; the barrel exports the same names. No user-visible behavior changes.
- The website source is apps/site and the Python clients are clients/python, the directories that were website and python; the source-checkout veyyon launcher, the binary build scripts and the brand-parity checks read them there, and nothing they produce changes.
- veyyon update on a source checkout regenerates the HTML export tool views from clients/web, the directory that was packages/collab-web, and the compiled binary reads the embedded stats dashboard from apps/stats, the directory that was packages/stats; the commands and their output are unchanged.
- Typed tuple and Set copies use spreads rather than .concat() or .slice(), which those types do not define. No user-visible behavior changes.
- web_search is constructed from tools/web/search rather than the retired web/search module. No user-visible behavior changes.
- normalizeRoots takes one working-directory string. No user-visible behavior changes.
- createCachedComponent lives in modes/terminal/draw/utils with the rest of the terminal drawing helpers, and the source map no longer lists src/web/ or src/swarm/ as top-level directories. No user-visible behavior changes.
- Tests that lived under retired folder names (test/tui, test/capability, test/web, test/vibe, test/repair, and the other pre-cutover aliases) now sit next to the source they cover. No user-visible behavior changes.
- ToolView cards that walk a JSON value read their bounds and scalar formatting from json-tree-view.ts rather than loading the terminal walker that draws tree-rail glyphs. No user-visible behavior changes.
- The terminal's ToolView drawer names every kind the contract declares, so a kind added to the union fails the type check instead of drawing as a one-line text row. No user-visible behavior changes.
- Session persistence, plugin loading and generic contribution registration use @veyyon/kernel; the turn loop, prompt rendering and tool-specific extensibility remain in the coding-agent package.
- Terminal drawing of a ToolView lives in src/modes/terminal/draw/, and web search lives in src/tools/web/search/. Subpath imports previously resolved through @veyyon/coding-agent/tui and @veyyon/coding-agent/web/search now name those directories. No user-visible behavior changes.
- Every tool module is grouped by domain under src/tools/<domain>/, each domain importing only core/ and itself, so the dispatch table no longer sits above 139 flat modules. No user-visible behavior changes.
- Source-path comments and the gallery search fixture name the terminal renderer at its new path, hosts/terminal/engine, and a new architecture gate records every module outside src/modes/terminal/ that still imports it. No user-visible behavior changes.
- A source-checkout update runs the native-addon ensure step in natives/bridge/bindings, the bindings package's path after it moved out of packages/.
- Sixteen tool modules keep their terminal drawing in a <tool>-render.ts sibling — ask, ast-edit, bash, debug, fetch, file-search, job, launch, read, resolve, search-tool-bm25, ssh, structure-search, text-search, todo and write — completing the convention eight tools already followed, and tools/json-tree.ts is tools/json-tree-render.ts. Twenty-four of the twenty-six modules under tools/ that name @veyyon/tui are render siblings, print mode no longer loads the renderer through the todo tool, and subpath imports of the moved renderers follow the new layout. No user-visible behavior changes.
- All five autoresearch experiment tools — init_experiment, update_notes, certify_arms, log_experiment and run_experiment — describe their call and result cards as a ToolView instead of building terminal Text, so none of them imports @veyyon/tui; the terminal draws the same bytes it drew before, including run_experiment's collapsed five-line output preview and its expanded full output.
- ToolDefinition.view renderers receive a ToolViewContext stating whether the card is expanded, so a tool can shorten its collapsed output without asking a host what it is.
- The goal tool describes its call row and result panel as a ToolView instead of constructing terminal components; panel and error formatting are unchanged.
- The report_finding tool describes its call row and its result row as a ToolView instead of building terminal Text, so it no longer imports @veyyon/tui; the terminal draws the same priority mark, tone and truncation bounds it drew before.
- The set_cwd tool describes its call row and its result frame as a ToolView instead of building terminal components in a set-cwd-render.ts sibling, which is deleted; the terminal frames the same header, rule counts and no-op wording, and the call row loses the blank row above and below it that Text's default padding added, drawing in the column every other tool's call row draws in.
- The retain, recall and reflect tools describe their cards as a ToolView instead of building terminal components in a memory-render.ts sibling, which is deleted; the terminal draws the same rows, memory bullets, preview caps and expand hints, and a memory cut to a terminal narrower than the eight-column floor the sibling clamped to now ends in an ellipsis inside its own colour instead of a hard cut mid-escape.
- The read_url tool describes its call row and its result card as a ToolView instead of building terminal components in a fetch-render.ts sibling, which is deleted; the terminal draws the same panel, metadata rows, preview caps, truncation notice and OSC 8 links, and the line stating how many preview lines were held back now draws in the dim its expand hint already used instead of a lighter muted.
- The resolve tool describes its call row and its result plate as a ToolView instead of building terminal components in a resolve-render.ts sibling, which is deleted; the terminal fills the same plate in the same colour for an accepted, failed and discarded resolution, and the renderer's inline flag goes with it, since the only reader was the gallery CLI.
- The debug tool describes its call row and its result panel as a ToolView instead of building terminal components in a debug-render.ts sibling, which is deleted; the panel draws the same session lines, output preview and truncation note, the header states the action after the tool name instead of concatenating both untoned, and the line stating how many preview lines were held back draws in the dim its expand hint already used instead of a lighter muted.
- The ssh tool renders through a host-agnostic ToolView instead of an ssh-render.ts sibling, and a command or output longer than the viewport is windowed by the rows it occupies after wrapping instead of by its line count.
- The todo tool describes its call row, its board and its finished line as a ToolView instead of building terminal components in a todo-render.ts sibling, which is deleted; the card draws the same rows, phase names, task marks, completion sweep and one-line summary it drew before, a task's mark and its words carry the tone as two runs instead of one, and a task whose status this build has no case for is drawn as open work rather than reaching the terminal with no colour to resolve.
- The inspect_image tool describes its call row, its answer panel and its failure card as a ToolView instead of building terminal components in an inspect-image-renderer.ts sibling, which is deleted; the card draws the same question line, four-line collapsed and sixteen-line expanded answer windows, held-back note and sanitised failure text, the settled panel states the outcome on its rail instead of taking the muted legacy edge, and the model and media type ride on the header row rather than a second row beneath it.
- The search_tool_bm25 tool describes its call row and its match list as a ToolView instead of building terminal components in a search-tool-bm25-render.ts sibling, which is deleted; the card states the same status line, five collapsed matches, label and description truncation bounds and fallback warning, the matches are a list the terminal marks and indents rather than rows carrying their own bullet and dot separators, and the held-back count closes the list with the expand gesture left to the host.
- ast_edit uses ToolView cards with host-managed expand hints; change content and error formatting are unchanged.
- The irc tool renders through a host-agnostic ToolView instead of an irc-render.ts sibling, a message states its direction in words (IRC to AuthLoader) rather than an arrow, and createIrcMessageCard and ircToolRenderer are no longer exported from the package root.
- The write tool renders through a host-agnostic ToolView instead of a write-render.ts sibling, the line-number gutter is three columns wide through a 999-line file instead of widening at each power of ten, and a partial result no longer leaves two blank rows between its progress line and the file.
- The file_search tool renders through a host-agnostic ToolView instead of a file-search-render.ts sibling, and a path too long for the frame is cut to the frame's width instead of wrapping onto a second row.
- The text_search tool renders through a host-agnostic ToolView instead of a text-search-render.ts sibling, and the rows of a card with no matches indent two columns under their header instead of starting in column zero.
- The structure_search tool renders through a host-agnostic ToolView instead of a structure-search-render.ts sibling, and a match group is held whole or dropped rather than cut at the row the budget ran out on.
- The launch tool renders through a host-agnostic ToolView instead of a launch-render.ts sibling, and each captured terminal row is cut to one row with an ellipsis instead of wrapping onto a second.
- The search tool describes its dispatching card as a ToolView instead of building terminal components in a search-renderer.ts sibling, which is deleted; a call reaches the same file, text or structure card it reached before, whether its type comes from the call or from the result's details, and the row for a call whose type is still arriving, the row naming a type that is not one of the three and the row for a failure that named no type draw in the column every other tool's row draws in instead of one column past it.
- The github tool renders through a host-agnostic ToolView instead of a gh-renderer.ts sibling, each failed job's held-back log count closes that job's own log rows instead of sitting under the last job in the group, and one held-back log line reads as 1 more log line.
- The browser tool renders through a host-agnostic ToolView instead of a render.ts sibling, a spawned browser's binary path is shortened against the home directory, and a rebuilt transcript holding a result without its call states no section for the script it does not have.
- The read tool renders through a host-agnostic ToolView instead of a read-render.ts sibling, the file is the row's description so the row reads Read: src/example.ts, and the line-number gutter is a constant three columns instead of widening at the 10, 100 and 1000-line crossings.
- The ask tool renders through a host-agnostic ToolView instead of an ask-render.ts sibling, and an option label keeps the emphasis its author wrote through an inline-Markdown run instead of the tool colouring it.
- The web_search tool renders through a host-agnostic ToolView instead of a render.ts sibling, and veyyon q's answer cap counts the answer's own lines rather than the rows a terminal wrapped them into.
- The five vibe tools render through a host-agnostic ToolView instead of a vibe-render.ts sibling, and the composer's caret blinks only on a surface that repaints and never on a message already delivered.
- The job tool renders through a host-agnostic ToolView instead of a job-render.ts sibling, and a collapsed card closes with one held-back note instead of a count on the closing branch of each tree it cut.
- The eval tool renders through a host-agnostic ToolView instead of an eval-render.ts sibling, a call is one card whose cells are labelled groups instead of one railed box per cell, and output that rewrote its row with a carriage return shows the row's last text instead of every draft of it.
- The lsp tool renders through a host-agnostic ToolView instead of a render.ts sibling, a diagnostic is one row of location, severity and message, and references are one row per location instead of a per-file tree two levels deep.
- The bash tool renders through a host-agnostic ToolView instead of a bash-render.ts sibling, and a sentence shaped like one of the tool's truncation, exit, wall-time, background or artifact notices that the program itself printed now survives instead of being deleted.
- The edit tool renders through a host-agnostic ToolView instead of an edit/renderer.ts sibling, an edit spanning several files is one card whose sections are the files instead of one card per file, and the change counts are stated at the end of the row instead of a ⟦+3/-1⟧ suffix in the tool's name.
- The task tool renders through a host-agnostic ToolView instead of a task/render.ts sibling, a call whose result has arrived stops repeating the brief and the agent list, and the live output under an agent is bounded to six rows instead of measured against the terminal's height.
- formatContextUsage is stated once in @veyyon/utils, which the status-line gauge, the subagent progress row and an eval cell's subagent tree all read, so a tool no longer imports a terminal module to format a token count. No user-visible behavior changes.
- Tool cards and late diagnostic messages share diagnostic parsing, severity ranking and structured rendering, with home-directory paths shortened in late diagnostic output.
- formatSessionSnapshot is stated once in debug/session-snapshot.ts for both halves of the debug tool. No user-visible behavior changes.
- A subprocess tool handler declares renderFinal alone: renderInline had one producer and two readers that both skipped it by name, so nothing it returned ever reached a screen. No user-visible behavior changes.
- A custom tool's renderCall and renderResult return HostView instead of a @veyyon/tui Component, so the published tool-plugin contract no longer makes every tool plugin a terminal plugin; a renderer that returns a Component still satisfies it unchanged. No user-visible behavior changes.
- An extension's MessageRenderer and AssistantThinkingRenderer and a hook's HookMessageRenderer return HostView instead of a @veyyon/tui Component. No user-visible behavior changes.
- The autoresearch setup console and init_experiment clamp breadth and attempts through clamp/clampLow from @veyyon/utils/math instead of local copies of the same arithmetic. No user-visible behavior changes.
- Time-Traveling Stream Rules, the todo board and thinking-effort resolution are session collaborators under src/session/runtime/, each owning its own state behind a host interface it declares (8, 13 and 12 names), instead of 22 fields spread across AgentSession, which drops from 19761 to 18356 lines. No user-visible behavior changes.
- #processAgentEvent records the turn's last assistant message once, in its synchronous prologue, instead of twice in the same synchronous stretch. No user-visible behavior changes.
- The hidden nudge vocabulary is session/nudges.ts alone: the customType names the session injects, the continuation cap, the plan-mode reminder budget, the plan-decision and prewalk trigger tables and the mid-run todo nudge gates, with HIDDEN_MESSAGE_TYPES naming the set. agent-session-message-shapes.ts reads message shapes and declares no type name, and runtime/todo-runtime.ts keeps no copy of the nudge thresholds. No user-visible behavior changes.
- Source-path comments in prompts/all-registries.ts, prompts/eval-overrides.ts and tools/reroot-hint.ts name the benchmark modules they cite at their new paths under tests/evals/; behavior is unchanged.
- Imports of the string, escape, keyboard, mouse and motion primitives name @veyyon/utils instead of @veyyon/tui, which no longer re-exports them. No user-visible behavior changes.
- No file under session/ names the terminal renderer: the session id comes from @veyyon/utils/ttyid and image visibility from the front end's probe, so @veyyon/tui is no longer loaded on the conversation engine's account. No user-visible behavior changes.
- Source directories are consolidated: memory (memories, memory-backend, mnemopi, hindsight), discovery (tool-discovery, capability), speech (tts, stt) and debugging (dap) each live under one directory, and seventeen single-module directories fold into the concern they belong to. Subpath imports of @veyyon/coding-agent follow the new layout. No user-visible behavior changes.
- The terminal component tree is grouped by concern: the 94 modules that sat flat in src/modes/terminal/components/ now live under transcript/, composer/, selectors/, dialogs/, chrome/, dashboard/ and account/. Subpath imports of @veyyon/coding-agent/modes/terminal/components/* follow the new layout. No user-visible behavior changes.
- The interactive terminal lives under src/modes/terminal/, and the modes that draw no terminal — print-mode.ts, rpc/, acp/ and the magic-keyword parsing in keywords/ — sit beside it rather than inside it. The palette moves to src/theme/ and extension state aggregation to src/extensibility/extension-state/, both of which a headless run reads. Subpath imports of @veyyon/coding-agent/modes/* and @veyyon/coding-agent/theme/* follow the new layout. No user-visible behavior changes.
- Goal mode, the working line and push-to-talk are their own modules under src/modes/terminal/controllers/ instead of living inline in the interactive mode, which drops from 5605 to 4495 lines. No user-visible behavior changes.
- The session runtime's module-level declarations move out of src/session/agent-session.ts into six siblings — agent-session-types.ts, agent-session-permissions.ts, agent-session-queue.ts, agent-session-retry-fallback.ts, agent-session-compaction-policy.ts and agent-session-message-shapes.ts — so importing the session event union or config record no longer pulls in the 20909-line runtime, which drops to 19704 lines. Subpath imports of @veyyon/coding-agent/session/agent-session follow the new layout; the package root barrel still exports every moved name. No user-visible behavior changes.
- The session factory's free declarations move out of src/sdk.ts into six siblings under src/session/ — factory-options.ts, factory-extensions.ts, factory-prompt.ts, factory-tools.ts, factory-mcp.ts and factory-notices.ts — so naming CreateAgentSessionOptions or calling a discovery helper no longer imports the composition root, which drops from 4861 to 3832 lines. Subpath imports of @veyyon/coding-agent/sdk follow the new layout; the package root barrel still exports every moved name. No user-visible behavior changes.
- Multi-target ast_grep searches now execute concurrently while preserving globally ordered paging, totals, parse errors, cancellation, and target-order failures.
- The vibe screens, the image-inspection call and an LSP hover code block draw no border of their own inside a tool block, so a block keeps one left edge; a tree connector remains only where a row belongs to the row above it, in the eval value tree, the grep line gutter, the job tree and the LSP reference tree.
- The legacy Pi bundled-module generator states which package roots a compatibility shim serves, so the compiled-mode override sweep derives that set instead of carrying its own copy; behavior is unchanged.
- The /agents dashboard uses a centered, bordered card with bracketed tabs and explicit agent status words.
- The status row reads its truncation limits from tools/core/render-limits, a leaf that imports nothing, rather than tools/core/render-utils, which drops the tool renderers, path helpers and image resizing from the launch card's import graph; first-frame time is unchanged, because those modules only declare functions.
- An MCP tool describes its call and result cards as a ToolView instead of building terminal components in mcp/render.ts, which is deleted; the terminal states the same arguments, structure walk, raw rows, held-back count and spill warning, indented two columns under the row that heads them and without the branch glyph the call row opened with.
- SETTING_KIND_HANDLERS is typed per setting kind, so each handler receives the definition variant its key selects instead of the whole union widened to any. No user-visible behavior changes.
- Subagent drive paths share abort-aware promise handling with unchanged cancellation behavior.
- Hook and user-message selectors share search editing without per-keystroke callback or query-array allocations.
Fixed
- Print, JSON and RPC mode flush Bun's stdout sink before exiting, so a piped consumer receives the whole last frame instead of losing up to 1 MiB of queued output.
- A spawned agent's card shows its resolved-model badge again on the live block, the registry path an extension wraps and the rebuilt transcript, per agent.showResolvedModelBadge.
- With VEYYON_FORCE_IMAGE_PROTOCOL=sixel and VEYYON_ALLOW_SIXEL_PASSTHROUGH=1, a bash card draws an inline Sixel image row as the program wrote it instead of blanking it.
- The extension graph walk reads each module file from disk once; the CommonJS check on a candidate reuses the walk's read instead of opening the file again.
- veyyon --help summarises worktree with the profile-scoped path ~/.veyyon/profiles/<name>/wt, matching the command's own description.
- Legacy hindsight.dynamicBankId and hindsight.agentName written as flat keys migrate to hindsight.scoping and hindsight.bankId and are dropped on rewrite instead of surviving as dead entries.
- Antigravity turns from a consumer Google account (aicode-consumers) no longer fail with 429 RESOURCE_EXHAUSTED on every request: the backend rejects any system instruction carrying the upstream oh-my-pi conventions header, so the preamble now opens Keywords follow RFC 2119: instead of RFC 2119:.
- A Gemini or Antigravity 429 whose body is Google's generic Resource has been exhausted (e.g. check quota) / RESOURCE_EXHAUSTED is a per-minute throttle and retries on the same account after 45–75 seconds instead of being read as a 30-minute daily quota that exceeded retry.maxDelayMs and ended the turn; the "exhausted your capacity … quota will reset" body still reads as the daily wall.
- Removing the retired providers.parallelFetch key no longer leaves an empty providers: section in the rewritten config.
- A nested legacy task.isolation.enabled no longer overrides an explicit task.isolation.mode during migration.
- Corrected comments that named a distribution channel or runtime API the project does not use; no behavior change.
- A subagent that inherits the session's model shows that model and effort in its Subagents row, the task widget and the /agents roster, and keeps the badge when a follow-up turn wakes it.
- An inherited subagent model's badge prints the effort the session settled on, so a parent running auto shows the resolved level rather than auto.
- A subagent's row label is generated with the session's live model when no tiny, commit or smol role is configured, as a session title is, instead of the persisted default role.
- A compaction candidate whose single-request summary timed out and was completed in stages starts the next compaction on that model staged, instead of waiting out the same timeout first.
- Command-mode detection recognizes shell and Python prefixes after Unicode leading whitespace in loaded drafts.
- An MCP server that repeats a pagination cursor or never ends its pages no longer hangs resources/list, resources/templates/list or prompts/list; every list method ends with a warning and the pages collected so far, as tools/list already did.
- Tool result cards preserve raw-string and multipart text, including MCP output and grouped read previews, while runtime result cards select eval or launch from their call arguments.
- Collab reconnect snapshots preserve completed tool result text and display metadata across current and historical tool-call record formats.
- HTML export preserves provider fallback transitions and redacts their model text in primary and nested transcripts.
- Empty job results render their success or error message for every registered job alias.
- The website model catalog refreshes from its relocated repository path before using the deployed copy.
- Release validation checks native sentinels under every discovered workspace root, and shortened release notes link to the complete tagged changelog.
- Terminal input delivery continues to later subscribers when an earlier subscriber throws.
- Tool cards retain wire-provided results during expansion and sealing, and restore expanded output when subsequent updates contain raw results.
- Clearing or replacing presentation rows stops detached animations, preserves completed-call history, and keeps subsequent reads visible.
- Stopping a terminal presentation driver releases card animation clocks even when its engine is not running.
- Extension discovery resolves installed plugins from the session's selected profile.
- Python composer borders retain their mode color when an agent view is focused.
- Completed and rebuilt tool cards retain their call arguments and rendered call details.
- Disposing a tool card stops its animation clocks and detaches its presentation subscription.
- Legacy tool result renderers receive the completed call arguments for partial and final results.
- Background provider usage refreshes repaint the status line without requiring further input.
- Tool cards retain both call and result renderer failure notices with their fallback output.
- The library entry point retains read-selector functions, write-preview helpers, filesystem-source extraction and the goal view after renderer separation.
- An auto-compaction pass that finds nothing to summarize warns about a compaction dead end only while the context is still over the recovery band, so a pass that runs after maintenance already freed the context no longer advises starting a fresh session.
- The MCP add wizard retains manually entered credentials for stdio, HTTP and SSE servers and opens OAuth settings after authentication errors.
- Retry and Edit OAuth settings accept pointer input immediately after OAuth failure or cancellation in the MCP add wizard.
- Kernel codec and shutdown defaults remain active when optional configuration fields are undefined.
- Startup frame capture stops retaining terminal output after typing, recording settlement, or frame release.
- Disabled launch status rows remain blank when the terminal is narrower than the composer inset.
- veyyon licenses reads the Open Sans and Source Code Pro notices from the tracked docs/handbook/fonts/ copies instead of the ignored mdbook build output, so the bundle regenerates and its test passes on a checkout without a handbook build.
- A compaction that had just freed context no longer reports "Compaction freed too little context to make progress" when its entry is written in the same millisecond as the kept assistant turn; whether a turn predates the latest compaction is read from its position on the branch, not its timestamp.
- The home anchor sizes its fills, the welcome hero mounts, and the per-frame sizing pass runs on the screen the interactive mode renders on rather than the one its constructor built, and startup.quiet is read from the session's settings like the other startup reads.
- An agent whose session is on screen is no longer parked under it: opening an agent pins it for as long as the main view points at it, a park deadline that elapses meanwhile is deferred, and the idle TTL counts again from the return to the main session.
- The task card lifts the missing-yield warning out of an agent's output under both its current spelling, SYSTEM WARNING: Agent exited without calling yield tool, and the Subagent spelling a session file recorded before it; the task:subagent:progress and task:subagent:lifecycle bus channels a collab guest matches on keep their spelling.
- Custom tools retain their declared call and result views when converted into extension tool definitions.
- Terminal tool cards shorten home-directory paths and replace tabs in metadata, notices, code, diffs, and generic argument previews before width fitting.
- Failed task results without agent details retain error text styling.
- Launch model context estimates exclude project context and clamp the remaining percentage to zero.
- Launched processes report completion even when they exit before the completion watch registers.
- Autoresearch best-result and confidence calculations exclude unmeasured placeholder zeros while retaining measured zero values.
- Configured shortcuts apply from the first editable frame, and model-selector shortcuts entered during startup preserve the draft through initialization.
- The launch composer repaints typed input before runtime initialization continues and preserves the mounted editor's change handler.
- Ordinary CLI launches no longer evaluate ACP authentication, and startup applies the configured theme once.
- Submissions entered during startup execute after initialization without waiting for a model turn, preserving later drafts and attachments through command handling and editor replacement.
- The launch composer shows the same linked-worktree location and draft-token estimate as the mounted session, avoiding a late footline repaint.
- bun run gen:tool-views in the coding-agent package uses the relocated clients/web generator.
- A web_search refusal, missing-credential, or provider-failure result is marked isError, so the model sees the failure as a failure.
- A tool result whose image-visibility notice is unchanged is memoized across turns instead of allocating a new wrapper each time.
- edit and apply_patch share one renderer object again, so a host that groups by identity (streamed-arg keys, the first-result replay) treats them as the same card. No user-visible change.
- A debug adapter command resolves against the debug working directory only when it is spelled as a relative path (./tool, ../tool), restoring the prefixes a mechanical path rewrite had widened to any leading dot.
- An overflow whose summary cannot fit any model no longer waits on a restore that never runs: the dead-end rescue truncates the oversized message to an artifact and the turn is retried, which the overflow-refusal suite now pins.
- A live tool card drawn from a ToolView spins again: a view is handed the frame it draws, so the spinner tick now rebuilds the card instead of only repainting it, and the streaming glyph on the browser, debug, eval, launch, ssh and vibe cards no longer sits frozen on the frame it was born with.
- The debug, resolve, retain, recall and reflect renderer entries declare the inline policy they declared before their cards became views. The flag reaches no reader in the terminal today, so nothing on screen changes.
- A tool card's header keeps the subject it states: the middle-cut the edit card needs was applied to every framed card, so ast_edit, file_search, text_search, structure_search, search_tool_bm25, inspect_image, launch and ssh cut a query, a glob or a path to … in a narrow terminal to keep counts that already fitted. A card now asks for the cut, and the edit card is the one that asks.
- A live card whose tool describes a ToolView obeys the merge policy its renderer entry states: debug, resolve, retain, recall, reflect and ssh drew the call row above the result card while the call was on screen, and drew one card when the transcript was rebuilt.
- veyyon config set and veyyon config reset create the profile's config directory before taking the file lock, so a first write into a profile that has no directory yet persists the setting instead of exiting 1 with ENOENT.
- goal-tool.ts no longer imports a ViewSpan type it stopped using when the goal card became a view. No user-visible change.
- A structure in a tool card stops at the nesting level its bound names: the view walk numbered a root key 0 where the terminal walk numbered it 1, so every task, eval and argument card showed one level deeper than the collapsed and expanded bounds allow.
- A JSON structure in a tool card states 1 more line where one line of a long string is held back, instead of 1 more lines; the view walk wrote the phrase by hand where the terminal walk it replaced counted through the shared formatter.
- The launch shell no longer evaluates the prompt registries: modes/keywords/{orchestrate,ultrathink,workflow}-keyword.ts kept imports of prompts/subagent/rows, prompts/turn-control/rows and the @veyyon/utils barrel after the notices they fed moved to magic-keyword-notices.ts, which pulled 62 extra modules into the first frame's import graph.
- The subagent model resolver's own precedence list no longer points at a fifth case it lost when subagent.model became the shared-switch layer. No user-visible change.
- HTML export works again: the five assets export/html/index.ts loads as strings — the markdown renderer, the template CSS, HTML and JS, and the generated tool views — lost their with { type: "text" } import attributes while unreleased, so each one loaded as a module and every export threw Missing 'default' export in module.
- Seven published entry points the reorganization dropped are served again at their new paths: ./modes/terminal/components/*, ./modes/terminal/components/extensions/*, ./modes/terminal/components/status-line/*, ./modes/terminal/controllers/*, ./modes/terminal/setup-wizard/*, ./modes/terminal/utils/* and ./export/markit/*. Every subpath 1.3.0 published now has a successor key.
- A source build of the compiled binary reaches the native addon package at natives/bridge/bindings, its path since the bindings moved out of packages/, instead of failing on a chdir to packages/natives.
- Tools are offered in BUILTIN_TOOL_NAMES declaration order again: composing the registry from the five domain manifests reshuffled seven names, and tool order is prompt order, so every cached prompt prefix was invalidated for a session whose tool set had not changed.
- The source launcher (scripts/veyyon, scripts/veyyon.cmd) finds the native addon at natives/bridge/bindings/native and provisions it through that package's ensure-native.ts, instead of dying at boot on packages/natives/scripts/ensure-native.ts after the bindings moved out of packages/.
- The compiled binary builds again: its legacy-extension module surface resolved each bundled package by its directory name under packages/, so the build died on packages/natives/package.json once the bindings moved to natives/bridge/bindings and the terminal engine to hosts/terminal/engine. Each bundled package is now found by the name its manifest declares, wherever the member sits.
- The compiled binary builds through its legacy-extension shims again: the @veyyon/ai and TypeBox compat shims were named by hand-written paths under packages/coding-agent/src/extensibility/, so the build reported two unresolvable entrypoints once both shims moved into @veyyon/kernel. Each shim is now resolved through its owning package's published subpath, at build time and at extension load.
- The launch card states the context percentage recorded at the end of the last launch instead of ?, and falls back to ? when the release, the model or the project changed.
- A debug adapter that exits during startup now reports its own stderr — pip install debugpy for a missing debugpy — instead of EPIPE: broken pipe, send.
- A submission arriving in the tick after the terminal asks for input is no longer dropped, and loop mode's auto-submit timer no longer arms a tick late: the goal-mode exit check ran as an await on every turn, and an async guard that returns early still yields before the input callback is installed.
- A run that draws nothing no longer tells the model its picture is on screen. -p, rpc and acp emit text, and the sentence attached to an image a tool returned was written from the launching terminal's graphics protocol, so the same read in a Kitty window reported the image as displayed to a pipe; the front end now states whether it draws, and a client that says nothing is taken at its word.
- A debug launch whose interpreter refuses now reports the interpreter's own exit code and stderr instead of EPIPE: broken pipe or DAP adapter disposed: writing the first request onto an adapter that has just died fails at the pipe, and the pipe's error names nothing the user can fix.
- An extension published against the old @veyyon/tui barrel loads again. Moving the width, key, mouse, motion, LaTeX, fuzzy and paint primitives to @veyyon/utils removed them from that barrel, so a plugin importing visibleWidth or Key from @earendil-works/pi-tui failed at import time and its whole extension went inactive; the bare tui package root now resolves to a compatibility surface carrying the renderer plus every module the barrel dropped.
- A turn that stops right after a tool round gets its stop-time passes again: the assistant message the settle reads was recorded behind the persistence await, so a text-only stop dispatched in the same tick as a tool result settled as if it still carried tool calls, and the todo reconciliation never fired past its first reminder.
- A model selector that names a provider and no model (openai/, openai/:high) is rejected where it is written instead of parsing to a model id of the empty string, which every caller then carried until a lookup failed somewhere else.
- A read, write, grep or image target that reaches outside the working directory through a symlink asks for approval even when it carries a selector suffix, so link.env:1-10, db.sqlite:users:42 and archive.zip:dir/file.ts:5-9 are no longer auto-approved where the bare path would have prompted.
- A tool status line shortens the paths it was given, so grep, glob, ast_grep, ast_edit, debug and set_cwd show ~/project/src instead of printing the home directory into the transcript, and a long path list is truncated rather than pushing the row past the terminal width.
- Multi-target ast_grep searches across overlapping paths deduplicate matches so totals, file counts, and paged results are not duplicated or truncated.
- grep reports why an archive could not be opened or read when the failure is not an Error, instead of the word undefined.
- The advisor configuration overlay, the autoresearch dashboard overlay and the autoswarm setup console share one set of box chrome, one stat strip and one key legend, and each frame ends where its content ends instead of being padded to the height of the terminal.
- The advisor overlay footer states the chord and the verb instead of repeating the advisor or model name already in the frame title.
- The autoresearch dashboard overlay opens on alt+x; ctrl+shift+x never reached veyyon under kitty, whose kitty_mod default consumes that chord.
- The autoresearch result table and summary no longer repeat the primary metric as a secondary column.
- A crashed autoresearch run reports - for the metric instead of 0ms, which sorted it as the fastest run in the table.
- A turn that calls a tool and then stops with text is treated as ending in text: the todo reminder fires again as the board changes instead of falling silent after the first one, and the rewind, plan-mode, verification and code-review checks run at that stop.
- The goal report from /goal show and the goal detail menu states the goal's status once: a paused goal read Status: paused (paused), and a finished one Status: complete (paused). Goal mode being off is now named only where the status does not already carry it, as active (mode off).
- A goal objective reaches every surface that shows it as one plain line: the /goal show report, the /goal menu title, the warning a disabled Goal Mode prints over a stored goal, the /goal autocomplete row and the goal tool's own card each formatted the objective raw, so an escape sequence in one styled or moved the rest of the surface, a tab opened a hole in it, and a newline split it across two fields.
- veyyon profile new runs in the compiled binary; 1.4.1 failed with awaitPromise is not defined from a mis-minified dynamic import, and --smoke-test and the installer CI now drive the profile seed path through the artifact.
- --export <path> of a missing or non-file session exits non-zero with Session file not found or Not a session file instead of writing an empty transcript and reporting success.
- --mode json exits EXIT_FAILURE on an errored turn and EXIT_INTERRUPTED on an aborted one, as text mode does; print and RPC mode wait for stdout to drain before exiting so a piped consumer receives the last frame.
- RPC mode answers a malformed stdin line with the documented parse error frame and keeps reading; the previous chunk parser threw on the first bad line and ended the session.
- veyyon install with no target exits 2 as a usage error, the same as a missing positional in every other subcommand.
- --help lists every --mode value from the parser's own table, acp included; the export example and the worktree description state the profile paths (~/.veyyon/profiles/<name>/…).
- --no-extensions disables discovery only: a path named with -e on the command line still loads, in a session and in veyyon models, as the flag's help text states.
- A --model @role whose role is unset, unknown or cyclic is reported as that role failure; a model id no model matches is reported with the count of models with usable credentials and the nearest candidates, instead of Model "x" not found. Run "veyyon models".
- A plugin's slash command runs from /<plugin>:<name> and from /<plugin> <name>; the parser split the namespaced spelling at the colon, so an exact lookup never matched.
- The goal tool is a read-tier tool: it prompted for approval in ask mode and was denied outright in plan mode, having no declared tier.
- An explicit agent.isolation.mode the host cannot provide runs on the next backend, records isolationFallback on the result, opens the merge summary with a notification naming the requested and actual backends, and is logged; auto reports no fallback.
- A spawned agent whose merge back into the parent tree does not land (a patch that does not apply, a branch that does not merge, a nested repository patch that fails) is reported as merge-failed instead of a clean completion whose work is not in the tree.
- The task card's line and size counts describe the block the reader sees: when the child's output was empty and stderr or a placeholder stands in for it, the artifact's 0B no longer labels that text.
- Claude Code's ~/.claude/plugins/installed_plugins.json is read only when discovery.importForeignConfig is on, and the plugin-roots cache is keyed on that setting; marketplace installs, --plugin-dir roots and a trusted project registry are the operator's own and load at the default, and their skills are part of the profile's skill set.
- The read card states depth and limit by name after the path; read { path: ".", limit: 3 } drew .:1-3, a line range the tool never read, and the HTML export's call line did the same.
- A ranged read of an immutable source (archive.zip:src/a.ts:2-3, artifact://x:2-3) numbers its lines whatever readLineNumbers is set to, so the requested lines are attributable.
- A read of a file over the snapshot size cap states Showing lines A-B (file not scanned to end) and no of N: the scan stops once the window is collected, so N was a lower bound presented as the file's length.
- The streaming bash preview reads the env object by walking the partial JSON, so "env" inside a command string is not an assignment list and a cwd or timeout after the object is not an entry.
- No tool card text reaches the terminal with a control sequence in it: drawToolView strips escapes from every text field of every view kind, so a model-supplied reason, a file's contents or a generic argument carrying \x1b[2J or an OSC 8 link is drawn as text; a captured run keeps the styles the terminal replays and loses the rest.
- A tool card whose renderer throws falls back to the generic arguments-and-output card, never to the exception's text; the vibe card reads a recorded session's details field by field, so a malformed record draws the generic card rather than failing the transcript.
- The job card lists a queued job as queued, with its position, rather than as running.
- A daemon the broker ran on a PTY that died to a signal reports that signal (SIGTERM, SIGKILL) instead of the shell's exit code 1; the addon recovers the signal from the wait status.
- The launch broker's idle reaper stops last-client-exit daemons when the last client disconnects and a persistent sibling keeps the broker alive, and re-arms when that persistent daemon ends so the broker exits too.
- A plugin whose package.json or .claude-plugin/plugin.json cannot be read or parsed costs that plugin and is reported through the operator channel and veyyon plugin doctor; it no longer aborts the session's plugin load.
- A plugin manifest's hooks and commands entries load: hooks through the extension runner and commands as plugin-sourced custom commands; only tools and extensions were read before.
- Two extensions registering the same tool or command name, and a custom tool or command that fails to load, are reported on the operator channel; the later registration wins and the earlier one was silently dropped.
- An MCP tool that withholds arguments withholds values only; a key-only error was delivered as undefined.
- An MCP server whose reconnects trip the breaker is reported on the operator channel with the server name and the suspension; the suspension was logged only.
- A CommonJS extension (module.exports = …, or a transpiled module with exports.__esModule) runs instead of being reported as missing its default export; the wrapper mirrors Bun's __esModule interop.
- A marketplace catalog entry the parser drops is reported with the plugin name, the failing field and the reason: veyyon plugin marketplace add/update print it to stderr and a session states it on the notice channel; the entry was skipped in silence and the cached catalog persisted without it.
Removed
- WRITE_GUTTER_MIN_WIDTH is no longer exported: the line-number gutter of a code card is the host's, stated once in src/modes/terminal/draw/draw-tool-view.ts, and no tool sets it.
- resolveModelFromSettings is removed from config/model-resolver; the role chain a session starts from resolves through resolveModelRoleValue, which reports why a role failed.
- ReadRenderArgs no longer carries offset: the read schema states a line window on the path itself (src/app.ts:50-200), and limit is the directory entry cap.