• v3.5.4 1ed376244c

    v3.5.4
    All checks were successful
    CI / build-and-test (push) Successful in 1m38s
    Stable

    joeyr released this 2026-07-20 20:49:00 -05:00 | 71 commits to main since this release

    Fixed

    Defensive-ban / counter data no longer freezes day-one-of-patch numbers for a whole week.

    The stats cache treated counter data as stable for the full TTL (previously 1 week), on the assumption it "only shifts per patch." But the first days of a patch are the exception: op.gg starts nearly empty and fills in over the following week. An entry cached on patch day one — e.g. a 6-matchup, ~200-game Veigar page where op.gg now shows ~55 matchups and 10k+ games — stuck for days, so the panel showed a handful of noisy games (Ahri "44% WR · 54 games") long after real volume had accumulated.

    Two changes fix it:

    • Default cacheTtlHours drops from 168 (1 week) to 24 (1 day).
    • Thinly-sampled entries (total games below LOW_SAMPLE_TOTAL_THRESHOLD) now expire on a much shorter LOW_SAMPLE_TTL_HOURS (6h) regardless of the configured TTL, so early-patch data self-heals as op.gg fills in — this also rescues existing installs whose settings.json still pins the old 168h value.

    Max configurable TTL stays 168 for anyone who wants it.

    Note: this is a source/tag release; the Windows installer is built locally.

    Downloads
  • v3.5.3 cfd41d95c2

    v3.5.3
    All checks were successful
    CI / build-and-test (push) Successful in 1m34s
    Stable

    joeyr released this 2026-07-20 20:35:09 -05:00 | 72 commits to main since this release

    Fixed

    • Importing a build now clears every previous companion rune page, not just one. The rune importer deleted only the first "LoLC: "-prefixed page it found, so if a second companion page ever lingered (e.g. from an older build) it survived the next import. It now removes all companion-owned pages before creating the new one — matching how Item Import already clears all companion item sets — so a fresh import always leaves exactly one companion build behind. User rune pages are still never touched.
    Downloads
  • v3.5.2 46d00cd0b9

    v3.5.2
    All checks were successful
    CI / build-and-test (push) Successful in 1m36s
    Stable

    joeyr released this 2026-07-20 19:59:55 -05:00 | 73 commits to main since this release

    Changed

    • Item Import now offers 4 core-build rows instead of 5. The list caps at the top 4 builds by pick rate (MAX_ITEM_OPTIONS); the trailing low-pick row is dropped to keep the section tighter. Ranking (by pick rate, never win rate) and the games floor are unchanged.
    Downloads
  • v3.5.1 1adbbef25d

    v3.5.1
    All checks were successful
    CI / build-and-test (push) Successful in 1m44s
    Stable

    joeyr released this 2026-07-20 18:42:33 -05:00 | 74 commits to main since this release

    Security

    • The Riot API key is now encrypted at rest. It was stored in plaintext in <userData>/settings.json; it is now sealed with the OS keystore via Electron's safeStorage (DPAPI on Windows) before it touches disk — stored as a tagged enc:v1: value and decrypted back to plaintext only in memory for the scout / harvest clients. A key written by an older build is read as-is and re-encrypted on the next settings save (transparent migration); a blob that can't be decrypted — e.g. settings.json copied to another OS user or machine — is dropped with a warning instead of crashing.
    • Hardened the renderer Content-Security-Policy on all three windows with base-uri 'none', form-action 'none', object-src 'none', and frame-src 'none' — directives default-src does not fall back to — closing the <base>-injection and form-exfiltration gaps. img-src https: is unchanged (op.gg serves the rune/item icons from its own CDN).

    Changed

    • CI now audits shipped dependencies (npm audit --omit=dev --audit-level=high) as a gate step, so a known high/critical advisory in a production (runtime) package fails the build instead of landing silently. Scoped to production deps: build/dev tooling runs only on trusted CI/dev machines and never reaches a user.

    Fixed

    • Corrected a stale code comment on the lol-item-sets write-allowlist rule ("future items phase" → the item build import that shipped in 3.5.0).
    Downloads
  • v3.5.0 cd434f9f3b

    v3.5.0
    All checks were successful
    CI / build-and-test (push) Successful in 2m2s
    Stable

    joeyr released this 2026-07-19 21:12:11 -05:00 | 75 commits to main since this release

    Added

    • Item build import — the build importer's second half (plan §12). When you
      lock in a champion (and the new Settings → Item import toggle is on), the
      app scrapes op.gg's items page and shows the top core builds — up to 5, ranked
      by pick rate with a ≥50-games floor, each with its own win% / pick% / games —
      as one-click imports. Importing writes a "LoLC:" item set into your client
      (visible in the in-game shop for that champion) containing Starter items
      (plus your support-quest item on support), the top 3 Boots, the chosen Core
      build in purchase order with its stats baked into the block label, and up to
      6 Situational late-game items (excluding the chosen core).
      • Own settings toggle, OFF by default (itemImportEnabled), independent
        of rune import — an item set occupies shop-panel real estate, so each
        feature is its own opt-in. While off, nothing is scraped and imports are
        refused.
      • User item sets are never touched. Sets live in one per-summoner LCU
        document; the importer re-reads it immediately before every write, passes
        every non-companion set through byte-identically, and only ever replaces
        the set carrying its own "LoLC: " title prefix (footprint = exactly one
        set). There is no slot cap, so no pages-full case.
      • The write uses the PUT /lol-item-sets/v1/item-sets/{summonerId}/sets
        endpoint that has been on the property-tested write allowlist since Phase 1
        (Req 6.5), and fires only on your explicit Import click (Req 6.7).
      • Rows are ranked by pick rate, never win rate — items are the worst case
        for the low-sample/high-win-rate trap (e.g. Mejai's at 79.9% WR on 34
        games), which also sits below the games floor.
      • Scraper keys on the embedded data's shape (metaBuildItems /
        metaStarterItems / metaItem + document order), never op.gg's localized
        section headers, and normalizes this page's quirks (percent rates,
        comma-formatted game counts). Verified against live-captured Lux-support
        and Ahri-mid pages.
    Downloads
  • v3.4.4 bcf152d3f7

    v3.4.4
    All checks were successful
    CI / build-and-test (push) Successful in 1m58s
    Stable

    joeyr released this 2026-07-19 16:24:11 -05:00 | 76 commits to main since this release

    Changed

    • The top rune board is no longer styled as a "primary" fast path. The first (most-picked) board used to carry a permanent accent-coloured border and a filled accent Import button. That styling is removed: all boards now render identically, and the only card-level highlight left is the ✓ Imported marker and success-coloured edge on the board you actually imported (from v3.4.2). The per-rune highlighting inside each board — that page's picks in full colour, the rest dimmed — is unchanged.
    Downloads
  • v3.4.3 d50e24e733

    v3.4.3 — full Chromium sandbox + navigation hardening
    All checks were successful
    CI / build-and-test (push) Successful in 2m3s
    Stable

    joeyr released this 2026-07-19 10:32:13 -05:00 | 77 commits to main since this release

    Changed

    • All three windows now run with the full Chromium sandbox (sandbox: true). The preload script is bundled by Vite (vite.preload.config.mts) into a single self-contained CJS file whose only runtime require is 'electron', which is what a sandboxed preload permits — previously it was tsc-compiled with an on-disk require of the shared IPC contract, forcing sandbox: false. No behavior change; renderer + preload now run fully sandboxed as defense-in-depth on top of the existing contextIsolation/CSP boundary.
    • In-window navigation is now blocked (will-navigate hardening). The renderer never legitimately navigates, so any attempt is denied and logged; opening the update notice in the browser is unaffected. Dev-server reloads under npm run dev stay allowed.
    • BRIDGE_VERSION no longer needs a manual bump on release — the Vite preload bundle inlines it from package.json the same way the renderer's version badge is inlined.
    Downloads
  • v3.4.2 e541de673e

    v3.4.2
    All checks were successful
    CI / build-and-test (push) Successful in 2m3s
    Stable

    joeyr released this 2026-07-19 09:46:12 -05:00 | 78 commits to main since this release

    Fixed

    • Rune Import now highlights the board you actually imported, not always the first one. The accent edge used to sit permanently on the top (most-picked) row, so after importing a different combo nothing showed which page had landed. The board you import now gets a ✓ Imported marker and a success-coloured edge, its Import button becomes Re-import, and the top row keeps its "recommended fast path" styling. The marker clears when a new champ-select lock-in fetches a fresh list, and a failed import (error / pages-full) leaves it off.
    Downloads
  • v3.4.1 84ce2fb234

    v3.4.1
    All checks were successful
    CI / build-and-test (push) Successful in 1m26s
    Stable

    joeyr released this 2026-07-18 19:48:47 -05:00 | 79 commits to main since this release

    Changed

    • Rune "pick" now means the share of all your games, not op.gg's within-group number. Each rune row's pick rate used to be op.gg's per-page figure — measured only against other pages with the same keystone — so the rows on one champion routinely summed well past 100% (e.g. Amumu jungle showing 89% + 80% + 82% + …). Each combo's pick rate is now its share of all of that champion and role's games, backed out of op.gg's own totals, so the rows read intuitively and never exceed 100%. The "games" count and win rate shown alongside are now the combo's rollup too (so all three share one denominator), while the page the Import button writes is still the combo's most-played variant.
    Downloads
  • v3.4.0 681d74fda3

    v3.4.0
    All checks were successful
    CI / build-and-test (push) Successful in 1m28s
    Stable

    joeyr released this 2026-07-18 19:28:22 -05:00 | 80 commits to main since this release

    Added

    • Enemy lanes are now guessed automatically. Locked enemies no longer pile up under "Unassigned" with a "LANE?" prompt — the board places each one into its most likely lane using the op.gg per-position tier lists (e.g. Kindred → Jungle, Nautilus → Support, Senna → Bottom when Nautilus holds Support), and the lane dropdown shows the guess as its default (e.g. "Guess · Jungle"). Picking a lane by hand still overrides any guess, manual/LCU-known lanes are never guessed over, and a champion with no tier data is only placed when it's the last one left. The guessed lanes also feed counter-pick targeting, so "VS YOU" and Suggested Picks lock onto your likely lane opponent without any clicking.
    Downloads