Repository navigation
Releases
HackDigest 0.5.0
Maintenance release: a data-robustness fix, the glaze dependency caught
up to its first tagged release, and the product site moves onto the
family design system. No new features; the app's settings schema and
routes are unchanged.
Fixed
- A UTF-8 BOM in
settings.json(produced by BOM-emitting editors such as PowerShell 5.1'sSet-Content -Encoding UTF8or legacy Notepad saves) maderead-jsonthrow, and the reader's error handler silently turned the whole configuration into an empty map — the provider config vanished with no diagnostics and the startup key migration saw no key. The data-file reader now strips a leading BOM once, forsettings.jsonandlibrary.jsonalike, and notes it on stderr (#47, regression-tested). - Windows WebView2 controller creation failing with
E_ABORTwhen several app instances or windows raced the machine-wideglaze-webview2user-data folder: absorbed by the glaze v0.18.0 pin (one data folder per process,GLAZE_WEBVIEW2_DATA_DIRfor a stable cache path) together with automatic retries for transient controller aborts.
Changed
- The glaze pin flips from the 0.4-era main head (
671ea4d) to the v0.18.0 release across CI and release workflows. Runtime deltas absorbed: per-process WebView2 data folders on Windows, atomic directory replacement in the updater, AppImage payload resolution through$APPDIR, Applications drop target and unique volume names for plain dmg builds, and a native Windows ARM64 webview backend. Schema compatibility verified (zero breaking changes); all four packaged-native CI legs selftest the v0.18.0 build. - The product site homepage is rebuilt on the family site-kit (v1.0.3): family design system (terracotta accent, Newsreader display), browser-locale language detection with a persisted override, and a unified download resolver over the real release assets.
Release infrastructure
- A keep-alive regression test locks in the #40 finding (the reported persistent-connection misframe was a mock artifact —
llm.rktopens a fresh connection per request and Racket sendsConnection: closeby default): 30 sequential titles batches against a real keep-alive server with server-side framing/parse assertions.
HackDigest 0.4.0
Added
-
Secure BYOK key storage (issue #2 secret-custody slice): the key moves out of plain
settings.jsoninto the system keyring — macOS Keychain (SecItem), Windows Credential Manager (CredWriteW/CredReadW), Linux Secret Service (libsecret) — behind a product-side FFI (backend/secure-store.rkt). Startup migration moves an existing plaintext key into the keyring, or stamps an explicitapiKeyStorage: "plaintext-optout"marker when no keyring is available (never silently). Settings gains a status row (keyring / plaintext opt-out) with move/opt-out actions over the newPOST /api/settings/key-storageroute, plus a clear-saved-key button; hosted license keys are exempt (visible by design). Red-green artifact-scan tests: a canary key is written, migrated, and every file under the data dir scanned — green proves zero plaintext residue with resolution still working, red proves the scan catches the pre-migration leak. CI exercises the logic against an in-memory store; the real keyring FFIs are validated on the family VMs per platform. -
Commit the real backend Glaze schema baseline and project manifest, with a CI compatibility check that imports the API without opening a window or database. Document the current delivery priorities and bounded hosted-usage policy.
-
HACKDIGEST_SELFTEST=1self-terminating launch assertion: the packaged app must open its WebView, render the served page from the controlled origin, and composite pixels (title poll + capture) before exiting 0; any failure or timeout exits non-zero with no browser fallback. Release CI runs it on every platform against the packaged artifact (app bundle, dist tree, MSI exe, AppImage), then re-probes the HTTP adapter (HACKDIGEST_TRANSPORT=http) over loopback.
Changed
- Remove the superseded hosted config surface (issue #2 free-product gate check): the "HackDigest Pro(托管)" provider preset, license-key activation, device-bound 7-day trial, and the trial/lifetime/pro quota panel are gone while hosted remains not on sale, per the
2026-10-v2pricing decision and the2026-10-auth-1authorization decision (account-bound entitlements, no desktop activation lease, no per-device trials). Legacy settings withproviderId: "hosted"remap on load to a working custom endpoint (same base URL / key / model; cachedhostedStatusdropped), and the auto-translate toggles that were stranded inside the hosted-only settings branch are now visible for every provider.racobackend untouched: the settings mask exception for legacy hosted keys stays until secure-storage migration. - Native transport is the default on all three platforms — the packaged-native switch of the Glaze 1.0-plan G4 cycle closes the consumer transport gap (#2).
HACKDIGEST_TRANSPORT=httpremains the explicit development adapter;GLAZE_API_TOKENapplies to that adapter only. CI and release installs now pin Glaze at the main head that carries the G4 native-host conformance matrix (flip to the next tagged release when it exists).
Fixed
- The key-storage route returned
migrated: nullfor both no-op and refusal, so the settings page could show a fake success on machines with a locked or missing keyring; it now raises a user error the page can render. - Every page-initiated non-streaming chat failed with an llm-contract internal error: the page always sent
maxTokens: null, which arrived as the'nullsymbol and violated the contract;chat-opts-from-jsexprnow centralizes null-safe option parsing for both chat routes.
Release infrastructure
- The CI packaged-native matrix now mirrors the shipped macOS flavors natively (arm64 on
macos-latest, x64 onmacos-15-intel) instead of selftesting an x86_64 build under Rosetta — the per-commit gate now exercises the flavors users actually receive. - The Windows HTTP-adapter smoke runs on a fresh runner: the selftest instance can wedge mid-exit on GitHub runners (GPU-less teardown hang, filed upstream as glaze#124) and keep the single-instance mutex alive for minutes, which no cleanup script can reliably beat. The mutex-gated cleanup (
taskkill /F /T+Mutex.OpenExistingprobes) stays in the smoke's retry loop as defense. - Transient-failure retries for the DMG
hdiutil attachverification and the appimagetool digest fetch.
HackDigest v0.3.1
Alignment release: the docs catch up with what v0.3.0 already ships, the
site joins the family dark-mode baseline, and the updater's download loop
gains a watchdog. No app-facing behavior changes beyond the hardening.
Added
- Download watchdog in the updater: a transfer that stops making byte
progress for 120 seconds, or that runs past a 30-minute wall-clock
total, is broken out of its worker (exn:break), the.partialfile is
cleaned up, and the phase lands on error — the UI always gets a terminal
state instead of resting on "downloading" forever. - User guide:
docs/guide.htmlon the product site — five-minute start,
engine and BYOK setup, reading preferences, shortcuts, and FAQ
(data location, privacy, platforms, updates incl. the 0.2.x path,
uninstall). Bilingual viadata-i18n, default Chinese.
Changed
- README (English and Chinese) now describes the updater as it actually
works since v0.3.0: startup fetch of the Ed25519-signed manifest,
in-place swap on macOS/Windows portable installs, download-and-reveal on
Linux, release page for installer channels — replacing the stale
"in-place updates wait on glaze#47" wording. The download table shows
the real v0.3.0 Linux matrix (tar.gz / deb / rpm / AppImage / zip, every
format on both architectures, per-asset.sha256sidecars). - CI and release workflows pin glaze to
v0.13.1(.git-suffixed URL)
instead of a floating branch install. - Product site: palette aligned to the family values (
#faf7f2/
#c15f3c/#e8e2d9…), full dark mode with a manual toggle,
localStorage persistence and a head anti-flash script, and download
copy that matches the real update flow.docs/GLAZE-MIGRATION.mdis
marked as completed with a pointer to the CHANGELOG.
HackDigest v0.3.0
Linux packaging closes the family benchmark gap format-for-format, and every
binary asset now carries a per-asset .sha256 sidecar.
Added
- Linux
.rpmpackages for x64 and arm64
(hackdigest-<version>-1-linux-x86_64.rpm,...-aarch64.rpm),
hand-rolled withrpmbuildfrom a generated spec that mirrors the deb
layout (/opt/hackdigest, ahackdigestlauncher, desktop entry,
pixmaps icon) and rivet's recipe: no%disttag and the libtinfo
dependency exclusion that keeps the Ubuntu-built Racket runtime
installable on Fedora.Requiresnames what the runtime FFI-loads
(gtk3, webkit2gtk4.1, openssl-libs, xdg-utils) - Linux
.zipportable archives for both architectures — the same
self-contained tree the tar.gz carries - The AppImage now ships for arm64 too (per-arch
appimagetoolbinary,
same digest-verified fetch), with the launch smoke running on both
architectures - The signed update feed carries a Linux arm64 tar.gz entry, so arm64
installs get in-app updates
Changed
- Every binary asset on every platform ships a per-asset
.sha256
sidecar (macOS dmg/zip, Windows msi/zip, and the full Linux set);
SHA256SUMScontinues to aggregate them
HackDigest v0.2.0
Linux packaging parity: the Linux line gets first-class installer assets,
matching the family bar on macOS and Windows. Nothing about the update feed
or the in-app updater changes — these are installer assets published beside
the portable tar.gz.
Added
- Linux
.debpackages for x64 and arm64, hand-rolled withdpkg-deb:
the app installs to/opt/hackdigestwith ahackdigestlauncher on
PATH, a desktop menu entry, and hicolor icons.Dependsnames what
the runtime actually FFI-loads (WebKitGTK, GTK 3, OpenSSL 3 for the
updater's signature checks, xdg-utils) instead of a laundry list, and
release CI installs the package into a cleanubuntu:22.04container
to prove the dependency set is sufficient. - Linux AppImage (x64), assembled with
appimagetoolfrom the same
distribution directory — same system-WebKitGTK requirement as the
tar.gz and deb, so it stays honest about what it bundles. - Linux arm64 builds: the release pipeline now runs its Linux leg on a
native arm64 runner, shippinghackdigest-<version>-linux-arm64.tar.gz
and.debbeside the x64 ones. Arm64 is an installer asset only for
now — the signed update feed still carries the x64 tar.gz.
Changed
- Release assets follow the family naming on Linux too:
hackdigest-<version>-linux-<arch>.<ext>now covers.tar.gz,.deb
and.AppImage, all covered bySHA256SUMSand build-provenance
attestations.
HackDigest v0.1.0
The in-app updater (R3 of the Glaze migration) and the 0.x epoch reset:
HackDigest can now update itself end to end, closing the gap v1.0.1
documented as "open the release page". The 1.x line's releases and tags
are withdrawn as the whole family enters its 0.x stage.
Added
- Full update flow on portable installs: the backend fetches the release's
Ed25519-signedupdate-manifest.json, verifies it against the embedded
key, downloads this platform's artifact with a progress indicator, checks
size and SHA-256 against the signed feed, and swaps the install:- macOS portable
.app: ditto-unpack, atomic bundle swap with a
.oldbackup, automatic relaunch. - Windows portable zip: unpack beside the install dir,
cmdhandover
(waits for the app to exit,.oldswap, restart); failures leave a
marker that the next launch reports. - Linux: the downloaded tar.gz is revealed in the file manager — extract
it over the app folder by hand (family rule for archive installs).
- macOS portable
- Settings → About now offers the same flow with live progress; the
startup banner drives it too. - Release pipeline:
scripts/make-update-manifest.shsigns the update
feed from the portable artifacts before publishing (key supplied via the
UPDATE_ED25519_PRIVATE_KEYsecret; releases without it fall back to
release-page-only updates), and the release workflow gained a
concurrency group.
Changed
- Updating honestly, by install type: portable macOS/Windows installs
update in place; DMG/MSI installs point at the release page (the app
cannot rewrite itself there without elevation); Linux downloads and
reveals the archive. The check falls back to the v1.0-style
release-page behavior whenever no signed manifest is published. - Settings → About shows the packaged version reported by the backend
(it previously showed a stale build number).