HomeChangelog
What changed, written for the people it affects.
Each entry is recorded alongside the change that caused it, so this page is generated from the repository rather than remembered afterwards.
Unreleased
1480 entries
These changes are merged and awaiting the first tagged release. Each entry was written when the change was made.
September 2026
577 entries
- Feature2026-09-29scheduler-run-latency
Faster scheduled agent runs. Chat, agent, and skill tasks now start the agent host up to two minutes before they are due, and a run's independent setup reads now happen in parallel. Project environments can opt into "Reuse setup when nothing changed", which skips the setup script when the last setup in that root succeeded and its definition, input files, and required outputs are unchanged. Identical setups running at the same time in one root now run only once. Each run records where its time went (fire delay, session, agent options, workspace, environment setup, first response, agent turn), shown in the run sheet. The desktop alarm clock now finds the next due task with a heap instead of scanning every armed task, and re-reads the wall clock at least every 30 seconds so tasks that come due while the machine sleeps fire promptly after wake.
- Feature2026-09-28files-page
Add a Files page (
/files): artifacts, canvas documents, images and uploaded files from every conversation in one searchable grid or list, with Recent / Favorites / Folders / Images / All views, body-text search, a workspace filter, previews and download. Favorites and folders keep an item even after its conversation is deleted; files can be uploaded straight into Files (text is extracted so they are searchable) and used in any chat. Artifacts, canvas documents and files are findable from ⌘K, canvas documents can be referenced with@canvas:, and Files data travels in portable backups. Desktop and web only for now. - Feature2026-09-28office-documents-work-mode-completion
Cognia Office workbooks keep their formulas correct through structural edits: inserting or deleting rows and columns, renaming a sheet, or deleting one now rewrites every formula reference across the workbook the way Excel does (references into deleted cells become
#REF!). Overlapping merges are refused instead of crashing the XLSX export,unmergereleases any merge the range touches, and a freeze with no rows or columns removes the frozen pane. NewclearRange,setRangeStyle, andappendRowsoperations, anoffice_read_rangetool that reads cell values under a budget, andoffice_list_versions/office_restore_versionround out editing; create, import, and apply return a compact summary instead of the whole workbook.Cognia Documents accepts Markdown:
documents_createtakes amarkdownbody and the newappendMarkdown/insertMarkdownoperations turn headings, nested lists, quotes, fenced code, and tables into real blocks, reporting any inline formatting it flattened.documents_read_markdownreads a document back as Markdown with optional block-id markers. Documents gain headings 1–6, nested list levels, quote and code blocks (exported with Word Quote and Source Code styles and read back from them),replaceBlock,findReplacewith optional tracked changes, and table row/column insert and delete. Session transcripts export their Markdown as structured Word content, and multi-line paragraphs and tracked changes now keep their line breaks in the right place in exported DOCX files.Both previews gain an Export button (with a confirmation when imported features would be lost), both plugins render their tool results as chat cards, and the artifact panel no longer offers PDF or "Download as Word" for plugin-owned workbooks and documents, which it could only print as JSON. Work mode can write documents and reports as native DOCX (
format: "docx"), reviews workbooks and DOCX documents as their text instead of their JSON model, reports a parsed review status, and points follow-up edits of native deliverables at their owning plugin's tools. - Fix2026-09-28draft-attachment-bytes
Fix files staged in the message box being restored as a 15-byte "[object Object]" after switching conversations or restarting: encrypted account data now stores byte arrays intact.
- Feature2026-09-26twin-embedding-override
Each digital twin can now use its own embedding model. The twin records which model built its index, skips retrieval with a "rebuild required" warning when the model changes, and can rebuild its index from the workbench Settings tab.
- Fix2026-09-26ast-grep-session-cwd
The agent's ast-grep search and replace tools now run in the chat's workspace and stop when you interrupt the turn; they previously ran in the app's own working directory and kept going.
- Fix2026-09-26notification-delivery-retention
Notification delivery history no longer grows forever. Once a message sent to a chat or webhook has settled and is older than your notification "Keep for" window (30 days by default), its text and the chat it went to are dropped. Only the record that it was sent (when, where, and the outcome) is kept, so an old notification can never be sent twice. Deliveries whose outcome is unknown are kept whole until resolved. Old send attempts, finished timers and sent digest entries are removed at the same time. The notification settings on desktop and phone now say that "Keep for" covers this too.
- Feature2026-09-26agent-a2ui-catalog
An agent can have its own A2UI component catalog: its surfaces render with it unless they name one, and the agent is told which extra components the catalog provides.
- Feature2026-09-26external-agent-duplicate
External agents can be duplicated from their settings page: the copy keeps every setting and its own copy of the credentials, and asks again for unsandboxed-launch approval.
- Fix2026-09-26notification-tables-governed
Notification delivery data is now encrypted on disk like the rest of your account's content: the rendered text queued to go to a chat or webhook, the chat each delivery target points at, and the run result summaries notifications quote. Rows already written stay readable and are encrypted the next time they're saved. None of the notification delivery data is copied to paired devices or into portable backups.
- Feature2026-09-26agent-advanced-overrides
The agent editor has an "Advanced overrides" area for the per-agent settings that used to be editable only through plugin packs: provider, thinking budget, output style, A2UI, plugin tools, built-in skills, OCR, tool filter, tool search, compaction, instruction files, workspace confinement, sandbox policy and platform defaults.
- Feature2026-09-26teammate-backing-agent
A teammate can run as a saved agent or variant picked in its character setting, and its subagent list now limits which subagents it can delegate to.
- Feature2026-09-26external-agent-config-pin
Squad teammates and subagent templates can now be pinned to one exact saved external-agent config (e.g. "Codex strict" instead of any Codex). A pinned config that is missing, disabled, or no longer of the chosen preset fails the run with a clear error instead of quietly using another config, and preset-only bindings now pick a config deterministically (enabled, connected, oldest, then id).
- Fix2026-09-26scheduler-override-copy
The scheduled-task editor now says what its overrides do: denied tools add to the agent's own denials, and the permission mode is a cap that can only lower the agent's mode.
- Feature2026-09-26agent-variants-and-workspace-default
Agents can now have variants: create a variant of any agent (including built-in and plugin-pack agents) and it follows its base for every setting it does not change, so fixing the base's prompt or adding a skill reaches all its variants. The agent list badges variants with their base and override count, offers reset and detach, and refuses to delete a base that still has variants. Workspaces can name a default agent (or variant) that new conversations started there begin as.
- Feature2026-09-26team-date-headings
In the expanded sidebar, conversations inside Chats and each team are now split under date headings (Today, Yesterday, Previous 7 days, and so on), the way the list already is when grouped by date. The headings follow the sort, so "Created" splits by creation date and "Oldest first" reverses them. Sorting by title or unread leaves the groups unsplit. A group's preview shows only the headings its visible rows sit under. Dragging reorders within one heading, and an order you set under "Today" doesn't pin that conversation to the top of "Yesterday" once it ages into it. While the pointer is over the list, a conversation that gets a new message stays under its current heading until you move away. Turn the headings off with "Date headings in each team" in the sidebar's Group by menu.
- Feature2026-09-26agent-capability-grants
Agent runs launched by other features now take per-run capability grants instead of patching the resolved options: scheduled tasks, workflow agent-turn nodes, plugin and bot turns can add skills, MCP servers, knowledge bases and instructions, deny tools and cap the permission mode, and every addition is still clamped by the agent's tool filter, Restricted Mode and permission ceiling. Scheduled
disallowedToolsnow add to the agent's denials instead of replacing them and a scheduledpermissionModecan only lower the resolved mode; a scheduled run whose agent was deleted, or whose skill is not enabled, fails instead of running a default persona. Fixes new agents losing computer-use, sandbox and account settings on create, preset-created external agents losing Codex options and model bindings,maxSteps/maxTurnsbeing ignored on plugin, workflow and subagent runs, connector and bot turns composing from the desktop composer's last mode, and plugin-pack agents not resolving in goals, scheduled outbound and workflow twin lookups. - Fix2026-09-26go-menu-from-catalog
The in-app Go menu (menubar and compact menu) now lists every destination, in the same order, sections and labels as the rail and the native Go menu. The Go menu no longer claims ⌘1–⌘8, so ⌘1–⌘7 reach the workbench panels in the desktop app again (pinned rail destinations keep ⌥1–⌥9).
- Fix2026-09-26rail-keyboard-roving
Navigation rail: the workspace switcher, the web shell's status buttons and plugin rail buttons now join the rail's single tab stop, so the arrow keys, Home and End reach every control on the rail.
- Fix2026-09-26unread-badge-single-source
The Windows taskbar button now shows the unread/attention count as an overlay badge (capped at "99+"), since Windows has no dock-style count badge. The Scheduler badge in the web shell no longer reads 0 until the scheduler page has been opened. All unread badges (desktop guild badges, dock/taskbar badge, mobile Chat tab and Inbox dot, installed-PWA icon) now read one shared live query per window.
August 2026
557 entries
- Feature2026-08-31designer-workflow-and-template-studio
Workflow designer and Template Studio overhaul.
The workflow editor's frame now uses the shell's own resizable panels, edge-panel motion clock, chrome-height token, Context Workbench phone drawer and Surface tiers, gains a tablet layout, and drops an unreachable mobile branch. The node palette splits its 124-entry "Actions" list into fifteen sections, the canvas and the palette stop rendering two different icons for the same node, and agent nodes carry their model, tool, skill and member counts on the card.
Agent-shaped inspector fields stop asking for hand-typed ids: model, tools, skills, subagents, external agents, team members and plan steps all open the registries the app already reads. Eight synthesizer-emitted node kinds get real labels and icons plus a diagnostic that explains, at edit time, which runtime context they need, and
/plan to-workflowoutput is finally runnable. Canvas nodes show each step's tokens and cost and open its run. Natural-language authoring gains entry points from the empty canvas, the command palette and a canvas selection, pluswf_list_teamsand a designer subagent that reads the live catalog.On a phone the canvas registers its loop and group renderers (they previously fell through to React Flow's default), gains a long-press action sheet with copy, paste, duplicate, delete and run-from-here, gains marquee multi-select on the desktop selection toolbar, and no longer forces the wide-axis orientation.
Template Studio stops answering its own confirmation questions on publish and instantiate, replaces thirteen kinds of text box with typed binding controls, wires the instance update/detach/fork/deprecate lifecycle that ADR-0100 advertised but never exposed, reports errors that previously vanished, and fixes the domain filter, node-group instantiation crash, two broken editor links, package download and card keyboard access.
- Feature2026-08-31squad-governance-in-settings
A squad's nine governance sections (overview, plugins, governance, execution, ultracode, worktrees, PR feedback, stacked delivery, memory) are now reachable from Settings, under one collapsed Advanced group on the squad's own page. They were editable only from a tab of the agent-teams workspace, a route that was taken out of navigation, so every one of those settings was on its way to being unreachable. They arrive as a single collapsed group rather than nine more rows, because the squad library is meant to answer what a squad is called, what it is for and who is on it without burying that under configuration. That page's delete is now the only way to delete a squad. The governance surface had a second one, and it redirected to the retired route.
- Feature2026-08-31run-coordination-tab
A squad run's consensus and delegations are now in the run cockpit, beside its activity and changes. They were tabs of the agent-teams workspace, a route taken out of navigation, so the decisions a run reached were only reachable by someone who still had the old URL. Both panels used to read whichever squad the app had last selected rather than the one the run belongs to, which meant that dropping them anywhere outside that workspace would have shown the wrong squad's data. They now take the squad to show, resolved from the run record itself, and they resolve it from an id that is present even while a run is live and streaming (the run's own id is not). On a device that does not carry squad run records the tab says so instead of rendering an empty list, which would have claimed the run reached no decisions at all.
- Feature2026-08-31agent-branches-move
The branches an isolated agent run leaves behind are now on the workspace page, where the repository that holds them is. They lived in a tab of the agent-teams workspace, a route that was taken out of navigation, so after a run settled the only durable trace of what it did was reachable only by someone who still had the old URL. The move also fixes their scope: that tab listed branches under one squad's configured working directory, while the branches actually accumulate in the checkout. The same tab mounted a third copy of the execution-environment inventory, scoped to a squad rather than a workspace, and that copy is gone.
- Fix2026-08-31mobile-reach-fixes
Five routes were reachable on a phone and rendered as a blank strip. The compact shell hands most routes a document scroll, which is not a definite height, so the height chain inside a feature-shell page collapses to zero and the page paints nothing under the top bar. Three routes had already shipped that way and been fixed one at a time. The list of exceptions was hand-maintained with no check, and
/workspace,/squads,/projects,/pluginsand/twinwere all missing from it. The list is now derived and guarded, so a new console route cannot repeat it. The settings home also stops cutting the wallpaper off at its own door, which every one of its sub-pages already renders. The mobile home's agent-teams tile now opens Squads, the surface that replaced it, instead of a route taken out of navigation, and it keeps its place on grids that already had it. The/meworkspace row shows which workspace the device is pointed at, which nothing outside the chat route said. A leftover mobile settings panel with no consumers is deleted. - Feature2026-08-31palette-workspace-reach
The command palette can now create, adopt and manage a workspace, not only switch between them, and it stops claiming the folder picker is desktop-only. Those three editors lived inside a popover in the desktop rail and a drawer on the chat route, so on any other route on a phone there was no way to reach them at all. The folder picker was gated on running the desktop app, while the workspace switcher on the very same device offered it, because a paired phone or browser browses the host's folders rather than its own. Navigation search also stops hiding routes a paired host actually serves: source control, the embedded browser and the performance dashboard were missing from the palette on every paired phone and browser, which on mobile is often the only way in.
- Feature2026-08-31ssh-and-machines-reach-every-shell
SSH hosts, remote hosts and Docker machines are now describable, testable and reachable from
/deviceson all three shells.An SSH row in the fleet console shows what was always in its saved profile and never on screen: the address, the auth method with whether the secret it needs is actually stored, the jump chain drawn as the ordered route it is, and the forwarding rules in both directions with their on/off state. A chain that cannot be resolved is refused rather than quietly connecting direct to a different machine.
A Test connection button gives an SSH host a real presence signal for the first time, so its row stops reading
unknownforever. It makes a real connection through the whole jump chain, never binds a port, and says up front what that costs: it authenticates, lands in the target's and every bastion's log, may prompt an ssh-agent, and trusts the host key on first contact. The result expires after ten minutes and is dropped when the host's address changes.A changed host key is now re-trustable wherever you connected. Previously only Settings could adjudicate one, while the device console and the terminal dock printed the raw
ssh_host_key_changed:{…}payload with no way forward. On a phone or a browser the mismatch and both fingerprints are still shown, with the re-trust pointed at the desktop that owns the host.A phone, a browser, or a desktop driving a remote host can now open an SSH session. The paired host makes the connection from a profile id, with credentials that never leave it. The mobile terminal gains the same shell picker the desktop dock uses. A host that does not have the named profile says so instead of returning a native error string.
Docker machines gained a shell and a summary. The device console now counts machines by state and says what an idle one costs, and a running machine can be opened as a real terminal, with tabs, replay, search and history, rather than only accepting one-shot commands.
cua-cloudandlumeare labelled as declared providers with no adapter wired instead of appearing usable./serversworks on a phone. The deployment fleet, the target detail with all five tabs and every action, and the operations rail behind a labelled trigger carrying the in-flight count. Previously it rendered as a desktop three-pane squeezed into two 16px panel icons.Three smaller honesty fixes:
/me/terminalnow sends a standalone browser to pairing instead of a dead screen, the paired-device terminal grant says why it is unavailable rather than sitting disabled in silence and states that it also reaches this machine's saved SSH hosts, and each capability cell finally names where its answer came from. - Feature2026-08-31workspace-roster-honesty
The workspace roster now says whether it is current, and who you are in it. It reads a local mirror of a server-owned list, which it never admitted: a week-old answer and a live one looked identical. It now carries the same staleness badge the issue board uses, says in words that it is a cached copy, and marks your own row so you are not scanning a list for your own name. Members get avatars, and a long roster gets a role filter. Inviting, changing a role and removing a member are shown as refused with the reason attached rather than left out, because the collaboration server publishes no workspace-member write API and exactly one part of this app is allowed to write those rows. The shared-activity panel gets the same freshness treatment, and the collaboration settings card now links to the workspace page it drives, which was the only place its effects were visible.
- Feature2026-08-31workspace-home
/workspacenow reads as the workspace's home rather than a stack of unlabelled sections. It carries the workspace switcher in its header, so the page about a workspace finally offers a way to change which workspace it is describing (on a phone the rail switcher lives inside a nav sheet only the chat route mounts, which left this page describing something you could not switch). Its numbers now include how many execution environments the workspace owns, which is the only hint the Environments tab existed. Every block sits in the shared console card, so the page matches the device console instead of inventing its own spacing, and it reflows against its own pane rather than the window. The Environments tab also offers the repository's declared configuration and its provisioning rules, which until now were reachable only from chat through the session settings sheet, so the page about the workspace could show you the worktrees but not the rules that produce them. - Feature2026-08-31worktree-row-truth
A worktree row now says which branch it is on, how much disk it is using, when it was last used, and what asked for it. The branch only ever reached the screen as a fallback in the Base column, so a worktree that had a branch was exactly the case that did not show one, and its HEAD was never rendered at all. Size and last-used have been on the host's registry record since it shipped and were dropped on the way to the UI, which left the one surface that lists worktrees unable to answer "what is taking up the disk" or "is anything still using this". The owner is now a link rather than a label, so a directory a squad or a scheduled task created takes you to it. The list is also grouped: locked, conflicted and prunable rows sort above the healthy ones instead of sitting in host order, where a worktree that needed a decision read the same as one that did not until the fourth column. The owner label for a squad-owned directory said "Agent Team", a name the app retired.
- Fix2026-08-31console-section-and-stat-strip
Console cards and their number strips are now one shared pair of primitives instead of a per-console rewrite. The card frame and the hairline stat strip that the device console had grown are lifted into
ConsoleSectionandStatStrip, which/workspaceand the other consoles can use rather than hand-rolling a bare<section>and a local stat tile. Both now carry the surface tier, so the device console's cards and stat strip finally answer to the style pack and the elevation setting: their corners follow the same named radius scale as the rest of the app instead of a fixedrounded-xl, and their depth follows the elevation preference instead of a hardcoded shadow. - Fix2026-08-31ssh-hosts-in-device-console
Saved SSH hosts now actually appear in the device console (
/devices) and in global search. All three read sites looked for them underAppSettings.terminalSettings, a key the settings shape has never declared, so the lookup resolved toundefinedand every saved profile was silently missing from both surfaces. They now read the real path,AppSettings.terminal.sshHosts, which is the same one Settings → Terminal writes. A saved SSH row whose profile is no longer in Settings now says so, instead of rendering a Connect button that is dead with no explanation. Device search also isolates its three sources, so one unhydrated store no longer empties the whole device section of the command palette. - Feature2026-08-31wan-signaling-dormancy
A paired device that has not checked in for 30 days no longer keeps a permanent WebRTC relay connection open. The desktop holds one relay socket per paired device, and nothing ever pruned the paired-device list, so reinstalls, dev pairings and retired phones accumulated until one real session was holding sixteen at once. The pairing itself is untouched: the record, its keys, its permissions and its grants all stay exactly as they were, and the device reconnects on its own the next time it checks in.
The device console now has a WAN connection card for each paired device saying whether a connection is being held and, when it is not, which of six reasons applies. "Idle for 30 days", "paused", "paired before relay connections existed", "the master switch is off" and "this shell does not manage relay connections" were previously indistinguishable from a device that simply never answered. Only the first is one click away, and its Connect now button starts a connection on demand, lasting until the device checks in or the app restarts.
- Fix2026-08-31signaling-reconnect-storm
The desktop no longer rebuilds every paired device's WebRTC signaling connection whenever an unrelated setting changes. The renderer re-pushed its signaling configuration on every
AppSettingswrite, because the settings row is a single Dexie record, so a theme change (or any of the ~169saveSettingscall sites) re-fired the live query. The Rust hub then applied each push by tearing down one WebSocket per paired device and re-running each one's full challenge / signature / key-exchange handshake. Both sides now compare before acting, so an unchanged configuration is a no-op.A device that is paused also stops holding a signaling connection open: pausing already puts it on the deny-list, so the socket could never serve a request. Cancelling a signaling client is now observed during its connect and handshake instead of only after, which removes a race where a torn-down client could reclaim the room and knock its own replacement offline. Finally, an established socket that the network drops is logged quietly and only escalates after ten consecutive losses, so ordinary WAN churn across many paired devices no longer buries real failures.
- Feature2026-08-31server-folder-picker-tree
Browse a paired Host's folders as a tree that starts where the Host actually allows. The picker now asks the Host which roots it will open (a new
fs_workspace_rootsread), opens inside one instead of guessing the local documents folder, expands directories lazily, and when a path is refused it offers the allowed roots as one click instead of leaving the Rust error on screen. Companion settings gain a read-only card naming those folders and where each is configured, andpnpm dev:headlesstakes--workspaces-dirto set the headless root, whichpnpm dev:web-headlessnow passes for you -- defaulting to the checkout itself, so the picker opens on your code instead of an empty data directory; pass--workspaces-dir ..if you want sibling repositories in reach too. - Fix2026-08-31encrypted-table-empty-and-transaction-writes
Fix writes to account-encrypted Dexie tables. An empty bulk write (
bulkPut([]),bulkAdd([])) and amodify()whose range matched no rows were both rejected as "criteria-only mutations", which made the Host dispatch queue logqueue drain failedon every quiet tick. Both are now the no-ops they were always meant to be. Decryption on theget/getMany/querypaths now holds the transaction open viaDexie.waitFor, so a read-modify-write such asTable.update()on an encrypted table no longer dies withInvalidStateError, and the field patch Dexie attaches to those writes is dropped so it can never land plaintext next to the ciphertext envelope. - Feature2026-08-31plugin-development-identity
A development build of a plugin now looks like one. The plugin detail header rendered
plugin.sourceas its raw enum, so it read "dev" or "marketplace" in English regardless of locale, and the library list showed no origin at all: a dev build sat among released ones with nothing to distinguish it, which is how an author ends up debugging a copy they are not running. Every origin now has a label in both locales, development builds are badged in the list, and a build that is standing in front of an installed one says which one it replaces. DevTools also stops telling you to restart the app and offers the restart: a plugin whose runtime is left dirty can only be cleared that way, and the workbench had been rendering that instruction as a sentence. Runningplugin newfrom the CLI launcher now points at the next step rather than leaving you to work it out. - Feature2026-08-31plugin-api-call-inspector
DevTools gains a Plugin API calls inspector. Every
ctx.*call a plugin makes into the host has been measured for a while (method, runtime, permission verdict, duration), but the only consumer was the trace bridge, which forwards a deliberately sampled subset to/logs. An author debugging a permission problem had to leave DevTools, open Traces, and hope their call was one of the sampled ones. The new pane, under Devtools → Advanced diagnostics, reads the same ring unsampled, with filters by plugin and outcome and a toggle that shows exactly which calls do reach Traces, so "my call isn't in Traces" stops being a mystery. It records metadata only: arguments and return values were never accepted into this ring and still are not. - Feature2026-08-31unified-plugin-runtime-logs
A plugin's output now reads the same wherever you look at it. Its logs were split across two screens with different gates: a frontend plugin's
ctx.loggerlines were reachable only from the DevTools Dev Session workbench and only after an activation had been verified, while a Python plugin's host output lived on the plugin detail page and never appeared in DevTools at all. A Python author watching the workbench saw an empty Runtime Logs card while their real output sat one page away, and a hybrid plugin only ever showed half of what it emitted. Both surfaces now read one merged, time-ordered stream, and every line says which host produced it. The workbench no longer hides everything until an activation is verified: with no proof it shows all generations and says so, which is exactly the situation where an author needs the output most. The detail page's Logs tab, previously Python-only, now appears for frontend and hybrid plugins too.wasmandvscode-extensiongenuinely have no per-plugin output channel, and DevTools now says which and why instead of rendering an empty list. - Feature2026-08-31in-app-plugin-file-watch
Plugin DevTools can now reload a plugin when its files change on disk, without the CLI running.
/plugins → Devtoolsgains a "Watch plugin folders" switch: a change under a locally-sourced plugin's install directory puts it through the same verified reload the CLI uses, so success is still only reported once the runtime reports a new active generation. Every plugin is listed with whether it is watched and, if not, why:wasmandvscode-extensionplugins need a build the app cannot do and still needcognia plugin dev, and a plugin installed from a package has no source folder to watch. This replaces a 546-line hot-reload module that no production code called and that would not have worked if it had, because it sent the watch command a flat payload where Tauri expected the arguments nested underargs.
July 2026
341 entries
- Fix2026-07-30appearance-typography-knobs-live
Settings → Appearance now actually changes the page. The line-height and letter-spacing sliders under Fine-tuning, and the line-height half of the Density presets, were written to the document on every change but read by no stylesheet, so moving them did nothing. Line height is now composed from both knobs and applied to every line-height token Tailwind resolves utilities against — plus markdown, which sets its own — and letter spacing is applied where it inherits to the whole document. Defaults are unchanged: at comfortable density and 1x scale the page renders exactly as before.
- Feature2026-07-30browser-companion-connection-resilience
Give the browser the same connection resilience the phone has when it talks to a Cognia server.
Opening Cognia in a browser against a self-hosted or cloud
cognia-serverproduced a client that could connect but could not recover well. Everything that keeps a connection alive across a changing network — learning the other addresses the host answers on, re-probing when connectivity returns or the tab comes back to the foreground, failing over to a different channel when the current one dies, provisioning TURN credentials, and the direct peer-to-peer tier — was written once and then gated behind a phone check, so a browser got none of it. All it had was the WebSocket's own reconnect backoff.None of that work is actually phone-specific. The one piece that genuinely is — discovering a host on the local network, which needs mDNS and a subnet sweep — is now the only thing still gated; the browser skips discovery and uses the addresses the host reports over the authenticated connection instead, which was the only route available to it anyway. Everything else runs in both.
The practical difference: a browser session survives a network change, follows the host if it moves between a tunnel and a direct address, and can negotiate a direct connection rather than relaying every message through the server.
- Fix2026-07-30close-review-gaps-truncate-audit-eval-mdns
Four fixes to cross-device behaviour that had been built but did not hold.
"Delete from here" on a phone deleted only the handset's own copy. The paired desktop still held every message, so the next sync pulled them straight back — the one deliberately destructive action in the conversation view silently undid itself. The deletion is now fanned out to the host first, the same way editing and resending a message already did it.
Evaluation defaults set on a phone never reached the desktop.
/me/evaledits the judge model, run count, gate thresholds and cost guard, but the field was classified as never crossing the wire in either direction — so the phone showed the built-in defaults rather than the host's real configuration, and every change stayed on the handset while the runs those defaults govern executed on the desktop.A refused attempt to run an agent on a host left no trace. The permission's contract is that every start and every refusal is recorded with the device that asked; the policy checks inside the spawn path were recorded, but the authorization gate an ungranted device actually hits returned its refusal before reaching any of them — so an unauthorized device probing the execution plane was the one denial that went unlogged. Both the HTTPS and WebRTC paths now record it.
The companion channel table reported mDNS as "blocked — server stopped" when mDNS was simply switched off and the server happened to be down. "Blocked" means the channel is on but something upstream is breaking it, which points at a fix that would not have helped: starting the server does not make a disabled advertiser advertise.
- Feature2026-07-30companion-channel-matrix
Settings → Mobile companion now answers "can my phone reach this machine, and how" in one table.
The four routes a paired device can take — the local network, local discovery, a public tunnel, and a direct WebRTC connection — each had their own card that knew only their own switch. Working out whether a phone could actually connect meant reading all four and knowing how they relate: that mDNS advertising a stopped server sends phones to a dead port, that a server bound to loopback is running but unreachable from anything else, that WebRTC switched on without a rendezvous server can never establish. Every one of those reads as "on" on its own card.
A Channels table now sits at the top of the section with one row per route: its state, the address a device would use, and the result of the last reachability test. It distinguishes a route that is simply switched off from one that is switched on but cannot work, and says which of those three reasons applies. A single badge in the header answers the summary question.
The separate "Connection diagnostics" card is gone. It ran the same reachability probe but printed a flat list of URLs with no indication of which route each belonged to; the test button now lives in the Channels table and its results are attributed to the route they came from.
- Feature2026-07-30conversation-branching-and-asides
Branch a conversation without losing the one you are in.
Branching used to mean one thing: fork the whole thread into a new session in the sidebar. That is the right move for a direction you mean to keep, and the wrong one for a question you want to ask on the side and fold back in a minute. The branch dialog now asks where the branch goes — a new conversation, or an aside that lives in the dock beside the thread it came from. Asides can be renamed, cleared, deleted, and promoted into a conversation of their own once one turns out to matter.
You can also choose what a branch carries. Alongside "copy verbatim" and "seed with a summary", the dialog now lets you pick individual messages, so a branch can start from the three turns that matter instead of the forty that preceded them. Selecting text in a message and choosing "Ask in an aside" does the same thing in one step.
Branches are visible from the thread they left: a message that has been branched from shows how many branches hang off it and lets you step between them, and the sidebar and session row show a session's branch count before you delete it.
Editing a question no longer destroys the answers below it. "Edit and resend" used to truncate the log from that message down — reword a question halfway up a long thread and everything after it was permanently gone. The edited message now joins the original as a sibling branch, and the edit is selected so you see your own version rather than the one that was pinned before. Deleting from a point is still available, but it is now its own explicit action ("Delete from here") behind a dialog that says how many messages go and warns that branch variants go with them.
Two storage fixes underneath. Branch rows and workbench sidechats were built by hand rather than through
createSession, so both omitted the workspace id — and because the sidebar reads sessions through a compound index, rows missing that field were not mis-filed but absent: branches vanished from the sidebar on the first reload after creation, and sidechats outlived the workspace they belonged to, along with all of their messages. Both are backfilled on upgrade. Workbench sidechats also gain an indexed binding, so opening one is a lookup instead of a scan of every session in the database. - Fix2026-07-30ios-push-entitlement
Fixed iOS push notifications:
pnpm mobile:sync:iosnow writes theaps-environmententitlement and links it into both build configurations. Previously this was a manual Xcode step, so a freshly synced iOS build could never register with APNs. - Fix2026-07-30island-over-fullscreen-and-rail-back-left
Keep the agent island visible over other apps' full-screen windows, and put the navigation rail back on the left edge.
The island used to withdraw completely — nothing painted, window shrunk to a click-through sliver — whenever a full-screen app owned its display, which made it look like it only worked on Cognia's own desktop. Its overlay panel is configured to float over every Space, so now it does: the island stays where you put it, on any Space, and the yield-the-top-strip behaviour moved behind a new "Hide under full-screen apps" switch in Settings → Agent fleet monitor that ships off. Turn it on if you want the top strip left alone while watching video or presenting; even then, a session that needs a permission or an answer still brings the island back. (macOS only — no other platform has the full-screen Space model this reads, and while the switch is off the window sweep behind it no longer runs at all.)
The navigation rail defaults to the left edge again. Right stays available in Settings → Sidebar and in the rail's right-click "Customize layout"; it is simply no longer where the rail lands out of the box.
- Feature2026-07-30mobile-byok-tool-loop
Standalone (BYOK) chat on mobile now runs a real tool loop: a phone with no paired desktop can search the web, fetch pages and call plugin tools instead of being a plain completion. Reuses the same renderer tool catalog, executor, and PII gate as the paired path — including when the Anthropic native-web-tools preference is on, which previously left a standalone turn with no web tools at all, because it swaps them for natives that only exist on the paired Agent-SDK path. Letting the model load skills mid-turn is the separate
Skillself-invocation preference, off by default; standalone honours it like the paired path does. - Feature2026-07-30mobile-cloud-account-sign-in
Sign in to a cloud Cognia account from the phone.
A multi-user cloud or self-hosted deployment authenticates through Logto, and the sign-in card lived only in the desktop's companion settings — where it also told you cloud sign-in was desktop-only. It never actually was: opening the authorize page already routes through the phone's in-app browser, the exchange is a plain PKCE flow, and the session store already had a non-desktop path. A phone connecting straight to a cloud server — the setup Logto exists for — simply had nowhere to do it.
There is now a Cloud account entry under Me. The card is the same one the desktop uses, so the two stay in step by construction.
One thing genuinely was broken underneath. Off the desktop the session is kept in an encrypted vault rather than the operating system keyring, and that vault refuses to store anything until it has been given its encryption key. Nothing ever gave it one for sign-in sessions, so a sign-in on a phone or in a browser would have completed the whole browser round-trip and then failed at the moment of saving the token. It now provisions that key the same way the plugin secret store does, and the card says plainly where your token ends up on each kind of device.
- Feature2026-07-30mobile-me-eval-page
Added
/me/evalso the Agent evaluation defaults (judge model, run k, gate thresholds, cost guard) are reachable from the phone. Shortcuts, the desktop pet and the external bridge are the sections still without a mobile entry. - Feature2026-07-30persistent-workbench-rail
The right-hand workbench now leaves its icon rail on screen when you close it (ADR-0098). Collapsing shrinks the column to the activity icons instead of hiding it entirely, dragging that rail's edge reopens it at the width you left it at, and releasing the divider snaps to the nearest width preset or back to the rail. Applies to the chat dock, Canvas, the workflow editor and the project editor; a new "Keep the icon rail on screen" switch in the workbench customizer restores the old collapse-to-nothing behaviour. Also fixes a toggle that needed two presses after dragging the dock shut, and plugin panels that reported themselves visible while the whole column was closed.
- Feature2026-07-30remote-agent-control-grant
Let a paired device run agents on another machine — and make elevated permissions grantable on a server at all.
Driving a remote Cognia host could open a terminal, read and write files and use git, but never start an agent there. Those commands accepted only the token the server's own brain uses internally, and pairing gives a device a different kind of credential — so there was no combination of settings that could reach them. There is now a per-device "Run agents" permission, separate from "Remote control": remote control steers work the machine already decided to run, while this starts new processes, and folding them into one switch would mean enabling the first quietly handed out the second. Both ask for biometric confirmation when you turn them on.
What a granted device may start does not widen: the host still only runs a fixed list of agent programs, only inside a workspace folder, and only with an allowlisted environment. Every start and every refusal is written to the host's audit log with the device that asked.
Underneath that, a bug that made the existing permissions unreachable on a server. Elevated permissions are stored per device and loaded into the running server at startup — but the only thing that ever loaded them was the desktop app's own window. A
cognia-serverhas no window, so its permission list was always empty and every elevated command was refused no matter what the operator intended. File writes, commits and pushes against a cloud host could not be granted from anywhere.cognia-server devices grant,revokeandgrantsare the missing half; grants are stored beside the server's other credentials and take effect at its next start, which the command tells you. - Feature2026-07-30remote-host-capabilities
Ask a remote host what it can do, instead of assuming it is like this machine.
When you connect to another Cognia host, the app had no way to find out what that machine is capable of. The only capability list it kept was for devices that had paired into this machine — phones, tablets — and connecting to a host runs the other way round, so the host you are driving was never in it. Everything was therefore judged by the local machine's own abilities: a workflow that needed something only a server can offer, like staying awake without a window open, was refused before it started even when the server you were connected to could have run it perfectly well.
Hosts now answer for themselves. On connecting, the app asks and remembers, and Settings → Remote hosts lists what came back — or says plainly that it has not asked yet. A host too old to answer, or briefly unreachable, keeps whatever it last reported rather than being blanked, because a slightly stale answer is still better than falling back to guessing.
The host answers through its own application layer rather than its network front door, so a desktop and a headless server both report themselves using the same definition of what a capability is.
This makes the cloud host visible and stops it being misjudged. It does not yet move work there: a scheduled task still runs wherever it was scheduled, and nothing hands it to a server when your desktop is off.
- Fix2026-07-30remote-scheduler-data-plane
Route scheduler CRUD, history, statistics, imports, and backfills to the active remote host while suspending the desktop scheduler to prevent duplicate execution.
- Feature2026-07-30settings-edits-reach-the-desktop
Settings you change on the phone now actually reach the paired desktop, and stop snapping back to the old value.
Two things were wrong at once. Mobile pages that embed a desktop settings section —
/me/appearancerenders the desktop appearance panel whole — wrote only to the phone's own database. The step that hands the change to the desktop lived in a helper that nine other/mepages called and this one structurally could not, so themes, custom themes, wallpapers, accent colour, custom CSS and imported VSCode themes changed on the phone stayed on the phone forever. The server had thirteen fields allowlisted specifically so those tabs would work, and not one of them was ever sent. That step now happens once, where settings are persisted, so every screen gets it — including whichever desktop section is reused next.The other was a visible flicker: change settings on a phone with no connection, and the moment it reconnected the first sync overwrote your edits with the desktop's older values, so the UI snapped back to the old setting and then changed again a second later once the queued writes drained. Fields with a write still waiting in the queue are now left alone until it lands. Writes that failed permanently are deliberately not protected — the desktop's value wins, because otherwise the two devices would never agree again.
Three settings deliberately stop travelling, because sending them was wrong rather than useful: biometric requirements belong to each device's own authenticator, the workflow editor's performance tier is chosen for one device's graphics, and the selected microphone is an identifier that means nothing elsewhere. Each still works normally on the device you set it on.
/me → Networkgains a read-only "Direct connection" panel showing the signaling server this device will actually dial, how many STUN and TURN servers it received, and whether those came from the host or are the built-in defaults. This was previously impossible to see and quietly wrong: a self-hosted signaling server or TURN relay configured on the desktop never reached the phone, and the only symptom was a direct connection failing on strict networks. - Feature2026-07-30settings-sync-one-classification-table
Make settings actually agree across your devices, and stop shipping desktop credentials to every paired phone.
Which settings travel between a phone and the desktop (or a cloud server) it is paired with used to be described by two separate hand-written lists — one in Rust for what the phone may write up, one in TypeScript for what the host mirrors back down. Nothing checked them against each other, and they had drifted a long way apart. Around fifty preferences could be pushed up but never came back down, so your appearance, text-to-speech, notification and web-search settings on the phone quietly diverged from the desktop's forever and no amount of syncing would reconcile them. One entry named a field that does not exist on the settings row at all. And the WebRTC fields were classified backwards: the phone reads the signaling address, STUN list and TURN relays from its own copy, but only ever received the built-in defaults — so if you pointed the desktop at a self-hosted signaling server or your own TURN relay, the phone never heard about it and simply failed to connect behind a strict NAT.
There is now one table that classifies every settings field as shared, server-authoritative, device-local, or desktop-only, and both lists are generated from it. Adding a settings field without classifying it fails the type check, and a gate fails the build if the generated Rust and OpenAPI copies drift from the table. Fields that deliberately do not travel now carry a written reason next to them.
Three settings stop being written from the phone to the desktop, because doing so was wrong rather than useful: biometric gating is a property of each device's own authenticator (pushing a phone's policy onto a laptop with no Touch ID could lock it out), the workflow editor's performance tier is chosen for one device's GPU, and the microphone selection is an identifier that means nothing on another machine. Each of these still works normally on the device you set it on. In the other direction, the remote-browser switch and the WebRTC endpoints now flow down from the host, which is what makes the cloud shared browser reachable from a phone or browser at all — it was gated on a value those clients could never receive.
Separately, and more seriously: the host used to put the entire settings row on the wire on every sync. The client only applied the portable subset, which made this look harmless, but the whole row had already been sent — including the host's API keys, provider and search-provider credentials, subscription tokens, WebDAV password, proxy authentication and working-directory path. Every paired device received all of it. The host now narrows the row to the mirrored fields before it leaves, because a client cannot un-receive a secret.
- Fix2026-07-30streaming-heading-size-parity
Markdown headings in a streaming assistant turn now render at their final size straight away. They were styled only on the finalised branch, so every
#/##heading rendered as plain body text for the whole stream and then jumped to its real size the instant the turn ended. - Fix2026-07-30sync-cursors-per-host
Stop two machines' data blending together after re-pairing a phone somewhere else.
Sync remembered how far it had got by table name alone, with nothing recording which machine a given position came from and nothing clearing it when a device paired to a different one. Re-pair a phone to another desktop — or to a server — and it resumed from the previous machine's position, asking the new one for "everything since a moment that means nothing here". The two machines' sessions, messages and characters then piled up in the same local store, silently and permanently.
Positions are now recorded per host, and the mirrored tables are cleared when a client starts talking to a different one. Those tables are a cache of a host's data rather than the device's own, so re-pulling them costs a little time and loses nothing. Device-local preferences are deliberately left alone.
Existing saved positions are discarded on upgrade: a position with no host recorded cannot be attributed to one after the fact, so the honest outcome is a single full re-sync rather than a watermark that might belong anywhere.
- Feature2026-07-30typeset-chat-typography
Markdown typography now runs on shadcn/typeset. Chat turns, plugin READMEs, skill docs and every other
MarkdownRenderersurface share one rhythm that scales with its container instead of the fixed pixel sizes each element carried before — headings, lists, quotes and inline code all track the surrounding text size, and the whole scale steps up on narrow viewports. Tables gain typeset's wide-block scroller. Cognia's own accents are unchanged: the primary-tinted italic blockquote, the bordered table grid with its filled header, and sentence-caseh6. - Feature2026-07-30unified-template-platform
Templates are now one system instead of twelve (ADR-0100). Agent teams, workflows, subagents, custom modes, characters and skills — plus Mini Apps, goals, scheduled tasks, prompt presets, subscription presets and documents — are searchable together in the new Template Studio at
/templates, filterable by kind, status and how much the source is trusted.Templates now have versions and a content hash, so a template can be published as an immutable release, forked, deprecated, and shared as a
.cognia-templatepackage that is size-bounded, checksummed and Ed25519-verified on import. Applying one shows a plan first — what it will create, what it needs to bind to, and what is blocking it — and the resulting resources remember which template and version they came from, so you can later see what drifted, update to a newer release, or detach them for good.Plugins can contribute templates through a dedicated API with its own four permissions, and instantiating one asks you first; a plugin never sees the ids of the resources its template binds to, and cannot apply a plan it did not have checked.
Your existing built-in and saved templates are converted on first launch. The conversion is journaled per device, so it is safe to re-run and can be rolled back per kind, and shipped built-ins keep tracking the app version rather than freezing at whatever shipped when you first launched.
Undated
5 entries
- Feature—desktop-browser-local-chromium
The desktop browser can run a local Chromium or attach to your own Chrome, with tabs, a download manager, Chrome extensions, cookie and password import from every major browser, a password vault with autofill, local files and dev-server discovery, and browser tools for external agents.
- Fix—router-fusion-chat-turn-fixes
Router + Fusion chat fixes: the chat breaker now trips after three turns in a row that each lost the ledger mid-turn; image-only turns are refused by Cascade and Panel (and never picked by Auto) instead of losing their images; retries, reroutes and durable replays reseal on the original turn's routing inputs and runtime lane; a replay that goes out unledgered is checked against the cost budget again; turns handed to the host are no longer sealed; the run card marks Claude Agent SDK runs as an estimated cap; every refusal the chat can show has a sentence; and recovery replays pending outbox effects at every boot.
- Fix—router-fusion-delegate-agents-workflows
Router + Fusion delegate now works from workflow steps and Squad members: the run gets its project, checkout and approved test profile, a run that needs your approval asks on the workflow or Squad run in Agent Runs and continues once you answer, and a delegate can be set to apply its verified patch to the workspace. The Run API reports the pending approval id and approval events, the E2B microVM tier falls back when it cannot take a local worktree, and patch writes no longer fall back to a non-atomic path on an authorization error.
- Fix—router-fusion-ledger-coverage
With Router + Fusion's ledger switches on, every model call of the
ai.promptv2 node (explicit and routed, each fallback attempt included),ai.council,ai.ensemble, the/councilcommand, Agent auto-compose and Agent text-only runs is now reserved and settled on the ledger under the right workspace; concurrent background calls are no longer double-counted, and a call that falls back unledgered raises a "Model call not ledgered" notice. - Fix—router-fusion-reservation-owner
A paired device can now answer Router + Fusion spending reservations only for turns it started itself, and removing a Companion Host deletes its encrypted database and Router + Fusion ledger along with the plaintext one.