• v3.5.8 048a3925bd

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

    joeyr released this 2026-07-26 17:21:50 -05:00 | 36 commits to main since this release

    Changed

    • Rune Import now shows at most four combos. The list emitted one row per distinct primary+secondary tree pair op.gg reports, with no cap — so a champion that runs two keystones could push past the intended four. Briar jungle listed five: Press the Attack in three pairings, Hail of Blades in two, the fifth a 161-game page whose 64% win rate is precisely the low-sample-high-winrate trap the importer is supposed to avoid. The list is now capped at the top four by total games, matching the item importer's existing MAX_ITEM_OPTIONS and the two-per-row board grid. The cap trims combos only — every build still rolls into its combo's stats and the pick-rate denominator is unchanged, so the four surviving rows read exactly as before.
    Downloads
  • v3.5.7 e73e8ca44a

    v3.5.7 — renderer lifecycle logging + dead-renderer recovery
    All checks were successful
    CI / build-and-test (push) Successful in 1m40s
    Stable

    joeyr released this 2026-07-23 19:19:16 -05:00 | 37 commits to main since this release

    Fixed

    • A dead renderer is now reloaded instead of leaving a permanently blank window. If a window's renderer process exits abnormally nothing repaints it, and for the transparent in-game overlay that is indistinguishable from "no game running". Renderers now reload automatically on render-process-gone, capped at 3 attempts.

    Added

    • Renderer lifecycle logging for all three windows (companion, overlay, scout): window.loaded, window.load_failed, window.preload_error, window.console_error, window.renderer_gone, window.renderer_reloaded. Renderer-side failures previously never reached the log at all.
    • overlay.shown / overlay.hidden — visibility flips right after the first successful live-metrics publish, separating "the poller never got data" from "data arrived but the panel painted nothing".
    Downloads
  • v3.5.6 0ad8a4bd4c

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

    joeyr released this 2026-07-21 18:40:41 -05:00 | 38 commits to main since this release

    Fixed

    • Existing installs now actually get the 24h counter-data TTL instead of staying frozen for a week. v3.5.4 lowered the default cacheTtlHours from 168 (1 week) to 24, but only for fresh installs — it shipped no migration, so anyone who had used the app before kept the old 168h value persisted in their settings.json. That TTL governs healthy (non-thin) matchup data, so the "Defensive Bans" counters kept serving snapshots up to a week old. Because op.gg's per-patch game counts accumulate daily, a multi-day-old cached entry showed far fewer games than op.gg currently reports (e.g. a jungle matchup cached at ~150 games while op.gg had already reached ~360) — which read as "the game counts are still really low." Loading settings now migrates a persisted cacheTtlHours equal to the old default (168) to the current default (24). The field has no in-app control, so a stored 168 can only be the inherited old default: only that sentinel is rewritten, and a value hand-edited anywhere else in the 1–168 range is left untouched. The max configurable TTL stays 168.
    Downloads
  • v3.5.5 24279baa81

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

    joeyr released this 2026-07-21 18:33:18 -05:00 | 39 commits to main since this release

    Fixed

    • The in-game Scouting Report no longer gets stuck showing empty team columns for the whole game. Opening the overlay during load-in — while you are at level 1 in the fountain, before Riot's Live Client Data API has populated the 10-player roster — read an empty player list and published a report with zero players, which rendered as bare "Your team / Enemy team" headers with no cards. Worse, that empty run was misread as a fully resolved one (an empty player list trivially has no unresolved identities), so it cleared the retry timers and latched the "already gathered this game" flag — meaning neither re-opening the overlay nor the live poller later seeing a full roster ever re-triggered gathering. The report now bails without publishing when the feed exposes no players yet, leaving the honest "Gathering report…" state and the retry path armed, so the next open — or the game becoming active with a populated roster — fills it in.
    Downloads
  • 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 | 40 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 | 41 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 | 42 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 | 43 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 | 44 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 | 45 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