This file provides guidance to coding agents when working with code in this repository.
- Codex's default task sandbox may remap supplementary groups to
nogroup, so a sandboxedidor Docker socket permission denial is not evidence thatnelluklacks Docker access. - For authorized read-only Docker or Compose inspection, retry the exact
command outside the sandbox through the normal escalation/approval flow,
without
sudo. Verify with elevatedidanddocker ps. - Do not chmod
/var/run/docker.sock, change group membership, add sudo rules, or authorize mutating Docker operations based only on sandbox results.
- GreenCloud production uses the ignored, operator-owned
compose.yamlin/srv/polyelo/PolyBot39with the ignored root.envand thepolyelo-productionproject. Readdocs/PRODUCTION_DOCKER.mdand the production section of/home/nelluk/SERVER_INFO.mdbefore operating it. - A disabled legacy
polyelo.servicemay still exist on the host, but currentmasterdoes not ship or support the systemd deployment. Never enable or start it while the Compose bot is running. Emergency reconstruction must use Git history (pre-cleanup checkpointe99ec18e), stop Compose first, and re-establish the one-writer boundary explicitly. - A normal reviewed source-only update uses ordinary primitives from the
production root:
git pull --ff-onlyfollowed bydocker compose up -d --build. Production recreation still requires Nelluk's explicit authorization and the usual backup/configuration/writer checks. - A retired host-only
/srv/polyelo/bin/polyelo-releasemay remain pending separate host cleanup. Never invoke it: it controls the legacy systemd unit and runs a superseded migration/command-release sequence. Its source and installer are intentionally absent from currentmaster.
- Before every beta setup, deploy, start, stop, restart, status, or log
operation, read the Development section of
/home/nelluk/SERVER_INFO.md. - GreenCloud's canonical beta uses the ignored, operator-owned
compose.yamlin/home/nelluk/PolyBot39-betawith the ignored root.envand thepolybot-mac-betaproject. It uses host PostgreSQL through the read-only/var/run/postgresqlmount; Compose must not own a beta database. - Before mutation, run
docker compose config --quiet,docker compose ps, and, while the bot is running, the runtime configuration check documented indocs/DEVELOPMENT_DOCKER.md. Verify the application identity, database transport, restart count, and one-writer census againstSERVER_INFO.md; stop and investigate any conflict. Beta Lab fixture readiness is not a deployment-health signal. - For a source-only beta correction with no schema or command-tree change:
run proportionate tests, keep the checkout clean, inspect the schema plan,
and run
docker compose up -d --build. Verify the authenticated application, stable container, and one-writer census. Do not synchronize commands when command definitions did not change. - GreenCloud has no deployment wrapper or bundled beta database. A bundled PostgreSQL topology remains a separately approved change.
Polytopia-ELO-Bot is a Discord bot for the mobile game Polytopia. It provides matchmaking, ELO-based leaderboards, and league management across multiple Discord servers (primarily the main Polytopia server and PolyChampions).
- No ordinary import, startup, reconnect, or ready path may create or alter database schema or synchronize Discord application commands.
- Blocking Peewee and filesystem work must not run on Discord's event-loop thread. Capture primitive identifiers, use a worker-local connection, reload mutable rows, and perform the complete write plus protected audit in one bounded transaction.
- Do not pass live Peewee models, Discord objects, lazy queries, connections, or transactions between the event loop and workers. Revalidate permissions and mutable state inside the transaction when they may have changed.
- Publish Discord effects only after commit. A committed-but-unpublished result requires reconciliation and must not encourage repeating the database write.
- Schema changes use the explicit configured-target schema manager and its reviewed plan/apply/verify boundary. Discord command changes use the explicit guild-only manager; global synchronization is unsupported.
- Production deploy/restart, schema or data writes, Discord inspection/apply, and external messages retain their separate authorization boundaries.
- For broad planned work, use isolated Git worktrees and never let two tasks switch or edit the same checkout concurrently. Define the bounded objective, affected command/data surface, authorization gates, and validation before splitting work across tasks.
Prefer the smallest complete solution and match process to demonstrated risk. Do not invent extra services, abstractions, rollout phases, generalized frameworks, or extended observation windows for a narrow reversible change unless a concrete failure mode requires them. Existing production, database, Discord, and destructive-action approval gates still apply; proportionality means satisfying those gates directly, not multiplying them speculatively.
For an additive, backward-compatible schema change that the running code does not read, an atomic apply plus exact verification in the planned maintenance window is normally sufficient. Require a soak period only when there is a specific runtime behavior to observe. Label optional hardening as optional and lead with the minimal recommended path.
docs/TODO.md is the maintainer-owned backlog for proposed work. Consult it
when planning related changes, but do not treat an entry as authorization to
implement, deploy, mutate data, synchronize Discord commands, or expand the
current task. Keep current operating guides limited to behavior that actually
exists; remove completed TODO entries after their durable behavior is
documented in the appropriate guide.
When Nelluk explicitly asks for a narrow fix directly in the production
checkout or on production master, that instruction overrides the ordinary
isolated-worktree workflow for that fix. Treat it as a proportional hotfix,
not automatically as a full production-cutover project.
This path is appropriate when the change is small and reversible and does not introduce a schema/data migration, dependency or runtime-topology change, command-tree synchronization, credential/configuration change, destructive operation, or broad architectural rewrite. Under this path:
- verify the exact production checkout, branch, clean starting state, and running version before editing;
- diagnose with narrow logs/read-only state, make the smallest complete fix with one writer, add focused regression coverage, run proportionate focused and adjacent tests, review the diff, and create a clean Git checkpoint;
- do not require a separate worktree/branch, beta deployment, full offline suite, independent multi-agent review, push, release ceremony, or extended soak unless a concrete risk in the actual change warrants it or Nelluk asks;
- keep aggregate operations such as
allscopes within their established guild/data boundary when restoring a cross-guild single-object path; and - treat production restart/deploy, Discord command sync or messages, database writes, and push as separate actions requiring their applicable explicit authorization. Nelluk may elect to perform the restart or smoke test.
If investigation expands beyond those limits, stop using the hotfix exception and propose the ordinary isolated workflow for the expanded change. The fact that code lives in the production checkout does not by itself raise a source-only correction to the highest engineering risk tier.
- CPython 3.12
- discord.py 2.7.1 (Discord bot framework)
- Peewee ORM with PostgreSQL database
- FastAPI for optional REST API
- Matplotlib/Pandas/SciPy for statistics and graphing
- uv with
pyproject.tomlanduv.lockfor reproducible environments
The deployed bot runs in Docker, but coding and test worktrees intentionally share a host-only development environment from the primary checkout. A fresh primary checkout must be bootstrapped, with dependency-installation approval, before its worktree helper can run:
cd /home/nelluk/PolyBot39-beta
uv sync --locked --python 3.12.13Do not run uv sync separately in each worktree. Run
/home/nelluk/PolyBot39-beta/scripts/setup_development_worktree.sh "$PWD"
and use /home/nelluk/PolyBot39-beta/.venv/bin/python for worktree tests.
The host .venv is development tooling only; its presence does not change the
Docker deployment model or authorize a native bot process.
# Create or synchronize the locked development environment
uv sync --locked
# Run the Discord bot
POLYBOT_ENV=development .venv/bin/python bot.py --skip_tasks
# Run with options
POLYBOT_ENV=development .venv/bin/python bot.py --add_default_data
POLYBOT_ENV=development .venv/bin/python bot.py --recalc_elo
POLYBOT_ENV=development .venv/bin/python bot.py --game_exportProduction runs in Docker with POLYBOT_ENV=production; the image installs
locked non-development dependencies. Production recreation and restarts
require separate explicit approval; see docs/PRODUCTION_DOCKER.md.
POLYBOT_ENV=development .venv/bin/python -m uvicorn server:server --host 127.0.0.1 --port 8000The development API is disabled by default and requires its separate runtime policy acknowledgement before this command can run.
config.ini/server_settings.py- ignored production profile filesconfig.development.ini/server_settings_dev.py- ignored development profile filesPOLYBOT_ENV- must be explicitlyproductionordevelopmentin deployed commands
bot.py- Main Discord bot entry point. InitializesMyBotclass and loads cog extensionsserver.py- FastAPI server entry point for REST API
models.py- Peewee ORM models (DiscordMember, Player, Team, Game, GameSide, Lineup, etc.). Contains ELO calculation logicutilities.py- Helper functions: DB connection management, game record locking, role lookupssettings.py- Runtime settings, permission checks (is_staff,is_mod), guild configuration lookup viaguild_setting()
games.py- Core game commands: win/lose, game info, player stats, ELO graphsmatchmaking.py- Open game hosting, joining via reactions, matchmaking lobbiesleague.py- PolyChampions-specific: team management, drafts, house/tier systemadministration.py- Staff commands: game corrections, bans, bulk operationsmisc.py- Utility commands: guide, roles, infobullet.py- Bullet league managementcustomhelp.py- Custom help command formattingapi_cog.py- Discord cog that wraps API functionality
DiscordMember- Discord user with Polytopia namePlayer- Server-specific player profile (DiscordMember + guild)Team- Competitive team with ELO ratingHouse- Affiliation of teams (PolyChampions)Game- A match with sides, date, completion statusGameSide- One side of a game (team or players)Lineup- Player assignments within a GameSide
The bot runs on multiple Discord servers with per-guild settings. Runtime
profiles explicitly select either static settings or a validated, published
database snapshot as the active per-guild authority. The ignored
server_settings.py / server_settings_dev.py module still defines the
allowed guild inventory and historical shortcut IDs in both modes. Use
settings.guild_setting(guild_id, 'setting_name') to read the active value
without depending on its storage source.
Default prefix is $ but can be configured per-guild via command_prefix setting.
User levels (0-7) control command access:
- Level 0: Unregistered
- Level 1-3: Progressive game hosting/joining permissions
- Level 4: Advanced matchmaking
- Level 5: Staff (helper roles)
- Level 6: Mod
- Level 7: Owner
Check with settings.is_staff(), settings.is_mod(), settings.get_user_level().