# Changelog What changed, per version, for somebody using or running LLeMbas — not a restatement of the commit log. If a change fixed something that *looked* like it worked, that is worth a line: those are the ones nobody would otherwise know to stop working around. Newest first. Versions are `__version__` in `src/lembas/__init__.py`, which is the only place a version is written. The first tagged release is **1.0.0**. Everything below it shipped as a running deployment rather than as a release, and is recorded here so the release notes for 1.0.0 have something to be assembled from. --- ## Unreleased Nothing since 0.9.8. ## 0.9.8 **Updates follow a channel, not a commit.** `stable` tracks the newest `vX.Y.Z` tag; `edge` tracks the branch tip. A branch tip is not a release — following one means deploying whatever was pushed five minutes ago — so stable is the default for anybody who is not the person writing it. - The Updates page shows a **version** rather than a commit sha: `1.0.0` at a tag, `1.0.0-7-gd4f56d` seven commits past one, and a bare sha only before the first release exists. - Release notes come out of the **annotated tag itself**, so no forge API is involved anywhere. That matters: the Gitea API this was checked against returns a 500 from a server-side panic on exactly the releases endpoint. - A tag with a suffix (`v1.1.0-rc1`) is deliberately not a release — git's version sort ranks it *above* `v1.1.0`, so accepting one would step a stable host onto a candidate. - Fixed: `deploy/update.sh` stopped silently after `== fetching ==` on any host with no release tags — which was every host. Fetched, not reset, not restarted, and no error printed. - Fixed: `install.sh` now refuses an `ssh://` repository URL up front instead of letting the clone fail as a service user with no key. ## 0.9.7 **Packaging, and updating without a shell.** - `/admin/updates`: what is running, what is available, and what changed between. A button applies it — answered by an **opt-in** systemd helper, because the service runs unprivileged and a web application that can restart its own service is one whose worst day is much worse. Without the helper the page says so and prints the command. - `Dockerfile` and `docker-compose.yml`. No secret key, no data and no `.git` baked in; loopback only; a TLS proxy expected in front, because a service worker and a microphone both require HTTPS or localhost. - `deploy/lxc-install.sh` creates an unprivileged Proxmox container and runs the existing installer inside it. - `/healthz`, which opens the database rather than only proving the socket is listening. ## 0.9.6 **Permissions, quotas and sharing.** - **"What can this account actually do?"** answered on screen, naming *where* each permission came from — admin, the baseline, or a group. - Users and groups are list-plus-detail, and membership is edited from **one** side. It was on both, and a save from either overwrote what the other showed. - Reading and writing split for notes, memory and skills. - **Quotas on a group** — monthly tokens, concurrent replies, agent wall clock, images a day, helpers a reply. Resolved by maximum across a person's groups, with zero meaning *no limit* and winning outright. - Fixed: **deleting a group or an account left every share naming it behind.** `forget_principal` had existed since shares did and was called by nobody. - Fixed: `library.share` defaulted to off, so sharing shipped documented as done and unreachable — the panel only renders for somebody who holds it. - The share panel is its own action with a search box. It used to be checkboxes inside the resource's save form, listing every account on the instance, and a tick only took effect if you also saved the resource. - Reports are shareable, and every listing has a **Shared with me** filter. ## 0.9.5 **Extraction settings, embeddings, and hybrid search.** - `/admin/extraction`: upload size, image edge, JPEG quality, PDF pages, extracted characters, orphan age, extra text extensions. - An **embedding model** can be chosen from models flagged for it. Library search then fuses keyword and semantic ranking, so *"how do I get paid"* finds a document that says *"invoicing"*. - **Choosing none is not a degraded mode**: no rows written, no requests made, and byte-for-byte the keyword search that was always there. - Vectors carry their model and width, and a mismatch is skipped rather than scored — comparing two embedding spaces produces a confident wrong answer. - Indexing happens in the background as records are written, with a rebuild button for everything that already existed. ## 0.9.4 **An instance can be somebody else's.** - Name, tagline, logo, favicon and launcher icons derived from the logo. - The Middle-earth wording is editable data. Leaving a box alone does not freeze it, so a later release can still improve the default. - **Custom themes** as a set of colours rather than a stylesheet, inheriting whichever built-in they start from. - Global CSS overrides, served as `/branding.css`. ## 0.9.3 **Subagents.** A reply can hand a self-contained piece of work to a helper that runs on its own and reports back — several at once, so research fans out instead of queueing. - A helper cannot ask questions, cannot send helpers of its own, writes nothing unless the call asked and the chat's mode allowed it, and on a machine runs only a fixed list of read-only commands — in **every** mode, including Auto. - Fixed, and it was live in scheduled runs too: an unattended chat that hit an approval built a card nobody could see and sat on it for fifteen minutes. ## 0.9.2 **Image generation defaults an administrator can actually set** — steps, cfg, size, sampler, scheduler, denoise, negative prompt, checkpoint, batch. There were none: one hard-coded set from the SD1.5 era, and prose in a box as the only way to change it. - The samplers and schedulers ComfyUI had been reporting all along are now the pickers; nothing had ever read them. - The tool's own schema restates the instance's defaults, instead of telling the model "Default 512" beside an instance that draws at 1024. ## 0.9.1 **Everything that arrives is announced, not only chat replies.** A scheduled run that filed a report used to light a dot in a corner and say nothing. - A count in the tab title while you are looking elsewhere. - **Web push**, so a schedule firing at seven in the morning reaches a browser that is shut. Opt-in per device. It is the one thing here that contacts an outside service, and `services/push.py` says so plainly. ## 0.9.0 **A model can schedule things.** There was no tool for it — asked to "remind me every Monday", a model wrote a note and reported that it had scheduled something, and every screen agreed with it. - `schedule_create`, `schedule_list`, `schedule_update`, `schedule_cancel`, over the same rule normaliser the manual form uses. - The reply says the resulting timing back in words, which is the only moment anybody can check that Monday was understood as Monday. ## 0.8.3 **An SSH connection may not point at this machine unless an administrator says so.** A profile aimed at `127.0.0.1` walked straight past "nothing runs on the LLeMbas host" — through a real login, onto the machine holding the database and the encryption key. Three positions: off, one named port, or anywhere. ## 0.8.2 - Fixed: **opening the canvas before a chat existed swapped the whole site into the panel.** `hx-get=""` is not "fetch nothing" — htmx looks for the attribute, not the value, so the empty one was a real request for the current document. - Fixed: the Canvas and Terminal buttons appeared where they could not work. - The bottom edge of the shell is no longer drawn, so the sidebar footer and the composer stop meeting a line at two different heights. - Admin pages scroll in one container; `/admin/prompts` no longer drops you at the bottom of a shorter panel.