Every release, in plain language — what was added, what changed, and what we fixed. 18 releases from April 26, 2026 to August 31, 2026.
1.5.140Latest
Changed
Title discounts now match the rest of the product, and several have moved. The panel was using its own out-of-date table — every other screen had been recalibrated back in May, and the extension's copy was never updated, so the same car could be worth one thing in the panel and another on the web. A salvage title is now a larger deduction than the panel used to apply; a lemon, a fresh-flood and a non-repairable title are all smaller deductions than before. You do not need to do anything — the old values are retired automatically when you update.
When we have no data for a section, it now says so. "Similar cars that sold" and "This car at auction" stay on screen with a plain line — "No sold records for this 2017 Tundra yet" — instead of quietly vanishing. A missing section now means a fault, not an absence, so it is obvious when something has actually gone wrong.
A section that is still loading says it is loading, and never reports "none" while an answer is still on its way.
Fixed
The sold average no longer appears and then disappears. The figure arrived, then a background refresh overwrote the record that held it, and nothing asked for it again for the rest of the session. It looked random; it was not. On a 2017 Tundra we hold 337 sales at a $8,950 median — the number was there the whole time.
"This car at auction" no longer vanishes on most cars. Its no-data state only appeared once an auction had ended, which is true of about one car in eight — so on 233 of 398 real cars the section simply was not there. A car with no prior auction history is normal, not an error.
A recalls check that never came back is no longer shown as a green all-clear. The panel treated "no answer" and "no recalls" as the same thing, so a timeout could report a car as clear. It now says when it could not reach NHTSA.
Market value no longer says "Loading…" forever in the classic layout. A stalled lookup now falls back to an honest neutral reading after two minutes, and a value that is on its way is correctly shown as loading in three cases where it previously showed a blank dash.
After updating the extension, a car you had already opened no longer shows a stale "no records" answer left behind by the previous version.
1.5.135
Added
"Most likely salvage" warning. When a car's record points to salvage but the title we hold says otherwise, the panel says so. It is a warning only — it never changes the title, and your number stays yours.
Changed
The photo read no longer decides a car's condition. Condition now comes from age and mileage; the AI read stays on screen as a note you can act on. About 6% of cars had an AI-influenced tier, and those values generally move up.
Shipping is a real distance now. It used to be measured centre-of-state to centre-of-state, so any car in your own state collapsed to the $150 minimum. It now measures from the yard the car is actually in.
Airbags deployed always counts as heavy damage.
A title we cannot read is priced as Clean and labelled NOT VERIFIED — on every surface. It is no longer quietly halved, and it no longer inherits whatever default title type you had set.
Sold prices search is far more forgiving. The make and the year can sit anywhere in what you type — "2019 BMW X5" and "X5 BMW 2019" both work — and a trim we don't recognise is dropped and named, instead of returning nothing at all.
Fixed
The first car you open in a session no longer loads without a sold average. The sign-in token used to arrive after the panel had already drawn.
Market values no longer give up after 29 seconds. The panel waits for the cached answer the same way the web app does.
Sold comparisons wait for your plan to load instead of racing a 9-second timer.
Setting damage to "none" now clears a hidden secondary damage that could still be priced into the estimate.
The panel priced a salvage car differently from every other screen. One number now.
Auction and non-auction cars have a single definition across the extension, the web app and the phone — so a private listing no longer gets the auction bidding instrument.
A title you set no longer erases the damage you entered, the fee on a non-auction car is a real number, and the fee explanation is back.
One vocabulary for damage severity everywhere, and a car is never drawn before your settings have loaded.
The app opens lighter — the startup request ships 42 KB instead of 207 KB.
1.5.118
Added
Inspection mode. A guided walkthrough for the car in front of you, ordered by where you stand rather than by category — one pass around the vehicle, with the checks that match its damage brought to the top. Includes a parts sheet with quantities and used / aftermarket / OEM pricing, a labour line, and notes. Open it from the lot panel; it runs on the web and everything saves against the VIN.
What to bring. A short, honest tool list — what each one actually tells you and what it cannot. No filler.
Comps page. A dedicated view of what cars like yours really sold for, with the reasoning shown: which step narrowed the number and where the evidence ran out.
Changed
The lot panel now opens Inspection mode where it used to offer a report.
Sold-price figures now count only cars that actually sold. Nearly half of all auction records are refused bids; including them was dragging averages down.
Fixed
Your parts sheet now reaches your account. It was saving in the browser only, so it never followed you to another device.
Title Discount now saves too — it had been browser-only for months.
Clearing the Title Discount field no longer inflates the car. Emptying it was being stored as a deliberate "0% discount", raising a salvage car's resale figure by more than half — and then hiding the row you would have used to undo it. Clearing it now restores the default, and the row stays put.
Comps no longer narrow by auction house by mistake. One auction site reports no title on any record, so the "matching title" step was quietly filtering by site. Cars we hold dozens of sales for were showing no price at all. Coverage of "here is a number" went from 74% to 91%.
The comps trail no longer says "no sales" when a step was deliberately skipped.
1.5.109
Added
Browse is ours now. Search runs against our own inventory rather than passing every keystroke to a third party — faster, and it keeps working when they wobble.
Filter counts that are real. Each filter shows how many cars actually match before you apply it, and you can pick several at once.
Nearest-first sorting by your own ZIP, worked out in the browser — the ZIP never leaves your device.
Colour and vehicle type now filter properly. The data was always there; it was never being read.
Fixed
An ended lot no longer says "Current bid" for a sale that finished.
Trailers no longer appear among the cars.
1.5.105
Fixed
Auction fees were badly understated — the real charge on a $4,200 car is about $990, not $300. Rebuilt from 13 published fee schedules and verified against them, so profit figures reflect what you will actually pay.
A slow provider no longer empties the grid. A 43-second response used to wipe the results; now it degrades and tells you.
The outage banner no longer sits under a "0 lots" heading that contradicted it.
Sold-outcome capture never fired — cars that ended were not being recorded.
1.5.99
Added
Analysis is explicit. Cars are analysed when you press Analyze this car, not automatically on every page you happen to open.
Reports generate from what is on screen, so the document can never disagree with the panel you were reading.
Comp rows link back to the original listing and carry a Copart / IAAI chip.
Auction history became a layer on the lot view rather than a separate lookup.
Changed
Your weekly allowance is silent until you reach it. No counter following you around; a clear message when you hit the wall.
1.5.69
Added
The modern lot view is now the default — collapsible sections, a proper theme system, and the full mobile layout on both modes.
Confirm / Adjust banners on title and condition, because both are the seller's claim until you verify them.
BUY NOW marker on the profit bar, matching web and mobile.
Settings folded into a drill-in, so the panel is not one long scroll.
A condensed watchlist filter bar — three rows down to one, with chips.
Fixed
A crash in the lot view that shipped in an earlier build.
Ended lots now show a clear "No record" state instead of an empty space.
1.5.19
Added
Implied repair cost now derives from researched repair percentages rather than being inferred from value loss.
Mobile: Android push notifications, a new default theme, per-theme navigation, recalls on auction lots, and a bookmark confirmation that tells you which list a car went to.
Fixed
Signing out now revokes the session server-side, rather than only forgetting it locally.
1.5.18
Added
AI photo read on the lot page — condition assessed from the auction's own images.
Free vehicle-specs enrichment: generation, configurations, recalls and safety ratings, at no extra cost to you.
"Likely salvage" inference when a title looks clean but the record does not support it.
Age-modulated salvage and rebuilt discounts — a 3-year-old salvage car and a 15-year-old one do not lose the same share of value.
1.5.17
Fixed
Auction History tile no longer freezes at 0 on fresh VINs. The server returns the audit before its auction-history lookup finishes; the panel now shows "Checking…" and re-fetches in the background until the history lands (the report already had it — the tile was the only thing left behind).
1.5.16
Changed
"Email the founder" → "Email support" in the Help sheet. Same inbox, more professional label — and the wording now matches the web app's new Help button.
1.5.7
Added (report — Phase 4)
Buyer Mode — simplified shareable report view that hides editable inputs and your private cost overrides. Use the new Share button to send a clean read-only link to a co-buyer, partner, or customer without exposing the math behind your bid.
Share button in the report toolbar — generates a shareable URL.
Changed (report — Phase 3 print polish)
PDF / print layout rebuilt — no orphan headings, no truncated rows, consistent margins across all sections of the report.
Standalone overrides now flow into the report consistently. Previously a value overridden in Standalone view could mismatch the same field in the rendered report.
Fixed (math integrity)
Market Valuation is now driven exclusively by `analysis.exitMultiplier` — single source of truth. Eliminates a divergence path between the in-panel card and the printed report that could have surfaced as off-by-cents amounts.
Internal
1052 tests pass.
1.5.6
Fixed (sync — multi-device data integrity)
`/audit` no longer wipes locally-uploaded scrape fields. Server's `lots.vehicle_data` upsert now uses JSONB shallow merge instead of whole-row replace. After a `/audit` call, fields the audit response doesn't carry (`images`, `title_type`, `odometer`, `current_bid`, `damage`, etc.) survive on the server. Was the root cause of "data disappears on Device B" reports.
Legacy `lot_number`-keyed `lotHistory` entries no longer skipped by backfill. ~40% of long-time users had entries keyed by lot_number from the pre-2026 storage convention. Backfill now rescues the VIN from `entry.full_vin` so those entries upload correctly to the server's shared cache.
`lotHistory` compaction — one-time re-key from `lot_number` to VIN, with the legacy key replaced by a small pointer stub so `lotOverrides` keyed by lot_number still resolves.
Pull-then-push migration with merge semantics. Both branches always run; push branch skips `createList` for lists that came from the same migration's pull (eliminates 9× 409 noise on every sign-in).
Render layer reads identity fields with fallback. `carTitle` reads year/make/model from `vdb_decode._year/_make/_model` when `specs.year/make/model` are unset (post-rehydrate state). Card render stamps `lot_number` and `full_vin` from the watchlist entry when missing on `lotHistory[VIN]` — fixes the "Lot #?" + empty-VIN + non-functional Select-mode bug.
Added (sync — propagation guarantees)
Background write-through (SYNC-LOTS-011). Any local write to `lotHistory[VIN]` from a syncable source (scrape, /audit, manual lookup, etc.) debounces 5s and uploads via `/lots/bulk`. Other devices see new data within seconds, not on next manual reload.
Auto-resync at 24 h (SYNC-MIG-004). Migration flag is no longer permanent — if older than 24 h, next sign-in re-runs pull-then-push. Catches anything the live write-through might have missed (service-worker eviction, offline edits).
Fixed (download report)
Top-quad "Current Bid" now uses BIN as the price when no live bid exists, matching the card. Label flips to "Buy It Now" in the BIN-fallback case.
Top-quad "Mileage" uses the same odometer-resolution chain as the card (override-first, then auction_history / sales_history fallback). Was reading raw `d.odometer` only.
Top-quad "Est. Repair" falls back through analysis's resolved repair when auction has no published estimate. Was empty when both `auction_history[0].est_repair_cost` and `d.est_repair_cost` weren't set.
Title & Condition table — Est. Repair Cost row reads `d.est_repair_cost` when `auction_history[0]` is missing.
Vehicle Details — Odometer row uses the same override + fallback chain as the top quad.
Auction Info — Current Bid row filters the `'-'` sentinel correctly (was rendering as a literal dash).
Internal
975 tests pass. SYNC-LOTS-010, SYNC-LOTS-011, SYNC-MIG-002, and SYNC-MIG-004 added with full regression coverage. lotHistory compaction utility extracted into `extension/lib/lotHistoryCompact.js` with its own test file.
1.5.5internal · not published to CWS
Added
Sync v2 Phases A–F. New `lots` shared per-VIN cache table on the server, populated by `/audit` and read by a batch `GET /lots` endpoint. Replaces the old "every device re-audits independently" pattern with a true shared cache.
Settings sync (Phase D) — `userSettings` JSONB blob synced via `/user/settings` push/pull with whitelist validation.
Recent-VIN sync (Phase E) — `user_recent_vins` table synced on audit/lookup so the recent-VIN list is consistent across devices.
On-focus refresh (Phase F) — when the side panel regains visibility, scan watchlist VINs and refresh anything older than 12 h via the lazy `/lots` batcher.
Staging environment via Fly.io + a dev-mode toggle in Settings that flips the extension between prod and staging API bases.
Fixed
Three correctness gaps in sync — lots backfill silently dropping legacy entries, pull-then-push not running both branches reliably, drift between local and server max-bid values.
Watchlist self-heal recognizes migration stubs (entries with `full_vin` + `savedAt` only) and re-fetches enrichment.
`/lots/bulk` body-limit raised to 8 MB so backfill of users with rich `lotHistory` (auction_history + market_values arrays) doesn't 413 the request.
`client_upload` is last-write-wins, regardless of source. Earlier precedence gate prevented client uploads from overwriting prior audit rows; that gate was wrong because client-side `lotHistory` often holds the freshest data the user has.
Internal
v1.5.5 manual test plan committed to `docs/testing/`.
1.5.4live on Chrome Web Store
Changed
Title-discount multipliers recalibrated against AAMVA + NHTSA research. The previous Salvage / Rebuilt / Flood / Theft Recovery values were rough placeholders; the new numbers reflect documented resale-loss ranges per title brand. Bucket-aware variants (A/B/B+/ C/D) follow the same recalibration.
Damage bracket label updated from "Estimated repair" to "Rough flipper estimate" with an `(i)` tooltip explaining the source. The label change protects users from interpreting the bracket as a guaranteed repair quote.
Est. Repair row hides on clean-title lots with no current damage. Showing it on a clean lot with `damage='Normal Wear'` was misleading — the auction's listed est_repair_cost (sticky from a prior listing) doesn't apply to the current state. Hidden when `title_type='Clean'` AND no damage label is present.
Added
Track C Phase 0 — server-side math. New `server/lib/` modules mirror `extension/lib/analysis.js`. New `POST /analyze` route returns the same verdict + profit zones the extension computes locally. Establishes parity so the future PWA / mobile clients can swap from local computation to server-driven without changing the renderer contract.
Estimator parked as a separate product (not a Pro feature). See `docs/estimator/STRATEGY.md`.
1.5.3
Changed
Profit & Decision card redesigned around a single horizontal bar. The three vertically-stacked market-value rows (Wholesale / Private Party / Dealer Retail) collapse into one bar with green/yellow/red profit zones (≥15 % margin / tight / loss). Below it: a uniform "Your Costs" section (Bid · Buyer Fee · Shipping · My Repairs) and a single "Est. Profit" headline with the formula spelled out in plain English ("Sales − Bid − Fee − Ship · My Repairs not included"). Three named sections — Resale Range & Profit Zones, Your Costs, Est. Profit — keep the card scannable.
My Sales Price is user-editable. Click the right endpoint label to type a custom resale target; capped at MSRP so the bar's zoom stays sane. When set, a ▼ arrow appears above the bar and the default-tier value shows struck-through next to it.
Bid + My Sales Price markers are draggable. Mousedown on either marker to slide it along the bar; profit zones recompute live. Snaps to $100 increments.
My Repairs is opt-in for the headline profit. The default profit is now optimistic (no repair budget subtracted). Tick the new "Include in profit" checkbox next to My Repairs to fold it in. Verdict banner mirrors this same toggle so the card and verdict can't disagree.
Internal
New pure helper `renderProfitBar()` consumes the cart-shape outputs added to `extension/lib/analysis.js` (`salesPrice`, `salesPriceTier`, `salesPriceOverridden`). Watchlist expanded cards reuse the same function with a per-lot ID prefix.
Pre-redesign `renderPDSection()` snapshotted to `docs/legacy/profit-decision-v1.js` for archival reference.
1.5.2
Fixed
Pro tips toggle now persists across restarts. A boot-order race between `chrome.storage.local.get` (which restored the last analysis) and `loadSettings` (which merged saved preferences) meant the tips carousel re-rendered against `DEFAULT_SETTINGS` on every cold start — so users who turned tips off saw them reappear after each panel restart. Settings now load before any UI restore.
Side-damage labels match the right multiplier. Copart/IAAI sometimes write primary damage as `Left Side`, `Right Side`, `Front Left`, `Rear Right`, etc. None matched the `SIDE` / `FRONT END` / `REAR END` keys in `DAMAGE_TIERS`, so the multiplier fell through to 1.0 (no damage applied). New `normalizeDamageType()` helper maps directional variants → canonical buckets, both for the multiplier lookup and for auto-selecting the right Damage Type dropdown option.
Captive auto-lenders no longer misclassify as bank repos. Server-side classifier was returning `bank` for "BMW Financial Services", "Mercedes-Benz Financial", etc., because the generic `financial` keyword in the bank list matched before the more specific `bmw financial` in the leasing list. Lease returns ≠ bank repos — different risk profiles.
Changed
"Standalone" tab renamed to "Look Up" (visible label only — storage keys + JS branches still use `standalone`). Reads more naturally for non-engineering users.
VIN input button changed from "Look Up" → "Go" so the tab name and CTA aren't echoing each other.
Watch List index cards inset from panel edges (`#wl-index` gains `padding: 0 8%`) so the four list cards (IAAI / cars.com / Carfax / COPART), search input, and "+ New Watch List" button don't run flush against the panel edges.
Watchlist toolbar wrap behavior fixed. At narrow widths, filter pills no longer get flung to the far edge as an orphan row — they now hug the same left gutter as the row above when they wrap.
Recently Viewed cards bumped up — taller padding, larger title/meta text, faint border so each row reads as a discrete card instead of a flat list.
Header wordmark restyled — heavy-weight all-caps "AUCTIONMATE" + bordered black-bg italic "Pro" chip mirroring the new logo.
Connection status pill redesigned as a subtle dot + small text instead of the generic `.badge` style.
VIN barcode icon redrawn with proper varying-width black bars (reads as a real barcode at small sizes).
Pencil rename icon flipped horizontally so the tip points bottom-left at the list name it edits.
Added
"Off" option in Settings → Default Reminder. Selecting it hides the bell entirely on every watchlist car card. Existing scheduled alarms still fire as scheduled — the bell UI just goes away.
Bell-off and side-damage handling are covered by 9 new tests in `tests/damage.test.js` and the seller classifier fix has 21 new tests in `tests/seller.test.js`.
Server (deployed but transparent to users)
Free tier `market_data` quota tightened from 50/day → 5/day so a small number of free signups can't blow the upstream API monthly cap. Pro tier likewise tightened from 500/day → 30/day to match realistic dealer usage (~25/day = 600–800/month). Existing JWTs carry old limits for up to 24h until refresh.
Per-IP rate limiting on unauth routes, request body size caps, NDJSON file-size guard.
1.5.1first public release
Highlights
Salvage profit math overhaul. Split current-state vs exit multiplier so salvage lots get the proper Rebuilt resale rate as their exit value, not the salvage rate. Visible "→ Rebuilt resale" label so the routing is clear. User-set Recon overrides implied repair (renamed "My Repair Estimate") so the Suggested Max Bid stops returning "No profitable bid" on lots where the user has already estimated their own repair.
Single profit headline — folded the previously contradictory "Profit After Fix" line into the headline callout so users see one authoritative number, not two competing ones.
Per-lot notes simplified. Single editable textarea, auto-save, 300-char cap, VIN-keyed (so notes survive tab switches between Standalone / Copart / IAAI). Replaced the timeline-of-discrete- notes model.
Cross-lot VIN rescue — VIN resolved on Standalone propagates back to the same lot on Copart/IAAI so the auction tab shows the full unmasked VIN automatically.
IAAI fullscreen photo-viewer guard — content script no longer blanks the side panel when the user opens IAAI's full-screen photo view.
Display size picker — Compact / Default / Comfortable scales the entire side panel via root font-size for users on different screen densities.
Recently Viewed VIN history on the Standalone empty state with source badges (Copart / IAAI / Standalone), lot / bid / title / damage context, never stores masked VINs.
Floating help bubble with feedback / how-it-works / email founder actions. Feedback posts to `/feedback` with quick-pick category tags.
"Likely salvage" flag rule — fires when damage is present but the title brand isn't confirmed (catches the common Copart pattern where a $4k damage estimate sits on a "Clean" title).
Compliance-aware footer — disclaimer surface on every page, data source attribution, no implicit guarantees.
Server / infrastructure
251 tests covering analysis math, flag rules, server routes (via fastify.inject), notes helpers, scrape-degraded detection, VIN rescue, salvage+damage matrix.