• v1.6.0 ed661ef407

    v1.6.0
    All checks were successful
    CI / build-and-test (push) Successful in 1m54s
    CI / docker-build (push) Successful in 1m6s
    Stable

    joeyr released this 2026-07-30 23:29:43 -05:00 | 77 commits to main since this release

    The live monitor's announced-queue list is now configurable, and LoL Classic
    games are announced by default.

    Added

    • LOL_TRACKED_QUEUES — configurable announce allowlist. The live monitor
      previously hard-coded [420, 440] (Ranked Solo/Duo + Flex) as the only queues
      it would announce; everything else was silently dropped. The list is now a
      comma-separated env var, defaulting to 420,440,4310. Untracked queues are
      still polled — that's what detects the end of a tracked game — just never
      posted. A malformed value rejects the whole list and falls back to the default
      rather than silently narrowing what gets announced.
    • LoL Classic (queue 4310) is announced by default. Riot reports this mode
      as gameMode: JADE on mapId: 453 — not the CLASSIC enum, which is
      Summoner's Rift and covers both ranked and normal queues. Because it is
      neither ranked nor CLASSIC, it fell through the old filter with no
      notification and no log line. Added 4310 → "LoL Classic" and JADE →
      "LoL Classic" to the queue/mode label maps used by the game-start embed and
      the prediction prompt.

    Changed

    • Untracked-queue skips now log at info instead of debug. At the default
      LOG_LEVEL=info a skipped game left no trace at all, which is
      indistinguishable from the monitor never seeing the game. The line now names
      the queue id, game mode, and the configured allowlist.

    Notes

    • Enrichment for non-Summoner's-Rift modes is inherently thin: lane detection
      bails unless gameMode === 'CLASSIC' && mapId === 11, ranked stats are
      solo/flex only, and LoL Classic's champion ids (observed in the 60015–60081
      range) aren't in Data Dragon, so names render as Champion #<id>. The Phase 1
      embed posts normally; the enrichment edits degrade rather than fail.
    Downloads
  • v1.5.3 40f0408858

    v1.5.3
    All checks were successful
    CI / build-and-test (push) Successful in 1m56s
    CI / docker-build (push) Successful in 22s
    Stable

    joeyr released this 2026-07-20 07:42:47 -05:00 | 78 commits to main since this release

    Code-review hygiene — no behavior change for valid configurations.

    Fixed

    • In-memory rate-limit entries are now reclaimed. RateLimiter accumulated one userRateLimits entry per distinct non-admin user for the life of the process; its purpose-built cleanup() (drops entries older than 2× the interval) was only ever called from tests. The 5-minute maintenance sweep now runs it alongside the expired-bypass cleanup, so the map stays bounded.
    • Log files are now size-bounded. The winston error.log and combined.log file transports had no rotation and could grow without bound on the logs volume. Each is now capped at 10 MiB with 5 rotations (~50 MiB per transport); production also streams JSON to stdout for Docker to collect.

    Removed

    • Dropped the non-functional LOG_FILE env var. config.logging.file read LOG_FILE and it was echoed in the startup config summary, but the logger hardcodes logs/error.log / logs/combined.log and never consumed it — so the knob did nothing. Removed it from config.ts and the .env.config / .env.development / .env.production templates. No behavior change: file log locations are unchanged.
    Downloads
  • v1.5.2 07842e911b

    v1.5.2
    All checks were successful
    CI / build-and-test (push) Successful in 2m10s
    CI / docker-build (push) Successful in 28s
    Stable

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

    Code-review hardening — no new features, no behavior change for valid
    configurations.

    Fixed

    • Config validation now rejects malformed numeric env values. parseInt on
      e.g. CLAUDE_MAX_TOKENS=abc yields NaN, and every comparison against NaN
      is false, so the old <= 0 checks let it through and the mistake only
      surfaced as an API 400 at request time. Config.validate() now requires
      every numeric knob to be a finite number, and also covers
      MAX_CONTEXT_MESSAGES, MAX_CONTEXT_HOURS, and RATE_LIMIT_INTERVAL_MS,
      which previously weren't validated at all.
    • web_fetch no longer buffers unbounded response bodies. The tool read
      the entire body into memory before applying its character-level truncation,
      so a huge (or deliberately unbounded chunked) page could pull tens of MB into
      the process. Bodies are now streamed with a hard 1 MiB cap, and a
      Content-Length above the cap is rejected before reading at all.

    Changed

    • RATE_LIMIT_INTERVAL_MS now flows through the central config.
      RateLimiter read it straight from process.env, bypassing
      Config.validate() and getSummary(); it now comes from
      config.limits.rateLimitIntervalMs (tests inject the interval via the
      constructor instead of mutating the environment). The never-implemented
      RATE_LIMIT_PER_USER / RATE_LIMIT_WINDOW env vars are dropped from config
      and .env.config — enforcement has always been one command per
      RATE_LIMIT_INTERVAL_MS.
    • RateLimiter no longer starts its cleanup timer at module load. The
      expired-bypass cleanup interval was a side effect of importing the module; the
      bot host now starts it explicitly during startup (paired with the existing
      bot-quiesce stop), so importing the module has no timer side effect.
    • Docs: single-replica requirement made explicit. RATE_LIMITING.md and the
      DEPLOYMENT.md production checklist now state that in-memory rate limits are
      per-process, so the Swarm service must stay at replicas: 1.
    Downloads
  • v1.5.1 b07f0abe6c

    v1.5.1 Stable

    joeyr released this 2026-07-19 15:21:20 -05:00 | 80 commits to main since this release

    Docs only — no change to the bot's runtime, image, or command surface.

    Changed

    • Deployment docs now describe the live Swarm deployment. With the bot
      running on Docker Swarm (service aufhocker_bot, registry-pulled image,
      shared Postgres over postgres_net, secrets as Swarm secrets),
      docs/DEPLOYMENT.md's production section was rewritten around that topology;
      the single-host self-contained docker-compose.production.yml stack is
      demoted to a documented alternative. docs/DOCKER_SETUP.md collapsed to a
      dev-only Compose/rebuild note that points production at DEPLOYMENT.md instead
      of duplicating it. README's deployment quick-links and CLAUDE.md's deploy
      note updated to match (the latter no longer calls
      docker-compose.production.yml the live deploy).

    Removed

    • docs/DOCKER_SWARM_SETUP.md — a "not implemented yet" plan for the Swarm
      move, which is now done (v1.4.5 shipped the registry publish; the live stack
      file aufhocker.yaml lives in the homelab compose collection). History is in
      git and this changelog.
    • docs/WHATS_LEFT.md — its only remaining item was that Swarm move, now
      complete, leaving the file empty of open work.
    Downloads
  • v1.5.0 cc0df6d371

    v1.5.0 Stable

    joeyr released this 2026-07-14 22:39:56 -05:00 | 82 commits to main since this release

    Changed

    • LoL game-start "Tips for your squad" are now off by default. The
      per-friend player tips in the prediction embed are gated behind a new
      LOL_PREDICTION_TIPS_ENABLED flag (default false); the win %, reasoning,
      and win condition are unaffected. When off, the prediction prompt also stops
      requesting playerTips, so no output tokens are spent generating advice the
      embed won't render, and any tips the model returns anyway are dropped.
      Set LOL_PREDICTION_TIPS_ENABLED=true to restore the previous behavior.
    Downloads
  • v1.4.5 ef85c121ce

    v1.4.5
    All checks were successful
    CI / build-and-test (push) Successful in 1m52s
    CI / docker-build (push) Successful in 30s
    Stable

    joeyr released this 2026-07-14 09:10:39 -05:00 | 83 commits to main since this release

    Added

    • CI publishes the Docker image to the Forgejo registry. On pushes to main, the docker-build job now pushes the image it builds to forgejo.jrendar.org/joeyr/aufhocker, tagged latest plus the commit SHA (a pinned rollback target); PRs still build-only. The job gained needs: build-and-test, so a red test run can never overwrite :latest. Auth is the REGISTRY_TOKEN repo Actions secret — a dedicated Forgejo token scoped to write:package only. This completes steps 2–3 of docs/DOCKER_SWARM_SETUP.md: the swarm stack can now pull instead of building on-host.
    Downloads
  • v1.4.4 7040db5ce0

    v1.4.4 Stable

    joeyr released this 2026-07-14 09:06:54 -05:00 | 84 commits to main since this release

    Fixed

    • Production compose dropped every non-secret flag. docker-compose.production.yml listed only .env in the bot's env_file, but all committed tuning — LOL_ENABLE_LIVE_MONITOR, LOL_PREDICTION_*, CLAUDE_MODEL, D2EMU_*, intervals, feature flags — lives in .env.config. The container never saw it, so the LoL live monitor came up disabled and every other flag silently fell back to its code default. Restored .env.config to the env_file list, ordered before .env so .env still wins on overlap.
    Downloads
  • v1.4.3 5e43ae5317

    v1.4.3
    All checks were successful
    CI / docker-build (push) Successful in 21s
    CI / build-and-test (push) Successful in 1m53s
    Stable

    joeyr released this 2026-07-13 21:31:33 -05:00 | 85 commits to main since this release

    Docs only — no change to the bot's runtime, image, or command surface.

    Changed

    • CLAUDE.md documents the deploy compose file. Deploys of the live bot always use docker-compose.production.yml; the base docker-compose.yml is dev-only. Running plain docker compose up against the live stack silently recreates it with drifted config — including postgres bound to 0.0.0.0 instead of localhost — which is exactly what happened (and was corrected) during the v1.4.2 redeploy.
    Downloads
  • v1.4.2 68d22d2bd6

    v1.4.2
    All checks were successful
    CI / docker-build (push) Successful in 20s
    CI / build-and-test (push) Successful in 1m53s
    Stable

    joeyr released this 2026-07-13 21:19:03 -05:00 | 86 commits to main since this release

    Tests only — no change to the bot's runtime, image, or command surface.

    Added

    • Query-flow tests. The query plugin's handleSlash path — the full Claude chat flow — now has direct coverage: the immediate ephemeral defer (ordered before even the rate-limit check, pinning the Discord 3s-ack property), rate-limit and permission short-circuits, context-option validation errors, default vs. parsed context params, multi-part delivery (button on the first chunk, ephemeral follow-ups, empty chunks skipped), the lazy expiry sweep on new queries, tool-executor wiring in init(), and a query → make-public round trip. Takes src/plugins/query/plugin.ts from ~59% to 100% statement/line coverage.
    Downloads
  • v1.4.1 19bdf29abd

    v1.4.1
    All checks were successful
    CI / docker-build (push) Successful in 20s
    CI / build-and-test (push) Successful in 1m51s
    Stable

    joeyr released this 2026-07-13 13:00:48 -05:00 | 87 commits to main since this release

    Tooling only — no change to the bot's runtime, image, or command surface.

    Fixed

    • CI format:check failure on v1.4.0. plugin-dispatch.test.ts landed unformatted; the local stage gates ran Prettier only on spot-checked files while CI checks everything.
    • package-lock.json version drift. The lockfile still said 1.2.6 — version bumps since then never touched it, which the CI node_modules cache masked (npm ci is skipped on cache hits) but would break any cache-miss run with a package.json/lockfile sync error. Now matches the manifest.
    Downloads