BoardRipper changelog

v0.50.2 — 2026-10-23

Added

five matching library files under the Library row — board number, file name

and folder, board or PDF — with a *N more…* spoiler for the rest. A click

opens the file; the Library row still opens the panel with the whole list.

copy and web search that searches the open PDF for the text under the

cursor.

Changed

with the selected part's name, *Find net* with a lit net's or a selected

pin's net — and the sidebar's Search tab follows whatever the ribbon field

holds. It used to send a selection to the linked schematic.

the query; otherwise the shortcut only focuses the field. It used to replace

the text with the board's selected part after the page had been dragged, and

re-ran the search, which jumped to another occurrence.

⌘D, ⌘P, ⌘O and the zoom keys never reach the browser, and a right-click on

the tab strip or any other chrome no longer opens its menu (text fields keep

it for paste).

Fixed

100 %, the ribbon's suggestion list, the context menus, the resize popup,

the link dropdown and the toolbar tooltips opened away from where they

belong — at 125 % a quarter of the screen to the right. They now land on

their field or pointer at every scale.

pointer until the button is released, over the toolbar, the sidebar or

outside the window; a scroll over the ribbon, the minimap or the slide sheet

moves the board; and the minimap only drives the view for a press that began

on it — it fades in under the pan being made and used to jump the view when

the drag crossed it.

auto-switch that brings the linked board forward left the board as the

active panel, so the shortcut answered with the panel the user had not

clicked.

the start never registered its find field, so the shortcut set the text

without focusing it.

panel is the active one the board panel is paused (no frames are drawn),

so a mode change made there — or any other change from the store — showed

only after the next tap on the board. The board now draws the frames such a

change needs and pauses again; a lookup from the schematic no longer leaves

it running until the panel is next activated.

a pinch.** Pressing the net-lines button changed the mode but drew nothing

until the next re-selection, and *off* left the old lines on screen; the

next recompute (a rotation, a camera restore, on a desktop a keyboard or

drag zoom) then wiped them, and the button could not bring them back. With

rotation unlocked, any pinch whose fingers twisted past 2° blanked the lines

for the whole gesture. Now a press redraws immediately, *off* clears, and a

live two-finger turn carries the lines with the board.

its selection orange and adjacent nets in blue, Atari in its orange and blue;

the dark schemes keep yellow and blue. The line colours in Settings ▸ Net

Lines apply on BoardRipper Default, and the row says so on a scheme.

change in Settings ▸ *this board* while Dark, Landrex, Light or Atari was

active saved the whole scheme as that board's overrides, so the board kept

the scheme's colours under BoardRipper Default. Cancel and Preview also

dropped the scheme until the next board switch. A board's own keywords and

part types now survive a scheme, and a scheme is in effect from startup, not

from the first board open.

board**: its body is washed in the highlighter colour, not the ink. Pin

numbers and net names on ink-filled pins (the *Ink pins* styles) are drawn

in white so they stay readable; the highlighter halo stops short of

neighbouring pins on fine-pitch parts; the spotlight dim fades toward the

scheme's colour instead of black; the minimap follows edits to a custom

scheme.

about 4.35:1). The ◐ and filter menus open in the window the PDF panel is in

when it has been popped out.

colours follow.

Docs

(rotation unlock 24°, the Rendering tab, 15 formats, dev port 8082, the

licence lines, and what shipped differently from the scheme spec).

v0.50.1 — 2026-10-11

Changed

did not show on paper (and on Atari it was the rail colour itself). The pins

of the selected net now sit on a yellow highlighter halo with a thin ink ring

and keep their own colour. Settings ▸ Selection & Highlight ▸ *Selected pins

on light schemes* offers two more: *Ink pins* (solid ink with a white rim)

and *Ink on highlighter*. The dark schemes and BoardRipper Default are

unchanged.

v0.50.0 — 2026-10-11

Added

Each of the four owns every colour on the board — pins, part bodies,

outlines, the selection, the dim and the copper:

  • Dark — near-monochrome: parts are grey outlines, every pin one quiet
  • grey, ground a dark teal, and colour only for what you select (yellow net,

    red part).

  • Landrex Classic (not new) is redrawn the way Landrex Test Link drew a
  • board: black, an olive board edge, lavender part outlines, every pin the

    same blue. Its old black-and-white look is gone.

  • Light — white sheet, dark ink, part tints from the same few hues as the
  • pins.

  • Atari (light) — the 2600's silver label and black ink, every colour
  • taken from the five rainbow-stripe colours.

    BoardRipper Default is unchanged and stays the default.

    power and nothing else.

    (a halo, or black/white text where the scheme's own would not read), the

    boxes behind net names follow the scheme instead of always being black, and

    the minimap is drawn in the scheme's colours.

    beside it. Besides inverting, it can darken the paper while keeping red and

    blue lines red and blue, or use exact background and text colours you

    choose. Two sliders handle coloured lines: *Colour* (down to grey, i.e. your

    text colour) and *Contrast* with *Auto*, which lifts pale lines so they stay

    readable on the new background. *Auto* is on by default for every style,

    including plain invert and night mode carried over from v0.49, so inverted

    pages now show pale lines stronger than before. The old plain invert is Auto

    off and Contrast at 0.

    Changed

    new ones. On the new schemes the dim appears only with a selection and fades

    toward the background instead of black.

    connector covering a third of the board is a tint, not a block.

    that had one of them selected opens in Light. A custom scheme is kept as it

    is.

    v0.49.0 — 2026-10-10

    Added

    zoom, the page is drawn at the preset's size; a moment after you stop, the

    part on screen is drawn again at the exact zoom. Fastest is now as sharp as

    Quality once the view settles — it was unreadable past 2×.

    whether the file is downloading, being read, opened or drawn; a file that

    cannot be opened says why. The banner over the board area covers PDFs too,

    and text indexing shows as "Indexing text 23 %".

    names: Quality, Balanced, Fast, Fastest.

    page. Fast and Fastest trade resolution, frame rate and trace corners for

    speed on tablets.

    board text renderer and diagnostics. It was System ▸ Performance & Debug.

    Smooth wheel zoom and two-finger rotation moved to Input ▸ Navigation.

    stored setting that left the board blank. Recent files, favourites, history,

    the session and PDF bookmarks are kept.

    Changed

    eight-step zoom settles in about 3 s instead of 6, and the page freezes for

    well under a second instead of three. Neighbouring pages are drawn only as

    sharp as they need to be, the same pixels are no longer rendered twice, and

    the pages you are reading stay ready instead of being re-read after four

    seconds.

    off screen, and empty part containers cost nothing.

    a selection or a rotation was redrawing every panel.

    Fixed

    the page into a canvas of about 700 MB next to a neighbour of the same size,

    more than Chrome's graphics memory. Canvas memory now stays near one screen.

    the fingers stop.

    no pin numbers or net names.

    first page about 300 ms sooner.

    v0.48.0 — 2026-10-05

    Added

    what the board file knows beyond its geometry. Today that is XZZ's

    "Common problems" boards: the repair table drawn on the board

    (symptom, fault point, fix) and the net glossary — what each net does,

    filterable, with the highlighted net's description at the top. Part and

    net names in it are clickable. The tab appears only on boards that carry

    notes, and it is plain text, so the browser's *Translate page* can

    translate the Chinese.

    selectable and part of their net — on the iPad Air 3 boards a net that

    showed only a BGA ball now shows its probe point too. Records that only

    repeat an existing pin are left out.

    files found sits above the tree; a click opens the branch, selects the

    file and scrolls to it. A folder with a hit also shows its other files

    (the schematic next to a board, say), dimmed, behind a toggle when there

    are more than five.

    Changed

    icon buttons beside the name, one line says what the file is, and the

    rest (facts, path, *Edit metadata*, *Mark as donor*) is behind

    *Details*. OpenBoardData takes two lines. The pane scrolls under a fixed

    header and takes at most 45 % of the Library.

    Fixed

    none before, over a thousand now), files carrying both reading formats

    keep both, and renamed parts keep theirs. Across the local test library

    the number of readings roughly doubled.

    read correctly instead of being dropped; Ω values show.

    the whole window when switching board tabs. Fixed throughout, with a

    recovery page for any crash outside the panels.

    90° turn rebuilt the whole scene. It now only moves the labels that

    depend on the turn.

    because the flip's own work made the press look long.

    statistics) or fail the library load (donor list).

    v0.47.0 — 2026-10-04

    Added

    as a PNG — for a repair ticket, a message to a colleague, a lesson. Draw

    arrows, boxes, freehand with a pen, and text in five colours and three

    weights; everything stays pinned to the parts while you pan, zoom or

    rotate. Every selected part gets a large label with its name, and

    ⌘+click (Ctrl+click on Windows, or the *Several parts* toggle on a

    tablet) labels several at once; under the label of the part you picked

    last are two boxes to note an Ω and a diode reading, which print on the

    label. The PNG carries the board file name and the date in a header, the

    labels, your annotations and the minimap. Copy puts the same picture on

    the clipboard. A guide card explains the tool in hand; Esc leaves, and

    the annotations come back when you return.

    eighth of the screen fades in a small map of the whole board at the top

    with a box for what you are looking at — click or drag on it to move.

    It leaves when panning stops, stays up in slide mode, and the ribbon

    button turns it off.

    with the watermark text filter and its terms, *Strip small watermark

    images* (which had no control before) and *Skip invisible content*.

    The two parse-time options show a *Reload & re-parse* row when an open

    PDF was opened under other values; page, search and extracted text

    survive the reload.

    a second one to open its menu. Any touch outside closes it.

    Changed

    a page-sized invisible overlay that pdf.js still decoded, rasterised and

    composited on every render — 100–190 ms per render on an iPad. It is

    dropped before it reaches the renderer; the picture is pixel-identical.

    Fixed

    pixels already existed, the viewer put the blurry preview on top of

    them for a moment, and in Safari a cleared tile could reach the screen

    for a frame. Both causes are gone.

    active panel, a wheel over the board took the zoom and drew nothing. A

    regression from July.

    boards; it now says the server was updated and offers a reload.

    are back.

    a zoom change; a failed strip left a permanent "reload needed"; a term

    typed in the filter menu and clicked away from was lost.

    v0.46.0 — 2026-09-29

    Added

    ⌘] forward again (Ctrl+[ / Ctrl+] on Windows and Linux) — across boards

    and PDFs alike. A visit is a part or pin you clicked, a PDF lookup in

    either direction, or a search and the result you picked from it. The

    view comes back exactly as you left it, not re-fitted. Going back and

    then somewhere new deletes nothing: the path you left is still there.

    The board ribbon has ‹ › buttons for touch screens; hold one for a list

    of where it leads.

    by file. Click a row to go there. Filter by kind — clicks, PDF lookups,

    searches, viewpoints — and by boards, PDFs or just the board in front of

    you. A row for a file you closed reopens it from the library. The

    history survives a reload.

    places you looked at with nothing selected are kept too: a region of the

    board, a PDF page, another board tab. Only a place you stayed on for two

    seconds counts, so paging through a document leaves one row.

    your recent searches when you click into them; typing narrows the list,

    ↑↓ and Enter pick one.

    Fixed

    Enter or ⌘F after panning away did not bring it back, and a drag that

    was still gliding pulled every jump off its target.

    v0.45.0 — 2026-09-28

    Added

    board about the point between them, live. Rotation starts locked: a turn

    under 12° does nothing (every pinch turns a little), a turn past it

    unlocks — a toast says so — and the board turns on from there. The angle

    is kept when the fingers lift, snapped to the nearest right angle when

    within 10°; the rotate buttons step to the next right angle from any

    angle. A double-tap with two fingers locks rotation again and squares the

    board. Settings ▸ Performance & Debug ▸ Two-finger rotation turns it off,

    and the unlock angle and the snap window are sliders there (a snap window

    of 0 never snaps). In Butterfly the whole spread turns as one picture.

    v0.44.0 — 2026-09-28

    Added

    browser turns Shift+wheel into a horizontal scroll before the page sees

    it, and both viewers took it for zoom. The three scroll slots — plain,

    Shift, ⌘ — are now independent, for the board and the PDF alike, in

    Settings ▸ Input and on the start page. A fresh install gets Shift = Pan,

    ⌘ = Zoom; an existing install keeps the layout it had, and the start page

    offers the one-click switch.

    boards showed the button and it did nothing. Traces, vias and copper

    pours are hidden while Butterfly is on — they belong to the board as a

    whole, not to a side — and a toast says so.

    freezes the page while its scene is built — a second or more on a

    tablet, during which a finger on the glass gets no answer at all. A

    "Loading …" banner now sits at the top of the board area from the moment

    the file is opened until the new board is on screen, and it is painted

    before the freeze begins.

    smoothing (MSAA), on by default. Off saves GPU work on a machine that

    cannot afford it, at the price of jagged thin lines.

    build at ripperdoc.de/boardripper/legacy-web, and a supported-devices

    page lists browsers, iPads and iPhones by model. A browser below the

    floor now sees a message with the minimum versions instead of a blank

    page.

    Fixed

    sub-variant (Jasper_Kronos) drove a rewrite of the pad walk. Pads come

    from the pad ring with the pin numbers the file carries — the old walk

    invented 1..n in file order, which swapped pins 1↔3 on every SOT-23 and

    1↔2 on every diode — and drawing symbols no longer become empty parts

    that blew up the board bounds. Against Allegro's own v17 re-save of the

    same board: 7982 of 7982 pins, 7910 nets agree, none disagree.

    URLs pdf.js was given for its character maps, standard fonts and wasm

    decoders pointed at nothing in every build; only the dev server worked.

    PDFs with non-embedded fonts or JPEG 2000 / JBIG2 images render now.

    on, a tap while the board was still gliding stopped the glide but selected

    nothing, which read as "sometimes a tap can't select a component". A tap

    during the glide now selects the part under it.

    used to answer the same hold with its own callout and cancel the touch.

    The first board opened on a touch screen says so once.

    turned off edge smoothing for the board, which left every thin line —

    the board outline first of all — jagged and at an uneven width. Edge

    smoothing stays on; the profile keeps its 60 FPS cap and 1.5× render

    resolution ceiling.

    bottom silkscreen out of the shared silkscreen layer to mirror it with the

    bottom half, and the toggle stopped reaching it there — the silk came on

    with Butterfly and could not be turned off.

    is cleared every frame, so it never showed anything.

    v0.43.4 — 2026-09-23

    Fixed

    seconds on a tablet.** After a tap lookup the board used to redraw every

    pin of the lit net thirteen times over three seconds — to blink the outline

    of the selected part, which is the only thing the blink changes — and force

    a full redraw of the whole board each time. On a large board that was the

    5–10 s of unresponsive pan and zoom after tapping a reference on an iPad. A

    net lookup no longer blinks at all (there is nothing to blink), and on a

    board where one redraw is already expensive the part lookup flashes once.

    once and pulsed, instead of being rebuilt on every frame.

    v0.43.3 — 2026-09-23

    Fixed

    for an update when the page was loaded fresh, which an iPad tab or a

    home-screen app almost never is — one was still running 0.40 three releases

    later. It now checks every time you come back to it, when the connection

    returns, and once an hour, and offers the usual *Reload*. A device already

    stuck on an old version needs one real reload (or a full quit and relaunch

    of the home-screen app) to pick this up; after that it stays current.

    v0.43.2 — 2026-09-23

    Fixed

    few zooms, panning only worked with two fingers. When the tablet's own

    gesture recogniser claimed a pinch before the second finger had registered,

    the board paused its one-finger drag for the gesture and never resumed it.

    It now resumes the moment the last finger leaves, whichever path handled

    the gesture.

    v0.43.1 — 2026-09-22

    Fixed

    server down or restarting, the Library said "Library is empty — no files

    indexed yet" and offered the scan button for as long as the request hung,

    then switched to the unreachable notice. It now says it is loading until

    the server has answered, and "empty" only once the file list has actually

    come back empty.

    promise a retry that never happened; a reload was the only way back. The

    app now retries on its own, at 2, 4, 8, 15 and then every 30 seconds, shows

    the current interval, and offers a *Retry now* button. When the server

    comes back the library loads without a page reload.

    fine, now says so and offers a Reload instead of either a spinner or a

    false "empty".

    Maintainers

    behind it, one transition per load — are in CLAUDE.md under status

    messages, with a spec that samples the panel over time through three ways a

    backend is unreachable in the field.

    side in the PDF search bar): docs/specs/2026-09-22-pdf-search-slots-mockup.html.

    v0.43.0 — 2026-09-22

    Updates on Docker Compose installs

    Docker installs were affected: any container on a user-defined network,

    which is every docker compose up and every Synology Container Manager

    *project*. A plain docker run on the default bridge always updated fine.

    The health check that decides whether a new version is alive ran from a

    helper container on the default bridge, and Docker drops traffic between

    two bridge networks, so the check timed out and the update was undone

    every time. The helper now joins the app's own networks and tries every

    address that could answer: the container's IP, the host at the published

    port, and the container name.

    update-orchestrator.log in the data directory, and a rollback keeps the

    failed container as <name>-failed instead of deleting it, so its log can

    be read afterwards.

    back cannot update itself onto this fix, because the drop-to-update bundle

    uses the same helper. Pull the image once by hand — `docker compose pull

    && docker compose up -d`, or Container Manager ▸ project ▸ Build — and

    in-app updates work from then on.

    Touch screens

    Every browser on iPadOS is WebKit, Chrome included, so these apply to all of

    them.

    under the first finger, jump, and land somewhere other than where the

    fingers were. iPadOS hands a two-finger gesture to its own recogniser and

    cancels the first touch before the second one arrives, which the board

    read as a tap; and both the board and the PDF viewer ran two zoom

    handlers on the same gesture — one for trackpad gestures, one for fingers.

    One handler owns a gesture now, a cancelled touch is never a tap, and the

    zoom follows finger distance exactly: the same spread gives the same zoom

    however fast the fingers move, and pinching in then out lands back where

    it started.

    the other and the page used to slide away from the finger that never

    moved, by up to 140 px. The zoom is now anchored on the moving midpoint

    in both viewers.

    still, so the board allows 12 px of travel for a touch against 5 px for a

    mouse, measured as a straight line rather than the sum of the two axes,

    which had rejected diagonal taps. A part that stopped responding to taps

    after being deselected from the net list or a worklist responds again.

    the page used to keep going onto blank paper; it now flips pages, and so

    does a flick. Flick inertia had never actually run, on any platform. A

    gentle flick carries a few pages, a hard one reaches the end of the

    document.

    second visible page did nothing on the iPad, because that page was not a

    touch target. One surface now takes every touch on the panel.

    while pinching, as one does when holding a tablet, matched neither the

    pan nor the pinch path.

    pinch and halved the frame rate on a large board. A single resting finger

    still reads a pin's net and diode value.

    without multisampling and at a capped render resolution; text keeps full

    resolution. The PDF viewer defaults to the *medium* quality preset and

    halves its cache budgets where the browser does not report device memory,

    which is every iPad. Settings ▸ Performance & Debug ▸ *Touch performance

    mode*. An iPad with a keyboard and trackpad, which reports a mouse-like

    pointer, is detected too. No effect on a desktop machine: wheel zoom,

    hover and clicking are measured unchanged.

    the page from 100 % to 739 %, because the handler took the event for a

    trackpad pinch. One notch is now about 2.4×, the same as on the board.

    Web and offline builds: a folder is the library

    single-file offline build had no library at all, only the file picker.

    Choose a folder, or drop one on the window, and it is indexed in the

    browser: the Library panel, the Board# and Folders trees, recents and

    worklists all work as they do with a server. Nothing is uploaded anywhere.

    remembered; opening a file after a reload asks the browser for access

    again, in the same click, and "Allow on every visit" or installing the

    app makes that permanent. Firefox, Safari and the iPad cannot remember a

    folder, so there the list comes back and the folder is asked for on the

    first open. A board opened once reopens from the cache with no folder

    dialog at all.

    the home folder, Desktop, Documents and system folders without a word of

    its own; the app now names them. A folder with no boards or PDFs says so.

    .brd file was labelled BDV, because three formats claim the extension.

    Ambiguous extensions are settled by reading the file header.

    Maintainers

    container at rd-nas:1234, the touch-screen test target; --test runs the

    WebKit iPad suite against it.

    descriptor. Every board PDF in the repo is proprietary, so the PDF specs

    had been skipping on a clean checkout; two generated PDF fixtures make

    them run.

    against a real Docker daemon in three topologies: Compose network, host

    network, and a new image that never serves.

    v0.42.0 — 2026-09-18

    Worklist

    one line naming the open worklist. Click it and you get a cursor: the

    worklists you touched most recently are listed, and typing searches them,

    across other boards as well as this one. New worklist, Paste a worklist and

    All worklists sit underneath.

    worklist takes the name you typed in the search, or opens for renaming if

    you typed nothing. Clearing and deleting ask in the panel itself.

    boxes whether or not anything had been measured, so ten nets were twenty

    lines of which ten were empty. A net now shows only the readings it holds,

    and the empty boxes open on the row you have selected, which is where you

    are about to measure something. Click away and they fold back.

    colours that were not the app's, so it stayed dark while everything else

    changed.

    you could not act on. Rows now say how much is in a worklist, how much of it

    is marked done and when you last touched it, and a worklist on the open

    board switches to it. One belonging to another board says which board.

    flags, the reference, the note, remove — all of it, in the same order.

    One slider, with or without a switch

    values, part names, type colours, dashed net lines and the HDR outline each

    used to be a toggle plus a separate size slider (some of the sizes only in

    Interactive mode). Each is now one slider: click the thumb or the row's name

    to turn the thing off — the row greys out and keeps its value — drag to set

    the size. Plain sliders look the same; only the on/off ones react to a click.

    Same control in Settings and in the Interactive-mode popups.

    of the board says so and carries a *Done* button — the mode repurposes a

    plain click, so the switch that ends it sits where the clicks happen, not in

    Settings.

    corner cell that continues into the activity rail below it, the global search

    spans the bar from top edge to bottom edge, and the bar's icons are one size.

    The board panel's own sidebar follows: its tabs and the ☰ toggle are one

    flat 40 px row with the same darker corner cell, instead of a floating chip

    over the tab strip.

    Selected part's pin labels no longer overlap

    one of its pin labels to the "Selected Part Labels" size, and on a dense part

    they overlapped each other. The selected part's pin labels now sit at 0.8 of

    that size; the selected pin, the pin under the pointer (on any part) and the

    part name keep the full size. The fraction is adjustable — Settings ▸ Zoom

    Level of Detail ▸ *Other Pins of Selected Part*, also in Interactive mode.

    Zoom Level of Detail) defaults to 8 px instead of 3 — at 3 the names showed

    at half zoom, unreadable and covering the whole chip. An install that never

    touched the value gets the new one; a changed value is left alone.

    pin and cannot overlap, so it now has its own, lower appear-floor ("Pin

    Numbers", 5 px) and is drawn centred in the pin until the net name shows —

    then it moves aside to make room, on the same zoom step the name appears.

    name is capped at the size that fits between the part's pin centres, so a

    selected BGA's labels cannot overlap; a label that would have to go below its

    appear-floor to fit is hidden. The pin you point at is exempt. Settings ▸

    Zoom Level of Detail ▸ *Fit pin labels to pitch*.

    labels swell into view past their appear-floor — the same mechanism as the

    part-name fade, at the small end. *Label Fade-In* in the same section; 0

    restores the pop.

    Fixed

    so they had been failing since the icon rail replaced it.

    Maintainers

    emulation. Its output is the same JavaScript for every target, and the

    emulated path was a coin flip: esbuild's install step runs its own native

    binary to check it, and that segfaults under QEMU — it failed this release

    once on dependencies that had not changed since the last one. Multi-arch

    builds are also about six times faster for that stage.

    v0.41.0 — 2026-09-14

    A fresh install that shows something

    after a scan started and the panel still waited for the scan to end — five

    minutes of an empty list on a 60,000-file library. The list now refreshes

    during the scan (5, 10, 20, 40 seconds in, then every minute).

    anything until someone found *Scan now* in Settings. The first visit now

    shows what is mounted, explains the two indexes — files now, PDF text in the

    background afterwards — and starts the scan. Two options, both on: link

    boards to their PDFs automatically, and download the OpenBoardData readings.

    A database reset reloads the page and the setup comes back.

    the port closed for ten seconds on every start.

    Linking boards to PDFs

    name; a similar name (at least 75 % of the shorter name's words, within the

    same folder by default); the only PDF in the folder (by default only when it

    holds one board too). Settings ▸ Library shows the ladder with a Preview

    — how many links each rule would make, with examples — before anything is

    written, and every link remembers its rule so the links one rule made can be

    removed together.

    which is why it was off by default. Rules 1–2 are lookups and rules 3–4 only

    look near the board's folder, so it can be on.

    every PDF in the library; with 7,500 it blocked for a quarter second to open

    and on every keystroke. It shows 200 and the filter narrows the rest.

    OpenBoardData

    couple of minutes — so readings are already there when a board is opened.

    only by a number in the filename.

    Comparing a component across two boards

    every pin that is not a plain match — red where the boards disagree, amber

    where the net is the same one named differently. Plain matches stay unmarked

    so the ten pins that matter are not buried among the 390 that agree.

    name and its net for that pin, coloured the same way as the mark.

    labels the pin's state and is stripped before names are compared, so

    NC_GPU_TRIGGER1_L and RSVD_GPU_TRIGGER1_L read as one signal. Two no-connects

    that carry different names are shown as a partial match, not as "no

    difference" — the pin may have been repurposed between models.

    against PP3V8_AON_MPMU_ISNS_VIN), and a rail's fanout no longer counts as

    evidence against a match — across two boards it differs by design.

    Library

    identical file already in the library is reported as existing; a same-named

    file with different bytes is saved as "name (n)", never overwritten. Dropped

    PDFs are indexed at once instead of waiting for the next sweep, and the

    Library merges the new rows instead of re-streaming the whole list.

    Docs

    lives in src/backend; the Vite proxy targets port 1336), the Synology

    docker run carries --user 0:0 and the incoming mount, the tarball name

    matches what the release script produces.

    v0.40.0 — 2026-09-12

    Comparing a component across two boards

    by pin. Pick a board and a component on each side. The two sides do not have

    to carry the same name — a chip can sit at U1700 on one board and U6800 on

    another, and comparing those is the interesting case once you leave one board

    family.

    lists the other open boards that carry the same name and fills both sides in

    with one click. "Compare with…" fills in only this side, for when the other

    board calls the part something else.

    often disagree only about naming — one carries PPBUS_G3H where the other

    carries N$21004. When the names differ, BoardRipper looks at which components

    each net actually touches. The same components means the net was renamed, and

    the row says so instead of reading as a fault. Rows where the wiring itself

    differs are marked separately, so a board full of renames does not bury the

    one pin that changed.

    two share marked in both. PPBUS_G3H against PPBUS_G3H_R is one rail written

    two ways, and marking what they share leaves your eye on the bit that

    differs. This only applies where one name contains the other, or where they

    differ only in punctuation — SMC_RST_L and SMC_RST_R are two different nets,

    not one, and are still shown as a difference.

    any pin where the two readings drift apart. A pin that agrees on its net but

    disagrees on its reading is usually the one you were looking for.

    number pins in the order they happen to appear in the file rather than by the

    pin on the package, so two files of the same board can number the same pads

    differently. BoardRipper tries the pad names, the numbers, the file order and

    the pad positions, and keeps whichever best explains the nets and the copper.

    It shows which one it used and how well it fit, and you can pick one yourself.

    mirrored. When the net names give no clue which way round the part sits, the

    pairing is a guess, and the tool says so rather than presenting it as fact.

    It also warns when the two footprints are too different in size to be the

    same package.

    one comparison you can mean. The components stay blank — which chip to look

    at is the actual question.

    on the clipboard. Widen the sidebar and the two sides get their own columns.

    Top bar

    pixels off its own grid, which was small but hard to unsee. It now shares

    the column's width and icon size, so the two read as one edge.

    had to hover to learn.

    version and the word Update, so it reads as something to do rather than a

    number that changed. The badge keeps its width while it swaps, and with

    reduced motion it simply says Update.

    Sidebar

    column as a pin, above the status bar button: pinned means the panel stays

    in the layout, a crossed-out pin means it floats over the board and leaves

    when you click into it. It was only in the right-click menu before, which is

    not where anyone looks for a mode. The menu item and the setting still work

    and show the same state.

    not what a click would do. Hovering used to show the opposite of the current

    setting, which read like a description of how things already were.

    Fixed

    the board, but it was also landing as a shift+click on whatever sat under the

    cursor, so zooming quietly filled the worklist with parts you never picked.

    Shift+click still adds and removes as before.

    Maintainers

    container, which retargets pointer events away from the canvas. PixiJS

    listens on the canvas, so it decides the pointer left and emits

    pointerupoutside; pixi-viewport reads that as the end of a gesture it

    believes never moved and fires clicked during the drag, one move in.

    The release-time latch that was supposed to swallow it therefore ran too

    late — and stayed armed, eating the *next* real click. Fixed with an

    in-gesture flag, a pointer-travel test for clicks emitted at release, and by

    clearing the latch on pointerdown. Regression: tests/shift-drag-worklist.spec.ts.

    no stores — so it can back an MCP tool later without a browser. The tool

    reads the raw parse, never the derived view: deriveBoardView filters parts

    and rebuilds nets, which would let a view filter shrink a topology

    fingerprint and turn a rename into a difference.

    panels/tools/tools-nav.ts so the right-click can navigate to a tool.

    one. _resolveAdjacentNets was split into a tab-scoped _adjacentNetsFor —

    the old form resolved the chain against the active tab's netlist, which was

    unreachable before and wrong for a background tab.

    compare-row + data-status.

    v0.39.2 — 2026-09-10

    Allegro boards

    keeps a parsed copy of every board it has opened, and it was handing back

    the old copy instead of reading the file again. So if you had already opened

    an Allegro board, nothing changed for you in 0.39.1 and there was no sign

    anything was wrong. Boards are re-read once after this update.

    planes — were never read, so Allegro boards showed bare traces over an empty

    board. Turn them on with "Copper fills" in the Layers panel.

    files describe a part in full — its name, its type, every pin and net — but

    never say where it sits. On one Lenovo board that is 67 parts, among them the

    battery charger, the graphics power controller, both memory sockets and every

    edge connector. Cadence's own viewer does not show them either, so on a board

    like that the parts you most want to probe were the ones nothing could point

    at.

    BoardRipper now finds them by following their own copper: a track that ran to

    a missing pad still stops where that pad was. 23 of the 67 come back this

    way, each pad within a thousandth of an inch of where it belongs. They are

    drawn with a dashed amber outline, because their position is worked out, not

    read from the file, and you should always be able to tell the difference.

    Parts with too little copper to go on — mounting holes, mostly — are left

    out rather than guessed at.

    v0.39.1 — 2026-09-09

    Allegro boards

    Allegro board units byte" message. The file's version line sits in one of

    two places depending on which Allegro 18 wrote it, and BoardRipper only

    looked in one of them. It now finds the line in either place, so these

    boards open. Seen on Compal LA-P161P.

    their copper layers from zero, both sides landed on the same layer, so the

    Layers panel could not tell them apart and every trace was drawn in one

    colour. Each side now gets its own layer, with its own colour, and can be

    turned on and off on its own. Which side is which was checked against where

    the traces actually meet their pins.

    v0.39.0 — 2026-09-08

    Toolbar and board bar

    (Top / Bottom), Butterfly, Rotate left / right, Traces and the rarer

    transforms (180°, mirror, flip axis, under ⋯) moved from the top bar into

    the board's own control bar, where they lead the row. They act exactly as

    before, with the same keyboard shortcuts. The top bar keeps the sidebar

    button, Open, search, 2-window mode, About and the version. Search sits in

    the centre and says what it searches.

    front of your arrangement, not inside it. Hide any of them with a

    right-click on the bar.

    Left, Centred or Floating (then drag it by its handle to wherever it does

    not cover the part you are working on), and Orientation Horizontal or

    Vertical. Both are remembered.

    magnifier with a chip or a net inside, so the column stays one button

    wide. Click one and the field pops out beside the column; Escape or a

    choice folds it back. The horizontal bar keeps the plain fields.

    under the field, and opens upward when there is more room above.

    XZZ boards

    iMacs the two halves of the board are drawn edge to edge, so the file holds

    them as a single shape and parts run right up to the seam. BoardRipper read

    that as one board, so "Folded" and "Show all sides" were two names for the

    same picture and an edge appeared to run from one half into its mirror

    image. These files now split at the seam and fold like every other board.

    around it. Both halves running the same way means the bottom is mirrored

    across the seam. Opposite ways means one half was drawn as seen through the

    board, and the bottom is moved onto the top instead.

    recognised and left alone.

    fold.

    Fixed

    version.** Its light tiles were fetched from a fixed address that only

    exists on the Docker install, so on the desktop app, the hosted browser

    version and the offline single file the outline quietly drew nothing.

    Butterfly on, a scene rebuild destroyed the dim layer that shades the

    unselected half and re-added the dead object next time, which stopped the

    render ticker; every button then looked fine but nothing on the board

    responded. The layer is now detached before the rebuild like its siblings.

    Moving, folding or re-orienting the board bar also no longer rebuilds the

    scene at all: those settings are pure layout.

    Sidebar

    below the tab strip, so you can switch boards while it is open, and in a

    split layout it stops above the lower group's tabs as well.

    Board panel

    where the Classic Mac collapse box was, rolls the whole bar up into itself

    and the board gets the room. Click the handle again to bring it back. The

    choice is remembered.

    the tab's name under the icon when you hover, the same way the rail does.

    any button, put the row on the left or in the centre, fold it, or reset it.

    Settings ▸ Board ▸ Board overlay is now one list with names: an eye to show

    or hide, arrows to reorder, and a × on separators. New buttons added in

    later versions land where they belong in the row, not at the end.

    Revisions and Worklist are now the same icon cells as the Library and

    Settings tabs: icons stay where they are, the open tab's name sits

    underneath.

    you opened the panel and was not useful. The ☰ now only opens and closes

    the panel.

    v0.38.0 — 2026-09-07

    Sidebar

    icons — Library and Tools at the top, Debug and Settings at the bottom —

    stays on screen whether the panel is open or not. Click an icon to open it,

    click the active one to hide the panel. The rail shows what is waiting for

    you: new errors in the log, a failed library sync, an available update.

    only, and nothing at all. The last state hides the status bar too and

    brings the small arrow at the screen edge back as the way home. The update

    badge and Library links reopen the panel from any state.

    position, expanded folders, search text and the tool you were in. Whether

    the sidebar was open, and on which tab, now survives a reload.

    navigation. The panel opens over the board instead of pushing it aside, and

    hides again when you click into the board. The board never moves.

    rail, in the status bar's own row.

    Text tabs. Side, captions and auto-hide are set there as well, for touch

    screens that have no right-click.

    Library and Settings tabs

    tab's name sits under its icon. Before, Settings put the name next to the

    icon and pushed the other tabs along.

    Maintainers

    data-library-tab and data-settings-tab, never by visible text.

    plan docs/plans/2026-09-07-activity-rail.md.

    v0.37.4 — 2026-09-07

    Selection

    outline keeps a minimum size on screen (Settings ▸ Selection, default 24

    px) so a small part does not shrink to a dot. Zoomed in, it sits exactly on

    the part outline. The line is a fixed width on screen (the selection width

    setting, in pixels now) and no longer grows into a band as you zoom in.

    The outline is redrawn on every frame the zoom changes, so it does not lag

    behind the board, and zooming with a large net lit costs the same as with

    nothing selected.

    highlighted net, search hits and the ghost outlines keep the fixed padding

    and width from Settings.

    selection outline hugs the pads. The gap that stayed even at 0 padding is

    gone.

    Diode readings

    above that green, and OL blue. The colours are set in Settings ▸ Diode

    readings.

    is never dimmed. Pin numbers, net names and single-pin designators stay

    hidden.

    XZZ board packs

    results, the net list and the info panel aimed the camera at the part's

    position in the file, not where it is drawn after the board is folded, so

    on iPhone files the view flew off the board or showed the wrong half.

    Maintainers

    v0.37.3 — 2026-09-05

    XZZ board packs

    and bottom side by side, and iPhone files pack two or three boards into one

    file. The parser now finds the boards, pairs the halves and folds each

    board, including pads, silkscreen, traces, vias and test pads. Before, only

    parts, traces and the outline were folded when you picked a board, and a

    notch or a cutout in the outline could break the pairing (iPhone 5, XS Max,

    6/6s/8) or fold a file across two physical boards (XR, iPhone SE).

    sides visible. The folded view is one click away in the board panel, and

    that is where "Swap sides" acts.

    traces, otherwise from the exporter's layout rule. Checked on the whole

    corpus. The old rule (the part with the most pins is on top) was a coin flip

    on iPhone boards and is no longer used.

    board.

    Library

    model, not by 820-number, and 124 of the 213 iPhone files in the corpus

    landed in "Unrecognized". The scanner now reads the model from the folder or

    the file name and groups the files under it. A model from the path beats the

    "unsorted-apple" placeholder in the board database, and an 820-number in the

    name no longer reads as an iPhone generation. Already-scanned files are

    re-resolved on the next scan.

    Selection

    outlines (XZZ iPhone files, TVW, Allegro) the yellow box around a part on

    the highlighted net sat a full pad outside the part border, and the gap did

    not follow the selection padding setting. Dense parts (BGA, fine-pitch QFN)

    had a smaller version of the same gap. Border, selection, hit box and halo

    now use one rule.

    Start page

    It is always shown, with the detection result on the right and a small

    mockup of the outline with and without HDR. The "Your monitor supports HDR"

    prompt is gone.

    and wrapped list items and bold code rendered broken.

    Landing page

    menu, with the latest version line.

    v0.37.2 — 2026-09-04

    A release for the browser version and for tablets. The browser build at

    ripperdoc.de/boardripper/web has been picking up users, and on an iPad it had

    one bug that blocked it outright and several that made it feel unfinished. All

    of the touch work applies equally to a Docker install opened on a tablet.

    Browser version, on a tablet

    extension to a system type; none of the boardview extensions are registered

    on iOS, so the Files app greyed out every board. Browsers no longer get an

    accept filter at all — the format is detected from the file's contents

    anyway. Select a board and its schematic together and both open.

    did not exist on touch. Hold half a second on a part or pin.

    Upload button, the only way in on a tablet, included. On touch devices the

    toolbar is now 60 px with 44 px buttons; mouse layouts are unchanged.

    but not a locally-opened PDF, and iPadOS discards background tabs often. PDFs

    opened from the picker are now kept (up to 6 / 256 MB) and come back with the

    board.

    window mode" is hidden where a pop-out window cannot exist (touch, and the

    offline single file).

    Browser version, first run

    of the start page. The sample is a real routed board (Tomu FPGA, KiCad,

    CC-BY-SA 4.0 — see THIRD_PARTY.md). The Docker and Library sections of the

    getting-started text are no longer shown in the browser build, which has

    neither.

    icon instead of a page screenshot, and the install manifest carries the PNG

    sizes Chrome expects. Installing also exempts the app from Safari's seven-day

    storage cleanup, so settings and cached boards persist.

    next load, which could also break a page that was open across the deploy.

    Now the app shows "A new BoardRipper version is ready" with a Reload button,

    and the swap happens when you reload.

    Smaller and faster

    glyph-overlay font parser load on first use instead of on every visit.

    Now once, minified: 2.2 MB → 1.2 MB, and the offline precache 7.0 → 5.2 MB.

    thread, so a large Allegro or Altium board no longer freezes the tab.

    Diode-only mode

    now hidden along with pin numbers and net names. Designators on part bodies

    stay.

    v0.37.1 — 2026-09-04

    Diode-mode reference readings now come through on the current generation of XZZ

    boardviews, and there is a way to actually read them on a dense board.

    Formats

    after the v6v6555v6v6 marker, and BoardRipper only understood the older of

    the two encodings that live there — newline-delimited =<mV>=PART(pin)

    records. Current deliveries (the iPhone-era files) put a JSON document there

    instead, so every one of them reported no readings at all. Both encodings are

    now read, chosen by content rather than by file name.

    On iPhone16_16Plus AP+BB Boardview.pcb that is 4750 readings where there

    were none, landing on 4195 pins. Its sibling …AP+BB YiDianTong.pcb is the

    same board delivered without diode data, and still correctly shows none —

    worth knowing if you have both, because the difference is in the file, not in

    the viewer.

    The JSON tail also carries the rename tables XZZ's own viewer applies, so two

    further things follow. Pin identifiers are no longer restricted to digits,

    which means BGA readings (M7, L9) can be represented at all. And parts a

    file named by internal id (C356_1) now show their real designator

    (C11814) — 2297 of them on the YiDianTong file. Net names get the same

    treatment where a file provides them. Neither rename will ever merge two

    parts, or two nets, into one name.

    Spec: docs/formats/XZZ_FORMAT.md.

    Board view

    in the sidebar's View tab and in Settings ▸ Board ▸ Pins. On a dense part the

    net name is usually what is covering everything else.

    state: off → on → *only*. In "only", a pin shows its reading and nothing

    else — no pin number, no net name, and no designator for single-pin

    testpoints, which are drawn directly on the pin and were the worst of the

    clutter (half the parts on an iPhone board are single-pin). Designators on

    part bodies stay, so the board is still navigable.

    Your own pin-number and net-name settings are left untouched while the mode

    is on and come back when you leave it. It is also considerably faster: on a

    dense area of iPhone16_16Plus the label count falls from 23 182 to 6535.

    v0.37.0 — 2026-09-03

    Two new board formats, both open and both with public test boards — the first

    formats in this project whose parsers can be tested by anyone. Plus a fallback

    for update checks when ripperdoc.de is unreachable.

    Formats

    tracks, vias and copper pours. An original implementation from KiCad's

    public file-format documentation — the only openly specified format

    BoardRipper reads. Two conventions were measured rather than assumed: the

    rotation sign (KiCad angles are CCW as displayed over a Y-down frame) and

    the fact that back-side footprints are stored already mirrored. Both were

    settled by placing every pad under each candidate and requiring a track

    endpoint at that spot to carry the pad's net — a position-only check cannot

    tell the conventions apart on a symmetric two-pin part. Copper pours use

    KiCad's own computed fills, so there is no fill algorithm; keepout areas are

    recognised as not-copper and skipped. Spec: docs/formats/KICAD_PCB_FORMAT.md,

    including a checklist for tools that write files BoardRipper reads.

    claim .brd; content sniffing keeps it apart from Apple BRD and Allegro. Pin

    positions are not stored in the file — each part references a library

    package, and every pin is the package pad run through the element's

    mirror-then-rotate placement. Verified by a routing oracle: on the fully

    routed test boards, 100% of pins land exactly on a trace endpoint of their

    own net. Pre-6.0 binary files are rejected with a message to re-save from

    EAGLE 6 or newer. Spec: docs/formats/EAGLE_BRD_FORMAT.md.

    several closed contours — perimeter plus slots and milled windows — and they

    were being welded into one run with a false edge leaping across the board.

    Contours are now chained with a join tolerance and separated, and the

    renderer punches inner contours as holes instead of painting them.

    Updates

    manifest had exactly one source, so any outage of that host stopped update

    checks outright — and, until v0.36.0, stopped them *silently*. Observed on

    2026-09-01: an install could not open a TCP connection to ripperdoc.de on any

    port while github.com and ghcr.io answered normally from the same host.

    Releases now publish manifest.json, its signature and the tarball as GitHub

    Release assets, and builds carry a second source pointing at the stable

    releases/latest/download alias. Whichever source answers first with a

    signature that verifies wins.

    This grants GitHub no additional trust. The manifest is signed either way, so

    a tampered copy from either host fails VerifyManifestAny identically — the

    fallback adds availability, not authority. GHCR is deliberately not a manifest

    source: it is an OCI registry and cannot serve /manifest.json, though it

    remains where the image is pulled from by digest.

    The tarball now also lists the GitHub asset in url_mirrors, a field Apply

    has always walked but which releases left empty.

    v0.36.1 — 2026-09-01

    Concave board features stop rendering inside-out. Reported in detail as #33 by

    Sean Johnson, whose write-up pinned both sites, the convention, and the blast

    radius — the fix below is his analysis applied.

    Formats

    stored as centre + start/end angle names *two* arcs, the counter-clockwise one

    and the clockwise one, and both share their endpoints exactly — so normalising

    the sweep is not angle hygiene, it *is* the choice of which arc to draw. Both

    parsers had independently reached the same wrong idiom, reducing the sweep

    into ±180° (a shortest-arc rule) and thereby swapping every arc over 180° for

    the other side of its circle. Every notch, slot mouth and re-entrant corner

    fillet became an outward lobe of the same radius, anchored at the same two

    points. The sweep is now lifted into [0, 360) instead.

    GenCAD had a second symptom from the same line: exporters write a full circle

    as two endpoint-swapped 180° records, which the old clamp left at +π and

    −π, so walking the second one backwards retraced the first half and the

    other side was never drawn. 3,038 such circles in one reference file alone.

    Nothing that renders correctly today can move: the two rules differ *only* on

    arcs whose true sweep reaches 180°, verified across 19,964 XZZ arcs and 37,586

    GenCAD arcs with zero geometry changes below that threshold.

    PARSER_VERSION is bumped, so cached boards re-parse rather than serving the

    old geometry.

    v0.36.0 — 2026-08-31

    The release signing key was unfortunately lost and had to be reset. This release

    is signed with a new one, and adds the mechanism that stops the next key loss

    from being a one-way door.

    Signing

    PUBKEYS build-arg, comma-separated) sits alongside the existing

    updater.PubKey; TrustedKeys() merges them and VerifyManifestAny accepts

    a manifest that verifies under any one. A key must still be compiled in via

    -ldflags to be tried, so this widens the set of accepted *signers* and

    nothing else — a trusted signer still cannot vouch for a tampered body, and an

    empty key set fails closed rather than open.

    outgoing key while the incoming key is already listed in PUBKEYS, and every

    install rolls onto an image trusting the new key with no manual step. The

    procedure is written up under "Rotating the signing key" in the release

    runbook. Without it a rotation strands every install, because the fields that

    would explain the problem — important_reason, notes_url — live inside the

    signed manifest that the install is correctly refusing to read.

    manifest that failed signature verification produced nothing in the UI at all:

    the badge kept showing the installed version and the error went only to the

    debug log, so a stranded install looked identical to an up-to-date one. The

    badge now turns amber and the dropdown says an update exists, that this build

    cannot verify it, and how to install it by hand — plus why the refusal is the

    protection working rather than a fault.

    Nothing from the unverified manifest is rendered. Its version, notes and

    important_reason are exactly what a hostile mirror would choose, so only a

    boolean crosses the trust boundary (signature_mismatch) and every word shown

    is compiled into the build. A signature failure is also kept distinct from an

    unreachable mirror (ErrSignatureMismatch), because those warrant different

    advice.

    Notes for existing installs

    Installs shipped before this release trust only the lost key and cannot be

    reached automatically. They need one manual docker compose pull, after which

    updates resume normally and this can never recur for them. The notice is on

    https://www.ripperdoc.de/boardripper/.

    No user data was exposed at any point. The key signed release manifests; it

    granted no access to any installation, and BoardRipper stores nothing remotely.

    v0.35.3 — 2026-08-14

    Two boardviews that would not open now do. One is an .fz written with old-Mac

    line endings; the other is a board delivered as a folder of loose .asc section

    files, which from now on opens whole from a click on any one of them — and reads

    two sections nothing had ever read. Plus the wedge that net highlighting cut

    across boards with elongated pins.

    Formats

    end every record with a bare carriage return instead of a newline, and those

    files failed with "contains no parts or pins" — the file was read and

    unpacked correctly, but the whole board arrived as a single 745,000-character

    line, so not one component was ever picked out of it. All three line-ending

    conventions are now accepted. Canary: XPS 15 9530 Compal HD055 LA-L663P

    Rev 1.0, which reads as 4,069 parts and 15,148 pins across 2,722 nets.

    Reported by the user. f06769e2

    eM-Test toolchain ships a board as a folder of section files, and opening

    one gave a fragment: Pins.asc a board with no outline, Format.asc a bare

    rectangle, Nails.asc an empty screen, and Nets.asc / Parts.asc an

    error. Clicking any of them in the Library now finds the rest in the same

    folder and opens them as one board, saying so in a toast. The OS file picker

    and drag-drop cannot see the folder, so there a lone section opens as before

    plus a toast whose "Add sections…" button takes the missing files. 6887a7d6

    bundle never carried, so they had never been seen: the placement list, which

    is the only source of part rotation and package name in the whole delivery,

    and the net listing. Net names containing spaces (3D VISION) are no longer

    truncated at the first word on pins and nails alike. Cached ASC boards

    re-parse. 6887a7d6

    Rendering

    with elongated pins — PL5TU1B, where 5,413 of 9,002 pins are capsules —

    selecting a net cut a wedge over the board, and some connection lines ran

    off to the board corner. Both were one defect: a capsule was drawn without

    first lifting the pen, so it stayed joined to whatever shape had been drawn

    before it, and to the origin when nothing had. Introduced in v0.35.0, when

    pins started drawing as capsules outside the pad overlay. 27d17f00

    v0.35.1 — 2026-08-07

    A hotfix for one long-standing defect: XZZ board outlines came apart at every

    rounded corner, and because the board fill closes each loose piece with a

    straight line, boards showed black wedges cut across them. It dates back to

    the first version of the two-halves fold.

    Formats

    apart — the edge broke into loose pieces at every rounded corner, and

    because the board fill closes each piece with a straight line, the result

    was black wedges cut across the board. The cause was a duplicate-edge guard

    in the two-halves fold that compared endpoints with a fixed 1-mil tolerance:

    a rounded corner is drawn as a run of 0.8-mil steps, and at that size a

    segment is indistinguishable from the one it is joined to, so each corner

    was deleted as a "duplicate" of itself. On the 16" A2485 the outline went

    from one closed 767-point loop to 18 open fragments. Across the sample

    corpus, boards with a correct outline go from 23 of 32 to 31 of 32 — the

    remaining one has a real 26 µm gap in the file itself. Reported by the user

    as long-standing; it dates back to the first version of the fold.

    v0.35.0 — 2026-08-06

    Connector legs on XZZ boards now draw with the hole in them — and where the pad

    is an elongated stroke, with the slot it is actually routed as. Two formats

    that had been sitting in the backlog are in: boardviews delivered as loose

    .asc section files, and ASRock .cae. Plus release notes that survive the

    update that delivered them.

    Most of this release came from outside: Sean Johnson reverse-engineered the

    XZZ drill field and the oblong-pad geometry down to the hex, and

    @luiztessadri filed both format requests. Apologies to the latter for the

    three-week wait — repair volume got ahead of the issue tracker.

    Updates

    to be gated on there being an update *available*, so applying one made them

    vanish — leaving "You are on the latest version." and nothing to read, to

    the one person who had just earned a reason to care. The notes for the

    version you are running now live in the badge dropdown and on the start

    page's Latest update card, cached locally at apply time so they survive a

    post-swap network outage. fa7ad0f5

    Interactive Mode

    writes global, persisted settings — that is the feature — but a drag left no

    trace, so a stray one read as a rendering bug. (It cost an afternoon chasing

    "BRD pins are too big" that was pinSizeScale all along.) A row whose value

    differs from the default now says so: an accent dot, an accent readout, and

    its own reset button. The footer says where the change lands and puts the

    whole group back in one click. 2e72faef

    Formats

    vendor tools ship the Honhan / Tebo-ICT boardview split into the three files

    it is made of — outline, test nails, part pins — instead of the single

    encoded .bdv. Select them together and you get one board, not three tabs;

    open just one and you get what it holds (a lone pins file still gives you

    parts, pins and nets). Requested by

    @luiztessadri in

    #26.

    as ASUS .fz and differ only in the key, so they now share the parser,

    which tries each key you have stored and takes whichever one actually

    decrypts the file. As with the FZ key, BoardRipper does not ship the ASRock

    key — there is a paste field for it. Untested against a real .cae: nobody

    has sent one yet. Requested by

    @luiztessadri in

    #25.

    the BOM value into a label block on the part — "22uF" under C757 — which

    the parser was skipping. It now reads it, so the Info pane, the net branch

    list and MCP part search show a value where the file has one. Apple boards

    are unaffected: their exporter fills the same field with placeholder text

    (Device1, Device2, … one per part), and a board-level guard drops a value

    column that never repeats rather than labelling every part with scaffolding.

    Found, documented down to the hex, and prototyped by **Sean Johnson

    (@sjohnson1021)** in

    #27. 721a34b9

    written off as a constant zero is the drill diameter, so connector legs,

    headers and mounting pins now draw with a hole in them and their parts are

    typed *through-hole* instead of claiming to be surface-mount. Where the pad

    is an elongated stroke the hole is drawn as a matching slot, the way it

    is actually routed, instead of a round dot floating in a blob. 5ca997e3

    whether an elongated pad is real assumed the narrow side was always the same

    axis. On a pad that ran the other way it flattened a 37 × 10 mil capsule

    into a Ø37 circle — 3.5× too wide on exactly the connector footprints you

    zoom in to read. Both axes are treated alike now, and the pads that really

    are exporter noise (a "pad" one mil wide) are still filtered out. 5ca997e3

    correctly-parsed oblong pads were still drawn as dots, and selection,

    hover, net highlight, search and the HDR outline each stamped a circle in

    the middle of one. All of them now trace the real shape, and the pin-size

    slider still moves it. 5ca997e3

    by Sean Johnson (@sjohnson1021) in

    #32 — the kind of

    report that arrives with its own hex dumps and worked examples.

    v0.34.0 — 2026-08-05

    On an HDR display the selected component's outline can now burn brighter than

    white, so the part you are working on cannot be confused with the thousands of

    white neighbours around it. Off by default, experimental, and invisible on an

    SDR screen. Plus testpoint labels that no longer print on top of each other,

    and an MCP auth switch that stops kicking agents out.

    HDR selection outline (experimental, opt-in)

    shape the selection already strokes (rotated OBB, AABB fallback, a 24-gon

    around single-pin parts), redrawn as HDR line segments that sit exactly on

    the SDR ones. Thickness tracks the normal selection stroke, so with the

    feature off nothing about selection changes at all. 4af3e4ad e774ca67

    intensity slider inline, because the right brightness depends on your

    display and a trip to Settings discourages finding it by eye. The Settings ▸

    Selection & Highlight control stays visible-but-hinted on an SDR display; the

    start-page card hides entirely. 6cbbc9c0 e774ca67

    boolean — a marginal HDR panel reports exactly what an XDR panel reports. So

    the prompt shows a real HDR patch beside reference white and says outright

    that if they look the same, turning the feature on will change nothing.

    Dismissable for good. b10eb952

    Rotate, mirror and butterfly all work for free — the layer projects through

    the same matrix as the board labels. e774ca67

    a PQ sprite keeps its headroom over the board canvas, but compositing it with

    opacity flattens it straight back to SDR. So the intensity slider swaps

    between 24 tiles baked from 4000 down to 200 nits (~7 KB in total) rather

    than fading one. The finding, and the alternatives it ruled out, are written

    down so they don't get "fixed" back into a bug. 14fbef4f 7c163591

    594b997a

    Rendering

    single-pin part — testpoint, fiducial, standalone pad — the two labels were

    emitted at byte-identical positions and drew straight through each other.

    They now straddle the pad the way a BGA's pin-number/net pair does, one above

    and one below, sized off the pad instead of a zero-width box. eaf10d1e

    0dcd63eb

    MCP

    Integrations back to Token used to kill live OAuth sessions instantly — the

    tokens stayed valid, the server just stopped looking at them, while discovery

    403'd so they couldn't reconnect either. The mode flag now means what it

    always should have: whether *new* agents can onboard via OAuth. Ending a

    session is an explicit act instead of a side effect. 699d453d

    Elsewhere

    wrote it, and where to find the source — in a place you actually walk past.

    It renders in every build, including lite and offline, which are exactly the

    ones a first-time user is likely to meet. The Settings ▸ About tab that

    briefly existed is gone again; one surface, not two. e5692c70 56a22dbc

    e4930150

    v0.33.0 — 2026-07-29

    Click a pin and the Info tab now shows the whole net hanging off it — every

    component that touches it, each one a click away — with the board pointing at

    whichever you are looking at. Plus a much faster cold library load and two

    rendering fixes.

    The net fans out from the pin you clicked

    other component sitting on the same net, each with the pins that land on it.

    The first three are open and the rest are one click away, so a big rail never

    buries the pinout underneath. 50d2519a 671de89e

    neighbour's own pinout in place without moving anything; a single click flies

    the board to it while the panel keeps your place; a double click makes it the

    subject, with the net still fanned out beneath it and the part you came from

    now a row in the list. Walking a rail is a sequence of steps you can walk

    back. 50d2519a

    five seconds on arrival — while that runs, disco mode goes quiet so exactly

    one component is blinking — then settles into a slow flash every two seconds

    that does not stop, so it is still findable when you look back at the board a

    minute later. 0ade4c2a

    only lit the net on the board while its components stayed out of view.

    6a942658

    the counts and the previewed row all derive from Settings ▸ Board ▸ Net Lines

    ▸ Color, so the trail in the panel and the lit net on the board are visibly

    the same thing. Change the colour and the whole thing follows. 50d2519a

    and answers nothing, so ground rails get no list. Which nets count as ground

    comes from your own Ground pin group, so an unusual name is taught once in

    Settings. 671de89e

    count now live on the pin row itself rather than a bar of their own.

    6a942658 bb31d55c

    Fixes

    database never reclaimed space: splitting out the PDF text tables in v0.31 had

    freed 1.45 GB to its free-list, but nothing ever compacted the file, so it

    stayed at 1.5 GB with 96% of its pages empty and every cold load paged the

    file list across all of it — around 29 seconds on NAS disk. It is compacted

    now, once, on upgrade. 8b66cc8b

    more boards open, each board's panel had mounted its own copy of the popup,

    and every copy treated a press in the visible one as a click outside itself

    and closed the shared popup. One board was fine; two made Interactive Mode

    unusable. c375c57e

    pin had used a fixed 6-mil radius, which is right only for exports that

    declare their units; on files that do not, pins rendered smaller than their

    own pin-number labels. The radius now comes from the pad geometry in the

    file's $PADS section. 5b50bc76

    end-to-end and 19-pixel rows land on fractional device pixels, so opening a

    component's details left hairline gaps in the line. 0ade4c2a

    v0.32.0 — 2026-07-27

    Altium Designer files now open — the twelfth supported format. Plus the Tools

    tab (component-code calculators and a worklist catalog), a much faster Library

    on slow connections, and a container-build fix that means two earlier fixes

    actually reach you for the first time.

    Altium Designer support (new, experimental)

    Circuit Maker (.CMPcbDoc) and Circuit Studio (.CSPcbDoc) variants, and

    the PCB ASCII v5.0 text export. Components, pins, nets, tracks, vias, arcs,

    fills and multi-layer copper all come through; every pin carries its net, so

    net highlighting and connectivity work as they do on any other format.

    shape varies per layer (common on BGA stackups) are not sized yet and render

    small — on our 4-layer test board that is 40 of 100 pads. Inner copper layers

    are parsed but only the outer two are listed, and the board outline is a

    bounding box rather than the true shape. Connectivity is unaffected. Expect

    a net list you can trust and a picture that is not yet finished.

    toggle in the sidebar controls them like any other format's.

    Tools tab (new)

    including the letter-position rule that tells EIA-96 from R-notation apart.

    instead of only the one attached to the open board.

    Library and PDF index

    the complete file list before drawing anything; it now renders as results

    stream in, and opening a file no longer waits for the whole list to load.

    5b452db7

    the wire — a large collection drops from tens of megabytes to a few, so a cold

    load over a slow connection finishes in seconds instead of most of a minute. A

    new "Bulk API" load mode in Settings ▸ Library offers a single compressed

    download as an alternative to streaming, and streaming falls back to it

    automatically if it fails. 663142d4 91d73e98

    stopped, can be restarted from Settings, and picks itself back up

    automatically after a container update. d5acd945

    Fixes

    Both were in the source (since v0.30.3 and v0.31.36) but were being dropped

    during the container build, so no web or NAS install has ever run them. If

    watermark filtering looks new to you, this is why.

    the pan that followed it.

    pads when you flip top/bottom, mirror, or change the flip axis, not only on

    rotation as before. efb5bb03

    selecting from the dropdown blurs the field (so Space flips the board again

    instead of typing a space) while keeping your typed text; re-focusing reopens

    the list with the active net/part clearly marked. efb5bb03 fbd19212

    Under the hood

    and because the container build was chained behind that lint step, the

    container build and smoke test were being skipped entirely rather than run.

    Both now run independently.

    v0.31.44 — 2026-07-24

    Interactive Mode: size any board element by clicking it. Plus the offline

    single-file build, and a batch of rendering fixes — including two faults that

    could stop the renderer mid-session.

    Interactive Mode (new)

    Board turns a plain click into a sizing gesture: whatever you click opens a

    popup at the cursor with the handles relevant to it, and the whole board

    previews live as you drag. Pan and zoom keep working. f37157a8 1c163d36

    size, net-label size, diode-value size, selection-highlight size/opacity and

    the selected-label floor/LOD; a component offers its label size and outline

    width; a highlighted net's connection line offers width, colour and opacity;

    empty board offers board opacity. Every handle carries a one-line

    description, scroll-to-nudge and double-click-to-reset.

    c798d216 a387fb20 746e761a 82070a22 e83eed9a

    component-label and diode-value sizes are now true multipliers, so they

    scale on every board instead of only nudging labels that happened to sit at

    the old minimum-size floor. 6bee409f 9f80f81e b40523b4

    Rendering

    (darklight) dimming and a part selected, the selection halo was destroyed

    along with the scene on each rebuild and then drawn again, halting the

    ticker until "Restart Render". 856c4343 5ff71f69

    geometry is chunked below the 65,535-vertex index ceiling, and the chunk

    budget now adapts when pins are scaled up.

    657ea5ef c40dffde 3df9f6f0 d656e3c9

    to a ghost as it grows, so the net names underneath stay readable instead of

    being blanketed by it. 1ab634f0 8babb0cc

    label and selected the whole component, which highlights no net; clicks now

    resolve to the specific pin. e1805871

    6a1777cf d7b0ed8e

    Offline & lite build

    from file://, downloadable from the toolbar, with the lite web app

    deployed alongside each release.

    2f39348b a23175ac 9aaa692d 5dc6d080 954f614b

    Library, PDF & Settings

    Folders source menu. 263686e1

    claims its slot immediately instead of after a long enumeration, so extra

    clicks fail fast rather than queueing a "stop previous index?" dialog each.

    b2ca9c82

    collapse when there isn't; the search bar moved below them.

    077b6827 6c74fe14 686d6439

    6e8c8f56

    MCP

    parsed data lands. 2b3987b0

    v0.31.43 — 2026-07-20

    MCP auth follow-ups to v0.31.42's session separation: clearer errors for

    logged-out agents, and mixed authentication so OAuth users and token users

    can coexist on one install.

    MCP server

    mode: per-browser and shared bearer tokens keep working when

    Authentication is set to "OAuth (no token)", so some users can connect

    via OAuth while others keep their tokens on the same install. 16e0b674

    carry an RFC 6750 WWW-Authenticate challenge explaining the v0.31.42

    token reset, and the OAuth endpoints answer an explicit 403 ("OAuth is

    disabled on this install") in token mode rather than a hidden 404. The

    404 remains only while the MCP server is disabled entirely.

    b35c1c7c 16e0b674

    v0.31.42 — 2026-07-20

    Multi-user MCP: per-browser agent pairing. On installs shared by several

    technicians every agent used one shared token and targeted the

    most-recently-focused page install-wide — so one user's agent could read

    (and even drive) another user's board. Sessions are now separated by

    pairing each browser with its own token.

    MCP server

    token sources: "This browser's agent" (default; scoped to the boards

    open in this browser, with an editable label and one-click rotate) and

    "Shared (all sessions)" (the install-wide token, kept for

    deliberately analyzing other users' sessions). An agent with a paired

    token only sees and drives its own browser's pages, and its default

    target is that browser's focused page — wrong-board mixups between

    users are gone by construction. e2c29dde 4c1b1c90 84b91b63

    f1dd68cd 95b1526c

    shared MCP token is regenerated once: agents configured before the

    update are logged out, because resetting the shared credential was the

    only way to migrate it properly. The 401 response and a notice in

    Settings ▸ Integrations explain the reset and point to the new tokens;

    open BoardRipper pages re-join the bridge automatically. fec25f66

    focused_at_ms, so multiple open sessions are distinguishable — and

    with the shared token lists every page, while a paired token lists only

    its own. f1dd68cd

    steals the "most recently focused" default target from the window the

    user is actually working in. 84b91b63

    v0.31.41 — 2026-07-20

    Renderer follow-up round: less per-frame work during interaction, no more

    rebuild storms across tabs, and Text fast mode is now on for everyone.

    Board view

    the default for new installs in v0.31.40). A one-time notice on first

    start explains the change and links to Settings; the previous text

    renderer remains available under Settings ▸ Performance & Debug ▸

    "Text fast mode", and turning it off sticks.

    labels, matching the classic renderer.

    stale transforms.

    Parsers

    with a plausibility guard against implausibly huge pins (PL5TU1B).

    7a474e6a *(shipped in this release but missing from its original

    notes; added retroactively.)*

    Performance

    inactive tabs rebuild once, when you switch back to them.

    entirely (previously re-stroked every frame while the viewport moved).

    rebuilding all line geometry 60× per second.

    changes, not on every hover while dimmed.

    after fold/filter toggles; deep-paused background tabs now release the

    fast-mode text layer's memory too.

    v0.31.40 — 2026-07-19

    Merges the renderer-optimization branch — the implementation round of our

    renderer performance plans from earlier this summer (see

    docs/research/rendering-review-2026-07-12.md and

    docs/research/wasm-webgpu-acceleration-plan.md).

    Board view

    overlay instead of tens of thousands of in-scene text objects — much

    higher FPS on label-dense boards (11→60 fps measured on a dense board).

    The previous text renderer stays available: Settings ▸ Performance &

    Debug ▸ "Text fast mode".

    the cursor at the same speed as before. Disable in Settings ▸

    Performance & Debug. Trackpad pinch, Ctrl-zoom and drag-zoom unchanged.

    "Selected Part Labels" slider (Settings ▸ Zoom Level of Detail) controls

    their minimum on-screen size.

    zoomed in — long-standing culling bug, affects both text modes.

    Performance

    frame, tooltip measurement cached, trace lookup on a spatial grid.

    v0.31.39 — 2026-07-18

    A small fix round: converter-produced GenCAD files open again, XZZ diode maps

    draw their zero readings, and pin numbers can be toggled straight from the

    View tab.

    Parsers

    exports (e.g. DAX3ACMBAF0 X3AC Rev F.CAD) start with NUL bytes before

    $HEADER, which content detection didn't strip — so the .cad fallback

    routed the file to the Mentor Neutral parser, which rejected it with

    "contains no placed components". Detection now tolerates the NUL prefix;

    the X3AC sample opens with 2,834 components / 1,732 nets. (7c00bd90)

    classified as "not measured" and hidden from the on-pin overlay, tooltip

    and component info — but a literal 0 is a real measurement (short to

    ground), and on connector diode maps it's most of the table (776 of 1,144

    on the iPhone 15 Pro map). Zeros now draw as "0" on the pin and show as

    0.000 V in the tooltip and info pane; cached boards re-parse

    automatically. (9d178fa5)

    Board view

    labels compete with the on-pin readings; hiding them previously meant a

    trip to Settings. The View tab now has a Pin numbers visibility toggle next

    to Diode values, mirroring the same global setting. (ec30722c)

    Also riding along: the desktop MCP-sidecar groundwork from v0.31.38 (an

    Electron-only release) is in a Docker image for the first time here; it is

    gated on Electron and inert in the web build.

    v0.31.37 — 2026-07-14

    An MCP release: the assistant can now drive the live board — open library

    files into tabs, work across several open boards at once, and read a

    selected component's pins — plus a smarter library search that finds a board

    by any of its metadata, including its folder path.

    MCP server

    board (and its auto-bound schematic PDFs) or a document by file id, so the

    assistant can go from a search hit to an open board on its own instead of

    waiting for the user to open it. (9eb9f0f6)

    tabs and switch_tab changes the active one; the inspection tools

    (part_info, net_info, list_parts, …) take an optional tab, so the

    assistant can compare two boards without losing its place — e.g. a

    pin-for-pin comparison of the same chip on two variants. (439f921e,

    9eb9f0f6)

    nets of whatever the user has clicked, so the assistant can pick the

    conversation up from the board. (439f921e)

    the folder path, manufacturer and extension in addition to filename /

    board number / model, with multi-word AND matching — so searching an Apple

    A-number like "A2991" returns its boardview even though the file is named

    by its 820-number and sits in an A2991 … folder. (1d05729a)

    assistant that boardview files (BRD/FZ/XZZ/BDV-ASC …) are encrypted or

    obfuscated and must be read through the live board tools, not fetched as

    raw bytes. (439f921e)

    an error instead of the list of open boards; now returns cleanly.

    (1d41e169)

    Library

    board by any metadata including its folder path, with multi-word matching,

    so typing an Apple A-number surfaces the boardview even when its filename

    only carries the board number. (23ad492f)

    v0.31.36 — 2026-07-13

    A memory and parse-performance release: closing board tabs now actually

    returns their memory, big boards parse without freezing the UI, and the

    status bar shows live memory usage.

    Memory

    every opened board stayed in memory forever — its parsed data (~15 MB per

    board, held via leftover viewport/resize callbacks) and its entire GPU

    scene (batched geometry and buffers, ~130 MB per few boards, pinned by

    PixiJS context-loss listeners and a pooling bug patched via

    patch-package). A session that opened and closed a handful of large

    boards used to park at 1 GB+; the same cycle now settles back near

    baseline, and background-tab deep-pause cycles no longer leak either.

    A regression test with GC-forced WeakRef canaries guards both fixes.

    (d5e16ee9, 2f3e49a6)

    (including the parse worker) where the browser supports it — the app is

    now served cross-origin isolated to unlock that API — and falls back to

    an approximate heap figure marked ≈ elsewhere. (466e2b74)

    Performance

    (100+ MB Allegro/BRD/TVW) no longer freezes the tab for the whole parse —

    the UI stays responsive while the progress overlay runs. Encrypted FZ

    files, the key dialog, and drag-and-drop all behave as before; if the

    worker is unavailable the old inline path is used automatically.

    (1e6d7e1a)

    IndexedDB write (hundreds of ms on big boards) now happens in the

    background, and a failed write no longer fails the whole load.

    (2f1a80a8)

    dropped its all-pairs scan for a spatial hash, ghost-component detection

    got a sweep prefilter, and the FZ RC6 loop lost an array shuffle — each

    parity-tested byte-for-byte against the previous implementation, so no

    re-parse of cached boards is needed. Parse stages now log timings to the

    Debug panel (perf scope). (ce455ab1, d7af8e5e, 2fb7723e,

    3986f879)

    Fixes

    pad geometry from the parser shrank them. (7b14c221)

    v0.31.35 — 2026-07-11

    A selection and small-UI fix pass.

    Fixes

    a zoomed-out view the "pin click radius" (a screen-pixel grab distance) grew

    large in board units, so a small surrounding test point registered as the click

    and — being the smallest thing there — won selection. Clicking inside a

    component now takes priority over a merely-nearby pin, and the default Pin Click

    Radius is tighter (30→15px). Genuinely stacked components still cycle

    smallest-first. (eb5eac27, ec18e86c, #24)

    mirrored.** The white highlight copy of a selected / net-highlighted name stayed

    frozen at its old orientation while the base name re-oriented, leaving two

    overlapping offset copies; the highlight now re-syncs on rotate/mirror.

    (eb5eac27)

    into one very wide line with its own line breaks collapsed; it now wraps and

    keeps its newlines. (d9127ee2)

    (not HTTPS or localhost) the browser Clipboard API is unavailable, so the button

    silently did nothing; it now falls back to a copy path that works there.

    (d9127ee2)

    v0.31.34 — 2026-07-09

    Continues the MCP build-out: a connected AI assistant now arrives primed as a

    repair technician and can pull on a built-in repair knowledge base. Off by

    default; enable it in Settings ▸ Integrations.

    MCP integration

    connection now carries a persona: understand the circuit before judging it,

    work from evidence not guesses, treat unlabeled nets as low-trust, follow

    sound measurement practice (diode mode for data lines, not power rails; ohms

    and diode only on an unpowered board; continuity mode for continuity only),

    and teach the *why* in plain terms — calibrated to how much guidance you want.

    (d59e812)

    diagnose, and explain (they appear as slash commands in Claude Code) walk

    the assistant through learning a circuit, running a symptom-driven diagnosis

    on the shared worklist, or teaching you about a net/part/concept — each

    grounded in the board you have open. (093a5c4)

    and concept notes on demand — short-to-ground localization, measurement

    hygiene, when diode mode helps vs misleads, power-rail basics — through a

    kb_search tool and read each note as an addressable resource. It searches by

    relevance rather than loading everything, so the connection stays lean.

    (a779430, 4800d3c, 53719d3)

    v0.31.33 — 2026-07-09

    Expands the MCP integration so a connected AI assistant can actually see and

    read the board it's helping with — the first of a phased build-out. Off by

    default; enable it in Settings ▸ Integrations.

    MCP integration

    captures the live board view as an image and pdf_page_image renders any page

    of the open schematic, so a copilot can visually correlate a part on the board

    with its symbol on the print instead of working from net names alone.

    (32ccf34, 6789416)

    returns a page's text and pdf_search_open searches within the open document

    instantly; the existing library-wide pdf_search now also accepts a single

    file id to scope a search. (f5db6d4, 908da01)

    schematic's bytes to the assistant and file_download retrieves any indexed

    library file by id, so a search hit becomes a document the model can read

    end-to-end. (4730d06, 3c49c0e)

    part/net counts, shown side, every open PDF (name/page/id), and a worklist

    summary in a single call — and the bridge now tells the assistant which PDF

    you have open. (39f30a1)

    tagged named or synthetic, so it won't read a function into an

    auto-generated name like N$123. (cba1b66)

    part, or flipping sides now returns what actually happened (pins highlighted,

    part found and its side), so the assistant can confirm an action instead of

    guessing. (4fc071c)

    Fixes

    WebSocket capped messages at 32 KiB and tore down the connection on any real

    image or PDF; the limit is raised so snapshots, page renders, and downloads

    round-trip cleanly. (a4ef066)

    v0.31.32 — 2026-07-08

    A memory-optimization pass. Across a long session BoardRipper now releases

    memory back to the system instead of holding on to many gigabytes — both in the

    browser (open boards and PDFs) and in the Docker backend.

    Performance

    full WebGL context and scene graph alive for the whole session, so opening many

    boards piled up gigabytes that came back only slowly. A board that stays hidden

    now releases its renderer and rebuilds — restoring the exact view you left — the

    moment you switch back to it. (1301612, 2935c2d, 6d1761d, 697ce08)

    visited page's render data until the document was closed; page resources are now

    trimmed as you navigate, off-screen tile and preview images are freed promptly

    instead of waiting for the browser's garbage collector, and clean mode no longer

    keeps a second copy of the document loaded once it's switched off. (31cc953,

    84ea23a, 200b2de)

    memory budget from its container limit and hands freed pages back promptly; the

    PDF-index workers cap and recycle their memory instead of holding a permanent

    high-water mark; large files stream to the browser instead of being buffered

    whole; and a real container memory limit is now actually enforced. (c5260ff,

    ad6d9d2)

    textures and detaches its ticker on teardown, and per-board diagnosis lookups

    are capped so a long browsing session doesn't grow them without bound.

    (b6c104c)

    v0.31.31 — 2026-07-08

    A broad correctness-and-hardening pass from a full multi-directional audit, plus

    a Library panel cleanup.

    Fixes

    files that vanished from disk were never removed from the database after the

    first restart, so the folder tree, file list, and duplicate groups slowly

    filled with ghost entries. (1227506)

    clears its old pages first, so search never surfaces text from a previous

    version of a file, and the watermark re-index reliably strips added watermark

    terms. (1227506)

    (slow boot, transient Docker error) used to consume the release and could never

    be re-applied from the in-app updater; it now re-offers the same release, and a

    Docker image-load error is detected instead of being reported as success.

    (1227506)

    actual board and PDF files, closing an over-broad path that could reach other

    files in the data directory. (1227506)

    millimetres are scaled properly instead of collapsing to an invisible speck.

    (409f570)

    get a correctly-oriented outline box, and formats that can't distinguish SMD

    from through-hole now report "unknown" rather than guessing "SMD". (409f570)

    casing no longer create duplicate "(missing)" rows, an out-of-range repair mark

    can't corrupt the board highlight, and measurement requests reach the right

    net. (c5d4d3a)

    resize and made in-document search noticeably faster on large schematics.

    (7efd5b3)

    Board# and Model views no longer stay empty while files stream in. (90ac02a)

    file surfaces the "materialize on host" message immediately instead of retrying

    for three minutes. (90ac02a)

    fire while a list panel is focused, and bright accent colours stay legible as

    text on light themes. (8357207)

    Library panel

    status line is a single row pinned at the bottom that expands — on click, or

    while a scan/index is running — to the full breakdown, keeping the "view failed"

    button; and switching tabs focuses the search field so you can type straight

    away. (d45d37c)

    small Database / Live menu that auto-dismisses, instead of taking a permanent

    row for one control. (8248438)

    Under the hood

    is bounded and hidden when the integration is off. Renderer pan/zoom hot paths

    shed redundant per-frame work. (1227506, c5d4d3a)

    v0.31.30 — 2026-07-06

    Select components hidden under others, and get a clearer read on what's selected

    versus what's merely on the same net.

    Features

    shared pads, a small part on a big pad, a component under a shield), a click

    now selects the smallest part under the cursor; clicking the same spot again

    cycles through the stack. On 2-pin parts the second click selects the whole

    component — the first still selects the pin/net. Right-clicking a stack lists

    every overlapping part so any of them can be pinned to a worklist or looked up

    directly. (be05bef, 0358378, 6ec512b)

    Fixes

    white outline with a white name label — distinct from the net-member parts it

    shares a net with (which stay in the net colour) and from the worklist mark

    colours. The selected name stays white at every zoom. (6ec512b, aeeaced,

    9142a7d)

    on/off now updates the on-board outlines immediately instead of waiting for the

    next pan or zoom. (aeeaced)

    when you click the board or switch the sidebar tab away and back. (#22,

    6961bb8)

    per-part geometry (all-zero part corners, e.g. X540UV 60NB0HF0-MB1020) had

    every part's outline and label pulled toward the board origin; parts now derive

    their box from their pins. (e8aa6b7)

    v0.31.29 — 2026-07-01

    The session-restore boot prompt now lets you pick which boards and PDFs to reopen

    instead of restoring all-or-nothing.

    Features

    lists every board and PDF that was open with a per-file checkbox (all checked

    by default). Uncheck any you don't want and only the rest reopen; the primary

    button reflects the count ("Reopen (N)") and disables when nothing is selected.

    Discard still clears the whole saved session. (e4ca016)

    v0.31.28 — 2026-06-30

    Board↔PDF links now persist across reloads, the worklist records full multimeter

    readings per net, two reported bugs (#20, #21) are fixed, and the tab/tooltip

    chrome got a round of polish.

    Features

    writes a durable backend binding — a single row no matter which side you link

    from — so the link survives a reload + reopen, and auto-open / auto-switch keep

    working. Unlinking *demotes* the link (it won't auto-open or get resurrected)

    instead of destroying it. Dropped files are ingested into the library with a

    real id at drop time, so they bind and restore just like library files.

    (9b18933, bc2855a, 7ed1c8a)

    a diode drop, *and* a resistance reading at once — three independent slots

    instead of one value you had to switch the type of. Copying a worklist carries

    the nets and their readings as round-trippable text. (c869aaa, 62ea78d,

    8d06ceb)

    the active worklist shows its mark + note inline; net readings render with the

    diode glyph. (e459913, 69bee13)

    Fixes

    preserved image/env/mounts/ports; it now also re-attaches the container's

    user-defined networks (with aliases), Compose labels, and memory/CPU limits —

    fixing the reverse-proxy 502 that hit networked deployments after updating.

    (cd95a7d)

    no longer snaps the view to the top-left. (8b8dc67)

    PDFs invisibly (no panel); they now reopen, and the "reopened N" toast counts

    what actually opened. (f2cf83c)

    link-off icons (identical size on Chrome and Safari). Long file names in tabs

    are truncated with a hover tooltip. Tab colours no longer flip when a group

    loses focus, so board↔PDF switching is visually stable. (bc2855a, f2cf83c,

    af1731b, 0f7609d)

    and the PDF ∞ "auto-open boardview" toggle is renamed **"auto switch

    boardview"**. (f2cf83c, bc2855a)

    v0.31.27 — 2026-06-25

    Reload no longer loses your work, and the update dropdown now shows what's new

    before you update.

    Features

    boards/PDFs were open and the page reloads (manually or after a self-update),

    BoardRipper now asks whether to Reopen or Discard the previous session.

    It never auto-restores — so if you reloaded *because* something hung, you just

    discard and nothing reloads. The open set is persisted continuously (so even a

    hard hang/crash leaves a record). On Reopen, library files re-fetch from the

    server, dropped files come back via the library's incoming/ folder, and a

    dropped board that isn't on the server falls back to the local parsed-board

    cache; anything genuinely unavailable is reported. (188e3c6, 28d9b13,

    c7d7802, b2fbb48)

    release's notes inline, under a collapsible What's new spoiler, instead of

    only linking out. The notes are embedded in the signed update manifest

    (sliced from this changelog at release time), so they're trustworthy and work

    offline; releases without embedded notes fall back to the "Release notes ↗"

    link. (Appears for updates *to* releases cut from here on.) (94108dc,

    e7d88c0, 65fb86d, 5afddcc)

    v0.31.26 — 2026-06-25

    Two new features — a Donor boards library tab that turns marked PDFs into a

    managed, auto-indexed, reset-proof donor pool, and Worklist v2 Phase 1

    (inline per-net measurements + a relay-only AI section) — plus interface and MCP

    fixes.

    Features

    row showing its live index status and linked board. Click a row to open its

    detail (bindings + Open); double-click to open the PDF. Export / Import /

    Restore controls manage the pool. (e562176, 212e08e)

    triggers a scoped backend pdfium index of exactly that file (server-side, so the

    UI, an MCP tool, or a script all benefit), plus a boot-time backfill of any

    donors that weren't indexed yet — so "search donors only" no longer silently

    misses a never-opened PDF. (b4367c4, af499d2, e148eae)

    auto-written before a reset and restorable in one click, with manual

    Export / Import for portability — wiping the scan no longer loses your donors;

    they re-resolve to the rescanned files by path. (98308fd, e9c8cc5, 0df3351)

    V / Diode / Ω strip where the technician types a reading directly — no separate

    "to measure" list. Values are stored as NetMeasurement objects with unit,

    value, timestamp, and source (user | agent). (a288871, 4a73959)

    transcript (messages + prompt box) only — measurement requests that target a

    net route to the net row's inline field, while part/pin targets land in the

    relay as a pending row the user answers or skips. (1b7902c, 7429650)

    all net readings regardless of who recorded them — the technician typing a value

    directly on a net row and the agent requesting it via request_measurement both

    appear in the same snapshot. Optional status (pending | answered | skipped)

    and source (user | agent) filters narrow the result. (7429650)

    old always-on automatic outlines: when on, worklist parts render in their mark

    colours and any net shared by two or more worklist parts glows; when off, the

    board is unaffected. The Clear button is decoupled from the toggle. (b200bb6,

    85a00f9)

    Phase 1 migrates any flat-array AI measurement entries onto the corresponding net

    rows automatically, so existing worklists carry forward without data loss.

    (7f2e5cc)

    Fixes

    pure-CSS pseudo-elements that couldn't clamp to the viewport, so buttons near

    the right edge ran off the screen. They're now a single JS-positioned tooltip

    that clamps horizontally and flips above the button when it would overflow the

    bottom; the board hover tooltip also clamps on every edge. (8e97b36, be1c442)

    sidebar (width persisted to localStorage), its tab labels no longer sit under the

    ☰ toggle, and the redundant × close button was removed — the ☰ toggle is the

    single close affordance. (be1c442, 8e97b36)

    means) now tears the WebSocket bridge down instead of reconnecting to a dead

    endpoint every three seconds forever; each reconnect re-checks that MCP is still

    enabled before retrying. (526f0a7)

    v0.31.25 — 2026-06-24

    Smarter schematic lookup, and two fixes that make ASUS laptop .cad

    boardviews open correctly.

    Features

    Fixes

    v0.31.24 — 2026-06-23

    Extends the MCP integration with a two-way worklist AI-mode loop — an

    agent (e.g. Claude Code via the BoardRipper MCP) and the bench technician

    collaborate on the same worklist, no in-app LLM required.

    Features

    v0.31.23 — 2026-06-19

    BoardRipper can now be driven by an AI agent: a built-in MCP server exposes the

    open board — its connectivity, the schematic PDFs, OpenBoardData and the board

    database — to Claude Code (or any MCP client), and a bundled repair-helper skill

    turns that into a hands-on bench copilot.

    Features

    v0.31.22 — 2026-06-18

    A theming overhaul: three light themes, an editable custom theme, and a

    net-class pin-colour system — all carried by the theme — plus the cleanup

    that makes light themes genuinely readable.

    Features

    Changes

    Fixes

    Performance

    v0.31.21 — 2026-06-16

    Two features: PDF orientation controls and a diode-value channel for XZZ

    boards.

    Features

    v0.31.20 — 2026-06-13

    Point fix for the board-side link menu shipped in v0.31.19.

    Fixes

    v0.31.19 — 2026-06-13

    A broad UX pass driven by a six-phase improvement plan plus bench

    feedback, layered on top of the library drop-to-incoming and

    auto-indexing work. Headline: the in-tab board panel now opens on

    component Info for single-layer boards instead of the visibility

    tab, board↔PDF linking works from both sides, PDF paging and search

    stop losing your place, Settings commit behaviour is consistent, and a

    clutch of long-standing rough edges (the vv0.31.x version badge, the

    interface-scale slider jitter, the inconsistent library stats line) are

    gone.

    Features

    Changes

    Fixes

    v0.31.18 — 2026-06-11

    Bigger update than the recent point-releases — covers four areas. The

    library-list pipeline was rebuilt around a streaming endpoint with an

    IDB chunk cache so opening a 100 k-file library no longer freezes the

    UI; the PDF text-click path got a stack of lookup-precision fixes;

    holding Space now lets you peek at the other side of the board and

    returns on release; the Landrex theme's selection halo behaviour

    matches its lower-contrast aesthetic.

    Features

    Fixes

    Performance

    v0.31.17 — 2026-06-08

    Follow-up to v0.31.16. Same root cause (pdfjs-dist@5 targets a modern V8

    baseline the Legacy Mac build's Electron 22 doesn't have), broader fix:

    audited every pdfjs reference against Chromium 108 and polyfilled the

    full set so this stops being a whack-a-mole.

    Fixes

    v0.31.16 — 2026-06-08

    Defensive fix for a PDF crash observed in an older Electron build —

    verified against current Electron 35, lands as forward insurance against

    future Chromium baseline lag relative to pdfjs-dist.

    Fixes

    v0.31.15 — 2026-06-07

    New top-level interface knob: a global scaling factor that resizes every

    chrome surface so the app reads well on dense laptop screens and 4K

    displays alike, without touching board / PDF render resolution.

    Features

    v0.31.14 — 2026-06-07

    Follow-up to v0.31.13. The load-overlay UI lockout had a second source

    on the linked-PDF auto-load path.

    Fixes

    v0.31.13 — 2026-06-07

    Hotfix for v0.31.12 — multiple users reported the load-progress overlay

    blocking the entire UI, including cases where the board was clearly

    loaded behind it but the overlay refused to close.

    Fixes

    v0.31.12 — 2026-06-07

    Pad geometry pass across every format that exposes it. TVW chamfered

    pads draw their real outline, XZZ pads carry net-coloured rectangles

    instead of generic circles, 2-pin overrides no longer halo. A clean-up

    sweep on XZZ orientation made every X-fold board (A2338, A2681, most

    Apple MLBs) display correctly, and the worst-case wrong files now stick

    to a manual rotation override. Plus a new toggleable Copper-fills layer

    for ground planes, a load-progress overlay so cold opens have feedback,

    and the part outline / selection rectangle finally hugs the real pads

    on resistor packs and overhanging-pad ICs.

    Features

    TVW + Allegro + XZZ pad geometry

    XZZ orientation

    Other fixes

    Internal

    v0.31.11 — 2026-06-06

    XZZ pass: the parser now extracts the geometry that was sitting

    unread in every Apple boardview — real pad shapes, per-part silkscreen

    outlines, via drills — and renders rotated chips with rotated

    outlines instead of axis-aligned boxes that miss the body. Plus an

    issue-#19 UX fix so a PDF-driven selection respects your dim

    preference.

    Features

    Fixes

    v0.31.10 — 2026-06-05

    Hotfix for v0.31.9 — opening a PDF while 2-Window Mode was already on

    silently added it to the popout but didn't raise the popout window, so

    the user looking at the main window saw nothing happen.

    Fixes

    v0.31.9 — 2026-06-05

    2-Window Mode: a single toolbar toggle that pops the entire PDF group

    out into its own browser/Electron window so the board can live on one

    display and the schematic on another, with the click-board → jump-PDF

    link still working across windows.

    Features

    Fixes

    Cleanup

    Tests

    v0.31.8 — 2026-06-03

    PDF open path broken on older browsers — single-edit hotfix to the

    vendored pdf.js worker.

    Fixes

    v0.31.7 — 2026-06-03

    Settings panel cleanup pass plus a new global search inside Settings.

    Mechanical-part auto-detection extended and made calmer. Desktop

    artifacts now mirror to ripperdoc.de alongside the landing-page rework.

    Features

    Cleanup

    Infra

    v0.31.6 — 2026-05-31

    Worklist gains first-class net support — pin a net to a worklist from

    the search tab or right-click, mark it short/solved/absent, optionally

    flag it with the lightning-bolt surge tag.

    Features

    Internal

    Known limitations

    v0.31.5 — 2026-05-30

    Sidebar Search tab redesign, configurable navigate-to-component zoom, disco

    mode polish, and a green-CI cleanup that knocked 91 lint warnings off the

    codebase. Same-day follow-on to v0.31.4.

    Features

    Fixes

    Internal

    v0.31.4 — 2026-05-30

    Two new things you can play with: an interactive first-run gesture setup, and a

    disco highlight mode on the ghost-toggle button that pulses every same-net part

    red on both sides.

    Features

    Fixes

    Internal

    v0.31.3 — 2026-05-29

    A roundup release: new multilayer trace-layer controls, PDF viewer default and

    zoom refinements, two format-robustness fixes (PADS rejection, TVW parts

    recovery), and a batch of audit-driven backend/UI hardening.

    Features

    Fixes

    Internal

    v0.31.2 — 2026-05-26

    The real fix for the v0.31.0 update failure. v0.31.1 turned out to address the

    wrong cause — this release makes the update actually succeed on installs with a

    large existing library. As before, no install was harmed: the orchestrator

    healthcheck rolled every failed update back to the prior working version.

    Fixes

    v0.31.1 — 2026-05-26

    Hotfix for v0.31.0, which failed to boot on linux/amd64. No user was left

    stranded — the orchestrator's healthcheck rolled every failed update back to the

    prior working version — but v0.31.0 could not be installed. This release makes

    the update succeed.

    Fixes

    v0.31.0 — 2026-05-26

    Library-wide PDF full-text search rebuilt on a real backend index, automatic

    content-deduplication folded into the scan, streaming search results, and a

    Brand → Model → Board# reorganisation of the Board# view.

    PDF text search (new backend index)

    Library content deduplication

    Library views

    Scan

    v0.30.13 — 2026-05-25

    Cross-lookup between two linked PDFs — for boards that only exist as PDF — plus

    copy-to-clipboard for the current selection, drag-dropped files filed into the

    library, and an FZ unit-detection fix.

    PDF↔PDF cross-lookup

    Selection

    Files

    FZ parser

    v0.30.12 — 2026-05-25

    Worklist connection-highlighting and a more capable hierarchical net-line mode,

    plus GenCAD bottom-side placement fixes and a clearer error for encrypted

    BRD_V1.0 boardviews.

    Worklist

    Net lines (hierarchical mode)

    CAD (GenCAD) parser

    BRD parser

    v0.30.11 — 2026-05-24

    Two parser fixes surfaced by ASUS G513R laptop boards (FZ and GenCAD exports

    of the same 6050A3348801/03 design), plus a Landrex theme refinement.

    FZ parser

    CAD (GenCAD) parser

    Theme

    v0.30.10 — 2026-05-20

    Allegro parser fixes surfaced by a Dell Nvidia Quadro 5000M board

    (Nvidia_5000M_Dell.brd) — the first v17.4, millimetre-units file in the

    corpus — plus the PDF pan-boundary follow-up.

    Allegro parser

    PDF viewer

    v0.30.9 — 2026-05-19

    Two self-update papercuts found while shipping v0.30.8.

    Updater

    v0.30.8 — 2026-05-18

    Right-click context menu redesign and two parser fixes.

    Context menu

    Parsers

    v0.30.7 — 2026-05-18

    PDF watermark wand toggle — fixes a long-standing bug where the user's custom watermark term list was destroyed on every wand-off→reload→wand-on cycle.

    PDF

    v0.30.6 — 2026-05-18

    FZ format — removed the bundled ASUS RC6 decryption key. Users now obtain it themselves through a small in-app dialog (fetch from public GitHub mirror or paste).

    FZ

    Migration note for existing users. After updating, the first time you open an encrypted .fz file you'll see the new dialog. One click on Fetch restores the previous behaviour. Unencrypted .fz files (the rare case where the raw zlib stream is already at offset 4) continue to open without prompting.

    v0.30.5 — 2026-05-17

    PDF tile render path — single perf change with measurable settle-time win on fresh-tile renders.

    PDF

    v0.30.4 — 2026-05-16

    PDF viewer feel — two complementary changes aimed at making zoom and multi-page navigation smoother on heavy schematics.

    PDF

    v0.30.3 — 2026-05-16

    The headline feature is a complete rewrite of the PDF watermark filter: it now runs *inside* pdf.js (via a patch-package-managed patch) and drops watermark glyphs at parse time instead of at render dispatch. Plus a stack of Worklist polish (waterdamage flag, ticket note, custom soldering-iron icon) and a couple of tooltip / hover-info improvements from earlier in the session.

    Worklist

    PDF watermark filter — complete rewrite

    The v0.4.2 – v0.30.2 implementation passed a Set<number> of pre-computed operator indices into pdf.js's public operationsFilter render callback. That had two latent bugs that manifested on more PDFs as the filter list grew: pdf.js's getOperatorList uses NullOptimizer (raw operator stream) while render uses QueueOptimizer (merges/reorders ops), so pre-computed indices didn't line up; and any PDF that emits one showText per glyph for sub-pixel positioning (Gigabyte schematics, for example) never matched substring filters per-op anyway.

    The new design lives inside the pdf.js worker, via a patch-package-managed diff at src/frontend/patches/pdfjs-dist+5.5.207.patch. The patch:

    Trade-offs and why this shape: we tried a per-op filter (broke on per-glyph PDFs), a whole-BT-buffer-then-emit approach (broke rendering whenever a real text block went through the buffer, because state ops emitted async to the operator list landed before the buffered BT did), and finally landed on in-place glyph-array zapping after the fact — the only approach that preserves pdf.js's strict op-stream ordering while still letting us decide at BT-block granularity.

    Notable shipped fixes inside this rewrite:

    The patch survives npm install / Docker builds via a postinstall script wired into src/frontend/package.json. Updating procedure for pdf.js version bumps is documented in src/frontend/patches/README.md.

    Hover tooltip

    Clipboard

    Renderer

    v0.30.2 — 2026-05-15

    Fixed

    Polish

    v0.30.1 — 2026-05-15

    Polish

    v0.30.0 — 2026-05-14

    Headline addition: the Worklist — a per-board, persistent multi-select with named lists, marks, notes, and roundtrip clipboard sync. Plus a stack of PDF / scanner / updater fixes from the day after the v0.20.x cleanup.

    The version jump from v0.20.9 to v0.30.0 marks the first release of the new stable pipeline (signed manifest + GHCR + ripperdoc.de archive + chat-runnable release.sh) as a milestone, distinct from the 0.20.x stabilisation series.

    New

    Fixed

    Self-update overlay

    v0.20.9 — 2026-05-13

    Fixed

    Release pipeline

    Docs

    CI

    v0.20.8 — 2026-05-13

    Important: silent-update-failure root cause

    Chicken-and-egg caveat: the fix lives in v0.20.8's binary, but the orchestrator that creates v0.20.8's container runs v0.20.7's (or earlier) code — which still has the bug. So the v0.20.7 → v0.20.8 update on an affected install will still roll back. Recovery: one manual NASdeploy.sh / docker pull ghcr.io/alexeyinwerp/boardripper:v0.20.8 && docker rm -f boardripper && docker run -d ... boardripper:v0.20.8 to land v0.20.8 in place. From v0.20.8 onward, every future auto-update works as designed.

    The update-test harness (tools/update-test/run.sh) now passes --user 0:0 on the OLD container, mirroring production. This reproduces the bug end-to-end (without the fix the harness fails the same way production fails); with the fix the harness passes in ~10 s. The new scripts/release.sh runs the harness as a mandatory gate before signing — same class of regression cannot land silently again.

    Fixed

    Release pipeline

    v0.20.7 — 2026-05-13

    Fixed

    Docs

    Release pipeline

    v0.20.6 — 2026-05-12

    Fixed

    Changed

    v0.20.5 — 2026-05-12

    Fixed

    - LianBao SWITCH (NM-D355 H11): pinCount=2, sum=1 — mechanical switch with one mirrored mechanical contact

    - Landrex vertical connector (Gigabyte GV-N5080 CN1): pinCount=82, sum=82 — every pin mirrored on opposite copper layer

    - Landrex edge connector (Gigabyte GV-R79X MPCIE1): pinCount=82, sum=82 — PCIe slot dual-sided

  • Verified across the 16-file TVW corpus: NM-D355 0 → 3957 parts, GV-N5080 28 → 3161 parts, GV-R79X 0 → 4825 parts. Every other working sample unchanged. The format note is captured in docs/formats/TVW_FORMAT.md so upstream eagleview and future parsers don't make the same Z2 == 0 assumption.
  • v0.20.4 — 2026-05-10

    Fixed

    Trade-offs

    v0.20.3 — 2026-05-10

    Fixed

    v0.20.2 — 2026-05-09

    New

    Fixed

    Docs

    v0.20.1 — 2026-05-08

    New

    Fixed

    v0.19.9 — 2026-05-08

    Fixed

    v0.19.8 — 2026-05-08

    Fixed

    v0.19.7 — 2026-05-07

    Fixed

    Tooling

    v0.19.6 — 2026-05-07

    Fixed

    New

    Performance — renderer hot-path

    Four findings from the 2026-05-07 review report; all sub-millisecond individually, compounding under sustained interaction. The bundle was reverted once when its eventMode interaction with the dim-layer bug surfaced as a click-blocking regression, then re-introduced piece by piece after that bug was traced to a separate root cause and fixed independently.

    Updater hardening

    Closes the two Important findings from docs/analysis/2026-05-07-updater-security.md. The crypto primitives were already well-covered; these tighten the surrounding I/O envelope.

    Release pipeline

    v0.19.5 — 2026-05-06

    New: update-in-progress modal

    When the user clicks Update Now, BoardRipper now shows a centered modal: *"Update in progress — the page will reload automatically in 30–60 seconds."* The modal stays up across the SSE-disconnect window (the orchestrator deliberately stops the running container, killing the progress stream — that is the expected success path, not a failure). Once the new container's /api/health responds, the page reloads automatically; the modal vanishes.

    A boardripper-update-in-flight flag in localStorage persists across page refreshes mid-update — refreshing the tab while the update is in flight no longer presents a fresh dashboard with an "Update" button that could be clicked again. The flag is cleared on completion or after 5 minutes (whichever comes first). Backend health-poll runs every 2 seconds for up to 120 seconds while waiting for the new container.

    New: drop-to-update fallback

    When the in-app update button can't reach GHCR or ripperdoc.de — or when a future broken-orchestrator bug strands an install — users can now download a single bundle file and drag it onto the BoardRipper window to apply the update. Each release publishes boardripper-update-vX.Y.Z.tar (and a stable latest-update.tar alias) at https://www.ripperdoc.de/boardripper/releases/. The bundle contains the signed manifest, its signature, and the OCI image tarball; the running container verifies the signature against its compiled-in public key, validates counter/expiry/min-version, checks the tarball sha256, then runs the same orchestrator restart as the network path. Same trust envelope: only the manifest signature grants trust; the file itself is untrusted bytes until verification passes. Recovery escape-hatch for any future broken-self-update situation, but only available once the running container is on v0.19.5+.

    Internal

    v0.19.4 — 2026-05-06

    Fixed

    Migration note

    Existing v0.19.0–v0.19.3 installs cannot auto-update to v0.19.4 (their bundled orchestrator still has the healthcheck-by-name bug). One manual docker pull ghcr.io/alexeyinwerp/boardripper:v0.19.4 && recreate-container is required. After landing on v0.19.4 once, future auto-updates work normally.

    v0.19.3 — 2026-05-06

    Fixed

    v0.19.2 — 2026-05-06

    Fixed

    v0.19.1 — 2026-05-06

    First release through the new pipeline end-to-end (no GitHub Actions). Pure cosmetic fixes; the update flow itself is what's being validated.

    Fixed

    Internal

    v0.19.0 — 2026-05-05

    New: secure update pipeline (replaces GitHub-token flow)

    Updates no longer require GITHUB_TOKEN. Each release is now signed offline by

    the maintainer (Ed25519 / minisign), and the running container verifies that

    signature against a public key compiled into its own binary before applying any

    update.

    For end users: you can remove GITHUB_TOKEN from your docker-compose.yml

    after this update. The toolbar update button keeps working with no token. If you

    prefer to update manually, both sources are public and free:

    docker pull ghcr.io/alexeyinwerp/boardripper:latest
    docker compose up -d
    

    …or the signed-tarball mirror (no Docker registry required, useful behind

    firewalls):

    curl -O https://www.ripperdoc.de/boardripper/releases/latest.tar.gz
    docker load < latest.tar.gz
    docker compose up -d
    

    What changed under the hood:

    fast layer dedup) and https://www.ripperdoc.de/boardripper/ (signed tarball

    mirror). Updater walks them in order and accepts the first source whose

    manifest signature verifies. A hijacked mirror cannot deliver a forged update.

    released_at, not_after, important flag, image digest, and tarball

    sha256. Replay/freeze attacks closed by a monotonic counter; dropped manifests

    closed by a 90-day expiry.

    installs without you clicking. Releases marked important (security fixes)

    show with a red banner instead of the normal blue.

    within 60 s of starting, the orchestrator auto-reverts to the previous image.

    first boot (/data/.update-secret, mode 0600). LAN drive-by requests to

    /api/update/apply now return 401. The web UI bootstraps an `HttpOnly +

    SameSite=Strict` cookie on first load.

    Maintainer release runbook: docs/RELEASE_RUNBOOK.md.

    Fixed

    on Win7 etc.). pdfjs-dist@5 calls it directly and would throw before any PDF

    byte was read.

    Misc

    Bridge release note (one-time)

    This release is the last one published to the private GitHub Releases page —

    it's the bridge release that moves existing token-using clients onto the new

    system. From v0.19.1 onward, releases will only appear at GHCR + ripperdoc.de.

    ---

    v0.18.1 — 2026-05-05

    Fixed

    v0.18.0 — 2026-05-05

    New: themes — accent / background / chrome split

    Themes are now two independent surfaces. The THEMES registry covers board-side concerns only (pin colours, part fills, background-of-board) and the board adopts whichever entry matches its file family. UI chrome obeys three independent knobs the user can set from the QuickSettings home dashboard or from Settings ▸ Themes:

    Five accent presets ship: BoardRipper default (recoloured away from generic AI-cliché blue), and four ATARI homages (Pantone Bright Red C plus the Atari 2600 silver-label rainbow stripes). Each knob persists separately.

    New: Mentor Boardstation Neutral parser

    11th supported format. Mentor Graphics Boardstation/Expedition exports a plain-text "neutral file" with the .cad extension shipped with some Samsung / Quanta / Compal / Acer notebook board packages — not GenCAD despite the shared extension. Detection cue: # file : ... first comment + BOARD ... OFFSET ... ORIENTATION record + ###Section banners. Outline is synthesized from drill-hole geometry. See docs/formats/MENTOR_NEUTRAL_FORMAT.md for the full spec; AGPL provenance recorded in the spec footer.

    New: board-overlay search dropdowns + customizer

    The floating in-canvas overlay (top/bottom toggle, flip-axis, parts/nets filters, dim-mode tri-state, selection-name label) is now slot-driven and user-customizable. Drag-and-drop in Settings ▸ Board overlay reorders or hides slots; "Add separator" inserts a divider; layout is persisted. Parts and Nets dropdowns use a shared popover scaffold with a memoized natural-sort index (refdes-aware) and a No-Connect partition for nets.

    The dim-mode button cycles three states (off / search-dim / spotlight) — spotlight is a smooth dark gradient with a clear core sized to the selected component; selected pins draw above the spotlight so the component stays fully bright.

    New: home dashboard — bindings matrix + behaviour toggles

    The HomeBackdrop dashboard now carries a Bindings matrix (board↔PDF associations from the library) and Behaviour toggles (auto-open PDF on board load, theme switch). The QuickSettings strip got a compact accent picker.

    Fixed

    Internal

    v0.17.1 — 2026-05-04

    New

    Fixed

    v0.17.0 — 2026-05-03

    New: Cadence Allegro v15.x BRD support

    A second Allegro parser family. v15.x (magic 0x0012XXXX) is a different binary from the v16/v17 family already supported (0x0013XXXX) — different header, different block table — but many block payloads are shared. Reverse-engineered blind from a 15.5.7 / 15.5.2 corpus over the previous week:

    Spec: docs/formats/ALLEGRO_V15_FORMAT.md. Future-work items captured inline.

    Fixed

    v0.16.15 — 2026-05-03

    Fixed

    v0.16.14 — 2026-05-03

    Fixed

    v0.16.13 — 2026-05-03

    Fixed

    v0.16.12 — 2026-05-03

    Fixed

    v0.16.11 — 2026-05-02

    New: library sync (WebDAV pull)

    A scheduled background sync pulls a remote WebDAV-served library mirror into the local /library/ mount. Settings ▸ Library exposes the endpoint, schedule, and a "Sync now" button. Diff-then-fetch semantics; per-file resume; never deletes remotely-missing files (Phase 1: pull-only). Useful for repair shops who keep an authoritative library on a NAS or office server and want every workstation to mirror it without manual copy.

    Performance

    v0.16.10 — 2026-05-02

    New

    Fixed

    v0.16.9 — 2026-05-01

    New

    v0.16.8 — 2026-05-01

    Fixed

    v0.16.7 — 2026-05-01

    New: OpenBoardData (OBD) integration

    BoardRipper now reads the public OpenBoardData corpus — community-maintained per-board diagnostics, pin readings, schematics, and notes — and surfaces it inline.

    The aligned-with-real-format scraper fix in this release brought OBD live.

    v0.16.6 — 2026-04-30

    New

    v0.16.5 — 2026-04-29

    New / Cleanup

    v0.16.4 — 2026-04-29

    New

    v0.16.3 — 2026-04-29

    New

    v0.16.2 — 2026-04-29

    Fixed

    Internal

    v0.16.1 — 2026-04-29

    New

    v0.16.0 — 2026-04-29

    New: boards.db 20× expansion (145 → 2,914 boards)

    The board reference database expanded from 145 hand-curated entries to 2,914 via three import slices, all converging on the v2 schema:

    1. Wikidata Macs import (Slice 1). SPARQL fetch of all Apple Mac models → staging file → apply with INSERT OR IGNORE under v2 placeholders. Family resolver auto-assigns MacBook / iMac / Mac mini / Mac Pro / Mac Studio.

    2. XZZ Apple-laptop skeleton import. Replaces the Wikidata path with a filesystem walk of the maintainer's XZZ corpus — recovers boards Wikidata doesn't carry (Quanta / Compal / Foxconn ODM codes).

    3. Filename-scan importer (Slice 1). A pattern battery walks /library/, cross-references existing boards, tokenizes unmatched substrings, and emits a Markdown observation report + JSON sidecar. The JSON sidecar feeds an importer that creates placeholder Brand/Family/Board entries with INSERT OR IGNORE. 2.8K new boards added in one pass.

    A snapshot of the 2026-04-29 observation report is archived under docs/scan/archive/.

    Internal

    v0.15.0 — 2026-04-28

    New: boards.db v2 schema redesign + Database Editor

    The flat boards table is replaced by an entity hierarchy: Brand → Family → Board, with a color cascade and an explicit family field on each Board. The v2 resolver walks the hierarchy and returns the most specific colour/identity available; UUIDs are always freshly generated in the migration so old BoardColorHex values don't pin to retired entries.

    Fixed

    ---

    v0.14.0 and earlier

    For releases prior to v0.15.0, see the git tags directly:

    git log --oneline --tags

    (maintainer-only access until the repo is open-sourced).


    BoardRipper — project page