Releases: Disble/autoreas-bridge
Release list
Autoreas Bridge v1.12.0
Added
- Keyboard shortcuts.
Alt+1throughAlt+0jump straight to the ten sections in the order the rail shows them — Today, Downloads, Editor, Catalog, History, Season, Devices, Activity, Notifications, Settings — andAlt+Rmarks the loaded notifications as read while the Notification Center is open. - Press
?for the list of shortcuts. It is built from the shortcuts themselves rather than written by hand, so it cannot drift out of date, and it shows the ones belonging to the screen you are on alongside the global ones. - Shortcuts stay out of your way while you type. Nothing fires from inside a text field, and any control that already uses a key keeps it: arrow keys still move through a table, and Escape still closes an open dropdown instead of triggering a shortcut behind it.
- Every shortcut is yours to change, under Settings → Shortcuts. The full list of shortcuts is the first thing on that screen — so you can find out what exists without having to know to press
?first — and each row rebinds by pressing the combination you want.Alt+is only the default now, not a decision made for you. - Getting out of a broken keymap never needs the keyboard. Any single shortcut reverts from its own row, and one button below the list puts them all back to the defaults, both reachable with the mouse alone. A combination already taken by another shortcut is refused while you are still pressing it, rather than silently stealing it.
- Your shortcuts travel with your backups. Exporting writes them into the bundle and importing restores them, and they take effect the moment the import finishes — no restart, no reload. A backup taken before this release simply leaves your current shortcuts alone rather than clearing them.
Internal
- Shortcuts are declared as data in one registry that the dispatcher, the conflict check and the help list all read, so adding one is a single entry rather than a key handler wired into a component. Two shortcuts claiming the same key is a test failure, not a silent loss. Recorded in
docs/adr/019-keyboard-command-registry.md. - Known limitation, deliberately not fixed: a keyboard layout with no Latin letters gets the digit and
?shortcuts but no letter ones. The one-line change that would address it is written down in the ADR and was left unshipped because no affected user is known. - A rebound shortcut is stored as one opaque document that the Go side never parses, so the chord vocabulary lives in exactly one place on the frontend and the backend cannot disagree with it. A round-trip test persists deliberate garbage to keep it that way. Recorded in
docs/adr/020-keymap-override-seam.md. - Shortcuts became the fourth backup group, and the first one whose contents are a single setting rather than a table — which is what made the import seam's granularity worth proving rather than assuming. Every import group now declares exactly which rows it may modify, and a test seeds two different states to catch an importer that reaches outside its own: without that two-state step a deliberately broken importer passes the check vacuously. Recorded in
docs/adr/021-portable-keymap-and-importer-footprints.md. - The pre-commit gate ran TypeScript's type check inside its group of cheap checks, where it starved the frontend test suite it ran beside — tests that take 454ms alone were taking almost six seconds and failing their budget. Type-checking now runs in the frontend lane instead. The gate takes the same wall-clock time as before and the type check itself got three times faster, having been starved too.
Autoreas Bridge v1.11.1
Internal
- The
autoreas-request-mcpdiagnostics sidecar no longer fails with a schema validation error when a search matches nothing.search_requestsencoded an empty result asitems: nullinstead ofitems: [], and because the tool validates its own response against a schema that requires an array, a legitimate "no results" came back as a hard error — indistinguishable from the tool being broken. Any filter combination that matched zero captured requests hit it, which is why it surfaced while investigating device-scoped diagnostics traffic. - The desktop application was never affected by the above: its own Wails binding already normalized the empty page before it reached the UI, so the defect only ever reached the MCP sidecar, which returns the reader's page shape directly. No user-facing behavior changes in this release.
Autoreas Bridge v1.11.0
Added
- Wire change. Paired mobile devices can now send their sync diagnostics to a dedicated endpoint,
POST /api/sync/diagnostics, instead of folding them into the body of a sync request. Each report is one sync cycle's post-mortem, and the bridge acknowledges it only once the record is actually stored — which is what lets a device delete its local copy safely. Documented indocs/openapi.yaml. - Diagnostic reports are stored with their cycle id, trigger and outcome as real, searchable columns rather than as an opaque blob, so questions like "how did the last background syncs end on this device?" can be answered directly instead of by reading raw request bodies.
- Every field on an incoming report is checked against a fixed list of permitted values, and anything outside it is rejected with the offending field named rather than quietly rewritten. Reports carry no free-form text at all, so nothing arbitrary from a device is ever persisted.
Changed
- Under database contention the diagnostics endpoint answers immediately with "try again shortly" instead of waiting for its turn. Diagnostics are the least important traffic the bridge handles, so they now yield to real sync work rather than competing with it, and a device that gets that answer keeps its report and sends it on the next cycle.
- Sending the same report twice is now harmless: the bridge accepts the repeat without storing a second copy, so a device that never received the first acknowledgement can safely retry.
Deprecated
- Wire change. The
client_telemetryfield on the sync reconcile request is deprecated in favour of the new endpoint. It is still accepted and still ignored, exactly as before, and is now declared and documented instead of being an undocumented field that no part of the bridge referenced. Mobile clients send it on both paths during the transition; nothing breaks when they stop.
Internal
- Recorded two defects found while verifying this release rather than fixing them here: the OpenAPI documentation gate reads only one of the thirteen registered routes and has therefore been passing without checking anything since the router moved to a table, and neither the bridge nor the mobile client bounds a request that stalls on the shared database connection, which is the leading candidate for the background syncs that run their full timeout in silence.
Autoreas Bridge v1.10.0
Added
- Every screen that comes back empty now tells you what to do next. Today, the Editor library and the Catalogue each answered "nothing here" with a bare line of text, and none of them could tell an empty collection apart from filters that hide everything — or from a request that had not finished yet. Each screen now shows artwork and the single action that fits what actually happened: "Create an anime" when you genuinely have none, "Clear search and filters" when they are only hidden. Today used to show its empty message before it had even asked what you had, inviting you to create anime you already owned.
- Loading now shows the shape of what is arriving instead of the word "Loading". Every screen in the app draws placeholder rows the size of the rows about to replace them, so the page no longer jumps when the data lands, and tables keep their header and column widths in place while their rows fill in. Screen readers are now told what is loading the moment it starts, on screens that previously announced nothing at all.
Changed
- Windows notifications now say how many anime a run is about, in their first line. Windows folds a notification's whole detail list into a single block of text and cuts it wherever it stops fitting, so a run that started three downloads could show only two and give you no way to tell. "Download run completed" was already safe because it opened with "3 episode(s) downloaded"; the others were not. A started run now reads "Download check started (scheduled) — 3 anime queued", and a run with failures says "2 of 5 animes failed to download" instead of "some animes failed". The count is in the part Windows cannot cut.
- A Windows notification no longer hands the system more text than it can show. A scheduled run naming fifty anime built a single 2,500-character message and left Windows to cut it wherever it liked. The list is now bounded before it is sent, so what arrives is predictable; nothing is lost, because the totals are in the first line and the full record is one click away in the notification centre.
- Long anime names are shortened inside Windows notifications so each one keeps to a single line. A name like "Nijuuseiki Denki Mokuroku: Eureka·Evrika" wrapped onto two lines and took the space two other anime would have used, which is why a run over three anime could look like a run over two. Names are now shortened with a "…" — never the line saying what happened to the anime, and never below the point where you can still tell which show it is. The full name is intact everywhere else, including the notification centre.
Fixed
- The empty-screen artwork no longer takes over the panel it is meant to decorate. It is authored at 512 pixels so it stays sharp on a high-DPI display, and nothing capped the size it was drawn at, so on Today the illustration filled the panel and pushed its own "Create an anime" button below the fold on an ordinary window. The empty card is now 328 pixels tall instead of 680, with the button on screen.
Internal
- Every loading branch in the frontend is now either a shape-mirroring placeholder or a shared
LoadingBars, and each one sits in arole="status"region named by ansr-onlyspan —statustakes its accessible name from the author, so a region named only by its contents announces nothing. Seven panels that already drew skeleton bars had exactly that gap, and were seven copies of the same markup; one shared component closed both at once. Seeopenspec/changes/archive/2026-09-08-loading-skeletons-completion/. - Three surfaces had written the placeholder as a block added above the content rather than one that replaces it, so a refetching screen stacked skeletons on top of the real cards. The tests could not fail on it: asserting that a skeleton appears and later disappears passes while both blocks render. The missing assertion is the negative — no real content while loading — and it is now on every surface, proved load-bearing by un-gating a content branch and watching it go red. The three-state rule (skeleton,
AirisEmptyState, error) is now mandatory in.claude/skills/autoreas-theme/SKILL.mdrather than conventional. - A placeholder's height is a contract, so a layout fixture measures every placeholder against the real row it stands in for, in headless Edge at two viewports — jsdom has no layout engine and passes a half-height placeholder. The same fixture had previously reported green on the oversized artwork by checking that it was present, non-zero and inside its card, all of which a wall of illustration satisfies; presence and containment are not proportion, and four proportion checks now run per composition.
frontend/src/test/setup.tsregistersafterEach(cleanup)once. Testing Library only does that underglobals: true, and 19 of 115 component suites had never registered it. Adding it unmasked zero failures.- Complexity attributed to this work by the changed-code gate was paid down by extraction rather than suppression:
SchedulePanel16 to 5,RunHistoryPanel17 to 7,SoloAnimeDownloadPanel16 to 3,useNetworkPanel23 to 14. - No wire change: the REST and WS contracts are identical to 1.9.0, so mobile clients need no update.
Autoreas Bridge v1.9.0
Added
- Two anime can no longer share a name. A name is how you find an anime in both search rails and how its download folder is chosen, so two records with the same name were indistinguishable in the app and collided on disk. Creating one now warns inline under the Name field as you type, and the catalogue refuses the duplicate outright — including when the existing record was only sent to the trash.
- The navigation rail now shows the app's own mark. The rail and the mobile header drew a generic bridge glyph while the taskbar, the installer and the tray all showed the "A". They now all show the same mark, traced from the same master image every icon is generated from, so they cannot drift apart.
Changed
- Wire change, additive — mobile clients are unaffected until they opt in. Each entry in
applied_operationsonPOST /api/sync/reconcilenow carries two optional fields:modified_at, the bridge's version token for that anime, andreason, which explains a rejected operation as eitherunsupported_operation(permanent) orconflict(retry after re-basing). Nothing was removed and no existing field changed shape, so a client that ignores them behaves exactly as before. Together they let a mobile client finally participate in conflict detection: until now it had no way to learn the token it needed to send back, so its writes always silently overwrote whatever the desktop had done. Announced indocs/openapi.yaml.
Fixed
- A sync conflict no longer discards the whole exchange. When the bridge rejected one operation for editing a stale value, the entire request failed and the client lost its list of applied operations, the pending changes it had not seen yet, and its place in the change log — for every other operation in the same batch. A conflict is now reported against the one operation it belongs to and everything else in the batch still lands.
- The bridge no longer sends a mobile client backwards through its history. Once every paired device had acknowledged the change log, the position the bridge reported fell back to zero, and a client that trusted it would restart from the beginning and re-download everything.
- Episode card actions on Today no longer misfire.
- Opening an anime folder now launches Windows Explorer by its real path. It was resolved through the user's
PATH, so anything earlier on that list namedexplorer.exewould have run instead. - Windows now draws a sharp app icon at every size. The icon shipped with a single 32×32 image, so Explorer's large and extra-large views, the taskbar on a scaled display, and the installer's own window were all upscaling that one small bitmap. The icon now carries 16, 24, 32, 48, 64, 128 and 256 pixel versions.
Security
- Paired-device tokens are no longer stored in the request log. The Authorization header was recorded exactly as sent, and a device token never expires and is never rotated, so every captured request held a permanent credential at rest — in a database that gets copied alongside its own backups. The value is now replaced before the record is written. The header name is kept, so the log still shows that a request was authenticated.
Internal
- The sync reconcile handler stopped treating a write conflict as a server failure. It had been converted into an error that aborted the batch and returned HTTP 500, which made the per-operation conflict outcome the API documentation already described unreachable — and untested. Conflicts are now reported per operation, a later operation for an already-conflicted anime that carries no version token is refused rather than allowed to overwrite silently, and the documentation was corrected to say this is new rather than long-standing. See
openspec/changes/archive/2026-09-04-sdd-66-occ-token-echo/. - Merge commits now run their own pre-merge gate. A merge of two independently green branches ran no checks at all, which is the one place a broken tree can appear without either side being wrong.
- The project is licensed under Apache 2.0, and the README was rewritten as a complete project reference.
- A long SonarQube sweep across both languages: duplicated string literals named, oversized signatures given parameter structs, single-method ports renamed after what they do, and the false positives marked at the call site with the reason.
- Every app icon is now generated from one master image,
build/appicon.png, bygo run ./tools/genicons, and a pre-commit check refuses a commit whose icons no longer match it. Two orphaned image files were removed: an unreferenced copy of the tray icon that still held the old pre-rebrand artwork, and the Wails template logo that nothing in the frontend imported. Seedocs/app-icons.md. - The repository root no longer holds 104 Go files. The desktop shell moved to
internal/desktopand the root keeps onlymain.go, which is all Wails actually requires besidewails.json. Nothing changed at runtime: no logic, no renamed symbol, and the bound surface the frontend calls is identical apart from its namespace (maintodesktop). Seedocs/adr/018-desktop-shell-package.md. - Release builds can no longer ship an unstamped version in silence, and the guard that promises it now works. Go ignores an
-ldflags -Xwhose symbol does not exist, so the failure is silent. Two checks shipped before this one and neither could report the truth:go version -mgreps the binary for the very flag the build just passed, so it could not fail; its replacement greppedgo tool nmfor a symbol a Windows PE keeps and a Linux ELF never carries, so it could not pass. The value is now read from inside the package by a test, which is exact on both platforms.
Autoreas Bridge v1.8.3
Fixed
- The software store now really does show Bridge's icon before you install
it. 1.8.2 claimed to fix this and did not: the package carried the store
metadata but never named an icon in it, and the image itself was installed
where the desktop menu looks rather than where the store looks. That is why
the icon was right in the applications menu and wrong in the store the whole
time. The icon is now declared explicitly and installed in five sizes where
both of them look, and installing the package refreshes the caches that
otherwise keep showing the old listing until you log out.
Internal
- No change to the application itself: the program in this release is the same
as 1.8.0. Only the Linux package metadata changed.
Autoreas Bridge v1.8.2
Fixed
- The Ubuntu and Debian software store now shows Bridge properly before you
install it. Opening the downloaded package used to show a generic gear
icon and "No details for this release", even though the icon appeared
normally once installed. The package now carries the metadata the store
reads beforehand, so it shows the real icon, a description, the publisher
and a link to the release notes.
Internal
- No change to the application itself: the program in this release is the same
as 1.8.0 and 1.8.1. Only the Linux package metadata changed.
Autoreas Bridge v1.8.1
Added
- Bridge now installs on Debian and Ubuntu. A
.debpackage ships next to
the archive. Install it withsudo apt install ./autoreas-bridge-1.8.1-linux-amd64.deb
and the system pulls in the WebKitGTK libraries Bridge needs, adds it to the
applications menu with its icon, and putsautoreas-bridgeon your PATH. The
previous archive shipped a bare program that stopped on a machine without
those libraries with a message naming a file rather than telling you what to
install. The archive is still published for distributions that do not use apt.
Removed
- The standalone Windows program is no longer published, only the installer.
Bridge registers itself to start with Windows, lives in the system tray and
expects a fixed install location, so a loose copy beside the installer was a
second, unsupported shape of the same application.
Internal
-
Releases are now built and published by GitHub Actions from a pushed tag,
covering Windows and Linux, with checksums for every downloadable file.
Development moves to thedevbranch;maincarries deployments only. -
No change to the application itself: the program in this release is the same
as 1.8.0. Only how it is packaged and delivered changed.
Autoreas Bridge v1.8.0
Added
-
Activity keeps its history now. The Runtime Events tab used to read a small
in-memory buffer that was emptied on every restart and trimmed to the last 200
entries. It reads Bridge's stored log instead, so what happened yesterday is
still there today. The domain filter also offers every domain the log actually
holds —download, the third busiest at 10% of all events, could not be
filtered for at all before. -
Transactions reaches the whole capture table. The tab loaded 25 rows and
stopped there, and the filters only narrowed those 25. Filtering now runs over
the full table and the list pages through all of it. Two controls changed as a
consequence: the status pills became an exact status field, and the free-text
box was removed — it searched under 2% of the data and returned misses that
looked exactly like real absences. Proper search needs backend support and
will arrive as its own change. -
A new Overview tab inside Activity summarises request health and events,
grouped the same way Bridge's own debugging tools group them. Captures with no
HTTP status — every WebSocket row, 40.8% of the table — are shown as
"No status" rather than folded into a zero. -
The Today tab strip marks the current day. Browsing to another weekday no
longer leaves you guessing which one today is.
Fixed
-
Saving anything in the Anime Editor no longer wipes the anime's scheduled
days. Eight animes lost their schedule between 2026-07-15 and 2026-08-29
this way, and seven were repaired by rescheduling them without anyone
realising why they had emptied. -
An anime cover can be removed again. Clearing the cover field and saving
did nothing at all: the removal never reached the backend in a shape it would
accept, so the old cover simply stayed. -
Activity no longer freezes a few seconds after you open it. The
Transactions and Notifications lists were paging themselves to the end of the
table with nobody scrolling, loading page after page until the window stopped
responding. Transactions also redrew every loaded row once a second to update
elapsed times; only the rows still running do that now. -
The Activity detail card stays inside the window. One long value used to
stretch the card until the whole application grew a horizontal scrollbar. Long
values now wrap and scroll inside their own panel, and the panels fill the
height the card already has instead of stopping short of it. -
Structured values in the Metadata tab read as formatted JSON instead of
[object Object].
Internal
-
Bridge's runtime log now records a domain that means something. Several
places wrote free-text prose where the log expected a domain, including one
that passed a whole sentence as the domain and a device id as the message.
Entries are findable by what happened and to what, rather than only by
searching message text, and a shape guard keeps new event types in the
domain.verbform. -
Two checks were added over the write log. One reports committed writes that
emptied a collection field they were never meant to touch — it found the eight
lost schedules above with no new instrumentation. The other measures how much
of the real anime write path is actually observed, as a ratio instead of a
count: the count had read as healthy while all 368 of its events came from a
test harness and 468 real writes committed silently. -
Wire note for paired phones: no REST or WebSocket shape changed. One
existing field changes behaviour.AnimeChange.changed_fields
(GET /api/animes/changes) and thechangedFieldsmember of the
anime_changedWebSocket notice have always shipped as an empty array because
no producer ever filled them; Bridge now derives the list inside the
transaction that commits the write. The field's type and required-ness are
unchanged, a client that ignored it is unaffected, and rows written before this
release keep reading as[]. Detailed indocs/openapi.yaml.