Changelog¶
All notable changes to ClotoCore are documented in this file.
Format follows Keep a Changelog. Versioning follows the project's phase scheme: Alpha (A), Beta (βX.Y = 0.X.Y), Stable (1.X.Y).
[Unreleased]¶
Added¶
- A remote MCP server's bearer can be rotated in place.
PUT /api/mcp/servers/:name/settingsacceptsauth_tokenfor streamable-http servers: a new value replaces the stored one and the server reconnects with it, and""clears it. Until now the token could only be set when the server was registered, so rotating it meant deleting the server and its per-agent grants and adding both back. The reply reports whether the reconnect succeeded and never contains the token. auth_tokencan be a${NAME}reference on every path. It is resolved from the kernel's environment when the server connects, so the database keeps only the variable's name. Before, onlymcp.tomlresolved references; a server added over REST or restored from the database sent the text${NAME}as its bearer. An unset or empty variable now fails the connection with a message naming it, instead of connecting without credentials. Settings responses show the referenced name asauth_token_reference.
[0.7.0a1] — 2026-09-21¶
The first pre-release of the 0.7.0 line. The number moves to 0.7 because the
dashboard was rebuilt rather than adjusted: the conversation, the connectors,
the agents and the settings are each a page of their own now, inside the
operating system's own window frame, with one search that reaches all of them.
Under the scheme this project versions by, X in 0.X.Y is the major
position, and a release that changes what the application looks like from its
first screen belongs there rather than in a patch.
A 0.6.9 line was prepared and written up, and then never published — no tag, no release, and no installed user ever received it. That work ships here. Its notes are kept below under their own heading instead of being folded in, so that what was one batch still reads as one.
Added¶
-
Two chat routes a connector panel can be given.
POST /api/chat/{agent}/sendsays something to the agent in the path, in one of its conversations, and has it answer; the kernel takes the sender from the conversation's owner, never from the request.GET /api/chat/{agent}/conversations/{id}reads one conversation with its newest messages. Until now a panel could store a message (POST .../messages) but not get an answer: the route that makes an agent reply names its target in the body, so no exact path could pin it, and reading one conversation needed a query string a panel cannot declare. -
Settings → Security: the hub access token. Paste a token issued on the hub to bind it; the field is cleared as soon as it is sent. The group shows the connectors it opens, the expiry, and the start of this kernel's key fingerprint (the full value on hover), with Renew beside the expiry. An expired token offers no Renew and says to ask for a new one on the hub. Forget is behind a confirmation. A notice that names an in-app page (the expiry and refusal notices do) now has Open in the bell, which goes to that page; only a path inside the app is followed. The marketplace says, under the description, when an entry is published only to you through the token. Checked against the review checklist (
docs/DESIGN_PHILOSOPHY.md§6): 1 of 25 — the loading state shows only the heading until the status arrives. - Restricted connectors: a hub access token for this kernel. The hub can
now publish a connector only to kernels that hold an access token for it.
Paste a token issued on the hub into
POST /api/hub-access/token; the kernel creates an Ed25519 key, binds the token to it, and from then on signs the catalog fetch and the connector download with that key. The headers go only to the hub the token was bound on, and a request carrying them never follows a redirect.GET /api/hub-accessshows what the token opens, when it expires and the key fingerprint, never the token.POST /api/hub-access/renewexchanges it for a new one andDELETE /api/hub-access/tokenforgets it. All four are refused to agent tokens, and the panel write gate now refuses a deny list of route prefixes (/api/modules,/api/hub-access) that no panel may declare. From 30 days before expiry the kernel raises one notice a day. A token the hub refuses raises a notice and the catalog falls back to the public view; installed restricted connectors keep working, and are not reported as dropped from the catalog. Design:docs/HUB_ACCESS_DESIGN.md. -
Connector panels can change kernel state, behind a gate. A panel may now declare
writesin its connector manifest: exactPOST/PATCHroutes under/api/, one per entry. A write goes throughPOST /api/modules/:id/write, which asks again on every write whether the panel's connector was installed from the marketplace at truststandardor above, whether its seal still verifies against the installed files, whether the route is one it declared, and whether the operator consented to exactly that list for that version. Only then does it forward the request, with the caller's own credentials. Every write and every refusal is audited, without the request body.GET /api/modules/:id/write-accesssays whether a panel can write and why not;PUT/DELETE /api/modules/:id/write-consentgive and revoke consent. Installs now keep a receipt of the trust level and seal they placed, because a connector that ships only panels has no server row to keep them in. Design:docs/PANEL_WRITE_GATE_DESIGN.md. -
An agent's model and effort can be chosen within a range.
POST /api/agents/:id/engine-selectionchanges onlymodelandeffortin the agent's engine settings (the metadata key named after its engine), and only to values listed in the same settings'allowed_modelsandallowed_efforts. The range itself is written elsewhere — by whoever owns the agent's desired state — and cannot be widened here. The write is a compare-and-set, so a concurrent change is a 409 rather than a lost update, and every change is audited (AGENT_ENGINE_SELECTED, from and to). It exists so a connector panel can offer the choice without being givenPOST /api/agents/:id, which can rename the agent or change its engine. -
Last usage shows the model an engine actually ran on. When an engine reports
model/reasoning_effortin its response,GET /api/agents/:id/last-usageshows those instead of the provider's configured model. An engine that drives an external harness knows what the harness ran; the provider row only knows what was configured. -
A consent can say who gave it.
PUT /api/modules/:id/write-consentaccepts an optional{"note": "..."}and writes it into the audit row. A release script that re-consents after shipping a new version and a person pressing Allow hold the same admin credential, so the audit actor alone could not tell them apart. -
The dashboard asks before a panel acts for you. A panel that declares writes and is allowed to make them shows a consent sheet the first time: what it may do, in words ("Send messages to agent.manager"), with Allow and Not now. Once allowed, the panel's header says "Can write" and lists the same actions on click. If the panel cannot write, the page says why, in the kernel's words, and offers no way to allow it. If the declared actions or the version change, the panel asks again. Settings → Security lists every panel you allowed, each with Withdraw. The host sends a declared write only to the kernel's write relay, never to the route itself, and sends nothing for a write the panel did not declare exactly. Scored against the review checklist (docs/DESIGN_PHILOSOPHY.md §6): 0 of 22 applicable signals, 2 partial (no focus rings of its own and no breakpoints, as elsewhere).
-
One agent's grants on one server, set in one call.
GET/PUT /api/agents/:id/mcp-access/:serverreads and replaces an agent's server and tool grants on a single server, and nothing else — unlikePUT /api/mcp/servers/:name/access, which replaces every agent's grants on the server, so writing one agent's there meant reading back and resending everyone else's. The answer carries the server'sdefault_policy, which decides every tool the set does not name. With no server grant on anopt-inserver, a set of allowed tools is closed: a tool the server adds later has no grant and is refused, which a server-wide allow with per-tool denies cannot say. A server or agent nobody registered is a 404, not a grant stored against a name that decides nothing. -
Themes you can write. A theme is now a JSON file of colours instead of a block of CSS compiled into the app. Import one from Settings → General → Theme packs — in the desktop app or in a browser — or, on the desktop, drop it into
Documents/ClotoCore/themes/. Export gives you the default theme as a template;docs/THEMES.mdis the author's guide. A file that is incomplete or not a theme is refused with the reason, and so is one whose body text could not be read (under it, the page that switches away could not be read either). A theme whose smaller text is faint is offered with a "low contrast" mark. Nothing in a theme file reaches the page as written — colours are parsed into numbers and the stylesheet is generated from those.
Changed¶
-
The line under an agent's face says what happens, not how they feel. On the new-chat screen and in an empty conversation, one of five lines was picked at random and put in the agent's mouth ("Good to see you…", "Take your time…"). The interface does not know who an agent is, and the warmth decided it for every one of them. The line is now the same for all: "Start a conversation with the agent." Under the face that creates an agent it is "Create a new agent."
-
A reply the engine could not produce looks like it. It used to arrive as an amber card with an icon tile, a shadow and a slide-in — and, when it came in live, it was first typed out as if the agent were saying
[Error] …, then swapped for the card. It is now drawn where the reply would be, straight away: a hollow mark (the agent said nothing), one sentence, the engine's own words in the status colour, and Again, Copy and Details for a report — the last opens the same pasteable report as a crashed screen — always shown rather than on hover. Scored against the review checklist (docs/DESIGN_PHILOSOPHY.md§6) the old card carried 4 of the 25 signals (a translucent tinted card, an icon tile, radius and shadow of its own, motion with no meaning) and part of a fifth (an error state with nothing to do about it); the new turn carries none. -
A message that could not be sent is no longer thrown away. When the kernel could not be reached, the message you wrote disappeared and a warning in the style of a date line showed for five seconds, then went too — what you had typed was gone. The message now stays where you wrote it, stepped back and marked "Not sent." with the reason, and Send again sends it as it was. Edit puts it back in the composer; what you send then replaces it as a new message, not as a branch of one the kernel never received.
-
The box under "Create an agent" says what it is for. On the new-chat screen, with nobody facing you, the composer was an empty box with a greyed send arrow: pressing it or typing anything opened the form, and what you had typed was thrown away. It now asks for a name, the button is a plus rather than an arrow that sends nothing, and Enter or the plus opens the form with the name already in it. Pressing or typing in the box no longer opens anything by itself, and a message half-written to someone else does not turn up there as a name.
- Theme and light/dark are two settings. "Light / Dark / System / Legacy" was one choice that mixed which palette with which face of it. They are now separate: a theme (Cloto, Legacy, or one you imported) and a mode (light, dark, or the device's). An existing choice carries over — Legacy stays Legacy following the device, as it did. Dark, light and Legacy draw exactly the colours they drew before (measured in a browser, every colour token on all four faces).
-
An agent's colour stays readable on a light theme. The accent was corrected for contrast against the dark raised surface whatever was on screen. It is now corrected against the surface that is actually drawn — darkened on a light one — and text set on it turns white when white reads better.
-
Stop stops the reply, not just the waiting. The stop button now asks the kernel to stop the reply where it is being produced (
POST /api/chat/{agent_id}/stop). Nothing of a stopped reply is stored, so it no longer reappears when the conversation is opened again, and every open window learns it stopped (aResponseStoppedevent takes the place of the reply). A stop pressed while the message still waits behind the agent's previous turn is kept and acts as soon as the message has been stored — what you wrote is never lost. If the reply had already finished, it is shown after all. The engine is told to stop as well: the kernel sends MCP cancellation for the call the reply had reached, so an engine running over stdio stops generating (and spending tokens) instead of finishing an answer nobody sees. -
Search, from anywhere (⌘K / Ctrl+K). A field over the page that goes to a screen or a settings section, a conversation (by its title or who it is with), an MCP server (by its name or what it is for) or a memory (among the recent ones the memory server lists, which the group says). Arrows move, Enter goes, Escape closes and hands the focus back to where it was; the sidebar's search button opens it too. What was said inside conversations is searched as well, archived conversations included: the group shows the first five matches with the text around each, where it was said and with whom, and how many more there are. The kernel answers it (
GET /api/chat/search, a full-text index that finds a phrase inside Japanese text as readily as an English word)./puts the caret in the composer when nothing else is being typed in, and ⌘N (new chat) now goes through the same one table of shortcuts. -
The keyboard can always see where it is. One focus ring for the whole app, shown only for keyboard focus: neutral everywhere, the present agent's colour in the chat. The workshop's ring had been the agent's colour, which the workshop does not wear, and six inputs had switched the ring off.
-
CLI agents is a page. Connecting a CLI harness moved out of a dialog to
/agents/cli: the harnesses on this machine down the left — whether each is usable, its version, how it is billed, where its credential lives, and how many agents run on it — and the chosen one on the right with its state, the connector's options and the agents that run on it. Each agent is listed under the harness its next run will actually use; an agent whose saved settings cannot be read, or that names a harness this machine does not have, is shown as such under every harness, because its runs fail. "None found" now means none is installed. Everything on the page comes from the connector: the harness list from its probe, the options from its catalog entry, the per-agent fields from its schema. Saving asks everything that can refuse — the agents still existing, the server settings being readable — before it writes anything, and writes the agents before restarting the connector. An agent's engine row points here when its engine runs a harness. Scored against the review checklist: 0 of 21 applicable signals, 2 partial (no focus rings of its own yet, and no breakpoint below the mock's width). -
A new agent can be given its icon, and its VRM, as it is made. The create dialog has an icon row under the name — the picture shows at once, can be taken back, and is refused before anything is sent if it is over the 5MB the kernel accepts — and a VRM row under Advanced. A VRM that carries a thumbnail offers it as the icon, as the settings page does. Nothing is uploaded until the agent exists. If the agent is made but its icon or VRM cannot be saved, that is said on the screen you return to, beside the new agent — not as a failed creation, which would invite making a second agent of the same name.
-
The memory screen is one time axis instead of a grid of cards. What an agent remembers is listed newest first under a band for each calendar day, and a run of days with nothing on them is drawn as a single compressed segment saying how long it was, so silence has a size. The screen wears an agent's colour in one place only — the line under the agent tab you have selected; points and the thirty-day band stay neutral. What was remembered is set in the reading face rather than monospace, clamped to two lines, and opened by the pointer or by keyboard focus. The right column holds the episodes — with a line saying how the first one is made when there are none — over a band of the last thirty days, counted from the memories already loaded. Filters across the top (all, each agent, long-term only, episodes only) narrow together with a search over the text, the agent's name and the date. Editing, locking, deleting, export, import and refresh are all still there, as text at the row's right when the row is under the pointer or holds focus. A refresh that fails says so and leaves the axis on the screen. Scored against the review checklist: 0 of 21 applicable signals.
-
Settings is a page. It opens at
/settingsinstead of over whatever screen you were on, with the sections down the left and, on the right, rows that each say what the setting is, what it is for, and carry one control. The cards are gone, and so is the coloured rail beside the selected section: the workshop has no accent. Which section is open is in the address, so the update notice sends you straight to About, and Back leaves settings in one step rather than walking back through the sections you looked at. The language, model and update-channel pickers are drawn by the app rather than by the operating system and answer to the keyboard the same way; in the model list Enter now picks a model, and Save is what saves it. Scored against the review checklist: 0 of 21 applicable signals, 2 partial (no breakpoints below the mock's width were designed; the key's reveal, copy and regenerate stay icon-only). -
Back, forward and the sidebar toggle are back, in a bar of the page's own. Making the window's frame the operating system's had taken them away with the old title bar. A thin bar across the top now carries three controls and nothing else: hide or show the sidebar (remembered between launches), back, and forward. Back and forward are dimmed when there is nowhere to go, and opening something new from an earlier page drops the way forward, as a browser does. The bar continues the sidebar's surface while the sidebar is shown, has no line under it, and everything in it that is not a button is what the window is dragged by. On macOS the controls start to the right of the window buttons.
-
The chat is the living room of the design mocks. The conversation is a 720px reading column: your turns sit right, on the receding surface; the agent's turns carry a dot in the agent's colour and no avatar per line. Each turn shows its clock, days are separated, and edit / copy / again / read aloud appear on hover. The composer is a textarea that grows with the text (Enter sends, Shift+Enter breaks the line, IME composition never sends), with attach, who you are talking to, the engine, the context meter and a round send button in one row. While a reply is being produced the send button is a stop button: what was shown stays, a line says the room stopped waiting, and the rest of that reply is not drawn. An empty conversation is the agent's presence — face, name, state, and the threads to continue from. Scrollbars are visible again and a "jump to latest" button appears when you have scrolled up.
-
The header names the agent, their state (thinking and how many tools they used, or waiting and when you last spoke) and the conversation's title. Agent settings and the 3D avatar window are behind the header's tools.
-
An agent's question is asked in the agent's words. A command approval, a refused tool call, one agent asking another and a message from outside are all drawn the same way: the agent's colour on the left edge, the question, the command in a mono box, the consequence as a sentence, and the answers — go ahead (from now on), just this once, not now — with the impact the kernel derived at the right. The question is asked inside the conversation while that conversation is open; the window-level deck asks it only for an agent you are not looking at, never twice on one screen. A refusal carries nothing to answer.
-
The MCP page is the workshop of the design mocks. One column with a band per kind — reasoning, memory, tools, senses, output — and the servers that need a hand first, whatever their kind. Every row carries the server's name, its id, the one line that says what it is for, and its tool count; a state is written only when it deviates (failing, an unset variable, connecting, stopped, an update waiting). The line comes from the server's own description, else the catalog's, never from the dashboard. Search covers names, ids and descriptions; the tabs are installed, marketplace and updates.
- A server's page replaces the settings modal: sections on the left (overview, environment, tools, access, logs), rows of item, explanation and control on the right, and a save bar below. Nothing reaches the kernel until save is pressed; discard puts the edits back. The overview names the description, the origin (installed from the marketplace on a date, at a version, or registered by hand), the launch command and the default policy in words. Tools are listed with their descriptions. Access is per agent — default, allow, deny for the server, and tool by tool when the agent is opened.
-
The kernel's server list now carries each server's description, installed version and registration time, and
GET /api/mcp/servers/:name/toolsanswers with the tools and their descriptions. -
A new chat is a screen, not an empty row. Pressing New chat (or ⌘N) used to create a conversation at once, so the list filled with untitled rows that nothing was ever said in. It now opens on the agent's presence — face, name, state and an opening remark, one of several — with the ordinary composer under it, and nothing is created until the first message is sent; the row appears in the list at that moment, and leaving without sending leaves nothing. Who the chat is with is chosen there: the faces turn by a horizontal swipe, a drag, or the arrow buttons, in the order you last spoke with them, and the accent follows whoever is facing. "Create an agent" is the face at the left end, and the only one when nobody exists yet; nothing can be sent while it is facing, or to an agent that is off. Turning keeps what was typed. Turning past an agent does not mark their waiting questions as read.
- On that screen, who is one movement away is shown: the neighbour's face stands beside each arrow, small, colourless and half lit, and pressing it turns to them; past an end there is no arrow. The empty face of "create an agent" is a plus and is itself the button. While it is facing, the composer is an empty box that says nothing — pressing it, or typing into it, opens the form that makes an agent — and the send button is in no one's colour, since the accent belongs to an agent and nobody is there. A face stands at the same height whoever it is, and the composer does not move as the faces turn.
- The conversation list no longer shows an empty list under a lone "show more" when nothing is from the last week: the older conversations are then the list.
- The faintest text step is a little lighter in the dark theme (62% from 58%). It was already above 4.5:1, but it is almost always 12px, and thin small type on a dark surface reads fainter than its ratio says.
- The Chat link is gone from the navigation. A conversation is reached by pressing New chat or by choosing it in the list; the link only reopened whichever one had been open.
- The window's frame is the operating system's. The bar the dashboard drew across the top of the window — back and forward, the product name, "N / N active", help, a connection dot and its own minimise / maximise / close buttons — is gone, and so is the line under it. On macOS the window buttons sit over the top-left of the page and the two surfaces run up to the top edge; elsewhere the OS draws its own title bar, in the app's theme rather than the system's. What the bar carried has moved to where it belongs: help is a link in the navigation, a newer build turns the version number in the sidebar's foot into the way to it, and that foot now says when the kernel cannot be reached instead of always saying it is running. Back and forward are not replaced. A window-state file written by an older build no longer takes the frame away again: whether the window has one is no longer restored.
- The agents screen is the roster of the design mocks. The card grid and the always-open create form are gone. On the left, everyone who exists in two groups — answering now, and idle — each row a face, a name, one line of state and when you last spoke. An agent that is off says so and is dimmed. On the right, the one you picked, read out a line at a time: role, engine (with the engine its routing switches to), memory server and how many long-term memories it holds, how many servers and tools it may call, its cron jobs with their times, whether it has an avatar, and its colour. The list is monochrome except the row you picked, whose face wears that agent's colour — and the colour is written onto this screen only, so opening the workshop no longer recolours the app around it.
- A mark on the row when an agent is waiting on you. It counts the questions an agent cannot proceed without — approvals and proposals — and deliberately not notices, which an agent raises whenever a tool call is refused and which would put a mark beside every busy agent. Opening the conversation reads them and the mark goes; the bell's count does not move, because reading is not answering.
- Making an agent is a question asked over the roster, not a panel that is always open: name, description, engine and memory, with the password and the routing rules folded away. Escape and the backdrop close it, the name has the focus when it opens, and it closes when the agent exists.
- An agent's settings is its own page (
/agents/:id/settings), replacing the MCP-access workspace. Six sections on the left — basics, engine, memory, appearance, tool permissions, danger zone — rows of item, explanation and control on the right, and a save bar below: nothing reaches the kernel until save is pressed, and discard and back make no call at all. Basics also shows the files this agent always reads, what each costs, and its share of the budget the kernel reports — with any file that did not fit named at the top, which until now only the model was told. Appearance holds the avatar, the VRM model and the agent's colour, written ashsl(H S% L%)with a live dot; a chosen colour is raised until it holds 4.5:1 on the raised surface, so choosing one cannot make an agent unreadable. Tool permissions answer default / allow / deny per server and per tool; each server's entry set is re-read immediately before it is written, so answering for one agent cannot delete another agent's grants. - A save that is refused leaves nothing half-written. The password is sent first, because a mistyped current password is the likeliest refusal: refused first, the rename beside it has not happened either. A server whose entries could not be re-read is not written at all — a list built on a failed read holds one agent's rows, and sending it would delete everyone else's.
- The settings page wears the colour of the agent it is about, including a colour being tried before it is saved; a colour chosen there reaches the chat and the approval card, not only the roster.
- Native
<select>is gone from these screens. The platform paints its own list with its own metrics, so the picker is now a button and a listbox that the workshop's own density and surfaces apply to, with the keyboard contract the native one has. - The power password can be changed and removed from the settings page
(
POST /api/agents/:id/power-password); the current one is required when one is set, so the admin key alone does not lift the guard it is there to be.
Removed¶
- The microphone button in the composer. It never sent audio — it inserted a note asking the agent to transcribe a recording that was not attached.
Scored against the design review checklist (docs/DESIGN_PHILOSOPHY.md §6). The chat: 0 of 21 applicable signals present, 5 partly (a rounded "latest" button, the greeting in the empty room, the blinking cursor, the reading column below 800px, the monospace context meter) — all five drawn as the mock draws them. The MCP list and page: 0 of 21 present, 2 partly (the fixed 200px section rail below 900px, the monospace ids under names). The agent's question: 0 of 21 present, 0 partly. The roster: 0 of 21 present, 4 partly (no loading state is drawn while the list arrives, the 400px list column is fixed below about 900px, ids are monospace, and every row carries a face — which here is the subject of the row rather than decoration, and monochrome except the one selected). The agent's settings page: 0 of 21 present, 3 partly (the fixed 200px section rail below 900px, monospace ids and file names, and the same absent loading state while the grants and the always-loaded files are read).
Fixed¶
- A connector that ships only panels is offered its updates. The marketplace read the installed version only from a connector's server row, and a panel-only connector has none, so it showed no version and a newer catalog version was never offered as an update. The version is now read from the install receipt when there is no row (bug-515).
- Settings → Conversations no longer says "nothing is archived" when it could not read an agent's conversations (a rate limit was enough). It names the agents it could not read, lists what it could, offers another try, and makes the "nothing" claim only once every agent has been read.
- A conversation that already has a name no longer asks the agent's engine for
one after its first exchange. The answer was always thrown away, and asking
is a whole engine run — for an agent on a CLI harness, one more
codex execorclaude -pagainst its subscription. A conversation that is still untitled, or still titled by its first line, is named by the engine as before, and a rename made while the engine is thinking still wins.
Prepared as 0.6.9a1, never published¶
This batch was written up as its own pre-release and then never published. It
introduced the shortened spelling the project uses from here on: 0.7.0a1
where the 0.6.8 line wrote 0.6.8-alpha.1. Inside the build the version keeps
its punctuation (0.7.0-a.1), because Cargo, Tauri and the updater all parse
semver and semver has no spelling without it. The stage and the number are the
same things they were — only the spelling is shorter, to sit closer to the
form the project's Python packages use. Nothing about how a version is ordered
or which channel it reaches has changed, and the older spelling remains valid
forever, because the update feed indexes every past release.
What it added is a place to put standing instructions for an agent, and a place to put the procedures it should not have to carry in every prompt.
Added¶
- An agent can be given files it always operates under.
CLAUDE.md,AGENTS.mdandMEMORY.md, placed in an agent's instruction directory, are composed into its system prompt on every dispatch — after the connected servers' instructions, so where the two disagree the operator's own files are what the model read last. Each file is clamped, the block is clamped, and a file that does not fit is named rather than dropped in silence. - Skills: procedures an agent loads when it needs them. A skill is a
SKILL.mdin the agent's skill directory. Only a one-line index of them rides on every prompt — an id and what each is for — and the procedure itself arrives when the agent asks for it by id. An agent with no skills is offered neither the index nor the tool, so it costs nothing to leave the directory empty. Reading them is not a privileged operation, but an operator who revokes the tool for an agent removes its index entry too, rather than leaving it looking at a list it cannot act on.
Changed¶
- A pre-release is now flagged as one because it is one. The release
workflow decided by looking for the words
alpha,betaorrcin the version. Any other spelling — including this release's — would have been published as a full release, which is what the install script resolves when asked for the latest. The flag now tests for the pre-release component itself. - The update feed says what it could not index. A tag outside the version grammar was dropped from every channel and from the manifest with nothing printed to say so — the one failure no consumer can detect. Such tags are now named in the run's output.
Fixed¶
- Corrupt-database quarantine no longer loses a race on Windows. The recovery path could find the file still held open and give up; it now waits the handle out. (The regression was intermittent, and the pull request that introduced it stayed green: the Windows leg of the test matrix is advisory, so a Windows-only failure does not fail a pull request.)
Internal¶
-
The operation catalog drives the six conversation routes (create, list, rename, archive and restore, delete, and the two bulk actions), asserting on what the lists show afterwards rather than on the calls returning. The route inventory the coverage ratchet counts against had been blind to
patch(...), so the one PATCH route was neither counted nor reported uncovered; it is now, and a CI self-test fails when a method router on alib.rsroute goes uncounted. Local phase-0 coverage went from 39/103 to 44/103. -
The issue registry — the mechanism that checks bug claims against the code — no longer accepts an empty verification pattern, a registry that declares no entries, or a name whose schema does not exist. Each of those read as proof of something while checking nothing.
- Release builds now use the same Node version as CI. They had drifted apart, which meant a regression that only appeared on the older one could not fail a pull request.
- Dependency updates:
tauri-plugin-updater,tauri-plugin-global-shortcut,dashmap,futures,chrono, and the dashboard's TypeScript, jsdom, Vite React plugin and testing-library packages.
[0.6.8] — 2026-09-07¶
The final of the 0.6.8 line. This is the release the stable channel carries, so it is the first time any of the beta line reaches an installed user who did not opt in to pre-releases.
What the line as a whole did: it closed the boundaries that were open by
default. Authentication moved onto the /api router behind an explicit public
allowlist, avatar, VRM and attachment reads began requiring the admin key, a
keyless start on a non-loopback bind became a refusal rather than a service,
and the LLM proxy started enforcing its per-boot token. The marketplace
installer's Rust path was replaced by the Go engine. A failure the user sees
can now be carried into a bug report the maintainers can read.
Added¶
- Installs the catalog no longer lists are reported. A connector retired upstream used to keep running with nothing in the app mentioning it — the catalog renders the entries it has, and a retired connector is not one of them. The marketplace now names them and offers to remove them. It does not claim to know what replaces one: the catalog keeps no record of what an entry used to be called.
Fixed¶
- A pending human-in-the-loop callback can no longer be discovered by an agent it was not addressed to. Answering one was already authorized against the server it belongs to, but the listing that hands out the ids returned every outstanding callback in the process — so the check was guarding a door whose keys were published beside it. The listing is now scoped to the servers its caller holds a grant for.
- "Installed" has one definition. The catalog, the install guard and uninstall each decided it separately and could disagree, which is how a connector ended up offered as new while the installer refused it as already present. A row named by a catalog entry now counts as that entry's install even when the key written at install time has gone stale, so a connector installed before an id was retired stops being invisible to the catalog.
[0.6.8-beta.7] — 2026-09-07¶
Soak release. Everything below landed after beta.6 was published and this line counts soak on the published artifact, so the changes needed a cut of their own before the final. Most of it tightens boundaries that were open by default, which is exactly the kind of change a soak exists to catch.
Added¶
- A failure can be carried to a bug report. The error screen offers a
report composed by the kernel — version, install engine, install receipt and
the tail of the log — shaped like the issue template. Two levels:
safenames the fields that may leave the machine and shortens paths under the home directory,fullkeeps the log and the component stack long. Neither emits a credential; secrets the kernel holds are removed from the text by value, so a key is caught wherever it appears rather than only where it is labelled. The text is editable before it is copied, because the person pasting it is the last check before it reaches a public issue. (#518) - An agent is told what the servers it was granted can do. A server's
initializeinstructions are read off the wire and composed into the agent's prompt, so a connector no longer has to restate its own usage in every tool description. (#514, #516) - Response language injection is back, with the test that would have kept it. (#515)
Security¶
/apiauthenticates at the router. Authentication became a layer with an explicit public allowlist — version, health, setup status and progress, marketplace progress — instead of relying on every handler to remember its own check; the per-handler checks remain as defence in depth.ANY /api/plugin/{*path}, which bypassed authentication and forwarded to a router nothing populated, is gone. (#487)- Avatar, VRM and chat-attachment reads require the admin key, accepted in
X-API-Keyor as?token=— the channel the event stream already uses.Cache-Controlbecomesprivate. This also fixes a latent dashboard defect: attachment images sat behind a header-only check that an<img src>cannot satisfy. (#486) - A keyless start on a non-loopback bind is refused with an explanatory
error rather than served to the network;
CLOTO_ALLOW_UNAUTHENTICATED_HTTP=1opts out. A loopback bind keeps its warning-only behaviour, and a non-loopback bind with a key now says plainly that the key is the only boundary. IPv6 binds work: the socket family follows the configured address. (#485) - The LLM proxy requires its per-boot token where the installation has earned it. The token is minted per boot and presented by the servers the kernel spawns; enforcement turns on from positive evidence that this installation's connectors present it, never from the mere absence of bad news — an installation that has served nothing has also never served an untrusted call. The health scan names any connector that called without one. (#489, #510, #511, #512)
- Kernel tools that reach a server the caller does not own are authorized rather than assumed safe, and a tool nothing classified is treated as needing approval instead of being waved through. What YOLO mode allows is recorded. (#505, #507, #509)
Changed¶
- The kernel stops cleanly on SIGTERM and SIGINT, draining its children instead of leaving them to be adopted by init. (#484)
- The marketplace install path the engine replaced is gone. The two implementations were kept side by side for one release so they could be compared; the engine shipped, nothing has called the old path since, and keeping it would leave a second way to install that no test exercises. (#517)
- An update whose version did not move is still an update — the marketplace no longer refuses to re-vendor a connector whose contents changed under an unchanged version string. (#513)
- sqlx 0.8 → 0.9. Verified against a real database copy written by 0.8: all seventy migration checksums match, so an existing installation does not meet the startup refusal. (#457)
- A reserved name is not an installed server. (#502)
Fixed¶
- The shutdown signal latches, so a task that was not parked when it fired still sees it. (#506)
- A prefix install is not drift, and the defender's receipt needs a directory to describe one. (#501)
- The service user gets a home and a data directory it can write, so a systemd install does not fail on first boot. (#500)
- The discovery probe's clock starts when the child speaks, not when the kernel writes to it — a slow interpreter start no longer reads as a server that never answered. (#498)
import_memoriesis classified as a Memory tool, so the REST import can reach the memory server. (#494)
Removed¶
- Unreachable VRM context, three uncalled Tauri commands, unused plugins and client methods; the maintenance marker, two unused dependencies and three dead fields. Dead code that tests still call reads as coverage while proving nothing. (#488, #492)
Verification¶
- opverify covers the routes the dashboard drives: 35 → 75 of 81. (#493)
- CI verifies
Cargo.lockis self-consistent before anything rewrites it (#483), and holds the test-count floor at what the lowest platform measures rather than at whichever platform ran last (#503).
[0.6.8-beta.6] — 2026-09-03¶
Soak release. It is the first cut that carries the separate install engine, and this line counts soak on the published artifact — an engine that only ever ran from a developer checkout has not been soaked at all.
Added¶
- Marketplace installs from a raw URL run through a separate install engine.
cloto-installeris a single binary shipped beside the application; it fetches the archive, verifies the seal, extracts it and builds the virtual environment, and the kernel records the resulting registration. When the engine is absent, or reports a version other than the one this build expects, the install stops with a message naming both versions instead of falling back to a second implementation — a missing engine is a visible failure, never a silent change of behaviour.GET /api/health/scanreports the engine's state underinstaller. (#469, #470, #471, #472) - A published documentation site, built from
docs/and gated: the build is strict, every in-site link and heading anchor must resolve, and the measurable claims documents make about the project — test counts, the current version, environment defaults — are checked against the code on every run. (#476, #477, #478)
Fixed¶
- Deleting a dynamic MCP server deletes its generated script (bug-505). The
three paths that create such a server wrote its Python into the directory
named by
MCP_SCRIPTS_DIR, while deletion looked under a legacyscripts/directory the writers had stopped using. The existence check was therefore always false, the unlink was never reached, and the user-supplied Python stayed on disk after the server and its connection were gone. The location is now derived in one place that every call site goes through, and a removal failure is logged with its path rather than discarded. (#463) - The Windows dependency tree is unified again. An
h2bump had splitwindows-sysinto two versions in the same build. (#460) - Lint and Security Audit are green on
masteragain. (#459)
Changed¶
- The repository's published text is English. (#461)
- The verification harness requires its host configuration to be supplied rather than shipping a default that pointed at one particular machine. (#458)
[0.6.8-beta.5] — 2026-08-09¶
Soak release, cut because the first fix below is a CRITICAL one that beta.4 does not contain — and this line counts soak on the published artifact, so leaving it on master would mean two weeks of soak that never exercised it.
Fixed¶
- Uninstalling actually uninstalls (bug-499, CRITICAL). The Danger Zone's
full uninstall removed nothing and left the window on a shutdown overlay
that never resolved.
POST /api/system/uninstallstaged the purge plan, copied the helper, launched it and signalled the kernel's shutdown — which stopped the HTTP server and nothing else. The detached helper waits for its parent to exit and, when it does not, bails without touching anything, which is correct on its own terms: deleting a running installation is how targets end up half-removed. The app now ends its process when the kernel says shutdown.POST /api/system/shutdownshared the same defect silently and is fixed with it. Verified end to end on a real installed build, not only in a test. (#432) - Escape closes a dialog (bug-501). No modal in the dashboard could be dismissed with the key every desktop application answers to — including the settings modal, whose close control also carried no accessible name, so a keyboard or screen-reader user had no way out but the backdrop. (#444)
- The window controls say what they are (bug-502). Minimise, maximise, close and the modal dismiss buttons were icon-only with no accessible name, reaching assistive technology as unlabelled buttons. (#441, #444)
Added¶
- The environment may pass extra WebView2 browser arguments at launch
(
WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS), which is what lets the verification harness reach the DOM of a shipped build rather than an instrumented one. Closed unless the variable is set, so a normal launch is unchanged. (#433)
[0.6.8-beta.4] — 2026-08-03¶
Soak release. It exists because the fix below is not in beta.3, and the promotion criteria for this line count soak time on the published artifact — not on whatever master happens to hold.
Fixed¶
- The chat pane follows new turns again (bug-498). Its scroll effect had
been reduced to a mount-only effect since 2026-03-15, when a lint autofix
removed the dependencies it used as change triggers, so a reply rendered
below the fold and the view never moved — indistinguishable, from the user's
side, from a reply that never arrived. Every release since had shipped that
way. Pinning now lives in a
useStickToBottomhook driven by a MutationObserver, which also follows a reply as the typewriter reveals it. Found by the opverify visual apex against the real installed GUI, and re-verified there after the fix. (#429)
Changed¶
- Dependency bumps (patch/minor only): tokio 1.53.1, tauri 2.11.5,
rust-embed 8.12.0, log 0.4.33;
@tauri-apps/cli2.11.4,@biomejs/biome2.5.6,@tauri-apps/plugin-global-shortcut2.3.2. (#421, #425, #426, #427, #422, #423, #424)
Note: 0.6.8-beta.3 (2026-08-03) shipped without an entry here; its contents are in the GitHub release notes.
[0.6.8-beta.2] — 2026-07-12¶
Second beta of the 0.6.8 line — and the first release whose updater
signatures verify against the shipped pubkey (see Fixed): desktop
auto-update works from this release onward. Also the first release published
through the signed updater feed (updater-feed release: manifest.json +
stable/current/experimental channel views). Installs of v0.6.8-beta.1
or older must update manually once — their embedded key cannot verify any
signature ever published.
Added¶
- Consensus revived as in-kernel orchestration: answers are
delivered to the originating agent's chat plus a dedicated Consensus tab,
engine-reuse quorum fallback (
CONSENSUS_ENGINE_REUSE), per-agent engine access enforcement, and long-term memory storage of verdicts. (#230–#232, #237, #242, #266) - Safe shutdown: tray quit and the new sidebar power button share one drain-then-exit sequence with a shutdown overlay; MCP subprocess trees are reaped on restart and app exit, with a forced group-kill sweep when the drain window expires (bug-426). (#248, #264, #265)
- Per-agent recall configuration: recall timing policy, session scope with the per-channel episode axis (default flipped after A/B), and read-edit-save precision control in the dashboard. (#190–#203)
- Per-server MCP log streaming in the dashboard Log tab. (#244)
- LLM provider metadata seeded from the marketplace catalog; the agent console lists only real engines and warns on uninstall. (#249–#251)
- Release pipeline: Release Lifecycle Standard adoption
(
SUPPORT.md/SECURITY.md), signed updater feed with per-tier channel views, certification recorded in.release/lifecycle.json. (#269–#271)
Fixed¶
This beta closes 33 registry-tracked bugs (2 critical / 13 high /
14 medium / 4 low) plus the updater key repair — the largest fix set of any
0.6.x release. Itemized below by area; qa/issue-registry.json is the
verification source of truth for every entry.
- Updater signing key mismatch (CRITICAL, latent since v0.6.0): the
2026-03-08 key rotation updated the client-embedded pubkey but not the CI
signing secret, so every published artifact was signed with a key no
shipped client could verify —
downloadAndInstall()always failed signature verification (update notifications worked, masking it). Rotated to a fresh pair (66FD7C5172819DEC); key-management runbook added to the pipeline design doc. (#272)
Security audit sweep (PRs #204/#209/#227/#237/#240):
- bug-400 (CRITICAL): marketplace uninstall was vulnerable to path
traversal —
DELETE /api/marketplace/servers/:idpushed the unvalidatedserver_idinto the on-disk path, allowing arbitrary directory deletion. (#209) - bug-415 (CRITICAL): the first bug-412 fix could poison the SQLite pool when an audit write was cancelled — a regression caught pre-merge by the post-fix adversarial review; never shipped. (#227)
- bug-403 / bug-407 / bug-414 (HIGH, SSRF hardening): the restricted-address check missed IPv6 link-local and IPv4-mapped addresses (403); the validated IP was discarded after the check, leaving a DNS-rebinding TOCTOU — the connection is now pinned to the validated address (407); redirects could escape the whitelist + IP pin — every hop is now re-validated (414). (#209, #227)
- bug-406 / bug-420 / bug-421 (HIGH, per-agent access enforcement): the
tool_hintdirect-execution path allowedagent_idspoofing (406) and bypassed per-agent MCP access control entirely — an I/O bridge could invoke tools on servers the agent was never granted (420); enforcement was fragmented across call sites and reasoning engines were never access-checked at all — now unified behind a single capability gate covering both tools and engines (421). (#209, #237, #240) - bug-409 / bug-410 (MEDIUM, resource exhaustion): unbounded allocation
in
StreamAssembler::record_chunkon an attacker-controlled chunk index (409); unbounded read buffer inparse_sse_streamwhen a server streams a large body with no newline (410). (#209)
Kernel stability & correctness:
- bug-401 / bug-402 (HIGH/MEDIUM): UTF-8 char-boundary panics — byte
slicing of log/error strings crashed on multibyte codepoints in the MCP
stdio response loop (401) and
parse_chat_think_resulterror paths (402). (#209) - bug-405 (MEDIUM): cron intervals had no upper bound — an oversized
value overflowed
i64and produced runaway perpetual dispatch. (#209) - bug-411 / bug-412 (MEDIUM):
McpClient::is_alive()inferred liveness from the write channel, so an idle child that died was never auto-restarted by the health monitor (411); the audit-log writer's DEFERRED read-then-write transaction hit un-retriedSQLITE_BUSY_SNAPSHOTunder concurrency (412). (#227) - bug-288 (HIGH): the
delete_agent_datamemory-plugin tool name was hard-coded in the kernel. (#204) - bug-395 (HIGH):
sandbox_base_dir— and therefore the Magic Seal key directory — defaulted to a CWD-relative path instead of anchoring to the absolute data dir. (#184)
MCP server management & marketplace:
- bug-396 / bug-397 / bug-398:
Agent.default_engine_idmind.deepseekwas unresolvable — engine resolution requires an exact server-name match (396, HIGH);GET /api/mcp/servers/:name/settingsreturned 500 for every server — the SELECT omitted thesealcolumn (397, HIGH); interpreter-launched servers were spawned without verifying the entry-point script exists, so stale paths failed opaquely (398, MEDIUM). (#204) - bug-399 / bug-404 (HIGH): monorepo connectors were installed to a
doubled on-disk path and failed to launch (399, #207); the MCP venv
resolver anchored to
exe_dir()/datainstead ofconfig::data_dir(), so installed builds couldn't find marketplace-created venvs (404, #209). - In-place marketplace update for installed servers preserves grants + env instead of destroy-and-reinstall. (#198)
- Orphan-process class closed from both sides: MCP subprocess trees
are reaped on server restart and app exit (#248);
drain_all's global timeout cancelled in-flight kills between SIGTERM and SIGKILL, leaking survivors past app exit — per-server drains are now detached tasks with a forced group-kill sweep on timeout (bug-426, MEDIUM, #265). The server-side half (mgp-discord exiting on stdin EOF) is clotohub-servers bug-009.
Consensus (revival hardening):
- bug-417 (HIGH): the terminal consensus response was never delivered to the originating chat — a silent hang from the requester's perspective. (#231)
- bug-408 (MEDIUM): a straggler proposal arriving during synthesis could be mistaken for the synthesizer's output — eliminated structurally by the event-driven in-kernel redesign. (#230)
- bug-419 (MEDIUM): the global
CONSENSUS_ENGINESlist ran on every agent, executing engines the requesting agent was never assigned. (#237) - bug-422 (MEDIUM): consensus verdicts were persisted to chat history but never written to the agent's long-term memory, so later turns couldn't recall them. (#242)
- bug-418 (LOW): the shipped
.envexample referenced an engine that is not auto-registered, so consensus failed out of the box for anyone uncommenting it. (#266)
Dashboard:
- bug-413 / bug-416: MemoryCore fetched a global most-recent top-N and filtered client-side, under-displaying per-agent memories (413, MEDIUM, #225); the tab bar rendered an un-scopable empty-string agent tab for global-pool rows (416, LOW, #227).
- bug-425 (MEDIUM): the agent console engine selector filtered grants by
the
mind.prefix only, hiding de-prefixed catalog engines. (#245) - bug-423 / bug-424 (LOW): the MCP log tab's SSE filter read
event.payload.*where kernel events carryevent.data.*, and matched'MCP'against mixed-caseMcp*discriminants — together the filter was never true. (#244) - Engines/memory classified by tool surface instead of id prefix (#234);
deleting a passwordless agent no longer sends an empty JSON body (#235);
recall
PillSelectpopover portaled todocument.bodyto escape clipping (#200); knob2 v2 store/recall channel symmetry (#201).
CI:
CREATED_MAPinitialization so the registry-sync no-new-entries path survivesset -u(#268); master unblocked on new clippy 1.97 lints + the crossbeam-epoch advisory (#267).
Changed¶
- Engine/server ids de-prefixed: the
mind.engine prefix and category id prefixes are retired; classification is tool-surface based. (#247, #252) - axum 0.8 migration and dependency refresh (tauri 2.11, tower-http, quinn-proto RUSTSEC advisory). (#224 et al.)
- Cross-platform release gate: Windows tests + headless
--smokein CI. (#185)
[0.6.8-beta.1] — 2026-06-13¶
Feature freeze for the 0.6.8 line. This beta completes the P1/P2 design-violation remediation programme: every remaining ARCHITECTURE.md §1 (Design Principles) violation in the kernel is resolved, alongside the Setup Wizard / marketplace robustness, MCP transport-timeout, and lifecycle hardening backlog. scripts/verify-issues.sh reports zero open HIGH/MEDIUM entries for that set. Published on the alpha channel (the Tauri Updater resolves latest.json via /releases/latest/download/ and skips prerelease entries, so production v0.6.7 stable installs receive no in-app upgrade prompt). No installer / upgrade-hook behaviour changes.
Fixed¶
- bug-365 / bug-366 / bug-367 / bug-369 (HIGH, Setup Wizard / marketplace robustness): empty-batch install now early-returns with an i18n error instead of a silent no-op (365); in-flight install tasks are tracked on
AppStateand aborted on shutdown so childuv/pipprocesses are reaped viakill_on_dropinstead of orphaned (366); a sha256 tarball mismatch no longer swallows theremove_fileerror (367);build_and_register's common+server pip install is unified onto the same null-stdiostatus()/ streaming-spawn path as batch installs, removing a pipe-buffer deadlock risk and adding a server-install timeout (369). (#178) - bug-304 / bug-355 / bug-356 / bug-357 / bug-358 (MEDIUM, MCP transport timeout & resource discipline): stdio writer
write_all/flushgains a 10 s timeout (355); HTTP transport adds a 30 s per-message timeout on top of the global cap (356); everyMcpClientsend goes through a 10 ssend_with_timeouthelper that cleans uppending_requestson failure (357); process kill escalates SIGTERM → 3 s grace → SIGKILL on Unix (358); the existingDrop+kill_on_dropresource guarantee is re-anchored and documented (304). (#179) - bug-282 / bug-285 (HIGH, §1.2 Capability over Concrete Type): the consensus synthetic agent id (
SYSTEM_CONSENSUS_AGENTconst) and the"consensus:"trigger prefix are no longer hard-coded — they areConsensusConfig.synthetic_agent_id(envCONSENSUS_AGENT_ID) andAppConfig.consensus_prefix(envCONSENSUS_PREFIX), both with back-compatible defaults. (#180) - bug-293 (HIGH, §1.4 Data Sovereignty): the kernel no longer interprets the
engine_routingagent metadata. TheRoutingRuleschema, its deserialization, and CFR/fallback evaluation moved from the kernel handler (handlers/engine_routing.rs, deleted) into an in-tree plugin (plugins/routing_default.rs); the handler now forwards opaque metadata via a direct in-process call with no added latency. (#181) - bug-305 / bug-313 / bug-342 (MEDIUM/LOW, lifecycle & window hardening): shutdown drains all MCP servers in a bounded task (5 s/server, 10 s global) before notifying shutdown waiters (305); restart-policy defaults are consolidated into
DEFAULT_MAX_RESTARTSet al. constants and documented inARCHITECTURE.md§3.1.2 so code and docs cannot drift (313); every fallible Tauri window op (show/unminimize/set_focus/hide/navigate) routes through awith_window_log!macro that logs a warning on failure instead of discarding theResult, so WebView2 corruption no longer leaves the backend running headless without a signal (342). (#181)
Changed¶
config::data_dir— the production user-data directory segment is promoted from a bare"cloto-system"string literal to a single named constantconfig::APP_DATA_DIR_NAME. No behavioural change: the value is unchanged and deliberately kept ascloto-system(not the current "ClotoCore" branding) becauseinstaller.nshand the bug-386 legacy-install detection preserve existing user databases at this exact path; renaming it would orphan installed users' data and require a boot-time migration. (#182)
Verified¶
scripts/verify-issues.sh: bug-293 / 342[FIXED](pattern absent), bug-305 / 313[VERIFIED](fix-marker present), with the full remediation set (bug-282/285/304/355–358/365–369) confirmed across PRs #178–#181; 0 stale / 0 errors.- CI green on every PR: clippy (workspace allow-list,
--exclude app) + fmt + workspace tests (371 passed, incl. 6 newrouting_defaulttests) +cargo check -p app.
[0.6.8-alpha.4] — 2026-06-13¶
Marketplace install-chain remediation + catalog seal verification. Fourth prerelease in the 0.6.8 line, published on the alpha channel (the Tauri Updater resolves latest.json via /releases/latest/download/ and skips prerelease entries, so production v0.6.7 stable installs receive no in-app upgrade prompt). This release lands the full ClotoCore-side fix set discovered during the 2026-06-10 live marketplace install debug (bug-388–392) plus the hub-mediated catalog seal verification chain ( bug-394) and the supporting raw_url distribution fixes. No installer / upgrade-hook behaviour changes — only kernel marketplace, DB migration, and dashboard paths.
Fixed¶
- bug-391 (CRITICAL): Magic Seal verification hashed
config.command("python") instead of the entry-point script. For interpreter-launched serversPath::new("python").exists()was false, so verification was skipped via theentry_point_not_a_filebranch and every Python marketplace server was force-downgraded to Untrusted — the catalog-issued seal was never checked. Fix: resolve the sealable file asargs[0]when the command is an interpreter (resolve_sealable_entry_point,managers/mcp.rs). (#167) - bug-389 / bug-390 (HIGH):
needs_commondetection probed the legacy flat layout (servers_dir/common/__init__.py) which marketplace git-clone installs never populate, and theuv pip install commonrescue was dead code (it required aservers/common/pyproject.tomlabsent from the monorepo). Connectors declaringinstall.dependencies=["common"]died withModuleNotFoundError: No module named 'common'. Fix: dependency-driven common provisioning for the nested clone layout. (#168, #173) - bug-388 (HIGH): migration
20260524010000(renamememory.cpersona→cpersona) aborted kernel boot with a PRIMARY KEY collision (UNIQUE constraint failed: mcp_servers.name) when both the legacy row and a marketplace-installedcpersonarow existed (any pre-0.6.6 user who installed cpersona from the catalog before first booting a ≥0.6.6 build). Fix:repair_cpersona_rename_collisionruns before the sqlx migrations ininit_db, merging legacy grants, dropping duplicateplugin_configs, and deleting the legacymcp_serversrow so the checksummed migration no-ops. The buggy migration file itself is intentionally unchanged (sqlx checksum). (#169) - bug-392 (MEDIUM): marketplace uninstall resolved the on-disk directory via the catalog cache and fell back to
server_id; when a server had no catalog entry and its install dir differed from its id (e.g.mind.deepseek→deepseek/),remove_dir_allwas silently skipped, orphaning the installed files. (#170) - bug-393: the dashboard discarded kernel error response bodies, surfacing only a bare
statusText(the long-standing "Bad Request" mystery on already-installed servers). It now surfaces the real kernel error message. (#171) - Tarball shared-prefix detection — real GitHub archives open with a
pax_global_header+ top-level dir entry, sodetect_shared_prefixreturnedNone;extract_tarball_strippedthen kept the<repo>-<ref>/wrapper and subdir selection matched nothing (a latent bug affecting everyraw_urlinstall to date). (#174)
Added¶
- bug-394 catalog seal verification (HIGH): the catalog seal is
HMAC(hub master key, canonical message), but the kernel spawn-check computedHMAC(local seal.key, file bytes)— they can never match, hard-blocking every fresh-kernel install with "Magic Seal verification failed". Landed in two steps: an interim keyless entry-point integrity check + local re-seal (#176), then the proper Ed25519 catalog-seal verification via hub JWKS with a "cannot-verify vs verification-failed" two-class model and a 1 h in-memory JWKS cache (kid-miss refetch) (#177).raw_urltarball transport integrity remains separately enforced via sha256. (#175, #176, #177)
Verified¶
- All ClotoCore-side fixes confirmed by
scripts/verify-issues.sh(bug-388 repair-guard present; bug-389–392 patterns absent) and by fresh-kernel end-to-end installs through the hub-mediated distribution chain (catalog → proxy → blob → subdir extract → common → Ed25519 seal verified → Connected with 42 tools), including the D2 three-branch matrix (verified → Connected; JWKS-unavailable → untrusted; tampered → TAMPER SUSPECT hard-block).
[0.6.8-alpha.3] — 2026-05-28¶
Verify-automation hardening. Third prerelease in the 0.6.8 line, published on the alpha channel. Pure infrastructure / tooling fix discovered during the first end-to-end run of scripts/proxmox-windows-verify.sh after v0.6.8-alpha.2 published. No kernel / dashboard / installer behaviour changes.
Fixed¶
scripts/proxmox-windows-verify.sh—capture_fingerprint()was passing the PowerShellFINGERPRINT_PSheredoc through a doubly-nested"…\"…\""quote chain. Windows OpenSSH delivers remote commands through cmd.exe, which strips inner quotes the heredoc relied on for path strings like"C:\Program Files\cloto-system". PowerShell then parsedTest-Path C:\Program Files\cloto-systemasTest-Path C:\Programplus an unrecognized positionalFiles\cloto-system, aborting the fingerprint with aPositionalParameterNotFounderror. Fix: switch literal paths to PowerShell single quotes, useJoin-Pathfor$env:APPDATAderivations, and ship the entire payload viapowershell -EncodedCommand(Base64 UTF-16LE) so cmd.exe sees no special characters at all.
Verified¶
- End-to-end Sandbox verify for
v0.6.7 → v0.6.8-alpha.2upgrade path on the Proxmox Windows guest: - 8/8 assertions PASS (NO-OP hook path — Tauri default upgrade flow, no legacy migration needed).
- Data preservation confirmed: dummy
cloto_memories.dbSHA-256 unchanged across upgrade. - Wall clock: ~6 min 20 s (rollback → guest SSH → download FROM → seed DB → silent install FROM → PRE fingerprint → download TO → silent install TO → POST fingerprint → assertion), well under the α→β promotion criterion of 20 min.
- Together with Pattern-C (landed in
0.6.8-alpha.2) and the verify automation (0.6.8-alpha.1), this satisfies all three α→β promotion criteria. The 0.6.8 line is eligible for beta.1 promotion.
[0.6.8-alpha.2] — 2026-05-28¶
Pattern-C capability tool name registry. Second prerelease in the 0.6.8 line; like alpha.1, deliberately published on the alpha channel so existing stable installs do not receive an in-app upgrade prompt. This release lands the structural refactor planned as PR #1 of that programme — the kernel no longer hard-codes MCP tool names as string literals in handlers/system.rs. It is the α→β promotion-criterion piece for the 0.6.8 line.
Added¶
ToolKindenum (crates/core/src/managers/capability_dispatcher.rs) — 11 well-known tool variants (Store,Recall,ListMemories,ListEpisodes,ArchiveEpisode,UpdateProfile,Think,ThinkWithTools,AnalyzeImage,Transcribe,Speak) plusCustom(String)escape hatch for non-well-known tools.CapabilityType::Display/FromStr— single source of truth for the JSON keys ("Memory" | "Reasoning" | "Vision" | "Stt" | "Speech") used both by the newbuild_from_capabilitiesingest path and by server-sidetools_for_capabilitydeclarations.MgpServerCapabilities.tools_for_capabilityvendor extension (Option<HashMap<String, Vec<String>>>) — MCP servers can now explicitly declare which tools they expose under each capability, overriding the kernel's heuristicclassify_toolfallback. Targeted for spec formalization in MGP 0.7.0 (Layered Manifest Layer 1/2, see the mgp-spec design).McpClientManagerToolKind shims (call_kind,call_kind_at,call_kind_streaming,call_kind_streaming_at,has_kind,has_kind_at) — typed entry points that keep handlers/ free of tool name string literals.- Tests — 7 new unit tests in
capability_dispatcher.rs(round-trip, capability mapping consistency, cross-capability rejection, Custom fallback, Display round-trip) and 3 serde tests inmcp_mgp.rsfor the new field.
Changed¶
handlers/system.rs— 17 call sites swapped from string-literal tool names toToolKind(categories: 11 directcall_server_tool, 1has_server_tool, 3call_capability_toolarg literal, 1 streaming, 1 event-dispatch string comparison). Theget_profiletool, which is not in any well-known capability whitelist, usesToolKind::Custom("get_profile".to_string())with an explicitserver_id(escape-hatch convention).- MCP handshake flow (
crates/core/src/managers/mcp.rs:1417) — capability mappings are now built from the server'stools_for_capabilitymanifest when present, falling back to the legacyclassify_toolheuristic only for backward compatibility with servers that have not adopted the extension. No behavior change for current servers — none emit the field yet.
Fixed¶
- bug-289 (HIGH P2):
"think_with_tools"literal no longer present incrates/core/src/handlers/system.rs. Tool name dispatched viaToolKind::ThinkWithToolsthroughcall_kind_at/has_kind_at/call_kind_streaming_atshims. - bug-290 (HIGH P2):
"archive_episode"(and the rest of the Memory-capability literals —store,recall,list_memories,list_episodes,update_profile) no longer present. ARCHITECTURE.md §1.2 Capability-over-Concrete-Type compliance restored for these dispatch paths.
Known limitations¶
classify_toolprivate fallback list remains incapability_dispatcher.rsfor servers that have not declaredtools_for_capability. Removal is scheduled for 0.6.9+ once every shipped server has adopted the manifest path. Server-prefix heuristics (memory.*,mind.*,vision.*,stt.*,output.*) are also still present and tracked separately under §1.2 audit.- bug-282 / bug-285 / bug-293 / bug-296 (other §1.2 violations from the 5-PR remediation plan) are unaffected by this release and remain open.
[0.6.8-alpha.1] — 2026-05-27¶
Verify automation MVP release. First prerelease in the 0.6.8 line, deliberately published on the alpha channel so that the Tauri Updater (which resolves latest.json via /releases/latest/download/ and therefore skips entries flagged prerelease) does NOT push it to existing stable installs. Production v0.6.7 users will not see an in-app upgrade prompt; the alpha is reachable only via manual download from the Releases page. This structural isolation is exploited intentionally so verify automation regressions cannot realize on production user machines while the automation itself is being iterated.
Added¶
-
NSIS hook structural gate (
scripts/check-nsis-hook.sh+ newnsis-hook-gateCI job). Source-level grep assertion that the bug-386NSIS_HOOK_PREINSTALLmacro indashboard/src-tauri/installer.nshremains intact (macro entry point, legacyUninstall\cloto-systemregistry probe, legacy silent-uninstallExecWait '"$0" /S'invocation, and thebug-386:audit log line). Fails CI in <1 sec with a GitHub Actions::error::annotation if any required pattern is missing — silent removal of the hook now becomes impossible without an explicit gate update. -
Proxmox Win11 verify driver (
scripts/proxmox-windows-verify.sh, ~250 LOC). Mac-side shell driver that rolls the Windows guest back to its pristine snapshot, downloads the FROM-version installer from GitHub Releases, seeds a dummy database to detect data preservation, runs silent install, captures a 9-field Windows fingerprint (install paths, bothHKLM+HKCUuninstall keys, currentDisplayVersion, db file SHA-256), then transports the TO-version installer (local file viascpor downloaded viagh release), runs silent install, captures the POST fingerprint, and diffs against an assertion matrix selected by the FROM version: hook-PRIMARY path for0.6.5(legacy productName migration) and hook-NO-OP path for0.6.6+(Tauri default in-place upgrade). Single iteration: ~6 min, vs ~30-45 min for Windows Sandbox manual verify. -
NSIS-touching PR detector (
.github/workflows/nsis-touching-detect.yml). Triggered onpull_requestopen/synchronize/reopen, scans the diff for changes toinstaller.nsh(always flagged),tauri.conf.json(only whenbundle/productName/identifier/windowskeys touched), or anyCargo.toml[[bin]]block /name =field. When a match is found and the PR title does not contain[no-sandbox], applies thensis-touchinglabel (auto-creates on first use) and posts a comment instructing reviewers to run eitherscripts/proxmox-windows-verify.shor a manual Sandbox verify pre-merge. Opt-out is recorded in the PR title for audit transparency.
Note (alpha channel)¶
The 0.6.8 line operates under an α/β promotion pattern: 0.6.8-alpha.N for feature / refactor iteration, 0.6.8-beta.N for soak after feature-freeze, 0.6.8 stable for the cumulative release. The Tauri Updater's stable-only resolution (memory clotocore-0.6.5-bug-385-release-land-30c6bd9-20260524 Known limitation) keeps every alpha and beta tag off the auto-update channel. This automation MVP lands first so subsequent alphas (the P1/P2 patches, the config.rs:37 data_dir literal migration, and other backlog work) can rely on it.
[0.6.7] — 2026-05-26¶
CRITICAL hotfix release. Restores the auto-update path for v0.6.5 users (broken by the v0.6.6 cloto-system → ClotoCore product rename), unblocks marketplace installs of any server that declares env vars, and removes the silent 404 window during the first seconds after a release publish. Cumulative since v0.6.6.
Fixed¶
-
bug-386 (CRITICAL — Auto-update) —
Tauri Updater downloadAndInstall()from v0.6.5 to v0.6.6 surfaced "Failed to apply update" because the v0.6.6 NSIS installer (withproductName = ClotoCore) could not detect or migrate the v0.6.5 install registered underproductName = cloto-system. Newdashboard/src-tauri/installer.nshinjects a TauriNSIS_HOOK_PREINSTALLmacro (wired viabundle.windows.nsis.installerHooks) that probesHKLM+HKCUfor the legacySoftware\Microsoft\Windows\CurrentVersion\Uninstall\cloto-systemkey (coveringinstallMode: "both") and, when found, silently invokes the legacy uninstaller before the new install proceeds. The Tauri 2.x uninstaller'sun.SEC_APPDATAsection is not selected by default under/S, so user data at%APPDATA%\Roaming\cloto-system\survives the migration —config.rs:37still resolvesdata_dirto that path post-upgrade, preserving chat history, agent state, embedding namespaces,mcp_access_controlgrants, and registered MCP servers. The new install lands at{autopf}\ClotoCore\and registers a fresh uninstall key under the new product name. The hook is a no-op on fresh v0.6.7 installs (no legacy uninstall key present). -
bug-387 (CRITICAL — Marketplace install) (PR #152, master =
1d1be73).dashboard/src/components/mcp/InstallDialog.tsxand theEnvVarDefTypeScript interface indashboard/src/types.tsstill read.keyfrom env var definitions aftermgp-sdkrenamed the field to.name(with#[serde(alias = "key")]covering only the deserialize path). Every env var field collapsed into a single{undefined: …}state slot, every input rendered the same value, and the install request body posted{env: {"undefined": <value>}}which the kernel marketplace handler rejected with HTTP 400. Replaces seven.keyreferences with.nameand aligns the dashboard interface with the catalog wire shape; covered every marketplace server that declares env vars (CPersona, cmemo, cscheduler, etc.) on v0.6.6. -
release.yml race (PR #151, master =
caa94d9). Switched the GitHub release workflow to a two-phase upload: binaries, signatures, and checksums upload first;latest.json(the Tauri Updater's "available version" indicator) uploads only after every other asset is in place. Closes the 404 window wherelatest.jsondeclared v0.6.6 was available whileClotoCore_0.6.6_x64-setup.nsis.zipwas still uploading.
Backward compatibility¶
- v0.6.5 users upgrading via the in-app Tauri Updater path get the legacy install silently uninstalled and replaced with
C:\Program Files\ClotoCore\— chat history and agent state preserved transparently because%APPDATA%\Roaming\cloto-system\is untouched. - v0.6.6 users (rare — bug-386 blocked most of them at update time) continue to upgrade through the normal Tauri default flow since their registry uninstall key is already under
ClotoCore; the new PREINSTALL hook simply no-ops. - Fresh v0.6.7 installs are unaffected by the hook and land at
{autopf}\ClotoCore\with a single clean uninstall key.
CI / QA¶
- Windows Sandbox in-place upgrade verified pre-tag: v0.6.5 install → silent run of v0.6.7 NSIS → confirmed legacy uninstaller ran,
%APPDATA%data preserved, freshClotoCorefolder created, new uninstall registry key written, v0.6.5 chat history visible in the upgraded app. - Marketplace install regression verified pre-tag: CPersona v2.4.21 dialog renders six env vars with distinct names and defaults, submit returns 200,
installed_serversrow created, kernel logs show nogitinvocation duringuv pip install(vendoredmcp-commonpath).
Known limitations¶
config.rs:37 data_dirliteral remains"cloto-system"(preserved across the rename for data safety). A future release will migrate the literal to"ClotoCore"together with an explicit data-directory move step.
[0.6.6] — 2026-05-24¶
Kernel structural cleanup release. Two long-pending architectural threads ship together in a single release with bisect-friendly per-PR isolation: (1) the surface product is renamed cloto-system → ClotoCore to align with the three-layer doctrine (ClotoCore + ClotoCloud + Cloto app + ClotoHub), and (2) the kernel is decoupled from hardcoded knowledge of any specific memory plugin id. Cumulative since v0.6.5.
Changed¶
-
Product rename
cloto-system→ClotoCore(PR #136).productNameintauri.conf.json, the Cargo[[bin]]name (cloto_system→clotocore, separate from the existingclotoMagic Seal CLI), all user-facing display strings ("Cloto System"/"CLOTO SYSTEM"→"ClotoCore"/"CLOTOCORE"),cli.rsinvocation help / version banner / self-update asset lookup pattern (cloto_system-{target}→clotocore-{target}), platform serviceDisplayName/ systemdDescription, dashboard tray tooltip, i18n titles, NSIS release artifact branding, install scripts (install.ps1/install.sh), anddocs/INSTALLER_DISTRIBUTION.mdartifact examples. Preserved invariants (rename-safe — would break in-place upgrade):identifier = com.cloto.app,cli.rs default_prefix(/opt/cloto,C:\ProgramData\Cloto), macOS launchdSERVICE_LABEL = com.cloto.system, Linux systemdSERVICE_NAME = cloto, Windowssc.exe SERVICE_NAME = Cloto,config.rs:37 data_dir = ".../cloto-system"(existing users' chat history / agent state / embedding namespaces live under this path). -
Memory plugin decouple Phase A + B (PR #137).
config.memory_plugin_id: String→Option<String>(env empty/unset →None);db::init_db(..., memory_plugin_id: Option<&str>)signature change;plugin_configs.database_urlINSERT gated onSome(_)so kernel boots successfully without an embedded-plugin seed.handlers/marketplace.rs::register_servergained abind_default_memory_if_unsethelper — when acategory == "memory"plugin installs, the helper mirrors its id intoagent.cloto_default.metadata.preferred_memory(only if absent / empty, never clobbers a user's manual choice). 41 test fixtures acrosstests//benches//src/test_utils.rs/db/mod.rsunit tests switchedinit_db(..., "memory.cpersona")→init_db(..., None). Aligns with MGP §10 invariant 3 (open standard, no privileged plugin). -
Memory plugin id rename
memory.cpersona→cpersona(PR #138). Catalog-canonical id propagated across dashboard preset lists (presets.tsMINIMAL / STANDARD / ADVANCED / EXPERT_SERVERS),SetupWizard.tsxALL_SELECTABLE_SERVER_IDS, i18n keys (server_memory_cpersona→server_cpersona),handlers_http_test.rstest fixtures, andREADME.mdMCP server table. Intentionally preserved: historical migration SQL literals (sqlx checksum constraint),marketplace.rs::effective_install_dirlegacy backward-compat tests,handlers/mcp.rsdotted-id acceptance test,capability_dispatchertest fixtures,format.test.tsnamespace-stripping assertion, and 5 design docs that discuss both old/new ids (deferred to follow-up editorial pass).
Migrations¶
20260524000000_backfill_default_memory.sql— back-fillsagent.cloto_default.metadata.preferred_memory = 'cpersona'for existing users whose pre-0.6.6 memory binding came from the env default (CLOTO_MEMORY_PLUGIN_ID) rather than dashboard selection. Idempotent: no-op whenpreferred_memoryalready has a value or when no memory plugin is installed yet.20260524010000_rename_memory_cpersona_to_cpersona.sql— renamesmcp_servers.namememory.cpersona→cpersona, re-issues themcp_access_controlserver_grantrow under the new id (DELETE + INSERT around the parent rename — mirrors the KS22 rename precedent at20260309000000, FK requires this shape), renamesplugin_configs.plugin_id, and cosmetically normalises anyagent.metadata.preferred_memory = 'memory.cpersona'row to'cpersona'. Idempotent: WHERE clauses target only legacy rows.
Backward compatibility¶
- Users with
CLOTO_MEMORY_PLUGIN_ID=memory.cpersonain env keep their pre-0.6.6 behavior (env value flows through asSome(...), plugin_configs row written as before). Phase D migration then renames the row socpersonabecomes the canonical id. init_db(..., None)is a new valid state — the kernel boots with no memory plugin pre-seeded, then the modern Setup Wizard / marketplace install path populatespreferred_memoryon the first memory-kind install (viabind_default_memory_if_unset).- Existing chat history, agent state, embedding namespaces, mcp_access_control grants — all preserved (
config.rs:37 data_dirandtauri.conf.json identifierare explicitly held constant).
CI / QA¶
- Test count: 324 tests pass (322 pre-0.6.6 + 2 new migration tests in
migration_test.rsfor Phase C+D smoke and Phase C idempotency). cargo fmt --all -- --check+cargo clippy --workspace --exclude app -- -D warnings -A …(CI lint suppressions) +npx biome lint src/all clean.
Fixed-points (irreversible from this release)¶
config.memory_plugin_id: Option<String>(downstream test fixtures depend on Option semantics)agent.metadata.preferred_memoryis the single source of truth for per-agent memory plugin selectioninit_dbsignatureOption<&str>- Cargo
[[bin]] name = "clotocore"(cascades to CI artifact names + install scripts + platform path constants) mcp_servers.name = 'cpersona'for the CPersona plugin (nomemory.prefix); legacy rows migrated and gone after first boot on 0.6.6+
[0.6.5] — 2026-05-24¶
CRITICAL hotfix release. Restores the auto-update path for all installer-based ClotoCore installs by switching the dashboard from a broken sidecar shell-out to the configured Tauri Updater plugin. Cumulative since v0.6.4 (2026-05-23).
Fixed¶
- bug-385 (CRITICAL — Auto-update) —
applyUpdate()indashboard/src/lib/tauri.tsshelled out to a sidecar namedcloto_systemvia@tauri-apps/plugin-shell, but the binary was never bundled into the NSIS / DMG /.debinstaller (bundle.externalBinis unset intauri.conf.jsonand the release workflow never copies the standalone kernel binary into the app bundle). Every "Update Now" click failed atCommand.create()with a program-not-found error which the UI surfaced as the default "Failed to apply update" message — affecting all installer-based ClotoCore installs since v0.6.3. The Tauri Updater plugin itself was already fully configured (pubkey + endpoint pointing atlatest.json+createUpdaterArtifacts: "v1Compatible"), and the release workflow generates a validlatest.jsonper release — the dashboard simply never invoked it.checkForUpdates()now uses@tauri-apps/plugin-updatercheck()(replacing direct GitHub API calls and freeing the path from the 60-request/hour unauthenticated rate limit);applyUpdate()callscheck()+update.downloadAndInstall()+@tauri-apps/plugin-processrelaunch()(withtry/catcharoundrelaunch()for NSIS install paths where the new installer kills the running process). The now-deadshell:allow-execute cloto_systementry was removed fromcapabilities/default.json. Existing v0.6.3 / v0.6.4 users must download v0.6.5 manually one last time to recover the in-app auto-update flow.
Known limitations¶
latest.jsonresolves through GitHub's/releases/latest/download/URL which only points to stable releases. Pre-release channel discovery (previously approximated by reading 30 release entries via the GitHub API) is deferred to a future feature — pre-release users on v0.6.X-beta.Y will not receive in-app upgrade prompts for v0.6.X-beta.Z.
[0.6.3] — 2026-05-20¶
First stable release of the 0.6.3 line. Promotes 0.6.3-beta.14 after coordinated Discord T1 session-continuity work and CRITICAL Setup Wizard fixes. Cumulative since v0.6.3-beta.13.
Added¶
- T1 SessionManager (kernel-owned short-term transcript) — new
SessionManagerkeeps an in-memoryAgentSessionper(agent_id, bridge_session_id)with bounded transcript +tool_history. Replaces stateless context-injection between Discord bridge and kernel: Discord callbacks no longer refetch channel history via REST or traverse 3-hop reply chains, and the agentic loop consumes T1 as the authority source for short-term context. CPersona handles long-term memory only. - Magic Seal verification —
cloto seal generate/verifyCLI binary;mgp-sealcrate integration (cut from external repo tomgp-rsworkspace);RegistryEntry.sealthreaded through DB + runtime config; verified/unverified badge onMarketplaceCard; force-untrusted on missing seal per MGP v0.6.3 §10 invariant 3. - Docker source dispatch —
install_from_dockerforSourceSpec::Docker(bare-command whitelist +docker pull+-e KEYno-value secret-leak guard +BTreeSetenv dedup). Companion to the new run_install dispatch oninstall.source.kind(Git / RawUrl / Pypi / Docker). - Marketplace catalog flip — default catalog URL switched to
https://hub.cloto.dev/api/catalog(Phase 5d-2). The legacyraw.githubusercontent.com/Cloto-dev/cloto-mcp-serverstarball template is retained for monorepo install path only; new catalog entries dispatch via the typedSourceSpecrunner. - Marketplace install helper —
effective_install_dirhelper extracted; uninstall fallback aligned; emptyinstall.directoryentries now probe the correct directory.
Fixed¶
- bug-359/360/361/362 (CRITICAL — Setup Wizard):
installingRef.currentre-entrancy guard closes the priorEventSourcebefore opening a new one on retry (bug-359 — multiple concurrent SSE connections).applyingRef.currentre-entrancy guard suppresses double-click duplicates on step 4 preset apply (bug-360).- Back-from-step-5 navigation resets installation state via
setInstallStarted(false)+ EventSource close + ref clear so step 4 re-entry is clean (bug-361). setup-complete.jsonis now written atomically viasetup-complete.json.tmp+ rename, eliminating the corrupted-file → re-setup loop (bug-362).- bug-287 (CRITICAL — Access Control) — removed the hardcoded
KERNEL_NATIVE_TOOLSallowlist fromregistry.rs; renamedcreate_mcp_servertomgp.kernel.create_mcp_serverso it is dispatched by themgp.prefix like every other kernel-native tool. Access control still routes throughresolve_tool_access(pool, agent_id, "kernel", tool_name);mcp_servershas noname='kernel'row so the default policy is opt-in → Deny without an explicit grant. Tool name renamed acrossmcp_kernel_tool.rs(schema +TOOL_NAME_CREATE_MCP_SERVERconst),mcp.rs(dispatch match),system.rs(rejection compose test),tool_rejection_smoke.rs,MGP_SPEC.md,MCP_PLUGIN_ARCHITECTURE.md. - bug-286 (HIGH — Memory Recall Contract) — kernel now owns short-term context via SessionManager (T1) and asks the memory plugin only for long-term
recall. The local payload variable was renamed and the call switched fromrecall_with_contexttorecall, so the originalrecall_argssymbol no longer appears inhandlers/system.rs. Full constant-ification of memory tool names is deferred to 0.6.4 (bug-290). - bug-310 (HIGH — Recall Timestamp Sort) —
parse_mcp_recall_resultnow sorts the parsed messages by timestamp ascending (result.sort_by_key(|m| m.timestamp);) before returning, guaranteeing chronological order for engines that expect oldest-first. - bug-344 (HIGH — Cross-User Memory Contamination) — CPersona
recallnow accepts asource_idprefix filter (cpersona v2.4.20); the kernel derivesrecall_source_idfrommsg.source(User →id, otherwise empty for v2.4.19 fallback) and threads it into the MCP recall payload athandlers/system.rs:504. The empty fallback preserves backwards-compatible all-users recall for Agent / System messages.
Changed¶
- Marketplace install dispatch —
RegistryEntry/EnvVarDefcut over tomgp-sdkv0.2.0;run_installnow dispatches oninstall.source(Git / RawUrl / Pypi / Docker) via the typedSourceSpecrunner instead of the legacy monorepo path. Legacy monorepo install retained for back-compat. - mcp-seal module → mgp-seal crate — internal
mcp_sealmodule swapped for themgp-sealcrate (now sourced frommgp-rsworkspace, no external repo dependency). - Phase 5 cutover prep — URL helpers extracted; catalog fetch now exposes a
Stale { cached, error }variant so the UI keeps showing the prior catalog when the origin is briefly unreachable. - Documentation language —
MGP_SPEC.mdretargeted as a pointer to themgp-specrepo; small-touch Japanese strings translated to English across 5 files;MCP_STARTUP_PERFORMANCEanalysis translated to English;V0_3_CHAT_UXarchive entry exempted + stale archive entries pruned. - Git hooks —
.githooks/pre-commitandscripts/install-hooks.share now source-controlled (was per-clone manual install). - Dependencies —
tauri-plugin-single-instance2.4.0→2.4.2;tauri-plugin-dialog2.7.0→2.7.1;tracing-appender0.2.4→0.2.5;tauri-build2.5.6→2.6.1;jsdom29.0.1→29.1.1 (dev);sigstore/cosign-installer4.1.1→4.1.2 (CI).
Security¶
- Force-untrusted on missing seal (MGP v0.6.3 §10 invariant 3) — connectors without a valid Magic Seal are forced to
untrustedtrust level on install, independent of the server's self-declared trust level. Closes the curation-layer bypass where a malicious connector could self-declarecoretrust.
CI / QA¶
qa/issue-registry.jsonupdated: 8 bugs marked fixed in 0.6.3 (bug-286/287/310/344/359/360/361/362) withfix_notereferencing the responsible phase and commit.scripts/verify-issues.shPASS (87 verified / 134 fixed / 0 stale / 0 errors). Fix marker patterns intentionally surface as[VERIFIED](= fix marker present) rather than[FIXED](= bug pattern absent) for the 6 in-place modifications; the script's PASS/FAIL gate is unaffected.
Companion releases¶
cpersonav2.4.20 —source_idprefix filter, fixes bug-344 cross-user memory contamination at the memory-plugin layer.cloto-mgp-discordv0.5.0 — deletes per-callback Discord REST history fetch and 3-hop reply chain traversal (183 LOC net reduction); relies on the kernel's T1 transcript instead.
[0.6.3-beta.6] — 2026-04-05¶
Added¶
- Health Check: venv detection and repair — scan now checks Python venv existence and version mismatch; repair rebuilds venv and reinstalls all server dependencies
- Uninstall data cleanup documentation in README
Changed¶
- Batch install optimization — replaced per-server sequential
pip install(N × 120s) with single unifiedpip installfor all Python servers, matching the pattern frommcp_venv.rs - SetupWizard title bar — now uses shared
ViewHeadercomponent instead of custom header
Fixed¶
- TypeScript type check failure in
repairHealthAPI call (authFetch→mutate)
[0.6.3-beta.5] — 2026-04-05¶
Added¶
- Kernel Health Check System — self-diagnostic scan with auto-repair for database integrity issues
- Quick Scan: 5 checks (DB connection, orphaned chat messages, orphaned trusted commands, orphaned permission requests, audit chain integrity)
- Standard Repair: automatic cleanup of orphaned records
- Startup scan: runs automatically on boot (configurable via
CLOTO_HEALTH_SCAN_ON_STARTUP, default: on) - API:
GET /api/health/scan,POST /api/health/repair - Settings > Health tab — dashboard UI for scan results, manual scan/repair buttons
- Japanese translation for Health tab
[0.6.3-beta.4] — 2026-04-05¶
Security¶
- Tar path traversal prevention — marketplace install now validates extracted paths stay within target directory (zip-slip mitigation)
- Missing authentication —
get_agent_accessendpoint now requires API key (was unauthenticated unlike all other endpoints) - Code validator bypass — blocked pattern matching now uses case-insensitive comparison, preventing
Eval()/EXEC()bypass - Revoked key check logging — lock acquisition failure during revoked key check is now logged instead of silently skipped
Fixed¶
- UTF-8 panic — tool hint truncation now uses char-based indexing instead of byte slicing, preventing panic on multi-byte characters
- Negative chat limit —
limitparameter now clamped to minimum 1, preventingusizewrapping on negative input - Iteration overflow — agentic loop counter uses
saturating_addto prevent theoretical u8 overflow - Script path inconsistency — dynamic MCP server script restoration now uses same path (
data/mcp_scripts/) as creation - Attachment storage path — uses
state.data_dirinstead of relative path, consistent with VRM/avatar storage - Non-transactional agent deletion —
delete_agentnow wraps all DB operations in a transaction for consistency - DB timeout gaps — added
db_timeoutto all cron (8 functions) and LLM (5 functions) DB operations - Audit log timeout —
write_audit_logtransaction now wrapped with configurable timeout - Mutex poison recovery —
StreamAssemblerandToolIndex/SessionToolCachenow recover from poisoned mutexes instead of panicking
Added¶
MgpCapabilitieshelper usage documented in quickstart guide- Coming Soon placeholders for non-functional log UI elements
[0.6.3-beta.3] — 2026-04-04¶
Fixed¶
- MCP server toggle race condition (Issue #65) —
stop_server()now waits for child process exit before returning, preventing DB lock conflicts on restart - Safe integer casts —
i64→i32(cron),usize→u8(delegation chain),u64→u8(cron generation) now usetry_frominstead ofascasts - Error logging — Cargo.toml read errors in marketplace and RwLock poison recovery now logged instead of silenced
- CVE-2026-33672 — picomatch 2.3.1→2.3.2, 4.0.3→4.0.4 (glob matching method injection)
Added¶
- MCP/MGP Server Quickstart — two-path guide for new server developers
CLOTO_YOLO_EXCEPTIONSdocumented in README configuration table- Tauri dev note in Quick Start section
Changed¶
- README: test badge 351→234, security section +3 items, documentation links updated
- CHANGELOG: removed internal marketing references from beta.1 and beta.2 entries
- CLAUDE.md: clarified issue registry as anti-hallucination tool
Dependencies¶
- jsdom 28.1.0→29.0.1 (dev)
[0.6.3-beta.2] — 2026-04-04¶
Security Hardening (8 layers)¶
- L2: Kernel tool RBAC —
mgp.*/gui.*tools now checked viaresolve_tool_access(server_id="kernel"); default Allow, explicit Deny entries restrict specific agents - L3: YOLO mode exceptions —
CLOTO_YOLO_EXCEPTIONSenv var (default:filesystem.write,network.outbound); excepted permissions require approval even in YOLO mode - L5: Merkle chain audit log —
chain_hashcolumn onaudit_logstable; each entry hashed with SHA-256(previous_hash | canonical_data) for tamper detection - L8: Runtime host whitelist audit —
add_host()logs a warning when a new host is added - L9: Event depth hardening —
MAX_EVENT_DEPTHcap lowered from 50 to 25; warning logged at depth > 5 - L11: MGP permission declarations — avatar and discord servers declare
permissions_required: ["network.outbound"]in initialize response (cloto-mcp-servers) - L12: destructiveHint HITL gate — parse MCP
annotations.destructiveHint, require approval for destructive tools via existing command approval flow - L14: Trust level mismatch warning — kernel logs when server self-declares higher trust than config allows
Added¶
McpTool.annotationsfield for MCP tool annotation parsingMcpClientManager::is_tool_destructive()helperCLOTO_YOLO_EXCEPTIONSenvironment variable- Planned breaking changes section in PROJECT_VISION (§10)
- DB migration:
audit_logs.chain_hashcolumn
Changed¶
- YOLO permission flow refactored to partition-based logic (auto-approvable vs excepted)
write_audit_log()now uses single SQLite transaction for chain hash consistency
Fixed¶
- 3 stale issue-registry bugs marked as fixed (bug-311, bug-314, bug-343)
Documentation¶
- Security layer audit report (15 layers verified against code)
- GitHub Sponsors FUNDING.yml
[0.6.3-beta.1] — 2026-04-03¶
Added¶
- Streamable HTTP transport for remote MCP server connections
- Agentic loop for
ask_agenttool execution chains - Discord conversation context injection into LLM calls
- Discord callback metadata forwarding to agent messages
- CPersona memory channel support for channel-based context separation
- Actions panel with inter-agent dialogue visibility
- CRON job execution display in Actions Dialogues
- Engine selector on CRON job creation form
- Memory export/import UI in MemoryCore
- Marketplace changelog display on update-available cards
- MGP badge and glow effect on MCP server cards
- Agent processing glow indicator in sidebar
- Speaker name display on memory cards
- IO category for bidirectional MCP servers in dashboard
- Process relaunch on error boundary restart
- Marketplace actions locked in dev mode by default
- Pre-compute archive/profile via CFR engine in background
- Generalized
tool_hintfor direct tool execution bypass CapabilityType::Speechwith capability-based auto-speak- Installer (Experimental) section in README with setup wizard fix
Changed¶
io.discord.karinrenamed toio.discord- Per-agent Discord server entry template
- Dialogues tab bar replaced with vertical scroll list
- Agent description limit increased from 1000 to 5000 bytes
Fixed¶
- MCP venv: parallel pip install replaced with single invocation
- Stale Python venv detection and automatic recreation
- pip install timeout and
--no-inputflags - Python venv and cargo build timeouts
- Duplicate tool names in LLM tool schemas
- Null reference in Discord callback metadata
- Avatar cache-bust on re-upload
- Avatar vision analysis skipped when agent lacks Vision access
- CRON dialogue response pairing
- Memory card text size and description textarea height
- Export/import icon semantics corrected
- Speech tool schema exclusion limited to "speak" tool only
- Setup wizard download URL fixed (points to cloto-mcp-servers releases)
- Setup wizard server/venv paths corrected for production layout
detect_project_root()recognizescloto-mcp-servers/directory
Security¶
- Authentication, cryptography, MCP server creation, and Tauri capabilities hardened
- GitHub Actions pinned to commit SHAs
- CVE-2026-33055, CVE-2026-33056 (tar crate update)
- Access control magic strings replaced with typed enums
aria-labeladded to all interactive dashboard components
Documentation¶
- Code quality audit report (65 findings — 2 critical, 19 high, all fixed)
- Documentation-codebase integrity audit (3 critical, 7 high, 5 medium fixed)
- CPersona design document updated to v2.4.6 (tool count, version table, architecture diagram)
- MGP specification kernel tool count corrected (17→25)
- GUI component map updated
- Test count corrected: 351 (234 Rust + 117 Python)
[0.6.3-alpha.11] — 2026-03-21¶
Changed¶
- MGP renamed from "Model General Protocol" to "Multi-Agent Gateway Protocol"
- Release assets consolidated from 34 to 22 (SHA256SUMS.txt replaces per-file checksums)
Fixed¶
- Kernel startup failure no longer silently ignored —
start_kernel()refactor with Tauri error dialog - LLM proxy bind failure reported in background — no longer blocks HTTP server startup
- MCP deferred boot race condition resolved —
Arc<Notify>replacesyield_now() - Tauri tray icon panic prevented
- EventManager mutex poisoning cascade eliminated across 13 sites
- McpAccessControlTab infinite re-render loop
- Cross-platform MCP path normalization
- MCP config parse error visibility improved
- Faster graceful shutdown — concurrent drain with 10-second cap
- pip install timeout and
--no-inputto prevent setup hangs - Stale venv auto-detection — compares Python major.minor, auto-recreates on mismatch
- Text size and color rule violations in dashboard
Security¶
aws-lc-sysupdated (RUSTSEC-2026-0044, RUSTSEC-2026-0048)rustls-webpkiupdated (RUSTSEC-2026-0049)
[0.6.3-alpha.10] — 2026-03-20¶
Fixed¶
- Empty MCP server list after NSIS installation —
mcp.tomlnow embedded in binary viainclude_str!and extracted todata/mcp.tomlon first launch with snapshot pattern - Removed broken Tauri
resourcesbundling (Tauri v2 transforms../into literal_up_directories)
[0.6.3-alpha.9] — 2026-03-20¶
Fixed¶
- Empty MCP server list after installation —
mcp.tomlbundled as Tauri resource for first-launch discovery exe_dir/mcp.tomladded as production fallback pathCLOTO_MCP_SERVERSfallback probes multiple candidate directories (bundled, sibling repo, legacy layout)- Always-true assertion removed from security forging test
[0.6.3-alpha.8] — 2026-03-19¶
Changed¶
.env.exampleupdated with Ollama config- Outdated
CODE_QUALITY_REPORT.mdremoved
Fixed¶
- Dashboard: gate console statements behind
import.meta.env.DEV - Dashboard: improve catch block type safety, extract magic numbers, remove dead CSS
- Rename legacy
karincolor tocloto - All clippy warnings resolved
- Warn logging added to silent I/O errors in system handler
- Benchmark helpers updated to match current
AppStatestruct ask_agenttool description improved- CI: cargo fmt violations and missing assertion fixed
[0.6.3-alpha.7] — 2026-03-17¶
Added¶
- Rust MCP server support in marketplace — servers with
runtime: "rust"built withcargo build --release, with toolchain detection and build progress streaming - Startup timing log (
startup: X.Xs) - Rust badge on marketplace cards
- MCP startup performance analysis report
Changed¶
- MCP server connections parallelized —
connect_server_configs()usesjoin_allfor concurrent connections - Parallel venv dependency sync — pip install runs concurrently for all servers
- Background venv sync —
ensure_mcp_venv()moved off critical startup path - Startup time reduced from ~40s to ~7s
output.avatarremoved frommcp.toml(marketplace-only distribution)
Fixed¶
- Sidebar "Agents" nav not returning to agent selection
- Agent config screen highlighting wrong sidebar item
- Sidebar agent click not working after returning from chat/config
- Config screen persisting when navigating away
- Marketplace install blocked for config-loaded servers
- Cargo build failing in data dir due to parent workspace detection
- CI: cargo fmt, flaky seal key test, issue registry
[0.6.3-alpha.6] — 2026-03-16¶
Changed¶
mcp.tomlportability:${CLOTO_MCP_SERVERS}env var with sibling-repo fallbackresolve_servers_dir_from_config()resolves relative paths against project root
Fixed¶
- Update checker detects pre-release versions via
/releasesAPI - Pre-release segment version comparison (alpha.4 vs alpha.5)
- Setup wizard Python pre-check with download link and retry button
- Hardcoded developer-machine paths removed from history
[0.6.3-alpha.5] — 2026-03-16¶
Added¶
- VRM thumbnail extraction and avatar offer dialog
- i18n: Japanese translations for VRM dialog and settings sections
- CFR default enabled for new routing rules
- Engine selection persistence per agent in localStorage
Changed¶
- Deferred save pattern unified for all agent config
output.avatarmigrated tocloto-mcp-serversrepository
Fixed¶
- VRM upload metadata COALESCE race condition
- Null injection prevention in metadata
- Marketplace refresh bypasses server cache
- Duplicate refresh buttons unified
[0.6.3-alpha.4] — 2026-03-16¶
Added¶
- Agent state persistence across navigation (thinking steps, chat, SSE)
- Code block header bar with language label, copy, and download
- Artifact panel collapse/expand with sessionStorage persistence
- MCP server lifecycle feedback (spinner + checkmark)
Fixed¶
- CI: MSI target exclusion, clippy errors, biome lint, sentinel assertion
- Workspace-wide cargo fmt
[0.6.3-alpha.3] — 2026-03-16¶
Added¶
- Auto-update check on startup (Tauri only, configurable)
- Discord-style update indicator in header
- Tool hint display shows actual command name
Changed¶
- Unified card styles across all dashboard components
Fixed¶
- Avatar upload/deletion race condition
- Avatar upload spinner hang with 30-second timeout
- Semver comparison for pre-release versions
Documentation¶
- CPersona v2.5/v3.0 roadmap added
[0.6.3-alpha.2] — 2026-03-16¶
Added¶
- MCP Server Marketplace (Phase 1 & 2) — catalog, install, batch install with SSE progress
- Setup flow unification with SSE progress streaming
- Tier-1 rate limiting and startup dependency sync
- Biome formatter, lefthook pre-commit hooks, sentinel script
- 14 unit tests for marketplace and setup
Fixed¶
resolve_servers_dir_from_configTOML parsing failure (critical)- Avatar deletion and AgentConsole TDZ crash
- Install path resolution fixes
[0.6.3-alpha.1] — 2026-03-13¶
Added¶
- CPersona background task queue (Phase 5) ported from predecessor
- SSE SequencedEvent with
Last-Event-IDreplay for reliable event streaming - Cron
source_typefield to distinguish user vs system messages - VRM thinking pose auto-application on agent thinking state
AgentThinkingevent emission before all LLM calls- Host OS info injected into agent system prompt
Fixed¶
- WebView2 startup crash (
ERR_CONNECTION_REFUSED) on release builds useLongPressstale closure in long-press handler- Chat message deletion not including system rows
- Web search false-positive health check
Documentation¶
- VOICEVOX credit added to README
- CPersona 2.x versioning adopted (inheriting KS2.x lineage)
- 8 internal audit docs moved to
.dev-notes/ - Comprehensive
CPERSONA_MEMORY_DESIGN.mdupdate (20 fixes)
[0.6.2] — 2026-03-11¶
Added¶
- VRM Avatar System (Layer 1) — full procedural animation pipeline (breathing, blinking, micro-sway, gaze drift, agent state transitions, default pose with smooth transitions)
- VRMA pose system with direct quaternion application, smooth slerp-based transitions, drag-and-drop loading
- VRM expression mapper — cross-avatar compatibility layer with fallback chains
- mgp-avatar MCP server — VOICEVOX TTS with automatic viseme extraction for real-time lip sync
- MGP
set_posetool for avatar pose control (relaxed, attentive, thinking, arms_crossed) - Auto-speak final LLM response with configurable bypass
- VRMA thinking pose preset (Blender-authored)
- Eye narrowing during thinking state
- Middle-click orbit rotation in VRM viewer
- Extended bone controls (neck, spine, head, hand)
- Core architecture refactor (Phase 1–8): CapabilityDispatcher, metadata JSON migration, unified state consolidation, process lifecycle safety, permission events, config-driven capabilities, agent type filtering
- OS-level isolation (MGP §8-10) for MCP server sandboxing
- MGP tool discovery latency tier scoring (Tier C/B/A/S)
Fixed¶
- VOICEVOX
accent_phrasesfield name for viseme extraction - Pre-phoneme compensation for accurate lip sync timing
- Audio cutoff prevention and viseme desynchronization
- Bypass agentic loop for TTS (prevent prompt readback)
- VOICEVOX pipeline and sandbox path resolution
[0.6.1] — 2026-03-09¶
Added¶
ask_agentkernel tool for inter-agent delegationAgentThinkingSSE events for LLM intermediate reasoning displaygui.mapandgui.readkernel tools for dynamic UI documentation- Agent config presets with deferred avatar save
- MGP dead code integrated into runtime (Phase 0-5)
- GitHub Issue Sync workflow: auto-create/close GitHub Issues from
qa/issue-registry.json
Changed¶
- Rename
memory.ks22tomemory.cpersonaacross entire codebase - Auto-grant MCP access on agent creation
- Settings screen text sizes increased for readability
Fixed¶
- Comprehensive data cleanup on agent deletion (bug-231)
- Dashboard API key delivery in Tauri mode and FK violations in MCP access control
useAgentscache race condition, wizard UX improvements, and 6 pre-existing TS errors- Dashboard UI/UX improvements and LLM thinking event support
Documentation¶
- Backfill CHANGELOG entries for v0.6.0-alpha.4 through v0.6.0 stable (MGP content)
[0.6.0] — 2026-03-08¶
Added¶
- MGP (Multi-Agent Gateway Protocol) Tier 1-4 implementation complete
- Tier 1: Security primitives — protocol-level access control and audit trails
- Tier 2: Observability — monitoring, metrics, and diagnostic capabilities
- Tier 3: Bidirectional communication — server→kernel notifications and tool discovery
- Tier 4: Intelligence Layer — context management, adaptive behavior, and compliance
- 17 MGP kernel tools in
mgp.*namespace (access control, audit, lifecycle, streaming, discovery) - MGP server creation with coordinator pattern
- Priority boot sequence for MGP servers
- Tool discovery stress tests and context reduction measurements
Fixed¶
- MGP Tier 1-3 spec compliance (bug-182 to bug-222)
- Missing Tier 4 tool schemas registered;
tool_historysanitization hardened - MGP kernel tool execution and LLM provider integration
- Stale connection status threshold removed for immediate disconnect detection
- Linux Tauri build deps: added libgbm-dev, libegl-dev, libxcb1-dev
- macOS CI: upgrade xcap 0.0.13 → 0.8
- Linux CI: switch to ubuntu-24.04 for libspa 0.9.2 compatibility
Documentation¶
- MGP implementation roadmap added
- MGP documentation updated to reflect Tier 1-4 completion
[0.6.0-beta.3] — 2026-03-07¶
Added¶
- First-run setup wizard
- Agent config export/import
Fixed¶
- Hide export button for default agent (Cloto Assistant)
[0.6.0-beta.2] — 2026-03-07¶
Added¶
- Modular i18n with react-i18next (EN + JA)
- Filesystem-based language packs with extended translations and text readability enforcement
Removed¶
- Container agent type from dashboard
[0.6.0-beta.1] — 2026-03-07¶
Added¶
- Semantic cache for research server
- TTL-based LRU cache for query embeddings in KS22
Removed¶
- Predecessor project references from codebase
[0.6.0-alpha.5] — 2026-03-07¶
Changed¶
- Codebase reduced by ~1,400 LOC with structural improvements
Fixed¶
- 5 LOW bugs resolved, Python MCP test base added, 2 reclassified as wontfix
Removed¶
- Orphaned
runtime_pluginsandagent_pluginstables dropped
[0.6.0-alpha.4] — 2026-03-06¶
Added¶
- Cross-platform Tauri desktop app support (Linux + macOS)
- macOS code signing and notarization configuration
- Configurable settings extracted from hardcoded values
Fixed¶
- Version prerelease label auto-generation from package version
[0.6.0-alpha.3] — 2026-03-06¶
Fixed¶
- 8 MEDIUM bugs resolved, improved Python MCP server quality
- Graceful shutdown now broadcasts to all tasks (not just one listener)
- MCP stderr log noise suppressed
[0.6.0-alpha.2] — 2026-03-05¶
Removed¶
- CLI crate (
cloto_systembinary removed) - Status UI page
Fixed¶
- MCP server restore bug on kernel restart
Security¶
- Authentication added to read-only APIs (agents, plugins, metrics, memories)
- YOLO mode audit log: all auto-approved actions recorded
- Revoked API keys now expire with TTL cleanup
[0.6.0-alpha.1] — 2026-03-05¶
Added¶
- MGP specification v0.6.0-draft: structural audit, architectural revision, split into maintainable part files
- SearXNG self-hosted search via Docker Compose
- Multi-provider search fallback chain for MCP
- Reliable chat message persistence with retry logic
Changed¶
- Replace Inno Setup installer with Tauri NSIS installer (Windows)
- Dashboard: extract shared UI components and utility hooks
Fixed¶
- MGP integrity scan findings resolved (S1-S3, I1-I3, X1)
- Windows console windows appearing from MCP server child processes
- Kernel images blocked by CSP
img-srcdirective - Release pipeline: Ed25519 signing, artifact paths, macOS runner, cosign verification
[0.5.11] — 2026-03-04¶
Changed¶
- Unified REST API response envelope (
{ "data": ... }/{ "error": ... }) - Auto-generate Tauri API key on first launch
[0.5.10] — 2026-03-04¶
Added¶
- Multi-user identity propagation across the full pipeline (chat, agentic loop, MCP tools, memory)
[0.5.9] — 2026-03-04¶
Fixed¶
- Memory contamination causing time hallucination in agent responses
[0.5.8] — 2026-03-04¶
Changed¶
- Dashboard UI/UX refinements: retry fix, MemoryCore design unification, engine selector polish
[0.5.7] — 2026-03-04¶
Added¶
- CRON autonomy security: recursion depth control and audit log guarantee
[0.5.5] — 2026-03-04¶
Added¶
- Gemini-style engine switcher in chat input bar
[0.5.4] — 2026-03-04¶
Added¶
tool.cronMCP server: stateless CRON job management via kernel REST API (create, list, delete, toggle, run now)tool.agent_utilsMCP server: 8 deterministic utility tools (time, math, date arithmetic, random, UUID, unit conversion, encode/decode, hash)- Default MCP server grants for Cloto Assistant: memory.cpersona, tool.cron, tool.terminal, tool.websearch, tool.research, tool.agent_utils
- Cydonia 24B v4.3 (TheDrummer) Q4_K_M Ollama model support with ChatML template
Fixed¶
- Default engine routing: Cloto Assistant was incorrectly using mind.deepseek instead of mind.cerebras (migration WHERE condition bug)
- ONNX embedding server: missing
token_type_idsinput caused all-MiniLM-L6-v2 inference to fail, breaking memory recall - Response latency reduced from ~7.4s to ~2s (engine fix + embedding fix)
Changed¶
- Ollama default model changed from glm-4.7-flash to cydonia
- Code cleanup: reduced ~600 lines across DB layer, handlers, and docs
[0.4.22] — 2026-03-03¶
Added¶
- CFR (Cost-First Router): high-speed engine tries first, escalates to high-quality engine on
[[ESCALATE]] - Auto-fallback: retriable errors (429/5xx/connection) automatically switch to fallback engine
- Routing rule extensions:
cfr,escalate_to,fallbackfields (backward-compatible) - Dashboard UI: CFR toggle, escalation target, fallback selector in routing rule builder
[0.4.21] — 2026-03-03¶
Added¶
- Command approval system: HITL gate for terminal commands (Yes/Trust/No)
- Kernel intercepts
execute_commandbefore MCP dispatch (YOLO mode bypasses) - DB-persisted exact match trust ("Yes") + session-scoped command name trust ("Trust")
- Inline approval card in chat with 60s countdown timer
- Tauri OS notification when approval pending and user is away
- API endpoints:
POST /api/commands/:id/{approve,trust,deny} trusted_commandsDB table +CommandApprovalRequested/Resultevents
Changed¶
- Chat persistence moved from frontend to kernel (backend-complete)
- User messages persisted in
handle_message()before processing - Agent responses persisted before SSE
ThoughtResponseemission - Frontend
postChatMessagecalls removed (no more fire-and-forget) - LLM error handling improved across all layers
- L1 (Proxy): HTTP status → user-friendly message + error code (
auth_failed,rate_limited, etc.) - L2 (MCP Python):
LlmApiErrorclass replaces rawraise_for_status(), structured error response - L3 (Kernel):
format_engine_error()adds actionable guidance per error code - L4 (Dashboard):
[Error]messages displayed as amber error cards instead of plain text - Internal URLs (
127.0.0.1:8082) no longer exposed to users - Reset button long-press reduced from 2s to 1.5s
- Thinking state recovery: 30s timeout +
visibilitychangelistener to handle missed SSE responses
[0.4.20] — 2026-03-03¶
Added¶
- Dashboard update checker: "Check for Updates" button in Settings → About
- GitHub API-based version comparison with release notes display
- "Update Now" via Tauri shell plugin (desktop mode only)
- Tauri Native Auto-Update design (integrated into
docs/INSTALLER_DISTRIBUTION.md§ 6) for future implementation
[0.4.19] — 2026-03-03¶
Changed¶
- Extract password verification helper to
handlers/utils.rs(deduplicate 2x20-line blocks) - Python MCP server factory:
create_llm_mcp_server()+load_llm_provider_config()reduce cerebras/deepseek to ~27 lines each - Split
AgentPluginWorkspace.tsxintoAvatarSection,ProfileSection,ServerAccessSectioncomponents
[0.4.18] — 2026-03-03¶
Changed¶
- Split monolithic
db.rs(1,732 lines) into 7 domain modules (db/{audit,permissions,chat,mcp,api_keys,cron,llm}.rs) - Extract
mcp_tool_validator.rs(~200 lines) frommanagers/mcp.rs - Centralize validation constants and MIME helpers into
handlers/utils.rs - Remove unused npm packages (
clsx,tailwind-merge) - Remove false-positive
#[allow(dead_code)]annotations (7 items) - Remove unused code:
Tickvariant,selected_agent(),create_slow_plugin()
Added¶
- Multi-Agent Delegation design document (
docs/MULTI_AGENT_DESIGN.md) for v0.5.x
[0.4.17] — 2026-03-03¶
Fixed¶
- Agent card buttons unclickable when avatar background is set (
pointer-events-noneon overlay image)
[0.4.16] — 2026-03-03¶
Added¶
- PaddleOCR hybrid vision: OCR + llava combined analysis with A/B test support (hybrid/vision/ocr modes)
- Agent card avatar background in agent selection screen (blurred, hover effect)
- Default agent protection: name, description, avatar changes blocked for Cloto Assistant
Changed¶
- Unified grid background: all 6 screens use
InteractiveGrid(Canvas) with bottom fade - Agent config UI: larger avatar preview (96px), bigger buttons, Remove button with red tint
- Agent card buttons enlarged (text-xs, size-14 icons)
- Chat avatar icons fill parent container (size 32-40px with overflow-hidden)
- Sidebar avatar icons enlarged to 24px
- MCP server grant/revoke: one-click on row (no separate button needed)
- Cloto Assistant description updated to reflect full capabilities
Fixed¶
- Avatar broken image after delete (local
hasAvatarstate tracking) - Backend-injected metadata fields polluting save (has_avatar, avatar_description excluded)
- Agent ID sanitization: URL-unsafe characters replaced with underscore
- Duplicate
apiimport in AgentTerminal
[0.4.15] — 2026-03-02¶
Added¶
- KS2.2 Phase 2: Vector embedding search (ONNX MiniLM, cosine similarity) activated via mcp.toml config
- KS2.2 Phase 3: LLM-powered memory extraction — profile fact mining and episode summarization via Cerebras
- Auto-download ONNX model on first embedding server startup
- Memory/episode delete API (
DELETE /api/memories/:id,DELETE /api/episodes/:id) - Memory Core dashboard: delete buttons on memory cards and episode entries
- Auto
update_profiletrigger after episode archival
Fixed¶
- Tauri:
mcp.tomlnot found due to absolute path fallback not resolving to project root - Tauri: venv Python not resolved due to
detect_project_rootnot shared across modules
[0.4.14] — 2026-03-02¶
Added¶
- Auto-setup MCP Python venv on first kernel startup (
mcp_venv.rs) - Auto-resolve
pythoncommand to venv Python in MCP transport (no venv activation needed) - Cerebras tool calling:
gpt-oss-120bnow exposesthink_with_tools - Missing
pyproject.tomlfor ollama, websearch, research MCP servers
Fixed¶
- Agents using Cerebras engine could not use MCP tools (terminal, etc.) due to
supports_tools=False
[0.4.13] — 2026-03-02¶
Added¶
- Agent avatar: image upload/serve/delete API (
POST/GET/DELETE /api/agents/:id/avatar) - Avatar vision analysis: auto-analyze via vision.capture MCP, description injected into LLM system prompt
- Agent rename: editable name/description fields in agent settings UI
- Clipboard paste: Ctrl+V image attachment support in chat input
- Window maximize on startup (Tauri)
- DB migration:
avatar_path,avatar_descriptioncolumns on agents table
Fixed¶
- Cursor dot remnant when mouse leaves window (add
mouseleave/blurhandlers) - Mermaid diagram text visibility on GitHub dark theme (
color:#333)
Quality¶
- YOLO mode issues registered (bug-170, 171, 172)
[0.4.8] — 2026-03-01¶
Added¶
- Engine routing: rule-based 3-layer engine selection (override > routing rules > default)
- MCP access control: wire up
resolve_tool_access()3-level priority resolution - Episode auto-archival:
maybe_archive_episode()triggers after 10+ unarchived messages - McpClient notification handling: Server→Kernel JSON-RPC notification support (MGP §13 foundation)
- CI:
verify-issuesjob in GitHub Actions - CI: Branch Protection with required status checks
- Discord Bridge design document (
docs/DISCORD_BRIDGE_DESIGN.md) - MGP spec §19.5
transport_websocketextension, §19.6 External Event Bridge Pattern
Fixed¶
- XSS: DOMPurify sanitization on
dangerouslySetInnerHTML - API key storage moved from localStorage to sessionStorage
- Unsafe
anytypes replaced with proper React event types - JSON parse guard (
safeJsonParse) in api.ts - Error state exposed from useAgents hook
- All clippy errors resolved (18 fixes)
- Test baseline updated, dashboard
--passWithNoTests
Security¶
default_policychanged fromopt-intoopt-outfor MCP serverssave_mcp_server()preservesdefault_policyon reconnect- rollup HIGH severity path traversal fix
[0.2.0] — 2026-02-26 (β2)¶
Theme: Bug fixes, security hardening, performance improvements, documentation, and refinements
Bug Fixes¶
- Resolve all open issues in issue registry (115/115 closed)
- Update 5 obsolete bug entries referencing deleted components
- Add error context to test assertions (
unwrap()→expect())
Code Quality¶
- Suppress
clippy::too_many_linesfor Tauri entry point - All
cargo clippy --workspacewarnings resolved - All 90 tests passing, 0 ignored
Security¶
- Install and run
cargo audit— 0 vulnerabilities, 16 warnings (all GTK3 indirect deps, Linux-only)
Documentation¶
- Rewrite CHANGELOG to version-based format (Keep a Changelog)
- Add v0.2.0 release scope document
- Fix 12 HIGH, 14 MEDIUM documentation inconsistencies across 9 files
- Align ARCHITECTURE.md, DEVELOPMENT.md, PROJECT_VISION.md with MCP-only architecture
- Update SCHEMA.md with 3 missing tables (runtime_plugins, revoked_keys, agent_plugins)
- Update MAINTAINABILITY.md metrics (crate count, file sizes, test count)
- Correct MCP server naming convention (core.cpersona → memory.cpersona)
- Clean up commit history (157 → 1 commit, author unified)
[0.1.0] — 2026-02-26 (β1)¶
Initial release of ClotoCore — an AI agent orchestration platform built on a Rust kernel with MCP-based plugin architecture.
Core Architecture¶
- Event-driven Rust kernel with actor-model plugin system
- MCP (Model Context Protocol) as the sole plugin interface
- 5 MCP servers: Cerebras, CPersona Memory, DeepSeek, Embedding, Terminal
- ConsensusOrchestrator for multi-engine LLM coordination
- SQLite persistence with 24 migrations
- Rate limiting, audit logging, and permission isolation
Dashboard¶
- React/TypeScript web UI with dark mode
- Agent workspace with MemoryCore design language
- MCP server management UI (Master-Detail layout)
- Real-time SSE event monitoring
- API key management with backend validation and revocation
- Tauri desktop application (multi-platform)
CLI¶
- Agent management (create, list, inspect, delete)
- TUI dashboard with ratatui
- Log viewer with SSE follow mode
- Permission management commands
Agent System¶
- Per-agent plugin assignment with config-seeded defaults
- Agent lifecycle management (create, delete, default protection)
- Custom skill registration with tool schema support
- Permission enforcement (visibility, revocation, runtime checks)
Security¶
- API key authentication with Argon2id hashing
- Key revocation system with SHA-256 tracking
- Path traversal prevention and input validation
- CORS configuration with explicit header allowlists
- Human-in-the-loop permission approval workflow
Infrastructure¶
- GitHub Actions CI/CD pipeline (5-platform build)
- Windows GUI installer (Inno Setup) with Japanese localization
- Shell and PowerShell installers with version validation
- GitHub Pages landing page with OS auto-detection
- BSL 1.1 license (converts to MIT on 2028-02-14)