diff --git a/.clue/id-ledger.yaml b/.clue/id-ledger.yaml index b01c3450a..7e2a97258 100644 --- a/.clue/id-ledger.yaml +++ b/.clue/id-ledger.yaml @@ -4,7 +4,7 @@ counters: ARCH: "26" C: "4" CAP: "17" - CH: "33" + CH: "34" G: "2" GTD: "1" IDR: "4" @@ -674,6 +674,11 @@ entries: state: live prefix: CH component: "33" + - id: CH-034 + kind: numeric + state: live + prefix: CH + component: "34" - id: G-001 kind: numeric state: live diff --git a/docs/design/rumble/user-documentation.md b/docs/design/rumble/user-documentation.md index 08d32fd1d..148814296 100644 --- a/docs/design/rumble/user-documentation.md +++ b/docs/design/rumble/user-documentation.md @@ -13,6 +13,8 @@ reversal-cost: low > **Status: DRAFT** - design direction captured. > Part of the [Tank Royale Rumble umbrella design](./README.md). +**Implementation note (CH-034, P-003/M-009):** the plan promised one quickstart per audience under `/web/docs/rumble/`, which now exists as `bot-author-guide.md`, `client-guide.md`, `moderator-guide.md`, and an `index.md` landing page. The moderator guide lives under `/web/docs/rumble/` rather than as a separate `rumble-data/docs/moderator-handbook.md`, since no such handbook exists yet; it links to each repository's `GOVERNANCE.md` instead. `onboarding.md` and `faq.md` below remain aspirational: folded into the shipped guides for now, not yet split out as their own documents. + ## Scope The documentation the rumble ships for its users: what documents exist, who they serve, where they live, and the onboarding journeys they support. The other design documents describe how the system works; this one describes how a person finds out what to do. Documentation is participation infrastructure: every workflow that lacks a guide costs participants, and the rumble's health is measured in participants. diff --git a/docs/plans/P-003-rumble.md b/docs/plans/P-003-rumble.md index d3c4b8c82..856ced21f 100644 --- a/docs/plans/P-003-rumble.md +++ b/docs/plans/P-003-rumble.md @@ -1,7 +1,7 @@ --- id: P-003 type: plan -status: active +status: completed links: [G-001] title: Tank Royale Rumble provenance: inferred @@ -21,6 +21,8 @@ The milestones mirror the design's Change Proposal Roadmap in order. Each milest | M-007 | `rumble-data` repository live | Result inbox drained by CI into immutable raw facts; aggregation produces leaderboard, pairings, and matches-needed projections; dashboard published on Pages | done | CH-011; [robocode-dev/rumble-data#4](https://github.com/robocode-dev/rumble-data/pull/4) merged on 2026-08-03, providing catalog synchronization and ranked advice for every V1 game type | | M-008 | Rumble client runs ranked battles | After the official Tank Royale 1.1.0 release, the client pulls the bot catalog and matchmaking advice, runs a ranked battle, and its submitted result lands in `rumble-data` via issue-ops with no human in the loop | done | CH-032; [rumble-data#11](https://github.com/robocode-dev/rumble-data/issues/11) accepted the client journal and `f25c02f20e2938545563a0d2a017e53e9a208a7e` published its immutable facts and projections | | M-010 | GUI supports TwinDuel | The GUI game-type dialog can select and start the `TwinDuel` preset using the common game-type contract; it is shipped in Tank Royale 1.1.0 | done | CH-013; CAP-017/GTD-001 and GUI acceptance evidence | -| M-009 | Rumble documentation published | User guides live under `/web/docs/rumble/` with one quickstart per audience: bot author, battle contributor, moderator | todo | | +| M-009 | Rumble documentation published | User guides live under `/web/docs/rumble/` with one quickstart per audience: bot author, battle contributor, moderator | done | CH-034; `web/docs/rumble/{bot-author-guide,client-guide,moderator-guide,index}.md`, wired into the VitePress nav and sidebar | M-006 and M-007 both depend only on M-005 and may proceed in parallel; M-008 depends on the `rumble-bots` catalog, the `rumble-data` engine/matchmaking files, the official Tank Royale 1.1.0 release, and merged BR-049 Runner support available through a local build during development; distributing the ranked client depends on a published Battle Runner artifact containing BR-049. M-010 depends only on M-005's common game-type contract and is shipped in Tank Royale 1.1.0; M-009 follows the settled client and GUI interfaces. + +All six milestones are done: P-003 is complete. Rumble's fuller published document set described in [`docs/design/rumble/user-documentation.md`](../design/rumble/user-documentation.md) (a separate `rumble-data` moderator handbook, an `onboarding.md`, and a `faq.md`) remains a candidate for future work but is not a plan promise; nothing here blocks it. diff --git a/docs/plans/README.md b/docs/plans/README.md index f967dcfbe..d4d05db08 100644 --- a/docs/plans/README.md +++ b/docs/plans/README.md @@ -9,5 +9,5 @@ Every change proposal names the plan item it serves, or explicitly declares itse - [P-001 — Cliewen adoption](P-001-cliewen-adoption.md) · `active` - [P-002 — TypeScript Bot API reaches npm](P-002-typescript-bot-api-npm.md) · `completed` -- [P-003 — Tank Royale Rumble](P-003-rumble.md) · `active` +- [P-003 — Tank Royale Rumble](P-003-rumble.md) · `completed` diff --git a/web/docs/.vitepress/config.mts b/web/docs/.vitepress/config.mts index 7c18736ce..d3f17db03 100644 --- a/web/docs/.vitepress/config.mts +++ b/web/docs/.vitepress/config.mts @@ -27,7 +27,8 @@ export default withMermaid(defineConfig({ { text: 'Home', link: '/' }, { text: 'Articles', link: '/articles/intro' }, { text: 'Tutorial', link: '/tutorial/getting-started' }, - { text: 'API', link: '/api/apis' } + { text: 'API', link: '/api/apis' }, + { text: 'Rumble', link: '/rumble/' } ], sidebar: [ @@ -103,6 +104,15 @@ export default withMermaid(defineConfig({ { text: 'Custom Game Setup', link: '/articles/custom-game-setup' }, { text: 'Team Strategies', link: '/articles/team-strategies' }, ] + }, + { + text: 'Rumble', + items: [ + { text: 'Overview', link: '/rumble/' }, + { text: 'Bot Author Quickstart', link: '/rumble/bot-author-guide' }, + { text: 'Battle Contributor Quickstart', link: '/rumble/client-guide' }, + { text: 'Moderator Quickstart', link: '/rumble/moderator-guide' }, + ] } ], diff --git a/web/docs/rumble/bot-author-guide.md b/web/docs/rumble/bot-author-guide.md new file mode 100644 index 000000000..08953937a --- /dev/null +++ b/web/docs/rumble/bot-author-guide.md @@ -0,0 +1,119 @@ +# Submit a bot to the Rumble + +This guide takes a bot that already works in Tank Royale and puts it into the [Rumble](index.md) ranked catalog. You need a GitHub account, Git, Python 3, and the runtimes used by the bots in your catalog checkout. CI has all four supported runtimes. + +If you have not written a bot yet, start with the [Tank Royale tutorial](../tutorial/getting-started.md) and the list of [official Bot APIs](../api/apis.md). Test the bot against sample bots with the normal [GUI battle setup](../articles/gui-battle-setup.md) before submitting it. Local GUI battles are private practice; they never affect the Rumble rankings. + +## Before you submit + +Ranked bots must meet these rules: + +- Use the official Tank Royale Bot API for Java, C#, Python, or TypeScript. +- Run directly from source through the normal Tank Royale booter scripts. +- Depend only on the official Bot API package and the platform's standard library. TypeScript bots must also commit their lockfile. +- Include no compiled programs, archives, generated dependency directories, custom protocol clients, process launchers, or raw socket code. +- Declare one of the permitted licenses: `MIT`, `Apache-2.0`, `BSD-3-Clause`, or `GPL-3.0-or-later`. + +The complete rules live in the [`rumble-bots` contribution guide](https://github.com/robocode-dev/rumble-bots/blob/main/CONTRIBUTING.md). + +## 1. Fork and clone the catalog + +A fork is your own GitHub copy of a repository. A pull request, usually shortened to PR, asks the Rumble moderators to merge your changes into the public catalog. + +Fork [`robocode-dev/rumble-bots`](https://github.com/robocode-dev/rumble-bots), then clone your fork and create a branch: + +```shell +git clone https://github.com//rumble-bots.git +cd rumble-bots +git switch -c add- +``` + +Replace the angle-bracket placeholders with your GitHub account and bot name. + +## 2. Add your bot source + +Copy your working bot into the folder for its language: + +```text +bots/ +└── / + └── / + ├── .json + ├── .sh + ├── .cmd + └── src/ + └── source files +``` + +Use `java`, `csharp`, `python`, or `typescript` for ``. The directory name, config filename, and bot `name` must match exactly. Source files belong under `src/`, and the boot scripts point at the entry point there, for example `"$SCRIPT_DIR/src/MyBot.py"`. Existing entries in [`bots/`](https://github.com/robocode-dev/rumble-bots/tree/main/bots) are useful working examples. + +Add a `license` field to the bot's JSON configuration, for example: + +```json +{ + "name": "MyBot", + "version": "1.0.0", + "authors": ["Your name"], + "description": "What my bot does.", + "platform": "JVM", + "programmingLang": "Java 17", + "gameTypes": ["1v1", "melee", "twinduel"], + "license": "Apache-2.0" +} +``` + +This example uses Java; keep the correct platform and language values from your working bot configuration. The license applies to the complete bot directory. By opening the PR, you certify that you have the right to publish the source under that license. + +## 3. Validate the submission + +Run the same validator used by CI: + +```shell +python scripts/validate_bot.py --root . --owner --smoke +``` + +The validator checks the directory layout, license, dependencies, source-only rules, ownership, and boot scripts. The smoke check also starts the source entry point. Fix every reported problem before opening the PR. + +## 4. Open the pull request + +Commit and push your branch, then open a PR against `robocode-dev/rumble-bots`: + +```shell +git add bots// +git commit -m "Add " +git push --set-upstream origin add- +``` + +Use the repository's bot-submission checklist in the PR description. CI runs the validator again, and a moderator reviews the submission. A green check is required, but it does not replace review. + +When the PR is merged, CI adds the bot to the generated catalog. `rumble-data` synchronizes that catalog at 23 minutes past every UTC hour. The bot then appears on the [dashboard](https://robocode-dev.github.io/rumble-data/) and waits for its first ranked battles. + +## Submit a TwinDuel team + +A TwinDuel team is its own catalog entry. Its `teamMembers` field contains exactly two member slots, each naming an active bot by its directory name: + +```json +{ + "name": "MyTwinTeam", + "version": "1.0.0", + "authors": ["Your name"], + "license": "Apache-2.0", + "teamMembers": ["MyFirstBot", "MySecondBot"] +} +``` + +Put the team under one of the recognized platform folders. Its directory contains only `.json`; it has no source or boot scripts of its own. Both slots may name the same bot for a true twin team. The slots may also name bots written with different Bot API languages, in which case the catalog publishes the team platform as `Mixed`. A team cannot contain another team, and every member must be an active individual bot. + +The generated catalog entry records the exact member versions that were active when it was published, so member versions are part of the published team identity. Bump the team's own `version` whenever you change which bots it names. + +## Ownership, versions, and slots + +The first merged PR for a bot or team name reserves that name for your GitHub account. Only that account, or another account registered to the same owner, may submit later versions. + +Published source versions are immutable. When the source changes, increase the version in the bot configuration and submit it again. The latest version becomes active; older results remain in history but no longer determine the current rank. + +Each owner may have five active catalog entries by default. An individual bot or a TwinDuel team each uses one slot. Updating an existing entry to a new version does not consume another slot. + +## Help your bot get ranked + +New entries need battle samples before their ranking means much. Community clients prefer matchups with too few samples, so coverage improves automatically as contributors run battles. You can also [run a Rumble client](client-guide.md) and list your own entries in `myBots`; the client then gives useful matchups involving them priority. diff --git a/web/docs/rumble/client-guide.md b/web/docs/rumble/client-guide.md new file mode 100644 index 000000000..5aab98f24 --- /dev/null +++ b/web/docs/rumble/client-guide.md @@ -0,0 +1,152 @@ +# Run ranked Rumble battles + +The Rumble has no central machine running every fight. Community members donate computer time by running the Rumble client locally. The client downloads the reviewed bot catalog, chooses a useful matchup, runs the battle, keeps replay evidence on your computer, and submits the result for validation. + +You do not need to own a bot to contribute battles. If you do own one, you can ask the client to prefer under-sampled matchups involving it. + +## What works today + +The native client can synchronize, run one ranked battle, and submit its result. You currently build it from source because there is no published production client image. The development Docker image contains all four bot runtimes, but its launcher scripts currently expose only configuration validation, runtime checks, and synchronization. Use the native path below for ranked `run` and `submit` commands. + +The client accepts a practice-mode configuration, but `--run` currently executes ranked battles only. Use the [Tank Royale GUI](../articles/gui-battle-setup.md) for local practice battles. + +## What you need + +- A GitHub account. +- Git and JDK 17. +- Java 17, .NET 8 SDK, Python 3.12, and Node.js 22 if you run natively. The client may select bots from any supported language. +- Two sibling source checkouts: [`tank-royale`](https://github.com/robocode-dev/tank-royale) and [`rumble-client`](https://github.com/robocode-dev/rumble-client). + +The runtime check reports exactly what is missing and does not install or change anything. + +## 1. Register your client + +Each battle contributor registers once so result submissions can be tied to a GitHub account. Fork [`robocode-dev/rumble-data`](https://github.com/robocode-dev/rumble-data), then add `clients/.json`: + +```json +{ + "schemaVersion": 1, + "account": "your-github-account", + "clientIds": ["your-github-account-desktop-01"] +} +``` + +The filename and `account` must match your GitHub account exactly. Choose a stable `clientId` for each computer you plan to use. Open a PR with this file; a moderator reviews and merges it. Ranked submissions from that account and client ID are accepted after the registration reaches `main`. + +## 2. Build the client + +Clone the two repositories beside each other: + +```text +work/ +├── tank-royale/ +└── rumble-client/ +``` + +From `rumble-client`, build against the adjacent Tank Royale checkout. + +On Linux or macOS: + +```shell +./gradlew --no-configuration-cache -PtankRoyaleSource=../tank-royale build +``` + +On PowerShell: + +```powershell +.\gradlew.bat --no-configuration-cache "-PtankRoyaleSource=../tank-royale" build +``` + +## 3. Create your configuration + +Copy `rumble-client.example.json` to `rumble-client.json`, then edit the copy. Do not commit it. + +```json +{ + "schemaVersion": 1, + "botsRepo": "https://github.com/robocode-dev/rumble-bots", + "dataRepo": "https://github.com/robocode-dev/rumble-data", + "clientId": "your-github-account-desktop-01", + "myBots": ["MyBot"], + "gameTypes": ["1v1"], + "battlesPerSession": 50, + "mode": "ranked", + "workDirectory": ".rumble-client" +} +``` + +Use the registered ID from step 1. `myBots` may be empty; otherwise, list the names of your active bots or teams without version numbers. The client prioritizes useful matchups involving them. + +Set `gameTypes` to the single format you want to run. During the current source-build phase, list exactly one game type: `--run` picks the alphabetically first entry and runs that one, so listing several formats silently runs only `1v1` and never the others. To cover another format, change `gameTypes` and run again. Each `--run` invocation runs one battle; the example file's `battlesPerSession` is not used by the current commands. + +`workDirectory` holds the bot cache, ranked journal, and replay evidence. Keep that directory private and backed up. + +## 4. Check and synchronize + +Every Gradle invocation needs the same two arguments as the build in step 2. `-PtankRoyaleSource` is what makes the client compile and run against your adjacent Tank Royale checkout; without it Gradle tries to download a Battle Runner release that does not exist yet, and the command fails to resolve its dependencies. `--no-configuration-cache` is required because the project enables the configuration cache by default. + +On Linux or macOS: + +```shell +./gradlew --no-configuration-cache -PtankRoyaleSource=../tank-royale run --args="--check-runtimes" +./gradlew --no-configuration-cache -PtankRoyaleSource=../tank-royale run --args="--validate-config" +./gradlew --no-configuration-cache -PtankRoyaleSource=../tank-royale run --args="--sync" +``` + +On PowerShell: + +```powershell +.\gradlew.bat --no-configuration-cache "-PtankRoyaleSource=../tank-royale" run --args="--check-runtimes" +.\gradlew.bat --no-configuration-cache "-PtankRoyaleSource=../tank-royale" run --args="--validate-config" +.\gradlew.bat --no-configuration-cache "-PtankRoyaleSource=../tank-royale" run --args="--sync" +``` + +Synchronization verifies your registration, the current engine behavior version, the catalog source hashes, and the matchmaking advice. It prepares an immutable local cache of the exact bot sources used for ranked battles. If synchronization refuses to continue, follow its diagnostic instead of bypassing the check. + +## 5. Run a ranked battle + +On Linux or macOS: + +```shell +./gradlew --no-configuration-cache -PtankRoyaleSource=../tank-royale run --args="--run" +``` + +On PowerShell: + +```powershell +.\gradlew.bat --no-configuration-cache "-PtankRoyaleSource=../tank-royale" run --args="--run" +``` + +The command chooses one valid matchup, runs all rounds for that game type, and appends the completed result to the local journal. An aborted, incomplete, or incompatible battle is not submittable. Replay evidence stays under `.rumble-client/evidence`; it is never uploaded automatically. + +## 6. Submit completed results + +Create a fine-grained GitHub personal access token limited to the `robocode-dev/rumble-data` repository with read and write access to Issues. It must not have permission to change repository contents, branches, releases, packages, or Pages. + +Supply the token only to the submission process. On Linux or macOS: + +```shell +export RUMBLE_CLIENT_TOKEN='' +./gradlew --no-configuration-cache -PtankRoyaleSource=../tank-royale run --args="--submit" +unset RUMBLE_CLIENT_TOKEN +``` + +On PowerShell: + +```powershell +$env:RUMBLE_CLIENT_TOKEN = '' +.\gradlew.bat --no-configuration-cache "-PtankRoyaleSource=../tank-royale" run --args="--submit" +Remove-Item Env:RUMBLE_CLIENT_TOKEN +``` + +The client posts pending journal records through the `rumble-data` issue inbox. The ingestion workflow validates each result, publishes accepted facts, and replies with receipts. Records remain retryable until the client observes their successful receipts, so an interrupted submission does not lose them. + +Never put the token in `rumble-client.json`, a shell script, Git, an issue, or a log. + +## Keep contributing + +Repeat `--run` to produce more battles and `--submit` to send pending results. You can change `gameTypes` between sessions. The client uses published matchmaking advice to cover new and under-sampled matchups; that advice is guidance rather than a reservation, so two clients may safely run the same matchup. + +Accepted results usually reach the [dashboard](https://robocode-dev.github.io/rumble-data/) within minutes. A scheduled ingestion sweep runs twice an hour if the immediate GitHub event is delayed. + +For command and implementation details, see the [`rumble-client` README](https://github.com/robocode-dev/rumble-client#tank-royale-rumble-client). diff --git a/web/docs/rumble/index.md b/web/docs/rumble/index.md new file mode 100644 index 000000000..6113b673c --- /dev/null +++ b/web/docs/rumble/index.md @@ -0,0 +1,75 @@ +# Tank Royale Rumble + +Writing a bot is one thing. Finding out how good it really is takes a lot of battles against a lot of opponents. + +Tank Royale Rumble is the community-run ranked competition for Robocode Tank Royale. It follows the tradition of RoboRumble and LiteRumble from classic Robocode: submit your bot, let it fight across the shared ladder, study the results, and come back with a better version. If you are serious about Robocoding, this is where you put your code to the test. + +You do not steer a tank during a Rumble battle. You write the program that controls it. Rumble clients run the battles automatically and publish the results, so rankings come from the same bot code fighting many different opponents. + +## The Rumble loop + +1. Build a bot with one of the official Tank Royale Bot APIs. +2. Practice locally in the Tank Royale GUI until your bot behaves the way you want. +3. Submit its source code to the reviewed Rumble bot catalog. +4. Community members run Rumble clients on their own computers. The clients choose useful matchups, run ranked battles, and submit the results. +5. The dashboard combines the accepted results into rankings. +6. Learn from the results, improve your bot, and submit a new version. + +The cycle never really ends. A bot that dominates today may meet a smarter opponent tomorrow. + +## Choose how you want to participate + +| I want to... | Start here | +|--------------|------------| +| Enter my bot in the rankings | [Submit a bot](bot-author-guide.md) | +| Donate computer time and run ranked battles | [Run a Rumble client](client-guide.md) | +| See which bots are winning | [Open the live dashboard](https://robocode-dev.github.io/rumble-data/) | +| Help review submissions and keep the competition fair | [Moderate the Rumble](moderator-guide.md) | + +You can submit a bot without running a client, and you can run a client without owning a bot. Many competitors do both because the client gives matchups involving their own bots priority when more samples are needed. + +## Ranked game types + +Each game type has its own leaderboard. + +| Game type | What fights | Rounds | Battlefield | +|-----------|-------------|--------|-------------| +| **1v1** | Two individual bots | 35 | 800 x 600 | +| **TwinDuel** | Two teams with two bots on each team | 75 | 800 x 800 | +| **Melee** | Ten individual bots at once | 35 | 1000 x 1000 | + +TwinDuel is the classic twin-team format, not a general team category. Mini, micro, nano, and other code-size classes from classic Robocode are not part of the Tank Royale Rumble because source-size limits do not compare cleanly across Java, C#, Python, and TypeScript. + +## How the system works + +The Rumble has three public GitHub repositories: + +- [`rumble-bots`](https://github.com/robocode-dev/rumble-bots) is the reviewed, source-only bot catalog. +- [`rumble-client`](https://github.com/robocode-dev/rumble-client) runs battles on contributors' computers. +- [`rumble-data`](https://github.com/robocode-dev/rumble-data) accepts results, calculates the rankings, and publishes the dashboard. + +There is no central battle server. Clients download the same pinned bot catalog and game settings, run battles locally, and send completed results through GitHub issues. Automation validates each result before it becomes part of the ranking data. The raw accepted results remain in Git, so the leaderboard can be rebuilt and checked by anyone. + +### Catalog + +The catalog is the list of bots and TwinDuel teams allowed in ranked battles. Every entry has an owner, a version, and a hash of its reviewed source. A new source version is a new ranked identity; only the latest active version appears on the current leaderboard. + +### Matchups and samples + +A matchup is a set of opponents that fought each other. One completed battle is one sample of that matchup. The client prefers new and under-sampled matchups, which helps new bots receive a meaningful rank and keeps older rankings fresh. + +### Rankings and APS + +The main ranking number is APS, or Average Percentage Score. For each matchup, Rumble calculates the percentage of the total score earned by a bot or team. It averages repeated battles of that matchup, then averages across all of the entry's matchups. Higher APS is better. + +A new bot or version starts with no battle samples, so its first position can move sharply. The ranking settles as it fights more opponents. When a game-observable engine change starts a new behavior version, the current leaderboard uses only results from that new epoch. Earlier results stay in the public data history, but they are not mixed with battles played under different rules. + +## When rankings update + +An incoming result submission starts the ingestion workflow as soon as GitHub applies its `result-submission` label. A scheduled sweep also runs at 17 and 47 minutes past every UTC hour in case an event was delayed. Accepted results regenerate the leaderboard, and GitHub Pages publishes the changed dashboard after the data commit. In normal operation, a result appears within minutes; the scheduled sweep is the fallback, not a guaranteed deadline. + +The bot catalog synchronizes at 23 minutes past every UTC hour. A newly merged bot normally reaches the dashboard after that synchronization, then waits for clients to produce its first ranked battles. + +## Current availability + +Bot submission, ranked battle execution, result ingestion, and the dashboard work end to end. The Rumble client does not yet have a published production container image, so battle contributors currently build it from source and use the native command line. The [client guide](client-guide.md) shows the exact supported path and calls out the parts of the Docker workflow that are still under development. diff --git a/web/docs/rumble/moderator-guide.md b/web/docs/rumble/moderator-guide.md new file mode 100644 index 000000000..75c57603b --- /dev/null +++ b/web/docs/rumble/moderator-guide.md @@ -0,0 +1,61 @@ +# Moderate the Rumble + +Rumble moderators protect a fair, reviewable competition. They review bot submissions and client registrations, handle disputes, and keep the GitHub automation healthy. There is no hidden admin panel: moderation happens through pull requests and the policy files in `rumble-bots` and `rumble-data`. + +The repository policies remain authoritative. This guide explains the normal workflow and points to those policies when judgment is required. + +## Review a bot submission + +Bot submissions arrive as pull requests in [`rumble-bots`](https://github.com/robocode-dev/rumble-bots). + +1. Wait for validation CI to pass. Never merge a submission with a failing check. +2. Confirm that the pull request changes only the author's bot or team entry and does not edit generated catalog files. +3. Check that the directory contains source rather than binaries, generated dependencies, archives, or unrelated files. +4. Confirm that the bot uses an official Bot API and declares an allowed SPDX license. +5. Review restricted-code diagnostics and suspicious or confusable names. Ask the author to resolve anything unclear before approval. +6. For an existing bot name, confirm that the submitting GitHub account owns it and that the version increased when source changed. +7. For a TwinDuel team, confirm that it has two member slots backed by active individual bot versions and contains only its team JSON. Repeated member identities are valid within one twin team. + +First-time authors deserve a closer look. Owners with a history of clean submissions may qualify for auto-merge on later version bumps, as described in [`rumble-bots/GOVERNANCE.md`](https://github.com/robocode-dev/rumble-bots/blob/main/GOVERNANCE.md). + +## Review a client registration + +Client registrations arrive as pull requests in [`rumble-data`](https://github.com/robocode-dev/rumble-data). + +1. Confirm that the PR adds `clients/.json` and does not change result facts or generated projections. +2. Check that the filename and `account` exactly match the submitting GitHub account. +3. Check that `clientIds` is a non-empty list of stable, non-empty identifiers. +4. Require the Verify Rumble data workflow to pass. +5. Merge after one moderator approval. + +Ordinary code, catalog, ban, exclusion, and policy changes in `rumble-data` follow the same green-CI and one-approval rule. CI is the only writer of accepted facts and generated projections on `main`. + +## Handle disputes and abuse + +Every action below is a reviewed pull request with the reason recorded in its description. Preserve the facts; change whether they count. + +### Exclude a disputed result + +Add its `battleId` to `rumble-data/exclusions.json`. The next aggregation omits it from rankings without deleting the accepted fact. Removing the exclusion restores it on a later recomputation. + +### Ban an account + +Add the GitHub account to `bannedAccounts` in `rumble-data/bans.json`. Future submissions are rejected, and earlier facts from that account stop contributing when projections are regenerated. + +If the account owns catalog entries, add those entries to `disqualifiedBots` in the same file. The generated catalog excludes disqualified bots, but their existing result facts remain in history. Bans may be temporary or permanent. + +### Resolve a suspicious name or submission + +The validator detects identical normalized name skeletons and restricted code constructs. Treat the diagnostic as a reason to inspect the submission, not as proof of bad intent. Resolve impersonation, name squatting, unsafe code, licensing complaints, account recovery, and appeals under [`rumble-bots/GOVERNANCE.md`](https://github.com/robocode-dev/rumble-bots/blob/main/GOVERNANCE.md). + +## Keep the automation healthy + +Result submissions normally trigger ingestion when GitHub applies the `result-submission` label. A scheduled fallback runs at 17 and 47 minutes past every UTC hour. Catalog synchronization runs at 23 minutes past every UTC hour. The Pages workflow publishes dashboard changes after accepted data is pushed. + +If GitHub disables scheduled workflows after repository inactivity, re-enable them. A newly labelled result issue also wakes the ingestion workflow, but moderators should not rely on incoming traffic as the only health check. + +Once a month, follow the `rumble-data` compaction procedure for facts older than three full months. It must produce verified rollups without changing the generated projections before the individual facts move to the archive branch. + +Once each quarter, run the fork drill: fork the repositories, enable their workflows and Pages, run validation and aggregation locally, and record the result in a governance issue. The drill proves that another maintainer can recover the Rumble from its public repositories and documentation. + +Operational details and decision authority live in [`rumble-data/GOVERNANCE.md`](https://github.com/robocode-dev/rumble-data/blob/main/GOVERNANCE.md) and [`rumble-bots/GOVERNANCE.md`](https://github.com/robocode-dev/rumble-bots/blob/main/GOVERNANCE.md).