-
v1.5.3
Stablereleased this
2026-07-20 07:42:47 -05:00 | 10 commits to main since this releaseCode-review hygiene — no behavior change for valid configurations.
Fixed
- In-memory rate-limit entries are now reclaimed.
RateLimiteraccumulated oneuserRateLimitsentry per distinct non-admin user for the life of the process; its purpose-builtcleanup()(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.logandcombined.logfile 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_FILEenv var.config.logging.filereadLOG_FILEand it was echoed in the startup config summary, but the logger hardcodeslogs/error.log/logs/combined.logand never consumed it — so the knob did nothing. Removed it fromconfig.tsand the.env.config/.env.development/.env.productiontemplates. No behavior change: file log locations are unchanged.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- In-memory rate-limit entries are now reclaimed.
-
v1.5.2
Stablereleased this
2026-07-19 15:23:19 -05:00 | 11 commits to main since this releaseCode-review hardening — no new features, no behavior change for valid
configurations.Fixed
- Config validation now rejects malformed numeric env values.
parseInton
e.g.CLAUDE_MAX_TOKENS=abcyieldsNaN, and every comparison againstNaN
is false, so the old<= 0checks 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, andRATE_LIMIT_INTERVAL_MS,
which previously weren't validated at all. web_fetchno 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-Lengthabove the cap is rejected before reading at all.
Changed
RATE_LIMIT_INTERVAL_MSnow flows through the central config.
RateLimiterread it straight fromprocess.env, bypassing
Config.validate()andgetSummary(); 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_WINDOWenv 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 atreplicas: 1.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Config validation now rejects malformed numeric env values.
-
v1.5.1 Stable
released this
2026-07-19 15:21:20 -05:00 | 12 commits to main since this releaseDocs 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 (serviceaufhocker_bot, registry-pulled image,
shared Postgres overpostgres_net, secrets as Swarm secrets),
docs/DEPLOYMENT.md's production section was rewritten around that topology;
the single-host self-containeddocker-compose.production.ymlstack is
demoted to a documented alternative.docs/DOCKER_SETUP.mdcollapsed to a
dev-only Compose/rebuild note that points production atDEPLOYMENT.mdinstead
of duplicating it. README's deployment quick-links andCLAUDE.md's deploy
note updated to match (the latter no longer calls
docker-compose.production.ymlthe 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
fileaufhocker.yamllives 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
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Deployment docs now describe the live Swarm deployment. With the bot
-
v1.5.0 Stable
released this
2026-07-14 22:39:56 -05:00 | 14 commits to main since this releaseChanged
- 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_ENABLEDflag (defaultfalse); the win %, reasoning,
and win condition are unaffected. When off, the prediction prompt also stops
requestingplayerTips, so no output tokens are spent generating advice the
embed won't render, and any tips the model returns anyway are dropped.
SetLOL_PREDICTION_TIPS_ENABLED=trueto restore the previous behavior.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- LoL game-start "Tips for your squad" are now off by default. The
-
v1.4.5
Stablereleased this
2026-07-14 09:10:39 -05:00 | 15 commits to main since this releaseAdded
- CI publishes the Docker image to the Forgejo registry. On pushes to
main, thedocker-buildjob now pushes the image it builds toforgejo.jrendar.org/joeyr/aufhocker, taggedlatestplus the commit SHA (a pinned rollback target); PRs still build-only. The job gainedneeds: build-and-test, so a red test run can never overwrite:latest. Auth is theREGISTRY_TOKENrepo Actions secret — a dedicated Forgejo token scoped towrite:packageonly. This completes steps 2–3 ofdocs/DOCKER_SWARM_SETUP.md: the swarm stack can now pull instead of building on-host.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- CI publishes the Docker image to the Forgejo registry. On pushes to
-
v1.4.4 Stable
released this
2026-07-14 09:06:54 -05:00 | 16 commits to main since this releaseFixed
- Production compose dropped every non-secret flag.
docker-compose.production.ymllisted only.envin the bot'senv_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.configto theenv_filelist, ordered before.envso.envstill wins on overlap.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Production compose dropped every non-secret flag.
-
v1.4.3
Stablereleased this
2026-07-13 21:31:33 -05:00 | 17 commits to main since this releaseDocs only — no change to the bot's runtime, image, or command surface.
Changed
CLAUDE.mddocuments the deploy compose file. Deploys of the live bot always usedocker-compose.production.yml; the basedocker-compose.ymlis dev-only. Running plaindocker compose upagainst the live stack silently recreates it with drifted config — including postgres bound to0.0.0.0instead of localhost — which is exactly what happened (and was corrected) during the v1.4.2 redeploy.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
v1.4.2
Stablereleased this
2026-07-13 21:19:03 -05:00 | 18 commits to main since this releaseTests only — no change to the bot's runtime, image, or command surface.
Added
- Query-flow tests. The query plugin's
handleSlashpath — 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 ininit(), and a query → make-public round trip. Takessrc/plugins/query/plugin.tsfrom ~59% to 100% statement/line coverage.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Query-flow tests. The query plugin's
-
v1.4.1
Stablereleased this
2026-07-13 13:00:48 -05:00 | 19 commits to main since this releaseTooling only — no change to the bot's runtime, image, or command surface.
Fixed
- CI
format:checkfailure on v1.4.0.plugin-dispatch.test.tslanded unformatted; the local stage gates ran Prettier only on spot-checked files while CI checks everything. package-lock.jsonversion drift. The lockfile still said1.2.6— version bumps since then never touched it, which the CI node_modules cache masked (npm ciis skipped on cache hits) but would break any cache-miss run with a package.json/lockfile sync error. Now matches the manifest.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- CI
-
v1.4.0
Stablereleased this
2026-07-13 12:54:03 -05:00 | 20 commits to main since this releaseExecutes P4-1 (fuller plugin decomposition):
query,lol, andd2all implement a realPlugincontract andAufhockerBotbecomes 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
Plugincontract + registry (src/plugins/Plugin.ts, documented indocs/PLUGINS.md): plugins own their command surface (buildCommandson the/aufhockerroot), 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
queryextracted intosrc/plugins/query/. The query-chat command definition moved out ofDiscordClient(core now defines only the bare/aufhockerroot); 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.tswrap 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
SubcommandGroupBuilderandregisterCommands' group parameter (dead once every plugin contributes viabuildCommands), andD2EmuPollingService.registerShutdown(superseded by the host hook).docs/PLUGIN_DECOMPOSITION_PLAN.md— folded intodocs/PLUGINS.md;WHATS_LEFT.md's P4-1 item is closed.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads