* docs(release): prepare v1.17.14 notes
Generate a bilingual, product-focused draft from merged pull request metadata. The reviewed catalog will drive the website, desktop app, and GitHub releases.
* fix(release): persist guide link revisions
Problem: Generated release-note guide URLs used the transient HEAD ref, which could stop resolving after the preparation branch was deleted.
Root cause: The generator interpolated the git revision expression directly into public GitHub URLs.
Fix: Resolve the source revision to an immutable commit SHA and update the v1.17.14 guide links to the reviewed candidate commit.
Verification: node --check scripts/generate-release-notes.mjs; node scripts/release-notes.mjs validate; node --test scripts/release-notes.test.mjs; rendered-link and privacy scan; git diff --check
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Problem: The release-notes preparation workflow failed after generating a new version because its test required 1.17.13 to remain the first catalog entry.
Root cause: The test duplicated mutable release data as a hard-coded constant even though loadCatalog already validates descending version order.
Fix: Remove the stale version assertion while retaining schema, ordering, and uniqueness validation through the catalog loader.
Verification: node scripts/release-notes.mjs validate; node --test scripts/release-notes.test.mjs; git diff --check
Problem:
Release notes were assembled independently from commit-oriented GitHub output, leaving the website, desktop updater, and CLI/Desktop releases without one reviewed product narrative.
Root cause:
There was no structured bilingual release catalog or review workflow shared by the site, desktop UI, and tag publishers.
Fix:
Add a validated release catalog and DeepSeek-assisted draft workflow, publish responsive website changelog pages with shared navigation, link Desktop update surfaces to the web history, and render the reviewed notes into CLI and Desktop GitHub releases.
Verification:
- node scripts/release-notes.mjs validate
- node --test scripts/release-notes.test.mjs
- npm test and Astro build in site/
- pnpm run build in desktop/frontend/
- actionlint for all affected workflows
- git diff --check
Cache-impact: none - release metadata, website UI, desktop links, and publication workflows do not change provider-visible prompts, tool schemas, request serialization, or ordering.
Cache-guard: existing scripts/cache-guard.sh remains applicable; no cache-sensitive path changed.
The cache-impact gate watched only internal/ prompt surfaces, but two
cache-sensitive surfaces lived outside it:
- desktop/session_prompt.go rewrites the persisted leading system
message with the freshly composed prompt on every tab resume/rebind;
any byte difference there invalidates the whole conversation's prefix
cache and persists the rewrite.
- internal/environment/* composes the environment section embedded in
the cached system prefix; probe output changes shift the prefix bytes
for every session.
Add both to the cache-sensitive list and to the system-prompt-sensitive
list so changes require Cache-impact/Cache-guard lines and an explicit
System-prompt-review note.
* @
fix(codegraph): resolve symlinks when extracting third-party bundle
The lexical tar/zip-slip guard missed the symlink-redirect escape: an
in-bounds symlink extracted as a parent component lets a later entry be
written through it to land outside the cache dir. Resolve the real parent
with EvalSymlinks before validating, and judge a symlink target from its
resolved location. Closes the go/unsafe-unzip-symlink + go/zipslip alerts.
@
* @
fix(scripts): run gh without a shell in backfill-issue-labels
execSync built a shell command string from interpolated values; switch to
execFileSync with an argv array so label and issue arguments can never be
parsed as shell. Closes the js/command-line-injection alert.
@
* @
ci(e2e-bot): gate untrusted PR-head run behind an environment
Running PR-head code with the provider secret was guarded only by the
author_association check. Add an `e2e-bot` deployment environment (configure
required reviewers to force per-run approval) and pin the checkout to the
head commit resolved at trigger time, detached, so a mid-run force-push
cannot swap in different code. Addresses actions/untrusted-checkout-toctou.
@
* @
fix: bound integer conversions flagged by code scanning
parseHexColor parses single bytes; parse them as 8-bit unsigned and return
int so the per-channel value is provably in range, dropping the
int64->int conversions at the call sites. Clamp the Myers maxD against a
negative n+m overflow too, so make() can never see a wrapped size.
@
---------
Co-authored-by: reasonix <[email protected]>
The desktop release dropped Debian/Ubuntu packaging in the v2 rewrite —
Linux only shipped a bare-binary tar.gz (discussion #3627). Add a .deb
built with goreleaser/nfpm in desktop-build.sh's linux branch.
- desktop/build/linux/nfpm.yaml + reasonix.desktop describe the package:
binary to /usr/bin, .desktop entry, icon to /usr/share/pixmaps, and
libgtk-3-0 + libwebkit2gtk-4.1-0 runtime deps apt resolves on install.
- The .deb is a human-download artifact only (like the macOS .dmg); the
Linux updater channel stays the tar.gz, so cmd/sign's manifest skips
.deb files. A test locks the linux-amd64 key to the tarball.
- release-desktop.yml installs nfpm (pinned v2.46.3) on the Linux runner.
The existing sign / upload / release / R2-mirror steps already glob dist/*,
so the .deb is signed, attached to the GitHub release, and mirrored with no
further workflow changes.
Co-authored-by: reasonix <[email protected]>
Replace the ad-hoc macOS codesign with Developer ID signing (hardened runtime + entitlements + timestamp), notarize and staple the .app and .dmg via notarytool. Gated on HAS_APPLE_CERT from the APPLE_* secrets; ad-hoc fallback when unset.
* feat(desktop): add opt-in canary update channel
A canary build (-X main.channel=canary) polls R2's canary/ pointer instead of
latest/, so a stable install can never auto-update onto it. Folded into the
existing desktop release workflow as a dispatch-only channel input: build/sign/
manifest are shared, only version/publish/mirror branch on channel. Tag/version/
channel resolution is centralized in scripts/resolve-desktop-release.sh. CLI is
unchanged (stays on the npm next tag).
* feat(cli): add opt-in canary npm dist-tag
A version containing -canary. publishes to the canary dist-tag instead of
next/latest, so npm i reasonix@canary opts in and 1.x (next) / 0.x (latest)
users are untouched. release-npm.yml gains a workflow_dispatch canary mode
that builds the current ref as <base>-canary.<run_number>.
---------
Co-authored-by: reasonix <[email protected]>
* feat(ci): AI-classify new issues into area/platform/severity labels
Add an issue-auto-label workflow that uses the DeepSeek API to classify new issues into a fixed area/platform/severity label set (with a needs-triage fallback when no area is identified), plus a backfill script for existing open issues. Labels are validated against an allowlist so the model cannot invent new ones.
* feat(ci): auto-label PRs by changed path
Add actions/labeler config + workflow that applies area labels to PRs based on changed file paths, complementing the AI-based issue labeler. Path-to-area mapping mirrors the area set in issue-auto-label.yml; severity/platform stay issue-only.
Ship a macOS .dmg (drag-to-Applications) for first-time install alongside the .zip updater channel; point the site's macOS download at it. The .dmg is named -universal so cmd/sign's manifest substring match skips it.
The Linux artifact linked libwebkit2gtk-4.0.so.37, which Ubuntu 24.04+
and Fedora 40+ no longer ship, so the app failed to start with a missing
shared-object error. Build with -tags webkit2_41 and install the 4.1 dev
package; 4.1 is available from ubuntu-22.04 on, so the runner is unchanged.
Closes#3154
Co-authored-by: reasonix <[email protected]>
The macos-13 Intel runner is scarce and often stalls the desktop release for a
long time. Build a single darwin/universal app on the macos-14 (arm64) runner
instead — it carries both Intel and Apple Silicon slices, so one runner covers
both and the slow Intel leg goes away.
desktop-build.sh publishes the one universal .app under both Reasonix-darwin-arm64.zip
and Reasonix-darwin-amd64.zip so the existing manifest keys (and the updater's
darwin-<arch> lookup) resolve unchanged — no updater or sign changes needed.
Co-authored-by: reasonix <[email protected]>
A `desktop-v1.0.0-rc1` tag aborted the NSIS build: VIFileVersion needs a strict
X.X.X.X, and goversioninfo's fixed version is numeric too, so the `-rc1` suffix
("1.0.0-rc1.0") is rejected. Strip the prerelease suffix (and leading v) for the
stamped productVersion; the full tag still rides in ldflags as the in-app
version. Verified a v1.0.0-rc1 build now produces the installer with a 1.0.0
version resource.
Co-authored-by: reasonix <[email protected]>
A local Wails build produced an exe with a blank "File version" in its Windows
properties. wails.json's info block carried no productVersion, so the generated
versioninfo template resolved `{{.Info.ProductVersion}}` to empty and the binary
shipped with no usable file version.
Fill the info block (companyName, productVersion, copyright) and have
desktop-build.sh stamp productVersion from the tag before `wails build` —
numeric only, since a leading "v" breaks goversioninfo's fixed-version parse.
The same productVersion feeds the macOS bundle version. Verified the exe's
FileVersionRaw now reads the tag version.
Co-authored-by: reasonix <[email protected]>
* feat(release): npm + homebrew distribution for the CLI
The CLI only shipped as raw GitHub-release archives; the README promised
`npm i -g reasonix` and brew, neither of which existed.
- goreleaser (.goreleaser.yaml) now owns archives, SHA256SUMS, the GitHub
release, and an auto-maintained esengine/homebrew-reasonix formula,
replacing the hand-rolled scripts/release.sh.
- npm/ ships the binary the modern way: a `reasonix` wrapper whose bin shim
exec's a per-platform `@reasonix/cli-<os>-<arch>` optionalDependency, so
npm installs only the matching native binary — no postinstall, offline-OK.
npm/build.mjs cross-compiles all six targets and publishes the set.
- release.yml fans out to goreleaser + npm jobs on a v* tag.
Publishing needs three one-time setup items: the @reasonix npm org, the
esengine/homebrew-reasonix tap repo, and NPM_TOKEN + HOMEBREW_TAP_TOKEN
secrets. Desktop (desktop-v* / Wails + R2 updater) is unchanged.
* fix(release): homebrew_casks + tag npm prereleases
Two issues caught running the release locally (goreleaser snapshot + npm
publish --dry-run):
- goreleaser removed `brews` in v2.16; the `~> v2` action would have failed
the release. Migrate to `homebrew_casks` (binary cask + a postflight that
strips the macOS quarantine xattr, since the archives aren't notarized).
Cask install is macOS-only, so the README brew line drops the Linux claim —
Linux installs via npm or the release tarball.
- npm refuses to publish a SemVer prerelease without an explicit dist-tag, so
a `v1.0.0-rc1` tag would have errored. build.mjs now publishes prereleases
under `next` and stable versions under `latest`.
---------
Co-authored-by: reasonix <[email protected]>
The Wails desktop had no CI release and no updater (Tauri's updater plugin
is gone in the Go rewrite). Add both, reusing the v1 R2/GitHub distribution.
- release-desktop.yml: desktop-v* tag → 4 native-runner matrix → minisign
sign → latest.json manifest → GitHub release → R2 mirror. The CLI's v*
release line is untouched.
- internal/update + cmd/sign: shared manifest type, embedded public key, and
minisign verify — used by both the CI signer and the updater, so the sign
and verify paths share one definition.
- updater.go / updater_app.go: CheckUpdate/ApplyUpdate over the two-endpoint
manifest. Linux and Windows update in place (selfupdate / per-user NSIS);
macOS falls back to the download page (unsigned bundle vs. Gatekeeper).
- Frontend: an update banner (startup auto-check) plus a Settings "Software
update" section, with en/zh strings.
- Per-user NSIS template (project.nsi) committed; README documents the
unsigned first-launch steps and minisign verification.
The first CI run needs MINISIGN_PRIVATE_KEY / MINISIGN_PASSWORD secrets
(the v1 minisign key, converted to the standard format).
Distribution shifts from "bundle the ~230MB CodeGraph runtime into every
archive/package" to "fetch it on first use into a per-version cache" — so
npm installs and release archives stay small, and only users who use the
feature pay the download.
- internal/codegraph/install.go: Install() downloads the platform asset +
SHA256SUMS from the pinned CodeGraph release, verifies the checksum, and
extracts (tar.gz/zip, zip-slip guarded, exec bits preserved) atomically into
<user cache>/reasonix/codegraph/<version>/. REASONIX_CACHE_DIR overrides the
base.
- Resolve() now prefers the cache, then PATH, then a bundle beside the binary.
- boot: when codegraph isn't installed, fetch it in the background (one-time,
non-blocking) if auto_install is on, else point at the install command.
- New `reasonix codegraph install|status` subcommand; mcp list reflects it.
- config: [codegraph].auto_install (default true).
- release.sh no longer bundles codegraph — bare binaries on all platforms.
- Docs (MIGRATING/CHANGELOG/example.toml) updated for the fetch model.
Verified end-to-end: `reasonix codegraph install` downloads + verifies +
caches the real v0.9.7 bundle; status/mcp-list resolve it from cache; the MCP
e2e passes against the cached launcher.
CI (ci.yml): on push/PR to main-v2, run gofmt check (root module),
go vet, build, and test on ubuntu + macOS, with the Go version pinned to
go.mod.
Release (release.yml + scripts/release.sh): on a v* tag, cross-compile all
six targets, bundle the matching CodeGraph runtime beside the binary on
darwin/linux (verified against CodeGraph's published SHA256SUMS), package
per-platform archives, and publish a GitHub release with a SHA256SUMS
manifest. Windows ships a bare binary for now — its bundle layout is not yet
verified, so it falls back to a PATH-installed codegraph.
Verified release.sh end-to-end locally: all six archives build, the four
darwin/linux ones carry codegraph/bin/codegraph beside reasonix (so the
bundled-path resolver finds it), checksums match.