• 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 | 10 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 | 11 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 | 12 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 | 14 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 | 15 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 | 16 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 | 17 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 | 18 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 | 19 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
  • v1.4.0 b2f8eab3b9

    v1.4.0
    Some checks failed
    CI / build-and-test (push) Failing after 15s
    CI / docker-build (push) Successful in 19s
    Stable

    joeyr released this 2026-07-13 12:54:03 -05:00 | 20 commits to main since this release

    Executes P4-1 (fuller plugin decomposition): query, lol, and d2 all implement a real Plugin contract and AufhockerBot becomes a thin host (~1100 → ~440 lines). Structural refactor — the command surface and responses are unchanged, with one deliberate security tightening (make-public expiry, below).

    Added

    • Plugin contract + registry (src/plugins/Plugin.ts, documented in docs/PLUGINS.md): plugins own their command surface (buildCommands on the /aufhocker root), slash/button routing, and lifecycle; the host owns infra, interaction wrapping, and dispatch. Lifecycle semantics preserved from the old inline wiring: init() always runs (so disabled plugins answer "feature disabled") and errors are fatal; start() runs only when enabled and errors leave the plugin degraded. One host-owned priority-3 shutdown hook stops all enabled plugins (replacing the per-poller hooks).
    • Make-public security tests. The per-user publish authorization and the 1-hour expiry are now covered by tests (previously only the public-header formatting was), plus registry dispatch/lifecycle tests.

    Changed

    • query extracted into src/plugins/query/. The query-chat command definition moved out of DiscordClient (core now defines only the bare /aufhocker root); the Claude query flow, the make-public button flow (pendingResponses + handler + sweep), and Claude credential validation (still startup-fatal on a rejected key) moved into the plugin. src/plugins/{lol,d2emu}/plugin.ts wrap the existing services behind the same contract.
    • Make-public expiry enforced at click time. The 1-hour TTL was only swept lazily when the next query ran, so an expired response stayed publishable in between. The button handler now age-checks the response id and rejects (and removes) expired entries — the one behavior change in the refactor, and it only tightens.

    Removed

    • SubcommandGroupBuilder and registerCommands' group parameter (dead once every plugin contributes via buildCommands), and D2EmuPollingService.registerShutdown (superseded by the host hook).
    • docs/PLUGIN_DECOMPOSITION_PLAN.md — folded into docs/PLUGINS.md; WHATS_LEFT.md's P4-1 item is closed.
    Downloads