Repository navigation
Releases: smallcatlabs/acquisition-qt
Release list
v0.18.7
This release moves Acquisition to a new home and renames it with -qt to mark that it's the C++/Qt version of acquisition. There were no other changes.
Acquisition has a new home
The repository is now smallcatlabs/acquisition-qt, under the Small Cat Labs organization. GitHub redirects every old gerwaric/acquisition link, so bookmarks, forks and existing installs keep working.
Installed copies of 0.18.6 and earlier check for updates through that redirect. This release reads the new address directly, in the update checker, the Help menu links and the installer metadata, so once you are on 0.18.7 you no longer depend on the redirect.
Upgrading is recommended for that reason alone.
I'm also going to see if I can start signing binaries or releasing via app stores. I've already got developer accounts for Small Cat Labs, so that was another reason for the move.
What comes next
A ground-up redesign of Acquisition is being built at smallcatlabs/acquisition. Right now it's just a CLI and an MCP and a giant pile of Rust. It is not fully functional. That repo is a sloppy mess, too, so caveat emptor.
I will maintain the C++/Qt version at least until the rewrite is close to feature parity, which I'd guess might happen in early 2027 if things go well.
Also in this release
- Documentation: the trade ground-truth record gains T16–T34 from hand tests of the price dialog and the trade site, and the network record gains N46 (a refresh token invalidated between sessions).
- Commits made with AI assistance now carry an
Assisted-by:trailer, written by a commit hook. - The release workflows declare the permissions they need, which the move to an organization made necessary.
What's Changed
- docs(ground-truth): T16–T19 — the owner's hand tests of the price dialog and the trade site by @gerwaric in #226
- docs(trade-ground-truth): T20–T22 — the substash link, the unpriced link, the spoiler shape by @gerwaric in #227
- docs(ground-truth): T25–T34, T17 rewritten, T11 amended — the site as the oracle; N46 by @gerwaric in #228
- chore(githooks): a commit-msg hook writes Claude's trailer as Assisted-by by @gerwaric in #230
- Rehome to smallcatlabs/acquisition-qt; ADR 0003 accepted by @gerwaric in #231
Full Changelog: v0.18.6...v0.18.7
v0.18.6
No new features; just keeping up with API changes for 3.29.3b.
--@gerwaric
This release brings Acquisition's copy of the Path of Exile API object
definitions back in step with the game updates. There are no changes to how
items are fetched, searched, priced, or displayed.
API object definitions
Path of Exile 3.29.3b added mercenary data to the API's objects, and
Acquisition's type definitions now match:
MercenarySkillis its own type. It previously existed only as
Item::MercenarySkills, nested inside the item object.LeagueAccountneeds
the identical shape, so the definition moved to its own header that both
share rather than being written out twice.LeagueAccountgainsmercenaries— a mercenary's name, level, build,
build hash, skills, and items.Charactergainsactive_mercenary_index.
Nothing in the program reads these fields yet. Acquisition's JSON reader
already ignores keys it does not recognize, so 0.18.5 parsed these responses
without complaint and no one was seeing errors; this is about keeping the
definitions honest so the fields are there when something wants them.
Building from source
The Linux build notes gain a section on a confusing failure when running a
local build against an official Qt kit: OAuth login, the Help menu links, the
update download, and the crash-report links all quietly do nothing.
The application is not at fault. It hands the URL to xdg-open, which passes
it to a desktop-specific helper, and that helper is a distribution binary built
against the distribution's Qt. If LD_LIBRARY_PATH points at an official Qt
installation, the helper inherits it, loads the wrong Qt, and fails to resolve
its own dependencies. Most helpers exit successfully even so, which is why
nothing surfaces in the application and the browser simply never opens.
The fix is to leave LD_LIBRARY_PATH unset; the binary's RUNPATH already
covers Qt. BUILD.md describes the symptom, the check, and the two places Qt
Creator sets the variable.
Also in this release
- Documentation: the network ground-truth record gains N37–N45 (per-account
rate-limit counters,/profileand/account/leaguesfirst contact, PoE2
character policies, per-realm lists, the item realm field, id-less granted
skills, and two policies pacing independently) and answers Q12 — GGG confirmed
/profileis not rate limited at present and promised a fix for
/account/leaguescounting HEAD requests. - A new trade appendix records T1–T15: the trade site's channels, the forum
link code, the in-game price dialog, and what the API reports of listings. - ADR 0003 notes that it needs no action from agents.
What's Changed
- docs(adr): 0003 needs no action from agents by @gerwaric in #220
- docs(ground-truth): N37–N40 + Q12 — per-account counters, /profile and /account/leagues first contact by @gerwaric in #221
- docs(ground-truth): Q12 answered by GGG — /profile unlimited at present, /account/leagues HEAD fix promised by @gerwaric in #222
- docs(ground-truth): N41–N45 — PoE2 character policies, per-realm lists, item realm, id-less granted skills, independent pacing by @gerwaric in #223
- docs(ground-truth): T1–T15 — the trade site's channels, the forum link code, the in-game price dialog, and what the API reports of listings by @gerwaric in #224
- Release 0.18.6: PoE2 0.5.5 and PoE1 3.29.3b API object changes by @gerwaric in #225
Full Changelog: v0.18.5...v0.18.6
v0.18.5
Oh, look--documentation! --@gerwaric
This release is mostly about documentation and packaging. There are no changes to how items are fetched, searched, or priced.
New: a user guide
Acquisition's features were documented only in the source code and in old release notes, so it was easy to miss that something already existed.
The new user guide covers, in eight short pages:
- logging in with OAuth, choosing a realm or private league, and where your data lives
- the search window, all 38 filters, and the item table columns
- the Mods filter and every pseudomod, with the real mods each one sums
- buyout types, tab-level prices and inheritance, prices set in the game, and the legacy buyout importer
- forum shop threads, the shop template, and POESESSID
- the currency overview and CSV export
- refresh modes, rate limiting, themes, logging, updates, crash reports, and a table of common problems
It is written from the code rather than from screenshots, and this is its first release, so expect gaps. If a page disagrees with the program, the program wins; please open an issue.
A new Help menu in the main window links to the guide and to the issue tracker.
Windows installer: Visual C++ runtime
0.18.4 fixed a startup crash caused by an old Visual C++ runtime, but only if you let the installer update it. The installer now treats the bundled Microsoft Visual C++ Redistributable as a prerequisite rather than an option: it runs it, checks the result, tells you if Windows wants a reboot, and removes any stale runtime DLLs left beside acquisition.exe by earlier installs. Packaging also refuses to build if the redistributable is missing or not signed by Microsoft. (#215)
Building from source
Thanks to @wigust for two Linux build fixes and a first contribution:
cmake --installnow works: it installs the application, the Crashpad handler it launches, and on Linux the.desktopfile for menu integration. (#210)- The vendored
qdarkstylelibrary now links Qt6::Core explicitly, fixing acopy relocation against non-copyable protected symbollinker error with recent system Qt builds. (#216) - GCC 16's new
-Wsfinae-incompletewarning onRateLimitPolicyis silenced withQ_MOC_INCLUDE; the code was correct, but the generated moc files probed the type before its definition was visible. (#217)
Also in this release
- Two menu items that were never wired to anything are gone: Settings → OAuth (Show/Refresh Token) and a hidden Refresh Mod List action.
- Documentation: the network ground-truth record gains N34–N36 (a 401 carries no rate-limit headers; the shape of an origin 503;
veiledModsis volatile).
What's Changed
- docs(ground-truth): N34 — a 401 carries no rate-limit headers; Q11 by @gerwaric in #208
- docs(ground-truth): N35 origin 503 shape, N36 veiledMods is volatile by @gerwaric in #209
- Cmake add install phase by @wigust in #210
- Fix Windows Visual C++ runtime installation by @gerwaric in #215
- qdarkstyle: switch to shared library to fix linker error by @wigust in #216
- Prepare 0.18.5: user guide, Help menu, GCC 16 warning fix by @gerwaric in #218
New Contributors
Full Changelog: v0.18.4...v0.18.5
v0.18.4
This is a bugfix release for Windows. If 0.18.3 died when you launched it, this release should fix that. The bug is a regression introduced earlier in the v0.18.x series that only affected Windows machines with MSVC++ runtimes from 2021 or earlier.
--@gerwaric
Fixed: instant crash at startup on Windows
Acquisition 0.18.3 could crash before it finished starting up, on the very first lock it took — inside logging, before there was anything to log to. It showed up as an access violation in MSVCP140.dll, the Microsoft Visual C++ runtime.
The cause is a mismatch between the compiler and the runtime on your machine. Recent MSVC compilers changed how std::mutex is initialized; a Visual C++ redistributable from 2021 or earlier does not understand the new form and dereferences a null pointer the first time the mutex is used. The build already had the flag that turns this off, but it was only applied to one of the several targets that make up the app — which, because of how the affected code gets emitted, is worse than not applying it at all: the linker picks whichever version it likes and the protection silently disappears.
The flag is now applied to the entire build, including every bundled dependency. The reported crash came from a Windows 10 machine running a February 2021 runtime, so the fix is aimed at exactly that case: Acquisition should now run against any 14.x Visual C++ runtime rather than needing a current one.
Verified on a fresh Windows Release build: all 55 compiled targets carry the flag, the executable links against the runtime-initialized constructor, and the test suite passes 39/39. Installing the bundled Visual C++ redistributable is still the more robust option if the installer offered it and you declined.
Tracked as F78 in docs/cleanup/findings.md, from Sentry issue 7687078638.
Also in this release
- Documentation only: the Rust spike on the
spikes/rust-playgroundbranch is now indexed from the docs map and referenced by ADR 0003.
What's Changed
- docs: index the Rust spike from the documentation map and ADR 0003 by @gerwaric in #205
- fix(build): define _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR for the whole build (0.18.4) by @gerwaric in #206
Full Changelog: v0.18.3...v0.18.4
v0.18.3
Claude has realized I like these preambles and started trying to write them for me. Heh.
--@gerwaric
This release is mostly about recovering buyouts that were lost when upgrading from an Acquisition older than 0.16. It also fixes two crashes, one of which has been around for a long time.
New: recover legacy buyouts
If you upgraded from a pre-0.16 Acquisition and most of your prices disappeared (#197), this release can recover them from the old data file. The workflow is offline — it reads buyouts from the old file and writes to your current one.
Back up your Acquisition data before using it.
- Buyouts → Recover legacy buyouts… reads an old Acquisition data file and produces an XLSX recovery plan listing every legacy price and its proposed destination. Database versions 4 and 5 are supported; older files are rejected without changing anything.
- Choose Import now to accept the suggested actions, or Save plan for review… to inspect or edit the plan in a spreadsheet and apply it later with Buyouts → Import buyout plan….
- Before importing, log into the intended account and complete a full refresh. The final confirmation names the account whose data file will be written; the legacy file you select is never modified.
- Existing manual prices are skipped by default, and re-checked when the plan is applied, so a price you set after building the plan is protected rather than overwritten. Accepted rows are written in a single transaction, and the workbook is updated with per-row results, so it also serves as an audit record.
Matching was validated against a real Acquisition 0.15 database: all 1,137 item buyouts and all 12 tab buyouts were recovered into the plan. This is the same workflow that shipped in 0.18.3-beta.1, unchanged; everything below is new since that beta.
Fixes
- Pressing Login without a league no longer kills Acquisition. The league is now checked in the login dialog, where you can still fix it, instead of reaching a fatal error deeper in startup. (#138)
- The login button works again after a failed login. A failed attempt left the dialog looking ready but inert, so the only way to retry was to restart.
- Fixed a long-standing crash in the search-filter panel. Laying out the filter panel could feed its own width back into itself and recurse until the stack ran out, closing the app with no message. This bug predates 0.18.3; it was found in a crash report on sentry.io.
Crash reporting
Nothing you interact with, but it crash reports from this release are more useful:
- Native crashes from released builds are now symbolicated: debug symbols for Windows, macOS, and Linux are uploaded at build time.
- Crash reports are separated by build type, so pre-release and local builds no longer count against a stable release's crash-free rate.
- Each report is tagged with the Qt version Acquisition was built against and the one it actually loaded, which is a recurring source of Windows crashes.
- The Windows symbol file attached to releases is now named for its version (
acquisition-0.18.3.pdb) instead of a bareacquisition.pdb, and CI now refuses to build a release whose tag disagrees with the version in the source.
Also in this release
- Network capture (a diagnostic feature) writes timestamps in UTC and uses a separate file per session.
- The item tooltip's minimap rectangle is computed in double precision; a cleanup, with no difference you are likely to see.
- Documentation: the rate-limit ground truth for the network redesign is now transcribed and cited by number, including the separate policy GGG applies to the OAuth token endpoint.
What's Changed
- Legacy buyout import (0.18.3-beta.1) by @gerwaric in #198
- docs(network): transcribe rate-limit-core ground truth (N27–N32) by @gerwaric in #200
- docs(ground-truth): N33 — oauth/token rate-limit policy observed by @gerwaric in #201
- ci: upload native debug symbols to sentry for all three platforms by @gerwaric in #202
- fix: stop the layout recursion and the fatal login abort by @gerwaric in #203
- Prepare 0.18.3 by @gerwaric in #204
Full Changelog: v0.18.2...v0.18.3
v0.18.3-beta.1
This beta adds an offline recovery tool for buyouts lost when upgrading from
Acquisition versions before 0.16.
The workflow has substantial automated and historical-data validation, plus a
limited live smoke test; the beta label reflects that broader real-world import
coverage is still needed.
Back up your current Acquisition data before using it.
New: recover legacy buyouts
- Open Buyouts → Recover legacy buyouts… and select an old Acquisition data
file containing the legacy buyouts. Database versions 4 and 5 are supported;
older files are rejected without changing current data. - Acquisition creates an XLSX recovery plan showing every legacy price and its
proposed destination. Choose Import now to accept the suggested actions,
or Save plan for review… to inspect or edit it before using
Buyouts → Import buyout plan…. - Before importing, switch to the intended account and complete a full refresh.
The final confirmation makes clear that prices will be written to that
account's current data file; the selected legacy file is never modified. - Existing manual prices are skipped by default and rechecked when the plan is
applied. Accepted changes are written in one transaction, and the workbook is
updated with per-row results so it also serves as an audit record.
Other changes
- Network-capture timestamps are now written in UTC.
- Each network-capture session now uses a separate output file.
Validation
- All 39 automated tests pass, including importer matching, edited plans,
rollback, repeated imports, and protection of existing manual prices. - Matching was validated against a real Acquisition 0.15 database: all 1,137
item buyouts and all 12 tab buyouts were recovered into the plan.
Full Changelog: v0.18.2...v0.18.3-beta.1
v0.18.2
This is a minor patch with a fix to item parsing. No other features or user-visible changes.
--@gerwaric
Fixes
- Item reward amounts are parsed as integers again.
Item.rewardsmaps a
reward type to an amount. The official developer docs describe that amount as
an int, but the API returned it as a string at some point, so the field had
been typed as a string to keep deserialization from failing. It now matches
the documented schema again, validated against live stash data.
Notes
- Nothing in Acquisition currently reads the
rewardsfield, so the change is
confined to item deserialization. This build was exercised in an extended
live-data test session before tagging.
Full Changelog: v0.18.1...v0.18.2
v0.18.1
Acquisition v0.18.1 is a small patch release: a handful of fixes and some credential-safety hardening on top of v0.18.0. There are no new features and no changes to how the app works.
Findings numbered like F30 refer to entries in the project's findings register, the ledger of known design and correctness issues tracked in the repository.
Fixes
- Buyout prices are no longer written in scientific notation. Very large prices (for example 1,000,000 chaos) used to come out as
1e+06in generated shop text; they are now written with full digits. (#150) - Clearer advice when a forum shop update can't find an item. The error message suggested a menu option ("Update stash index") that no longer exists; it now gives the correct advice — simply resubmit, since every shop update fetches a fresh index.
- Less alarming logs during normal refreshes. The rate limiter's "BORDERLINE" pacing message was logged as a warning even though it is a normal part of pacing near a limit; it is now informational. Refresh behavior itself is unchanged. (F30)
Credential safety
Hardening around what can end up in log files — worth having before you ever share a log when reporting a bug:
- Your OAuth token is no longer written to the log when trace-level logging is enabled; it now appears masked. (F71)
- Fixed a bug in the log-masking helper that could have let
Authorizationheaders through unmasked in future logging paths. (F72) - Token parsing errors can no longer include raw token text in the error log. (F73)
There is no indication any of this affected you unless you enabled trace logging and shared the resulting log file. If you ever did that, you can invalidate the old token by logging in again.
Internal cleanup
- Removed dead code found during recent code audits: unused website endpoint headers (which also had incorrect contents), an unused shop signal, and unused OAuth session state. (F68, F69, F76)
- Build fix: the crashpad helper copy and
ctestnow work under any CMake generator/shell. - Welcome Auro (@aurokin) to the contributors list!
Credits
- Two small fixes: BORDERLINE log level (F30) and buyout price formatting (#150) by @aurokin in #193
- Resolve the mechanical findings F68-F73 and F76 by @gerwaric in #194
Full Changelog: v0.18.0...v0.18.1
v0.18.0
I'm releasing 0.18.0 sooner than planned because of #189. This release addresses that issues by clearing your POESESSID the first time it appears to invalid.
--gerwaric
Acquisition 0.18.0
This release adds support for Path of Exile 3.29 and substantially improves how Acquisition refreshes, displays, and publishes item data. Refresh results now appear incrementally without repeatedly resetting the item view, making large stashes more responsive while preserving your selection, expansion, and scroll position.
User-facing changes
- Added support for the Path of Exile 3.29 item-data format.
- League and realm selections are preserved after logout, even when “Remember me” is disabled.
- Added private-league support: you can now type a private-league ID into the league selector.
- Refreshes now update the interface incrementally as stash tabs and characters are received.
- Refreshing items no longer repeatedly resets the item view. Existing expansion, selection, and scroll state remain intact when unrelated tabs change.
- “Refresh selected” and “Refresh checked” now fetch only the requested tabs, even when other tabs have not previously been cached.
- Stash tab renames, moves, and other metadata changes are reflected during any refresh without unnecessarily downloading their contents again.
- Newly discovered tabs and characters appear in the list immediately. Their contents are fetched during a full refresh or when explicitly selected.
- Buyout and shop-related updates are now limited to the affected items instead of rebuilding the entire view.
- Forum shop submission now waits for a cleanly completed refresh and uses the latest eligible item data.
- A malformed stash or character response no longer prevents the refresh from continuing with other content.
- Forum updates are safely stopped when the configured
POESESSIDis rejected. - Fixed handling of rate-limit policy changes returned by authenticated Path of Exile requests.
- Added automatic repair for databases created by early 0.16.0 alpha builds.
Backend and technical changes
- Reworked the items worker around owned coroutine tasks, per-refresh cancellation, staged batch submission, and deterministic shutdown.
- Added stronger cancellation, lifetime, and leak-safety guarantees, backed by an ASan/LSan CI test gate.
- Replaced snapshot-based refresh propagation with source-keyed, per-tab deltas.
- Reworked the item model, search views, sorting, and buyout propagation to apply changes in place instead of resetting and rebuilding the complete model.
- Added stable item-location identity and authoritative row reconciliation across the By Tab, By Item, and search views.
- Added a typed terminal refresh event and explicit refresh outcome handling.
- Reworked forum shop generation around captured item revisions and single-active-job submission.
- Changed the stash and character cache to retain the exact response bytes received from the API, avoiding lossy JSON reserialization.
- Updated the cached JSON schema and Path of Exile domain types for the 3.29 API.
- Added extensive worker, model, search, shop, migration, integration, and large-dataset benchmark coverage.
Included work
#175, #177, #180, #181, #182, #183, #184, #185, #186, #188, and #190.
Thanks to @aurokin for the private-league and login-selection improvements.
Full changelog: v0.17.1...v0.18.0
v0.18.0-alpha.5
Acquisition should now remain usable while you are refreshing tabs.
Technical Changes
- Store received wire bytes in the stash/character cache (F62) by @gerwaric in #183
- docs: freeze the items-pipeline M2 spec at revision 9 (S1-M2 spike result) by @gerwaric in #184
- Items pipeline M2: streamed per-tab deltas, typed terminal event, skip policy, and the shop gate by @gerwaric in #185
- M3 spec: delta-native items model (frozen at revision 4) by @gerwaric in #186
- Items pipeline M3: delta-native items model — the refresh path no longer resets by @gerwaric in #188
Full Changelog: v0.18.0-alpha.4...v0.18.0-alpha.5