From 8966de4c4ff184ee84fbee82df49f92d3d0ac2a7 Mon Sep 17 00:00:00 2001 From: Vijit Singh Date: Sat, 1 Aug 2026 16:04:02 -0500 Subject: [PATCH 1/4] chore(perf): record miner-0 baseline for v1.13.1 Co-Authored-By: Claude Fable 5 --- tests/perf-baselines/miner-0.history.jsonl | 1 + tests/perf-baselines/miner-0.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/perf-baselines/miner-0.history.jsonl b/tests/perf-baselines/miner-0.history.jsonl index e7de36b..4c00168 100644 --- a/tests/perf-baselines/miner-0.history.jsonl +++ b/tests/perf-baselines/miner-0.history.jsonl @@ -8,3 +8,4 @@ {"tag":"v1.10.0","recorded":"2026-07-17","bench_1m_hs":10736.5} {"tag":"v1.11.1","recorded":"2026-07-18","bench_1m_hs":10743.9} {"tag":"v1.13.0","recorded":"2026-08-01","bench_1m_hs":10733.4} +{"tag":"v1.13.1","recorded":"2026-08-01","bench_1m_hs":10762.5} diff --git a/tests/perf-baselines/miner-0.json b/tests/perf-baselines/miner-0.json index 8873ca1..339b0f3 100644 --- a/tests/perf-baselines/miner-0.json +++ b/tests/perf-baselines/miner-0.json @@ -1,5 +1,5 @@ { - "bench_1m_hs": 10733.4, + "bench_1m_hs": 10762.5, "cpu": "AMD Ryzen 7 7800X3D 8-Core Processor", "recorded": "2026-08-01" } From de8239869b6385121810573c77b5da5429e9eb45 Mon Sep 17 00:00:00 2001 From: Vijit Singh Date: Sun, 2 Aug 2026 10:10:56 -0500 Subject: [PATCH 2/4] fix(setup): probe the distro's cpupower package name so Debian installs don't fail (#327) (#337) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The apt dependency list named linux-tools-common unconditionally, but that package is Ubuntu-only — Debian ships cpupower as linux-cpupower — and apt's install transaction is all-or-nothing, so the one unknown name failed the ENTIRE dependency install: git, build-essential and cmake never arrived either. Probe with apt-cache show (the same guard the kernel-versioned linux-tools-$(uname -r) package already had) and add whichever name the distro actually ships; when neither exists, warn and carry on — cpupower is a tuning aid, never worth losing the compiler toolchain over. Closes #327 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 --- CHANGELOG.md | 10 ++++++++++ rigforge.sh | 15 ++++++++++++++- tests/run.sh | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd99125..b9fe290 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,16 @@ All notable changes to RigForge are documented here. The format is based on ## [Unreleased] +### Fixed + +- **Debian: dependency install no longer fails on `linux-tools-common` (#327).** The apt dependency + list named `linux-tools-common` unconditionally, but that package is Ubuntu-only — Debian ships + cpupower as `linux-cpupower` — and apt's install transaction is all-or-nothing, so the one unknown + name failed the ENTIRE install: git, build-essential and cmake never arrived either. `setup` now + probes with `apt-cache show` (the same guard the kernel-versioned `linux-tools-$(uname -r)` + package already had) and adds whichever name the distro actually ships; when neither exists it + warns and moves on — cpupower is a tuning aid, never worth losing the compiler toolchain over. + ## [1.13.1] - 2026-08-01 ### Fixed diff --git a/rigforge.sh b/rigforge.sh index f6fa9e0..2fefea9 100755 --- a/rigforge.sh +++ b/rigforge.sh @@ -738,7 +738,20 @@ _detect_pkg_manager() { DEP_LIST="git build-essential cmake libuv1-dev libssl-dev libhwloc-dev gettext-base python3" if [ "$OS_TYPE" == "Linux" ]; then # msr-tools (rdmsr): lets `doctor` verify the prefetcher MSR mod actually applied (#66). - DEP_LIST="$DEP_LIST linux-tools-common msr-tools" + DEP_LIST="$DEP_LIST msr-tools" + # cpupower's package name differs by distro: linux-tools-common on Ubuntu, + # linux-cpupower on Debian. apt's install transaction is all-or-nothing, so one unknown + # name would fail the ENTIRE dependency install — gcc/cmake included (#327). Probe with + # apt-cache show (same guard as the kernel-versioned package below) and add only the + # name this distro actually ships; when neither exists, warn and carry on — cpupower is + # a tuning aid, never worth losing the compiler toolchain over. + if apt-cache show linux-tools-common &>/dev/null; then + DEP_LIST="$DEP_LIST linux-tools-common" + elif apt-cache show linux-cpupower &>/dev/null; then + DEP_LIST="$DEP_LIST linux-cpupower" + else + warn "No cpupower package found (tried linux-tools-common, linux-cpupower) — skipping it. Frequency tuning via cpupower may be unavailable." + fi if apt-cache show "linux-tools-$(uname -r)" &>/dev/null; then DEP_LIST="$DEP_LIST linux-tools-$(uname -r)" fi diff --git a/tests/run.sh b/tests/run.sh index 10c3d02..b01cec6 100644 --- a/tests/run.sh +++ b/tests/run.sh @@ -2534,6 +2534,56 @@ chmod +x "$LT"/* PATH="$LT" CALL_LOG="$LT/calls.log" install_dependencies /dev/null 2>&1 assert_contains "apt install list includes linux-tools- (#74)" "$(cat "$LT/calls.log")" "linux-tools-6.0.0-rig" +# The same run doubles as the Ubuntu cpupower shape (#327): apt-cache says linux-tools-common +# exists, so it's picked and the Debian name never enters the list. +assert_contains "Ubuntu shape: cpupower via linux-tools-common (#327)" "$(cat "$LT/calls.log")" "linux-tools-common" +assert_absent "Ubuntu shape: linux-cpupower stays out (#327)" "$(cat "$LT/calls.log")" "linux-cpupower" + +# #327: cpupower's apt package is distro-dependent — linux-tools-common (Ubuntu) vs linux-cpupower +# (Debian) — and apt's all-or-nothing transaction means one unknown name kills the ENTIRE dependency +# install (gcc/cmake included). The probe must pick the name the distro ships, and a double miss must +# warn without touching the toolchain install. Ubuntu shape is asserted on the #74 run above. +echo "== unit: apt cpupower package probe — Debian / neither exists (#327) ==" +DEB="$(mktemp -d "$SANDBOX/deb327.XXXXXX")" +printf '#!/bin/sh\nexit 1\n' >"$DEB/dpkg" # every dep "missing" -> all go to the install list +cat >"$DEB/apt-cache" <<'EOF' +#!/bin/sh +# Debian trixie shape: linux-cpupower exists; linux-tools-common and linux-tools- do not. +case "$*" in *linux-cpupower*) exit 0 ;; *) exit 1 ;; esac +EOF +printf '#!/bin/sh\necho "[apt-get] $*" >>"$CALL_LOG"\n' >"$DEB/apt-get" +printf '#!/bin/sh\nwhile [ "${1#*=}" != "$1" ]; do export "$1"; shift; done\nexec "$@"\n' >"$DEB/sudo" +printf '#!/bin/sh\necho 6.0.0-rig\n' >"$DEB/uname" +chmod +x "$DEB"/* +: >"$DEB/calls.log" +( + source "$SCRIPT" + OS_TYPE=Linux REAL_USER=test + PATH="$DEB" CALL_LOG="$DEB/calls.log" install_dependencies /dev/null 2>&1 +assert_contains "Debian shape: cpupower via linux-cpupower (#327)" "$(cat "$DEB/calls.log")" "linux-cpupower" +assert_absent "Debian shape: linux-tools-common stays out (#327)" "$(cat "$DEB/calls.log")" "linux-tools-common" + +# Neither name exists (apt-cache always says no): warn, keep going, and the toolchain still installs. +NC="$(mktemp -d "$SANDBOX/nc327.XXXXXX")" +printf '#!/bin/sh\nexit 1\n' >"$NC/dpkg" +printf '#!/bin/sh\nexit 1\n' >"$NC/apt-cache" # no cpupower package under ANY name +printf '#!/bin/sh\necho "[apt-get] $*" >>"$CALL_LOG"\n' >"$NC/apt-get" +printf '#!/bin/sh\nwhile [ "${1#*=}" != "$1" ]; do export "$1"; shift; done\nexec "$@"\n' >"$NC/sudo" +printf '#!/bin/sh\necho 6.0.0-rig\n' >"$NC/uname" +chmod +x "$NC"/* +: >"$NC/calls.log" +nc_out="$( ( + source "$SCRIPT" + OS_TYPE=Linux REAL_USER=test + PATH="$NC" CALL_LOG="$NC/calls.log" install_dependencies &1)" +rc=$? +assert_rc "no cpupower package never fails the install (#327)" "$rc" "0" +assert_contains "warns when no cpupower package exists (#327)" "$nc_out" "No cpupower package found" +assert_contains "toolchain still installs without a cpupower package (#327)" "$(cat "$NC/calls.log")" "build-essential" +assert_absent "no cpupower name reaches apt when neither exists (#327)" "$(cat "$NC/calls.log")" "linux-tools-common" +assert_absent "linux-cpupower also stays out when absent (#327)" "$(cat "$NC/calls.log")" "linux-cpupower" # check_prerequisites (the jq bootstrap) had NO test. jq is deliberately kept OFF the scenario PATH so the # install branch runs; each dir holds ONLY the package manager(s) under test, so `command -v` selects the From 3a9e6dfc08b70c9be3972ec19985a7bf09482f51 Mon Sep 17 00:00:00 2001 From: Vijit Singh Date: Sun, 2 Aug 2026 11:24:23 -0500 Subject: [PATCH 3/4] feat(doctor): surface missing AES-NI / AVX2 instead of mining silently slow (#339) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(doctor): surface missing AES-NI / AVX2 instead of mining silently slow (#338) RandomX without AES-NI falls back to XMRig's soft-AES path, roughly 4x slower, and nothing anywhere said why — the last undelivered acceptance criterion from #1 ("unsupported hardware is surfaced rather than silently failing"). setup/apply now warn at configure time when the CPU flags lack aes (and, advisory, avx2 — that one only slows dataset init), and doctor counts a missing AES-NI as an issue. Judged only when an x86-style flags line exists in /proc/cpuinfo (same CPUINFO override util/proposed-grub.sh already uses); macOS, ARM and stubbed sandboxes read as unknown, and unknown never manufactures an issue — the #333 lockdown stance. Never aborts: a knowingly-old rig is a valid choice. Closes #338 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Fable 5 * refactor: collapse one-arm case blocks to [[ ]] guards (ponytail-review) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Fable 5 --------- Co-authored-by: Claude Fable 5 --- CHANGELOG.md | 10 ++++++++ rigforge.sh | 41 ++++++++++++++++++++++++++++++ tests/run.sh | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9fe290..0c78524 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,16 @@ All notable changes to RigForge are documented here. The format is based on ## [Unreleased] +### Added + +- **Missing AES-NI / AVX2 is surfaced instead of mining silently slow (#338).** RandomX without + AES-NI falls back to XMRig's soft-AES path, roughly 4x slower, and nothing anywhere said why — the + last undelivered acceptance criterion from #1. `setup`/`apply` now warn at configure time when the + CPU flags lack `aes` (and, advisory, `avx2` — that one only slows dataset init), and `doctor` + counts a missing AES-NI as an issue. Judged only when an x86-style `flags` line exists in + `/proc/cpuinfo`; macOS, ARM and stubbed sandboxes read as unknown, and unknown never manufactures + an issue (the #333 lockdown stance). Never aborts: a knowingly-old rig is a valid choice. + ### Fixed - **Debian: dependency install no longer fails on `linux-tools-common` (#327).** The apt dependency diff --git a/rigforge.sh b/rigforge.sh index 2fefea9..322fa62 100755 --- a/rigforge.sh +++ b/rigforge.sh @@ -132,6 +132,9 @@ BIN_DIR="${BIN_DIR:-/usr/local/bin}" # Read-only system paths the `doctor` health check inspects (overridable for tests). MEMINFO="${MEMINFO:-/proc/meminfo}" +# CPU flags source for the ISA preflight (#338). Same override name util/proposed-grub.sh already +# uses for its pdpe1gb probe — one knob, and the test harness already isolates it from the host. +CPUINFO="${CPUINFO:-/proc/cpuinfo}" MSR_MODULE_DIR="${MSR_MODULE_DIR:-/sys/module/msr}" GOVERNOR_FILE="${GOVERNOR_FILE:-/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor}" HUGEPAGES_1G_NR="${HUGEPAGES_1G_NR:-/sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages}" @@ -1001,6 +1004,13 @@ generate_xmrig_config() { # where only one CCD has the V-cache). See issue #44. if [ "$OS_TYPE" != "Darwin" ]; then log "Detected CPU: ${CPU_MODEL:-unknown} — using XMRig auto-tuning (threads, asm, MSR, NUMA auto-detected)." + # ISA preflight (#338): surface missing AES-NI/AVX2 here, at the moment the rig is being + # configured, instead of letting unsupported hardware mine silently slow. Warn, never abort: + # XMRig still runs (soft AES / non-AVX2 init) and a knowingly-old rig is a valid choice. + local _missing_isa + _missing_isa=$(_cpu_missing_isa) + [[ " $_missing_isa " == *" aes "* ]] && warn "This CPU has no AES-NI: RandomX falls back to soft AES, roughly 4x slower. Mining will work, but expect a fraction of a modern CPU's rate." + [[ " $_missing_isa " == *" avx2 "* ]] && warn "This CPU has no AVX2: dataset init will be slower (steady-state hashrate is unaffected)." fi # Rig label for the pool `user` field (#22): any pool entry that didn't set its own `user` gets the @@ -4398,6 +4408,22 @@ _lockdown_state() { # -> none|integrity|confidentiality, or empty when unknown return 0 } +# RandomX ISA preflight (#338, the last acceptance criterion from #1): echo which of aes / avx2 the +# CPU lacks, from the kernel's flags line. RandomX without AES-NI silently falls back to XMRig's +# soft-AES path (~4x slower) and without AVX2 dataset init slows — neither aborts anything, so a rig +# on unsupported hardware "works" at a mysteriously bad rate unless somebody says why. Judged ONLY +# when an x86-style "flags" line exists: no flags line (macOS has no /proc, ARM cpuinfo says +# "Features", sandboxes stub the file) means unknown, and unknown never manufactures an issue — the +# same stance as #333's lockdown probe. `-w` so vaes/avx2_vnni style neighbors can't false-match. +_cpu_missing_isa() { # -> "aes", "avx2", "aes avx2", or empty when all present / undeterminable + grep -q '^flags' "$CPUINFO" 2>/dev/null || return 0 + local missing="" + grep -qw aes "$CPUINFO" || missing="aes" + grep -qw avx2 "$CPUINFO" || missing="$missing${missing:+ }avx2" + printf '%s' "$missing" + return 0 +} + # True when lockdown is at a level that blocks MSR writes (#333). LOCKDOWN_MSR sits below # LOCKDOWN_INTEGRITY_MAX in enum lockdown_reason (include/linux/security.h), so both `integrity` and # `confidentiality` deny the write; only `none` permits it. @@ -4759,6 +4785,21 @@ doctor() { _ck_warn "1GB HugePages not reserved (optional; needs a pdpe1gb CPU + reboot)" fi + # CPU ISA support (#338): a rig without AES-NI mines at soft-AES speed (~4x slower) with no + # error anywhere — exactly the "silently failing" #1's acceptance criterion forbids, so it's a + # counted issue. Missing AVX2 only slows dataset init: advisory. Quiet when there's no x86 + # flags line to judge (unknown, not unsupported). + local miss_isa + miss_isa=$(_cpu_missing_isa) + if [[ " $miss_isa " == *" aes "* ]]; then + _ck_warn "CPU has no AES-NI — RandomX runs soft AES, roughly 4x slower; this hardware cannot mine at a competitive rate" + issues=$((issues + 1)) + else + # The ok line only when there IS a flags line to have judged; no flags line = unknown, say nothing. + grep -q '^flags' "$CPUINFO" 2>/dev/null && _ck_ok "CPU supports AES-NI (hardware RandomX path)" || true + fi + [[ " $miss_isa " == *" avx2 "* ]] && _ck_info "CPU has no AVX2 — dataset init is slower (steady-state hashrate unaffected)" + # Resolve the worker's xmrig.log once — the MSR-applied (#66) and HUGE PAGES checks both read it. local wr="" log_file="" if [ -f "$CONFIG_JSON" ]; then diff --git a/tests/run.sh b/tests/run.sh index b01cec6..4b6599f 100644 --- a/tests/run.sh +++ b/tests/run.sh @@ -3468,6 +3468,77 @@ assert_contains "bios menu: Gigabyte Secure Boot path (#333)" "$(bm_sb "Gigabyte assert_contains "bios menu: MSI Secure Boot path (#333)" "$(bm_sb "Micro-Star International")" "Windows OS Configuration" assert_contains "bios menu: unknown vendor falls back generically (#333)" "$(bm_sb "Some OEM")" "usually under Boot or Security" +# #338 (the last #1 acceptance criterion): missing AES-NI/AVX2 must be SURFACED — soft-AES mining is +# ~4x slower with no error anywhere. AES-NI missing = counted doctor issue + setup warn; AVX2 missing = +# advisory only; no x86 "flags" line (macOS, ARM's "Features", stubs) = unknown = silence, never an issue. +echo "== unit: CPU ISA preflight — AES-NI / AVX2 surfaced (#338) ==" +printf 'processor : 0\nflags : fpu vme aes avx avx2 vaes\n' >"$DOC/cpuinfo_full" +# vaes but NOT the standalone aes word: proves the -w match can't be satisfied by a neighbor flag. +printf 'processor : 0\nflags : fpu vme avx avx2 vaes\n' >"$DOC/cpuinfo_noaes" +printf 'processor : 0\nflags : fpu vme aes avx\n' >"$DOC/cpuinfo_noavx2" +printf 'processor : 0\nflags : fpu vme avx\n' >"$DOC/cpuinfo_neither" +printf 'processor : 0\nFeatures : fp asimd aes\n' >"$DOC/cpuinfo_arm" # ARM shape: no "flags" line + +# --- the pure helper, exercised directly --- +isa_miss() { (source "$SCRIPT" && CPUINFO="$1" _cpu_missing_isa); } +assert_eq "isa: full flags -> nothing missing (#338)" "$(isa_miss "$DOC/cpuinfo_full")" "" +assert_eq "isa: vaes does not satisfy the aes word-match (#338)" "$(isa_miss "$DOC/cpuinfo_noaes")" "aes" +assert_eq "isa: missing avx2 reported alone (#338)" "$(isa_miss "$DOC/cpuinfo_noavx2")" "avx2" +assert_eq "isa: both missing, space-separated (#338)" "$(isa_miss "$DOC/cpuinfo_neither")" "aes avx2" +assert_eq "isa: ARM Features line -> unknown, not unsupported (#338)" "$(isa_miss "$DOC/cpuinfo_arm")" "" +assert_eq "isa: absent cpuinfo -> unknown (#338)" "$(isa_miss "/nonexistent-cpuinfo")" "" + +# --- doctor: counted for aes, advisory for avx2, silent on unknown --- +out="$(CPUINFO="$DOC/cpuinfo_noaes" run_doctor "$DOC/meminfo_ok" "$DOC/msrmod" "$DOC/gov_perf" "$DOC/nr1g")" +assert_contains "doctor: missing AES-NI named (#338)" "$out" "CPU has no AES-NI" +assert_contains "doctor: missing AES-NI is a counted issue (#338)" "$out" "issue(s) found" +out="$(CPUINFO="$DOC/cpuinfo_noavx2" run_doctor "$DOC/meminfo_ok" "$DOC/msrmod" "$DOC/gov_perf" "$DOC/nr1g")" +assert_contains "doctor: missing AVX2 is advisory (#338)" "$out" "CPU has no AVX2" +assert_contains "doctor: missing AVX2 alone still passes (#338)" "$out" "all critical checks passed" +out="$(CPUINFO="$DOC/cpuinfo_full" run_doctor "$DOC/meminfo_ok" "$DOC/msrmod" "$DOC/gov_perf" "$DOC/nr1g")" +assert_contains "doctor: AES-NI present reported ok (#338)" "$out" "CPU supports AES-NI" +out="$(CPUINFO="$DOC/cpuinfo_arm" run_doctor "$DOC/meminfo_ok" "$DOC/msrmod" "$DOC/gov_perf" "$DOC/nr1g")" +assert_absent "doctor: unknown ISA raises no alarm (#338)" "$out" "AES-NI" + +# --- setup path: generate_xmrig_config warns at configure time, and never aborts --- +export STUB_CPU_MODEL="Old Xeon E5405" STUB_NPROC=4 STUB_HOSTNAME=rigbox +ISA338="$(mktemp -d "$SANDBOX/isa338.XXXXXX")" +gen338_out="$( + cd "$ISA338" || exit 1 + source "$SCRIPT" + OS_TYPE=Linux + WORKER_ROOT="$ISA338" + POOL_ADDRESS=myrig.local + POOLS_JSON='[{"url":"myrig.local:3333","user":"","pass":"x","keepalive":true,"tls":false,"enabled":true}]' + ACCESS_TOKEN=tok123 + DONATION=1 + LOGROTATE_DIR="$ISA338" + CPUINFO="$DOC/cpuinfo_neither" + set +e + PATH="$STUBS:$PATH" generate_xmrig_config 2>&1 +)" +assert_rc "config-gen still succeeds on unsupported hardware (#338)" "$?" "0" +assert_contains "config-gen warns about missing AES-NI (#338)" "$gen338_out" "no AES-NI" +assert_contains "config-gen warns about missing AVX2 (#338)" "$gen338_out" "no AVX2" +assert_contains "config-gen: the config was still generated (#338)" "$(J "$ISA338/config.json" '.pools[0].url')" "myrig.local:3333" +# A fully-capable CPU stays quiet — the warn must not become noise on normal rigs. +QUIET338="$(mktemp -d "$SANDBOX/isaq338.XXXXXX")" +genq_out="$( + cd "$QUIET338" || exit 1 + source "$SCRIPT" + OS_TYPE=Linux + WORKER_ROOT="$QUIET338" + POOL_ADDRESS=myrig.local + POOLS_JSON='[{"url":"myrig.local:3333","user":"","pass":"x","keepalive":true,"tls":false,"enabled":true}]' + ACCESS_TOKEN=tok123 + DONATION=1 + LOGROTATE_DIR="$QUIET338" + CPUINFO="$DOC/cpuinfo_full" + set +e + PATH="$STUBS:$PATH" generate_xmrig_config 2>&1 +)" +assert_absent "config-gen: no ISA warning on a capable CPU (#338)" "$genq_out" "AES-NI" + # #278: doctor reports control receiver health when `control` is enabled. Active + responding (200 or # 503, per util/control-server.py) is ok; enabled-but-down (service inactive, or active but not # answering) warns with a hint and counts as an issue; disabled prints no control-receiver lines at all. From ad632751874b0baf777c42128f64b767d95475f7 Mon Sep 17 00:00:00 2001 From: Vijit Singh Date: Sun, 2 Aug 2026 17:10:44 -0500 Subject: [PATCH 4/4] release: v1.14.0 Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 2 ++ VERSION | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c78524..e045bf9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ All notable changes to RigForge are documented here. The format is based on ## [Unreleased] +## [1.14.0] - 2026-08-02 + ### Added - **Missing AES-NI / AVX2 is surfaced instead of mining silently slow (#338).** RandomX without diff --git a/VERSION b/VERSION index b50dd27..850e742 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.13.1 +1.14.0