Greatly Improve Memory Overhead & Fix some typing errors #8

Merged
smell-of-curry merged 6 commits from greatly-reduce-memory into master 2026-04-26 16:20:00 +00:00
smell-of-curry commented 2026-02-10 00:55:15 +00:00 (Migrated from github.com)

Reduced Memory usage by 100MB!!! will need to improve more but this is great.


Note

Medium Risk
Touches core Dex loading/mod selection and narrows supported mods/random-battles modules, which can break legacy formats or mod-dependent data if configurations expect them.

Overview
Reduces memory/startup overhead by deleting the large generated dex-module-map.ts and switching sim/dex.ts to a small, explicit DataRegistry (base data + pokebedrock only) instead of dynamic/generator-driven module registration.

Makes mod resolution more forgiving: DexFormats.load() and Dex.mod()/forGen()/forFormat() now fall back to the default/gen9 dex when a requested mod isn’t registered, avoiding startup crashes from legacy format entries.

Simplifies random battles module loading to only explicitly support gen9 (random-battles-module-map.ts), and updates team generation to throw a clear error when a requested random-battles module is missing.

Hardens a few ruleset paths with safer global.Config access + default hosts for dex/client links, uses this.dex consistently, and tightens typing in godlygiftmod.

Written by Cursor Bugbot for commit f2d9258887. This will update automatically on new commits. Configure here.

Summary by CodeRabbit

  • Bug Fixes

    • Safer runtime access to global configuration with guarded lookups and fallback hosts for external links and assets.
    • Clearer errors and safer handling when optional modules or random-battles data are missing; missing mods now fall back instead of crashing.
  • Refactor

    • Replaced large generated module maps with an inline data registry and streamlined module loading.
    • Simplified build flow by removing pre-build module-map generation.
  • Behavior Change

    • Random-battles support narrowed to an explicit Gen9 path.
  • Chore

    • Package version bumped.
Reduced Memory usage by 100MB!!! will need to improve more but this is great. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches core `Dex` loading/mod selection and narrows supported mods/random-battles modules, which can break legacy formats or mod-dependent data if configurations expect them. > > **Overview** > Reduces memory/startup overhead by deleting the large generated `dex-module-map.ts` and switching `sim/dex.ts` to a small, explicit `DataRegistry` (base data + `pokebedrock` only) instead of dynamic/generator-driven module registration. > > Makes mod resolution more forgiving: `DexFormats.load()` and `Dex.mod()`/`forGen()`/`forFormat()` now fall back to the default/gen9 dex when a requested mod isn’t registered, avoiding startup crashes from legacy format entries. > > Simplifies random battles module loading to only explicitly support `gen9` (`random-battles-module-map.ts`), and updates team generation to throw a clear error when a requested random-battles module is missing. > > Hardens a few ruleset paths with safer `global.Config` access + default hosts for dex/client links, uses `this.dex` consistently, and tightens typing in `godlygiftmod`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit f2d9258887bb229373a39e1b991693cdd26930bf. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Safer runtime access to global configuration with guarded lookups and fallback hosts for external links and assets. * Clearer errors and safer handling when optional modules or random-battles data are missing; missing mods now fall back instead of crashing. * **Refactor** * Replaced large generated module maps with an inline data registry and streamlined module loading. * Simplified build flow by removing pre-build module-map generation. * **Behavior Change** * Random-battles support narrowed to an explicit Gen9 path. * **Chore** * Package version bumped. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
coderabbitai[bot] commented 2026-02-10 00:55:35 +00:00 (Migrated from github.com)

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Replaced generated module maps with an explicit DataRegistry and inline imports; removed build-time generation of dex/random-battles maps; Dex/teams now fallback to base mod when registry entries are missing; runtime Config access switched to guarded global lookups and several Dex static calls moved to instance context.

Changes

Cohort / File(s) Summary
Removed autogenerated module map
sim/dex-module-map.ts
Deleted the entire generated export (DexMods, DexModuleMap) and its long list of requires.
Dex core & registry
sim/dex.ts
Introduced a static DataRegistry built from inline imports; loadDataFile now reads the registry; ModdedDex.mod/forGen/forFormat fall back to base (gen9) when a mod is unregistered; includeMods simplified to construct only the pokebedrock mod.
Random battles mapping
sim/random-battles-module-map.ts
Removed broad RandomBattlesMods list and mappings; replaced with getRandomBattlesModule(mod: string) that returns only the Gen9 teams module for 'gen9' and undefined otherwise.
Teams generator safety
sim/teams.ts
Teams.getGenerator now assigns the random-battles module to a local rbModule, null-checks it, and throws an explicit Error if missing before using .default.
Formats fallback
sim/dex-formats.ts
Changed hard error on unknown format.mod to a lazy fallback to DEFAULT_MOD with a clarifying comment to avoid startup crashes for legacy gens.
Build tooling
tools/build-utils.js
Removed pre-build generation of Dex and Random Battles module maps and deleted helper functions; transpile() now calls esbuild.buildSync directly.
Runtime Config & small fixes
data/rulesets.ts
Replaced direct Config uses with guarded (global as any).Config?.... and host fallbacks for potd and generated URLs; switched some Dex.* calls to this.dex.*; added an explicit const stat: keyof StatsTable annotation.
Manifest bump
package.json
Incremented version from 0.1.13 to 0.1.14.

Sequence Diagram(s)

sequenceDiagram
    participant Caller as Requester
    participant Dex as Dex (mod()/forFormat())
    participant Registry as DataRegistry
    participant ModDex as ModdedDex
    rect rgba(200,230,255,0.5)
    Caller->>Dex: request mod or format
    Dex->>Registry: lookup mod data
    alt data found
        Registry-->>Dex: module data
        Dex->>ModDex: instantiate ModdedDex(module data)
        ModDex-->>Dex: ModdedDex instance
        Dex-->>Caller: return ModdedDex
    else data missing
        Registry-->>Dex: undefined
        Dex->>ModDex: create fallback ModdedDex (base/gen9)
        ModDex-->>Dex: ModdedDex instance
        Dex-->>Caller: return ModdedDex
    end
    end

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰
I hopped through maps now thin and neat,
A registry wakes when calls compete,
Mods stretch and fall back to base,
Guarded Config keeps links in place,
I nibble bytes and drum a beat.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main objectives: reducing memory overhead by eliminating the large auto-generated module map and fixing type annotations. It is concise and reflects the primary focus of the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch greatly-reduce-memory

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

<!-- This is an auto-generated comment: summarize by coderabbit.ai --> <!-- This is an auto-generated comment: review paused by coderabbit.ai --> > [!NOTE] > ## Reviews paused > > It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the `reviews.auto_review.auto_pause_after_reviewed_commits` setting. > > Use the following commands to manage reviews: > - `@coderabbitai resume` to resume automatic reviews. > - `@coderabbitai review` to trigger a single review. > > Use the checkboxes below for quick actions: > - [ ] <!-- {"checkboxId": "7f6cc2e2-2e4e-497a-8c31-c9e4573e93d1"} --> ▶️ Resume reviews > - [ ] <!-- {"checkboxId": "e9bb8d72-00e8-4f67-9cb2-caf3b22574fe"} --> 🔍 Trigger review <!-- end of auto-generated comment: review paused by coderabbit.ai --> <!-- walkthrough_start --> <details> <summary>📝 Walkthrough</summary> ## Walkthrough Replaced generated module maps with an explicit DataRegistry and inline imports; removed build-time generation of dex/random-battles maps; Dex/teams now fallback to base mod when registry entries are missing; runtime Config access switched to guarded global lookups and several Dex static calls moved to instance context. ## Changes |Cohort / File(s)|Summary| |---|---| |**Removed autogenerated module map** <br> `sim/dex-module-map.ts`|Deleted the entire generated export (`DexMods`, `DexModuleMap`) and its long list of requires.| |**Dex core & registry** <br> `sim/dex.ts`|Introduced a static `DataRegistry` built from inline imports; `loadDataFile` now reads the registry; `ModdedDex.mod`/`forGen`/`forFormat` fall back to base (`gen9`) when a mod is unregistered; `includeMods` simplified to construct only the pokebedrock mod.| |**Random battles mapping** <br> `sim/random-battles-module-map.ts`|Removed broad `RandomBattlesMods` list and mappings; replaced with `getRandomBattlesModule(mod: string)` that returns only the Gen9 teams module for `'gen9'` and `undefined` otherwise.| |**Teams generator safety** <br> `sim/teams.ts`|`Teams.getGenerator` now assigns the random-battles module to a local `rbModule`, null-checks it, and throws an explicit `Error` if missing before using `.default`.| |**Formats fallback** <br> `sim/dex-formats.ts`|Changed hard error on unknown `format.mod` to a lazy fallback to `DEFAULT_MOD` with a clarifying comment to avoid startup crashes for legacy gens.| |**Build tooling** <br> `tools/build-utils.js`|Removed pre-build generation of Dex and Random Battles module maps and deleted helper functions; `transpile()` now calls `esbuild.buildSync` directly.| |**Runtime Config & small fixes** <br> `data/rulesets.ts`|Replaced direct `Config` uses with guarded `(global as any).Config?....` and host fallbacks for potd and generated URLs; switched some `Dex.*` calls to `this.dex.*`; added an explicit `const stat: keyof StatsTable` annotation.| |**Manifest bump** <br> `package.json`|Incremented version from `0.1.13` to `0.1.14`.| ## Sequence Diagram(s) ```mermaid sequenceDiagram participant Caller as Requester participant Dex as Dex (mod()/forFormat()) participant Registry as DataRegistry participant ModDex as ModdedDex rect rgba(200,230,255,0.5) Caller->>Dex: request mod or format Dex->>Registry: lookup mod data alt data found Registry-->>Dex: module data Dex->>ModDex: instantiate ModdedDex(module data) ModDex-->>Dex: ModdedDex instance Dex-->>Caller: return ModdedDex else data missing Registry-->>Dex: undefined Dex->>ModDex: create fallback ModdedDex (base/gen9) ModDex-->>Dex: ModdedDex instance Dex-->>Caller: return ModdedDex end end ``` ## Estimated code review effort 🎯 4 (Complex) | ⏱️ ~45 minutes ## Possibly related PRs - smell-of-curry/pokebedrock-showdown#1 — touches `sim/dex-formats.ts` and relates to formats-loading/fallback behavior. ## Poem > 🐰 > I hopped through maps now thin and neat, > A registry wakes when calls compete, > Mods stretch and fall back to base, > Guarded Config keeps links in place, > I nibble bytes and drum a beat. </details> <!-- walkthrough_end --> <!-- pre_merge_checks_walkthrough_start --> <details> <summary>🚥 Pre-merge checks | ✅ 5</summary> <details> <summary>✅ Passed checks (5 passed)</summary> | Check name | Status | Explanation | | :------------------------: | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. | | Title check | ✅ Passed | The PR title accurately summarizes the main objectives: reducing memory overhead by eliminating the large auto-generated module map and fixing type annotations. It is concise and reflects the primary focus of the changeset. | | Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. | | Linked Issues check | ✅ Passed | Check skipped because no linked issues were found for this pull request. | | Out of Scope Changes check | ✅ Passed | Check skipped because no linked issues were found for this pull request. | </details> <sub>✏️ Tip: You can configure your own custom pre-merge checks in the settings.</sub> </details> <!-- pre_merge_checks_walkthrough_end --> <!-- finishing_touch_checkbox_start --> <details> <summary>✨ Finishing Touches</summary> <details> <summary>📝 Generate docstrings</summary> - [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> Create stacked PR - [ ] <!-- {"checkboxId": "3e1879ae-f29b-4d0d-8e06-d12b7ba33d98"} --> Commit on current branch </details> <details> <summary>🧪 Generate unit tests (beta)</summary> - [ ] <!-- {"checkboxId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Create PR with unit tests - [ ] <!-- {"checkboxId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Commit unit tests in branch `greatly-reduce-memory` </details> </details> <!-- finishing_touch_checkbox_end --> <!-- tips_start --> --- Thanks for using [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=smell-of-curry/pokebedrock-showdown&utm_content=8)! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. <details> <summary>❤️ Share</summary> - [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai) - [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai) - [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai) - [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code) </details> <sub>Comment `@coderabbitai help` to get the list of available commands and usage tips.</sub> <!-- tips_end --> <!-- internal state start --> <!-- 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= --> <!-- internal state end -->
coderabbitai[bot] (Migrated from github.com) reviewed 2026-02-10 01:03:01 +00:00
coderabbitai[bot] (Migrated from github.com) left a comment

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@sim/random-battles-module-map.ts`:
- Around line 1-5: The stubbed RandomBattlesMods array and
getRandomBattlesModule function cause non-special-case random battle formats to
get undefined modules and crash; restore a correct module map or make
getRandomBattlesModule return the proper module for supported gens. Update the
exported RandomBattlesMods to list the supported mod names and implement
getRandomBattlesModule to lookup and return the module object (or dynamically
import) for the requested _module string (used by sim/teams.ts when falling into
the else branch), ensuring it returns a { default: ... } object instead of
undefined for Gen 9 random formats (or remove the failing format definitions if
you intend not to support them).
🧹 Nitpick comments (1)
sim/dex.ts (1)

485-493: Consider adding validation to catch mod references that don't exist in data.

The silent return for unregistered mods is intentional for graceful inheritance, but a typo in a format's mod field would silently use base data instead of failing—e.g., if a format mistakenly specifies mod: 'gen9typo' instead of a valid mod, the error would only surface through incorrect rulesets/learnsets. All currently referenced mods (38 excluding gen9, which is aliased to base at module load) are properly set up on disk, but adding validation or a fail-fast error for non-existent mod directories would catch such mistakes early.

Optional fail-fast guard
-			if (!dataObject && basePath.includes('mods/')) return;
+			if (!dataObject && basePath.includes('mods/')) {
+				throw new Error(`Mod "${this.currentMod}" is not registered in DataRegistry (${filePath})`);
+			}
**Actionable comments posted: 1** <details> <summary>🤖 Fix all issues with AI agents</summary> ``` In `@sim/random-battles-module-map.ts`: - Around line 1-5: The stubbed RandomBattlesMods array and getRandomBattlesModule function cause non-special-case random battle formats to get undefined modules and crash; restore a correct module map or make getRandomBattlesModule return the proper module for supported gens. Update the exported RandomBattlesMods to list the supported mod names and implement getRandomBattlesModule to lookup and return the module object (or dynamically import) for the requested _module string (used by sim/teams.ts when falling into the else branch), ensuring it returns a { default: ... } object instead of undefined for Gen 9 random formats (or remove the failing format definitions if you intend not to support them). ``` </details> <details> <summary>🧹 Nitpick comments (1)</summary><blockquote> <details> <summary>sim/dex.ts (1)</summary><blockquote> `485-493`: **Consider adding validation to catch mod references that don't exist in data.** The silent return for unregistered mods is intentional for graceful inheritance, but a typo in a format's `mod` field would silently use base data instead of failing—e.g., if a format mistakenly specifies `mod: 'gen9typo'` instead of a valid mod, the error would only surface through incorrect rulesets/learnsets. All currently referenced mods (38 excluding gen9, which is aliased to base at module load) are properly set up on disk, but adding validation or a fail-fast error for non-existent mod directories would catch such mistakes early. <details> <summary>Optional fail-fast guard</summary> ```diff - if (!dataObject && basePath.includes('mods/')) return; + if (!dataObject && basePath.includes('mods/')) { + throw new Error(`Mod "${this.currentMod}" is not registered in DataRegistry (${filePath})`); + } ``` </details> </blockquote></details> </blockquote></details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
@ -29,3 +1,1 @@
'randomroulette': require('../data/random-battles/randomroulette/teams'),
'sharedpower': require('../data/random-battles/sharedpower/teams'),
}[module];
export const getRandomBattlesModule = (mod: string): { default: any } | undefined => {
coderabbitai[bot] (Migrated from github.com) commented 2026-02-10 01:03:01 +00:00

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search for random battle format references in config/
echo "=== Searching for random battle format references ==="
fd -a -E node_modules -E dist -E build 'formats.*' config 2>/dev/null || true

# Search broadly for random battle references in formats
echo -e "\n=== Searching for random-battle format references ==="
rg -i "randombattle|random.battle|random\s*battle" --type ts --type js -l 2>/dev/null | head -20 || true

Repository: smell-of-curry/pokebedrock-showdown

Length of output: 777


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find usages of RandomBattlesMods and getRandomBattlesModule
echo "=== Searching for RandomBattlesMods usage ==="
rg "RandomBattlesMods" --type ts --type js -B 2 -A 2 2>/dev/null || echo "No matches found"

echo -e "\n=== Searching for getRandomBattlesModule usage ==="
rg "getRandomBattlesModule" --type ts --type js -B 2 -A 2 2>/dev/null || echo "No matches found"

Repository: smell-of-curry/pokebedrock-showdown

Length of output: 1413


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check sim/teams.ts for how random battles are handled
echo "=== Checking sim/teams.ts ==="
if [ -f "sim/teams.ts" ]; then
  wc -l sim/teams.ts
  echo -e "\n=== Searching for random battle references in sim/teams.ts ==="
  rg -i "random" sim/teams.ts -B 1 -A 1 2>/dev/null || true
else
  echo "sim/teams.ts not found"
fi

Repository: smell-of-curry/pokebedrock-showdown

Length of output: 1120


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check for random battle formats in format definitions
echo "=== Checking for random battle format references in all TypeScript files ==="
rg "\"random" --type ts -l 2>/dev/null | grep -i format | head -10 || true

# Also check for specific format names that might use random
echo -e "\n=== Checking for randomBattles format exports ==="
rg "randomBattles|RandomBattles" --type ts -B 2 -A 2 2>/dev/null | head -30 || true

Repository: smell-of-curry/pokebedrock-showdown

Length of output: 1207


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Checking config/formats.ts for random battle formats ==="
# Look for format definitions that include random battles
rg -i "randombattle" config/formats.ts -B 3 -A 3 2>/dev/null | head -50 || echo "No random battle formats found"

Repository: smell-of-curry/pokebedrock-showdown

Length of output: 170


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Checking full sim/teams.ts logic for random battle handling ==="
# Get the context around getRandomBattlesModule usage
sed -n '1,100p' sim/teams.ts | head -50

Repository: smell-of-curry/pokebedrock-showdown

Length of output: 1246


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Extracting the full random battle team generation function ==="
# Find and display the function that uses getRandomBattlesModule
rg -A 30 "function.*team" sim/teams.ts | grep -A 30 "getRandomBattlesModule" | head -40 || true

Repository: smell-of-curry/pokebedrock-showdown

Length of output: 145


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Checking if RandomBattlesMods is ever iterated or accessed ==="
rg "RandomBattlesMods" . --type ts --type js -B 3 -A 3 2>/dev/null || true

echo -e "\n=== Checking all format definitions ==="
cat config/formats.ts | head -100

Repository: smell-of-curry/pokebedrock-showdown

Length of output: 3659


Active random battle formats will fail during team generation.

The stub breaks all random battle formats defined in config/formats.ts except the four hardcoded Gen 9 special cases (gen9ssb, gen9babyrandombattle, gen9randombattle with CAP tag, gen9freeforallrandombattle). When any other random battle format attempts to generate teams, it falls through to the else branch in sim/teams.ts and calls getRandomBattlesModule(), which returns undefined, throwing "Random battles module not found for mod: {mod}".

The following formats in config/formats.ts will fail:

  • [Gen 9] Random Battle
  • [Gen 9] Unrated Random Battle
  • [Gen 9] Free-For-All Random Battle
  • [Gen 9] Random Battle (Blitz)
  • [Gen 9] Multi Random Battle

Either restore the module map for supported generations or remove these format definitions.

🤖 Prompt for AI Agents
In `@sim/random-battles-module-map.ts` around lines 1 - 5, The stubbed
RandomBattlesMods array and getRandomBattlesModule function cause
non-special-case random battle formats to get undefined modules and crash;
restore a correct module map or make getRandomBattlesModule return the proper
module for supported gens. Update the exported RandomBattlesMods to list the
supported mod names and implement getRandomBattlesModule to lookup and return
the module object (or dynamically import) for the requested _module string (used
by sim/teams.ts when falling into the else branch), ensuring it returns a {
default: ... } object instead of undefined for Gen 9 random formats (or remove
the failing format definitions if you intend not to support them).

✅ Addressed in commit d79a615

_⚠️ Potential issue_ | _🔴 Critical_ <details> <summary>🧩 Analysis chain</summary> 🏁 Script executed: ```shell #!/bin/bash set -euo pipefail # Search for random battle format references in config/ echo "=== Searching for random battle format references ===" fd -a -E node_modules -E dist -E build 'formats.*' config 2>/dev/null || true # Search broadly for random battle references in formats echo -e "\n=== Searching for random-battle format references ===" rg -i "randombattle|random.battle|random\s*battle" --type ts --type js -l 2>/dev/null | head -20 || true ``` Repository: smell-of-curry/pokebedrock-showdown Length of output: 777 --- 🏁 Script executed: ```shell #!/bin/bash set -euo pipefail # Find usages of RandomBattlesMods and getRandomBattlesModule echo "=== Searching for RandomBattlesMods usage ===" rg "RandomBattlesMods" --type ts --type js -B 2 -A 2 2>/dev/null || echo "No matches found" echo -e "\n=== Searching for getRandomBattlesModule usage ===" rg "getRandomBattlesModule" --type ts --type js -B 2 -A 2 2>/dev/null || echo "No matches found" ``` Repository: smell-of-curry/pokebedrock-showdown Length of output: 1413 --- 🏁 Script executed: ```shell #!/bin/bash set -euo pipefail # Check sim/teams.ts for how random battles are handled echo "=== Checking sim/teams.ts ===" if [ -f "sim/teams.ts" ]; then wc -l sim/teams.ts echo -e "\n=== Searching for random battle references in sim/teams.ts ===" rg -i "random" sim/teams.ts -B 1 -A 1 2>/dev/null || true else echo "sim/teams.ts not found" fi ``` Repository: smell-of-curry/pokebedrock-showdown Length of output: 1120 --- 🏁 Script executed: ```shell #!/bin/bash set -euo pipefail # Check for random battle formats in format definitions echo "=== Checking for random battle format references in all TypeScript files ===" rg "\"random" --type ts -l 2>/dev/null | grep -i format | head -10 || true # Also check for specific format names that might use random echo -e "\n=== Checking for randomBattles format exports ===" rg "randomBattles|RandomBattles" --type ts -B 2 -A 2 2>/dev/null | head -30 || true ``` Repository: smell-of-curry/pokebedrock-showdown Length of output: 1207 --- 🏁 Script executed: ```shell #!/bin/bash set -euo pipefail echo "=== Checking config/formats.ts for random battle formats ===" # Look for format definitions that include random battles rg -i "randombattle" config/formats.ts -B 3 -A 3 2>/dev/null | head -50 || echo "No random battle formats found" ``` Repository: smell-of-curry/pokebedrock-showdown Length of output: 170 --- 🏁 Script executed: ```shell #!/bin/bash set -euo pipefail echo "=== Checking full sim/teams.ts logic for random battle handling ===" # Get the context around getRandomBattlesModule usage sed -n '1,100p' sim/teams.ts | head -50 ``` Repository: smell-of-curry/pokebedrock-showdown Length of output: 1246 --- 🏁 Script executed: ```shell #!/bin/bash set -euo pipefail echo "=== Extracting the full random battle team generation function ===" # Find and display the function that uses getRandomBattlesModule rg -A 30 "function.*team" sim/teams.ts | grep -A 30 "getRandomBattlesModule" | head -40 || true ``` Repository: smell-of-curry/pokebedrock-showdown Length of output: 145 --- 🏁 Script executed: ```shell #!/bin/bash set -euo pipefail echo "=== Checking if RandomBattlesMods is ever iterated or accessed ===" rg "RandomBattlesMods" . --type ts --type js -B 3 -A 3 2>/dev/null || true echo -e "\n=== Checking all format definitions ===" cat config/formats.ts | head -100 ``` Repository: smell-of-curry/pokebedrock-showdown Length of output: 3659 --- </details> **Active random battle formats will fail during team generation.** The stub breaks all random battle formats defined in `config/formats.ts` except the four hardcoded Gen 9 special cases (gen9ssb, gen9babyrandombattle, gen9randombattle with CAP tag, gen9freeforallrandombattle). When any other random battle format attempts to generate teams, it falls through to the `else` branch in `sim/teams.ts` and calls `getRandomBattlesModule()`, which returns `undefined`, throwing "Random battles module not found for mod: {mod}". The following formats in `config/formats.ts` will fail: - [Gen 9] Random Battle - [Gen 9] Unrated Random Battle - [Gen 9] Free-For-All Random Battle - [Gen 9] Random Battle (Blitz) - [Gen 9] Multi Random Battle Either restore the module map for supported generations or remove these format definitions. <details> <summary>🤖 Prompt for AI Agents</summary> ``` In `@sim/random-battles-module-map.ts` around lines 1 - 5, The stubbed RandomBattlesMods array and getRandomBattlesModule function cause non-special-case random battle formats to get undefined modules and crash; restore a correct module map or make getRandomBattlesModule return the proper module for supported gens. Update the exported RandomBattlesMods to list the supported mod names and implement getRandomBattlesModule to lookup and return the module object (or dynamically import) for the requested _module string (used by sim/teams.ts when falling into the else branch), ensuring it returns a { default: ... } object instead of undefined for Gen 9 random formats (or remove the failing format definitions if you intend not to support them). ``` </details> <!-- fingerprinting:phantom:poseidon:eagle --> <!-- This is an auto-generated comment by CodeRabbit --> ✅ Addressed in commit d79a615
copilot-pull-request-reviewer[bot] (Migrated from github.com) reviewed 2026-02-10 01:03:22 +00:00
copilot-pull-request-reviewer[bot] (Migrated from github.com) left a comment

Pull request overview

This PR aims to reduce runtime/build memory overhead by removing the auto-generated “module map” approach and replacing it with a smaller, inline registry plus stubs to avoid pulling in large sets of modules (notably mod data and random-battles team generators).

Changes:

  • Removed build-time generation of Dex/random-battles module map files.
  • Replaced sim/dex-module-map.ts usage with inline static imports + a minimal DataRegistry in sim/dex.ts.
  • Stubbed sim/random-battles-module-map.ts and added an explicit error in sim/teams.ts when a module can’t be found.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tools/build-utils.js Removes generation steps for dex/random-battles module map files during transpile.
sim/dex.ts Replaces generated module map with inline imports and a minimal registry; changes mod loading behavior.
sim/dex-formats.ts Switches from failing fast on missing mods to lazily creating ModdedDex instances.
sim/teams.ts Uses getRandomBattlesModule and throws if the module isn’t found.
sim/random-battles-module-map.ts Replaces generated map with a stub returning undefined.
sim/dex-module-map.ts Deletes the previously auto-generated dex module map file.
data/rulesets.ts Adjusts Config access and a couple of Dex references (minor correctness/typing changes).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

## Pull request overview This PR aims to reduce runtime/build memory overhead by removing the auto-generated “module map” approach and replacing it with a smaller, inline registry plus stubs to avoid pulling in large sets of modules (notably mod data and random-battles team generators). **Changes:** - Removed build-time generation of Dex/random-battles module map files. - Replaced `sim/dex-module-map.ts` usage with inline static imports + a minimal `DataRegistry` in `sim/dex.ts`. - Stubbed `sim/random-battles-module-map.ts` and added an explicit error in `sim/teams.ts` when a module can’t be found. ### Reviewed changes Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments. <details> <summary>Show a summary per file</summary> | File | Description | | ---- | ----------- | | tools/build-utils.js | Removes generation steps for dex/random-battles module map files during transpile. | | sim/dex.ts | Replaces generated module map with inline imports and a minimal registry; changes mod loading behavior. | | sim/dex-formats.ts | Switches from failing fast on missing mods to lazily creating `ModdedDex` instances. | | sim/teams.ts | Uses `getRandomBattlesModule` and throws if the module isn’t found. | | sim/random-battles-module-map.ts | Replaces generated map with a stub returning `undefined`. | | sim/dex-module-map.ts | Deletes the previously auto-generated dex module map file. | | data/rulesets.ts | Adjusts Config access and a couple of Dex references (minor correctness/typing changes). | </details> --- 💡 <a href="/smell-of-curry/pokebedrock-showdown/new/master/.github/instructions?filename=*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.
@ -624,7 +624,9 @@ export class DexFormats {
if (format.bestOfDefault === undefined) format.bestOfDefault = false;
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-02-10 01:03:21 +00:00

This change removes the explicit error for formats that reference an unknown/non-registered mod and instead creates a ModdedDex instance. Given the new restricted DataRegistry, this can mask configuration errors and/or cause formats to run with inherited base data rather than the intended mod. Recommend either restoring the validation error (fail fast) or validating that the mod’s Scripts/data are actually loadable before creating the ModdedDex.

			// Fail fast if the format references an unknown/non-registered mod
			if (!this.dex.dexes[format.mod]) {
				throw new Error(`Format #${i + 1} references unknown or non-registered mod '${format.mod}'`);
This change removes the explicit error for formats that reference an unknown/non-registered mod and instead creates a ModdedDex instance. Given the new restricted DataRegistry, this can mask configuration errors and/or cause formats to run with inherited base data rather than the intended mod. Recommend either restoring the validation error (fail fast) or validating that the mod’s Scripts/data are actually loadable before creating the ModdedDex. ```suggestion // Fail fast if the format references an unknown/non-registered mod if (!this.dex.dexes[format.mod]) { throw new Error(`Format #${i + 1} references unknown or non-registered mod '${format.mod}'`); ```
@ -41,2 +72,4 @@
'../data/mods/pokebedrock/scripts': ModPBScripts,
};
const BASE_MOD = 'gen9' as ID;
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-02-10 01:03:22 +00:00

DataRegistry only includes base data + pokebedrock, but the repo’s format list references many other mods (gen1–gen8, other OMs). With the current loadDataFile behavior, those mods will silently inherit base (gen9) data/scripts, leading to incorrect generation logic rather than loading their own data or failing fast. Consider either (a) restoring/keeping dynamic loading for mod data files when not present in the registry, or (b) expanding the registry at least to include each supported mod’s Scripts (gen) and any required data files, and keep the “nonexistent mod” validation for unsupported mods.

DataRegistry only includes base data + pokebedrock, but the repo’s format list references many other mods (gen1–gen8, other OMs). With the current loadDataFile behavior, those mods will silently inherit base (gen9) data/scripts, leading to incorrect generation logic rather than loading their own data or failing fast. Consider either (a) restoring/keeping dynamic loading for mod data files when not present in the registry, or (b) expanding the registry at least to include each supported mod’s Scripts (gen) and any required data files, and keep the “nonexistent mod” validation for unsupported mods.
@ -446,24 +485,19 @@ export class ModdedDex {
}
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-02-10 01:03:20 +00:00

loadDataFile currently returns early for any basePath containing mods/ when the module isn’t in DataRegistry. This causes modded dexes (e.g. gen1/gen8/etc) to skip loading their own data files and fall back to inheriting the parent’s tables, which will produce incorrect behavior for non-base generations/mods. Suggest falling back to require(filePath) (or another lazy loader) when DataRegistry doesn’t contain an entry, at least for mods that exist on disk, and reserving the early-return only for truly unsupported mods.

loadDataFile currently returns early for any `basePath` containing `mods/` when the module isn’t in DataRegistry. This causes modded dexes (e.g. gen1/gen8/etc) to skip loading their own data files and fall back to inheriting the parent’s tables, which will produce incorrect behavior for non-base generations/mods. Suggest falling back to `require(filePath)` (or another lazy loader) when DataRegistry doesn’t contain an entry, at least for mods that exist on disk, and reserving the early-return only for truly unsupported mods.
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-02-10 01:03:21 +00:00

includeMods now only registers the pokebedrock mod. Other parts of the codebase (e.g. formats list / validation, mod enumeration) historically assume Dex.includeMods preloads the available mods. If the intent is to support the full set of mods in config/formats.ts, this will leave Dex.dexes incomplete and can lead to unexpected lazy-creation paths. Consider either keeping a lightweight mod listing (e.g. scripts-only) or retaining the previous mod-discovery behavior while still avoiding eager loading of all mod data.

		// @pokebedrock - ensure the pokebedrock mod is always available
		if (!dexes['pokebedrock']) {
			dexes['pokebedrock'] = new ModdedDex('pokebedrock');
		}

		// Discover and register all other available mods without eagerly loading their data
		try {
			// Use local requires to avoid changing top-level imports
			const fs = require('fs') as typeof import('fs');
			const path = require('path') as typeof import('path');

			const modsDir = path.resolve(__dirname, '../data/mods');
			const entries = fs.readdirSync(modsDir, {withFileTypes: true});
			for (const entry of entries) {
				if (!entry.isDirectory()) continue;
				const modid = entry.name;
				if (!dexes[modid]) {
					dexes[modid] = new ModdedDex(modid);
				}
			}
		} catch {
			// If the mods directory is missing or unreadable, fall back to pokebedrock only.
		}
includeMods now only registers the pokebedrock mod. Other parts of the codebase (e.g. formats list / validation, mod enumeration) historically assume Dex.includeMods preloads the available mods. If the intent is to support the full set of mods in config/formats.ts, this will leave Dex.dexes incomplete and can lead to unexpected lazy-creation paths. Consider either keeping a lightweight mod listing (e.g. scripts-only) or retaining the previous mod-discovery behavior while still avoiding eager loading of all mod data. ```suggestion // @pokebedrock - ensure the pokebedrock mod is always available if (!dexes['pokebedrock']) { dexes['pokebedrock'] = new ModdedDex('pokebedrock'); } // Discover and register all other available mods without eagerly loading their data try { // Use local requires to avoid changing top-level imports const fs = require('fs') as typeof import('fs'); const path = require('path') as typeof import('path'); const modsDir = path.resolve(__dirname, '../data/mods'); const entries = fs.readdirSync(modsDir, {withFileTypes: true}); for (const entry of entries) { if (!entry.isDirectory()) continue; const modid = entry.name; if (!dexes[modid]) { dexes[modid] = new ModdedDex(modid); } } } catch { // If the mods directory is missing or unreadable, fall back to pokebedrock only. } ```
@ -29,3 +1,1 @@
'randomroulette': require('../data/random-battles/randomroulette/teams'),
'sharedpower': require('../data/random-battles/sharedpower/teams'),
}[module];
export const getRandomBattlesModule = (mod: string): { default: any } | undefined => {
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-02-10 01:03:22 +00:00

getRandomBattlesModule is currently a stub that always returns undefined, but sim/teams.ts depends on it for random team generation in most formats. As-is, random battles will consistently error at runtime. If the goal is to avoid bundling all generators, consider mapping only the actually-supported mods (e.g. gen9) or returning a lazy require for the requested module instead of undefined.

	try {
		// Lazily require the requested module so only actually-used generators are loaded.
		// The result is normalized to always expose a `default` export.
		// eslint-disable-next-line @typescript-eslint/no-var-requires
		const required = require(_module);
		if (required && typeof required === 'object' && 'default' in required) {
			return required as {default: any};
		}
		return {default: required};
	} catch {
		// If the module cannot be resolved, indicate that there is no generator available.
		return undefined;
	}
getRandomBattlesModule is currently a stub that always returns undefined, but sim/teams.ts depends on it for random team generation in most formats. As-is, random battles will consistently error at runtime. If the goal is to avoid bundling all generators, consider mapping only the actually-supported mods (e.g. gen9) or returning a lazy require for the requested module instead of undefined. ```suggestion try { // Lazily require the requested module so only actually-used generators are loaded. // The result is normalized to always expose a `default` export. // eslint-disable-next-line @typescript-eslint/no-var-requires const required = require(_module); if (required && typeof required === 'object' && 'default' in required) { return required as {default: any}; } return {default: required}; } catch { // If the module cannot be resolved, indicate that there is no generator available. return undefined; } ```
@ -713,3 +715,4 @@
TeamGenerator = rbModule.default;
}
return new TeamGenerator(format, seed);
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-02-10 01:03:21 +00:00

With sim/random-battles-module-map.ts now stubbed to always return undefined, this code path will throw for most random battle formats (including standard "[Gen 9] Random Battle" where formatID doesn’t match the special cases). Either implement getRandomBattlesModule for the required mods (at least gen9) or add a fallback to the existing dynamic require approach when the static map returns undefined.

			if (rbModule) {
				TeamGenerator = rbModule.default;
			} else {
				// Fallback to dynamic require for mods not covered by the static map
				TeamGenerator = require(`../data/random-battles/${mod}/teams`).default;
			}
With sim/random-battles-module-map.ts now stubbed to always return undefined, this code path will throw for most random battle formats (including standard "[Gen 9] Random Battle" where `formatID` doesn’t match the special cases). Either implement getRandomBattlesModule for the required mods (at least gen9) or add a fallback to the existing dynamic require approach when the static map returns undefined. ```suggestion if (rbModule) { TeamGenerator = rbModule.default; } else { // Fallback to dynamic require for mods not covered by the static map TeamGenerator = require(`../data/random-battles/${mod}/teams`).default; } ```
cursor[bot] (Migrated from github.com) reviewed 2026-02-10 01:07:27 +00:00
@ -446,24 +485,19 @@ export class ModdedDex {
}
cursor[bot] (Migrated from github.com) commented 2026-02-10 01:07:27 +00:00

Non-pokebedrock mods silently load incorrect gen9 data

Medium Severity

The loadDataFile silent fallback was broadened from basePath.includes('mods/pokebedrock') to basePath.includes('mods/'), but DataRegistry only contains base and pokebedrock data. Combined with the lazy ModdedDex creation (which replaced error throws), any non-pokebedrock mod loaded via Dex.mod(), Dex.forFormat(), or custom formats will silently inherit all gen9 base data — wrong type chart, moves, abilities, and mechanics — instead of failing with a clear error. Server code paths like Dex.mod('gen1') in datasearch.ts would return gen9 data.

Additional Locations (2)

Fix in Cursor Fix in Web

### Non-pokebedrock mods silently load incorrect gen9 data **Medium Severity** <!-- DESCRIPTION START --> The `loadDataFile` silent fallback was broadened from `basePath.includes('mods/pokebedrock')` to `basePath.includes('mods/')`, but `DataRegistry` only contains base and pokebedrock data. Combined with the lazy `ModdedDex` creation (which replaced error throws), any non-pokebedrock mod loaded via `Dex.mod()`, `Dex.forFormat()`, or custom formats will silently inherit all gen9 base data — wrong type chart, moves, abilities, and mechanics — instead of failing with a clear error. Server code paths like `Dex.mod('gen1')` in `datasearch.ts` would return gen9 data. <!-- DESCRIPTION END --> <!-- BUGBOT_BUG_ID: d43b4ecd-c833-4900-b6b5-bf3ff2cec506 --> <!-- LOCATIONS START sim/dex.ts#L491-L492 sim/dex-formats.ts#L626-L630 sim/dex.ts#L537-L539 LOCATIONS END --> <details> <summary>Additional Locations (2)</summary> - [`sim/dex-formats.ts#L626-L630`](https://github.com/smell-of-curry/pokebedrock-showdown/blob/b42744edc13999be13e0ddc4cf79b44230468e32/sim/dex-formats.ts#L626-L630) - [`sim/dex.ts#L537-L539`](https://github.com/smell-of-curry/pokebedrock-showdown/blob/b42744edc13999be13e0ddc4cf79b44230468e32/sim/dex.ts#L537-L539) </details> <p><a href="https://cursor.com/open?data=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImJ1Z2JvdC12MiJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9DVVJTT1IiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjgwMmY5ZTg3LTU0YjctNGIyNy04ZTQwLWFlNTgyMmIzY2Q3MSIsImVuY3J5cHRpb25LZXkiOiJzZDh1ak5hdXBHZThzM1I3Tmw1eFJubzR0M2lQWFNPQXZQT2xTcFJ2UEdVIiwiYnJhbmNoIjoiZ3JlYXRseS1yZWR1Y2UtbWVtb3J5IiwicmVwb093bmVyIjoic21lbGwtb2YtY3VycnkiLCJyZXBvTmFtZSI6InBva2ViZWRyb2NrLXNob3dkb3duIn0sImlhdCI6MTc3MDY4NTY0NiwiZXhwIjoxNzczMjc3NjQ2fQ.w361Z0kqx7P-RNcOacyffwBKpNtoFf3hNAyDTZEZjxtlW6g_wavwXzw9vXIeEZvDrMB-qc4kJFFn56t8rUVsCzNPEIRd4boEvNONxAAUHckKU6Pk_8PW_CUM-wpjt9zzhpXdr_hQfUWuKJfzU8cUb921G8Wi8xWAT1RU9E5dEZ5aPzrV89XRsRZg6LJDpMXYUVGW-3HBSS9H87l8VDDkD7lPMQxCiI4IgPGBHJJqCGL5TGhl7PcTQAQQW1r6s_f9nKgw0sYw7I20XvSseA50IocBMv_CrrU1o4mTzP5b6hb9Q7aV6CII2N3vQK8Z7viIV-NQZxY497RbDQ8MnhXksQ" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-cursor-light.png"><img alt="Fix in Cursor" width="115" height="28" src="https://cursor.com/assets/images/fix-in-cursor-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/agents?data=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImJ1Z2JvdC12MiJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9XRUIiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjgwMmY5ZTg3LTU0YjctNGIyNy04ZTQwLWFlNTgyMmIzY2Q3MSIsImVuY3J5cHRpb25LZXkiOiJzZDh1ak5hdXBHZThzM1I3Tmw1eFJubzR0M2lQWFNPQXZQT2xTcFJ2UEdVIiwiYnJhbmNoIjoiZ3JlYXRseS1yZWR1Y2UtbWVtb3J5IiwicmVwb093bmVyIjoic21lbGwtb2YtY3VycnkiLCJyZXBvTmFtZSI6InBva2ViZWRyb2NrLXNob3dkb3duIiwicHJOdW1iZXIiOjgsImNvbW1pdFNoYSI6ImI0Mjc0NGVkYzEzOTk5YmUxM2UwZGRjNGNmNzliNDQyMzA0NjhlMzIiLCJwcm92aWRlciI6ImdpdGh1YiJ9LCJpYXQiOjE3NzA2ODU2NDYsImV4cCI6MTc3MzI3NzY0Nn0.klHN4XN9o5tR3iizKnCMz1-XiinVdtWz84Zq0_A1bxThcTNgaOtp1hsLCcaP5y0ppeRw3f_iWZg1K-x5IMS6TM1zmgEbUbDUAiBOhV8EgcVqMlpNH0ZZ1frTOTp9G-E2eSAdS7QWW0odO4_T_Tk4qK-zTKG59qVEr0rNcx7yyDqljv0UbkCjNfaIGWwkwYKOUwCtAqrhqP8DNoZfUupZmiUROtpTQoJ5gVn_17yL5-CIFSpqU39XdOvT4cnZFFwcEPO6LCX1oXtX9ubI18S4BX4MDZilrLQDURTpz1iaBWUGortcaSV7EK_O-PYMLkyiPyMcleGi4DCagW-JiuG3ZA" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-web-light.png"><img alt="Fix in Web" width="99" height="28" src="https://cursor.com/assets/images/fix-in-web-dark.png"></picture></a></p>
cursor[bot] commented 2026-02-10 01:10:45 +00:00 (Migrated from github.com)

Bugbot Autofix prepared fixes for 1 of the 1 bugs found in the latest run.

  • ✅ Fixed: Non-pokebedrock mods silently load incorrect gen9 data
    • Restricted loadDataFile’s silent fallback to pokebedrock-only so non-registered mods now throw instead of inheriting gen9 data.
<!-- BUGBOT_AUTOFIX_COMMENT --> [Bugbot Autofix](https://cursor.com/docs/bugbot#autofix) prepared fixes for 1 of the 1 bugs found in the latest run. - ✅ Fixed: **Non-pokebedrock mods silently load incorrect gen9 data** - Restricted loadDataFile’s silent fallback to pokebedrock-only so non-registered mods now throw instead of inheriting gen9 data.
cursor[bot] (Migrated from github.com) reviewed 2026-02-10 01:24:29 +00:00
@ -624,7 +624,9 @@ export class DexFormats {
if (format.bestOfDefault === undefined) format.bestOfDefault = false;
cursor[bot] (Migrated from github.com) commented 2026-02-10 01:24:30 +00:00

Removed mod validation causes delayed confusing errors

Medium Severity

The old fail-fast validation (throw new Error("Format requires nonexistent mod")) was replaced with lazy ModdedDex creation. Since config/formats.ts still references gen3–gen8 and blankcanvas mods, these ModdedDex instances are created during format loading but will crash with a confusing TypeError during data loading — loadDataFile throws a TypeError for entries missing from DataRegistry, and the catch block only suppresses MODULE_NOT_FOUND/ENOENT codes, so the TypeError propagates.

Additional Locations (1)

Fix in Cursor Fix in Web

### Removed mod validation causes delayed confusing errors **Medium Severity** <!-- DESCRIPTION START --> The old fail-fast validation (`throw new Error("Format requires nonexistent mod")`) was replaced with lazy `ModdedDex` creation. Since `config/formats.ts` still references gen3–gen8 and blankcanvas mods, these `ModdedDex` instances are created during format loading but will crash with a confusing `TypeError` during data loading — `loadDataFile` throws a `TypeError` for entries missing from `DataRegistry`, and the catch block only suppresses `MODULE_NOT_FOUND`/`ENOENT` codes, so the `TypeError` propagates. <!-- DESCRIPTION END --> <!-- BUGBOT_BUG_ID: b4db64e1-c80d-48d2-a8ee-4502af777bcd --> <!-- LOCATIONS START sim/dex-formats.ts#L626-L630 sim/dex.ts#L487-L504 LOCATIONS END --> <details> <summary>Additional Locations (1)</summary> - [`sim/dex.ts#L487-L504`](https://github.com/smell-of-curry/pokebedrock-showdown/blob/329b85dad100b44d0238b0b8914badccb0f6fabe/sim/dex.ts#L487-L504) </details> <p><a href="https://cursor.com/open?data=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImJ1Z2JvdC12MiJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9DVVJTT1IiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjBmYmVmNjhmLWFkMGEtNGNlNC1iNGQzLTBhN2QzM2I2M2Q4NCIsImVuY3J5cHRpb25LZXkiOiJZamg4ZDBYbFdzM1pqSWRWYkU0V011cWhPX050bERLS1ZhaTJBem4yX2kwIiwiYnJhbmNoIjoiZ3JlYXRseS1yZWR1Y2UtbWVtb3J5IiwicmVwb093bmVyIjoic21lbGwtb2YtY3VycnkiLCJyZXBvTmFtZSI6InBva2ViZWRyb2NrLXNob3dkb3duIn0sImlhdCI6MTc3MDY4NjY2OSwiZXhwIjoxNzczMjc4NjY5fQ.OrETM2eObkpYzV4UFuBi-z_hiqII23mTZzytj1OLXYalRjCfly1IpYxzcJ9nSUfu7E1pimzuFpkkaKv7sqZmY30OxlpsYme7lSB6ilPZ0gjWXMtLBmUbUdgSkaVRMpWxWKTFOINMCQsyown9YUuQIHM0T17L3pDINRj6JeP5NSscGJ712Wgsarsqw1i1fetfNN_7CBhcLsG26k_8d43JXzzlPbBj-Lo9SgDnl3Yupdn6EE8RBlvowQU8FjnfrFx2av3oqnqqW4xZhInGKnF6nJ9oXJXJlNv6X0IC0ZHQOt4sUA15Gsd4nCYBJiIuqCtlUO6rUvgbrla7i_5NjuKRMQ" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-cursor-light.png"><img alt="Fix in Cursor" width="115" height="28" src="https://cursor.com/assets/images/fix-in-cursor-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/agents?data=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImJ1Z2JvdC12MiJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9XRUIiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjBmYmVmNjhmLWFkMGEtNGNlNC1iNGQzLTBhN2QzM2I2M2Q4NCIsImVuY3J5cHRpb25LZXkiOiJZamg4ZDBYbFdzM1pqSWRWYkU0V011cWhPX050bERLS1ZhaTJBem4yX2kwIiwiYnJhbmNoIjoiZ3JlYXRseS1yZWR1Y2UtbWVtb3J5IiwicmVwb093bmVyIjoic21lbGwtb2YtY3VycnkiLCJyZXBvTmFtZSI6InBva2ViZWRyb2NrLXNob3dkb3duIiwicHJOdW1iZXIiOjgsImNvbW1pdFNoYSI6IjMyOWI4NWRhZDEwMGI0NGQwMjM4YjBiODkxNGJhZGNjYjBmNmZhYmUiLCJwcm92aWRlciI6ImdpdGh1YiJ9LCJpYXQiOjE3NzA2ODY2NjksImV4cCI6MTc3MzI3ODY2OX0.Xzz3iTrgyaxSUvlzd1oYIAfPfdw8ww7sf-M5kmxsSiqd-Kj8PaQn9CIpHK-oT0Np_vy-_DXSBGy_gVvwVAPeJll4vCT_OKIhxP04rWhsUKnY3qsy3RmNuHdstds5DtXCk-QXb1VXkHMfWVmcvFhnA-2hvPvYpnip3KpyS8JHYZrLMWM7raj74YZB-cdBz8BAW0uRRPYYsWE0tr3GaMKzru6Pr1Tll-VvXDsnsNcBxNL7bpU2RhoKurtM3uql_QpebdnW6R8s0KqEglwnAeM08SkX2JLw2y8qCzZvDYant5MFl-mAwPEt9uI4VSRTlMDcUWylKPPDmzI6HrCjpu71YQ" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-web-light.png"><img alt="Fix in Web" width="99" height="28" src="https://cursor.com/assets/images/fix-in-web-dark.png"></picture></a></p>
@ -29,3 +1,1 @@
'randomroulette': require('../data/random-battles/randomroulette/teams'),
'sharedpower': require('../data/random-battles/sharedpower/teams'),
}[module];
export const getRandomBattlesModule = (mod: string): { default: any } | undefined => {
cursor[bot] (Migrated from github.com) commented 2026-02-10 01:24:30 +00:00

Gen 9 Random Battle breaks due to stub module

High Severity

getRandomBattlesModule always returns undefined, but [Gen 9] Random Battle (and several other random formats in config/formats.ts) fall through to the else branch in getGenerator that calls this function. The format ID gen9randombattle matches the gen9randombattle substring check on line 706, but fails the +pokemontag:cap ruleTable condition, so it isn't caught by the special cases and hits the stub. This throws Error: Random battles module not found for mod: gen9 when any standard Gen 9 random battle is started.

Additional Locations (1)

Fix in Cursor Fix in Web

### Gen 9 Random Battle breaks due to stub module **High Severity** <!-- DESCRIPTION START --> `getRandomBattlesModule` always returns `undefined`, but `[Gen 9] Random Battle` (and several other random formats in `config/formats.ts`) fall through to the `else` branch in `getGenerator` that calls this function. The format ID `gen9randombattle` matches the `gen9randombattle` substring check on line 706, but fails the `+pokemontag:cap` ruleTable condition, so it isn't caught by the special cases and hits the stub. This throws `Error: Random battles module not found for mod: gen9` when any standard Gen 9 random battle is started. <!-- DESCRIPTION END --> <!-- BUGBOT_BUG_ID: 89a9325e-daa4-4f67-b8ae-7cb1f1b71234 --> <!-- LOCATIONS START sim/random-battles-module-map.ts#L3-L5 sim/teams.ts#L709-L714 LOCATIONS END --> <details> <summary>Additional Locations (1)</summary> - [`sim/teams.ts#L709-L714`](https://github.com/smell-of-curry/pokebedrock-showdown/blob/329b85dad100b44d0238b0b8914badccb0f6fabe/sim/teams.ts#L709-L714) </details> <p><a href="https://cursor.com/open?data=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImJ1Z2JvdC12MiJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9DVVJTT1IiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjFhY2I0ZjM5LTgzMTgtNDY1Yi1hYzI4LTFjYjI2ZmIyOGE5OCIsImVuY3J5cHRpb25LZXkiOiJ3VGlwNGI2WDdIQ3BuWWc2NEFWZExOODdjQzZBaXpYbmhNOVc0TGlmU0hJIiwiYnJhbmNoIjoiZ3JlYXRseS1yZWR1Y2UtbWVtb3J5IiwicmVwb093bmVyIjoic21lbGwtb2YtY3VycnkiLCJyZXBvTmFtZSI6InBva2ViZWRyb2NrLXNob3dkb3duIn0sImlhdCI6MTc3MDY4NjY2OSwiZXhwIjoxNzczMjc4NjY5fQ.cOmGH4JQQK2C7nodF-0tr7RfIM6bL_Fq6BzTlr4K7MkhDg5A1LcyQtNQp-qiqumIXFVyqmG0x3cGgxCx9JSGk3LfKXXvOBVLSyWM6RNvWtbKx_2J-DnCbkj8UQiGKREvkwPI7Bl8FA-ETKQf-twlxDeAO1DUjQ-vCyofTYSYks8zzBRLMx_4N878fQLEd7xih8GLavPiWLZ4uVbg-diLbsXVWJTugfvllbTZrJw_MllpoKmj7drFEQGryGwU43uH5DQ7VPMrbz48BqR5ZHB4TpswGdmDeqPM8jMtPlZ69YN6RjtA2RJMYhKfNJyJAvCmHsldzB2BL1lHzYcgV1OJTA" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-cursor-light.png"><img alt="Fix in Cursor" width="115" height="28" src="https://cursor.com/assets/images/fix-in-cursor-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/agents?data=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImJ1Z2JvdC12MiJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9XRUIiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjFhY2I0ZjM5LTgzMTgtNDY1Yi1hYzI4LTFjYjI2ZmIyOGE5OCIsImVuY3J5cHRpb25LZXkiOiJ3VGlwNGI2WDdIQ3BuWWc2NEFWZExOODdjQzZBaXpYbmhNOVc0TGlmU0hJIiwiYnJhbmNoIjoiZ3JlYXRseS1yZWR1Y2UtbWVtb3J5IiwicmVwb093bmVyIjoic21lbGwtb2YtY3VycnkiLCJyZXBvTmFtZSI6InBva2ViZWRyb2NrLXNob3dkb3duIiwicHJOdW1iZXIiOjgsImNvbW1pdFNoYSI6IjMyOWI4NWRhZDEwMGI0NGQwMjM4YjBiODkxNGJhZGNjYjBmNmZhYmUiLCJwcm92aWRlciI6ImdpdGh1YiJ9LCJpYXQiOjE3NzA2ODY2NjksImV4cCI6MTc3MzI3ODY2OX0.y4GiCsWE8CVbY7BKTZ9xn16P7zHMlOkwQCsN0MXSM0WC_SqyDYHYAGmGnc5ykpKglyy62U_mg3pVP57Ck86KHOtm50awTq4Xo2YdiJirPArVD_AkOC0pHvOAnGcGV2yMYKTNWSDXd1xhkTrdenY7U7AYK5_Lh0OdZ3qbENSUFJmWJyVpn3wNxhhOqYb3mtflDHyy0vBC5d05i7OI5WmgAOaQiw6iuqY7IwAfZI9YrkkkIsBJHmAc4JQ2eFRKtcxr2WyiVyVTsOCWKZkUeDnkFZVIuLTnr7fEskWdm1fhYsMtilsa0MyaaGY_ZAytkjVO5wFrTuv8lc06eRylIbDfJQ" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-web-light.png"><img alt="Fix in Web" width="99" height="28" src="https://cursor.com/assets/images/fix-in-web-dark.png"></picture></a></p>
cursor[bot] commented 2026-02-10 01:30:54 +00:00 (Migrated from github.com)

Bugbot Autofix prepared fixes for 2 of the 2 bugs found in the latest run.

  • ✅ Fixed: Gen 9 Random Battle breaks due to stub module
    • Implemented a static mapping in getRandomBattlesModule to return the Gen 9 random teams module, preventing the undefined module error.
  • ✅ Fixed: Removed mod validation causes delayed confusing errors
    • Reinstated fail-fast mod validation in dex-formats to throw a clear error when a format references an unregistered mod.
<!-- BUGBOT_AUTOFIX_COMMENT --> [Bugbot Autofix](https://cursor.com/docs/bugbot#autofix) prepared fixes for 2 of the 2 bugs found in the latest run. - ✅ Fixed: **Gen 9 Random Battle breaks due to stub module** - Implemented a static mapping in getRandomBattlesModule to return the Gen 9 random teams module, preventing the undefined module error. - ✅ Fixed: **Removed mod validation causes delayed confusing errors** - Reinstated fail-fast mod validation in dex-formats to throw a clear error when a format references an unregistered mod.
cursor[bot] (Migrated from github.com) reviewed 2026-02-10 01:50:33 +00:00
cursor[bot] (Migrated from github.com) commented 2026-02-10 01:50:33 +00:00

Lazy mod creation crashes on missing DataRegistry entries

High Severity

mod() and forFormat() lazily create ModdedDex for unregistered mods, but loadDataFile will throw a TypeError for any mod not in DataRegistry (except pokebedrock). The TypeError bypasses the MODULE_NOT_FOUND catch guard and crashes. This affects any call to forGen() with non-9 values, including the natdexmod rule at rulesets.ts:141 which loops from gen 9 down to gen 7 when validating non-standard items in National Dex formats. The old forFormat() had a clear "ModdedDex not found" error; the new code fails with a confusing message about file exports.

Additional Locations (2)

Fix in Cursor Fix in Web

### Lazy mod creation crashes on missing DataRegistry entries **High Severity** <!-- DESCRIPTION START --> `mod()` and `forFormat()` lazily create `ModdedDex` for unregistered mods, but `loadDataFile` will throw a `TypeError` for any mod not in `DataRegistry` (except pokebedrock). The `TypeError` bypasses the `MODULE_NOT_FOUND` catch guard and crashes. This affects any call to `forGen()` with non-9 values, including the `natdexmod` rule at `rulesets.ts:141` which loops from gen 9 down to gen 7 when validating non-standard items in National Dex formats. The old `forFormat()` had a clear "ModdedDex not found" error; the new code fails with a confusing message about file exports. <!-- DESCRIPTION END --> <!-- BUGBOT_BUG_ID: 9817bb71-3592-4d9e-af8a-5633da5a3f33 --> <!-- LOCATIONS START sim/dex.ts#L203-L207 sim/dex.ts#L487-L494 sim/dex.ts#L217-L221 LOCATIONS END --> <details> <summary>Additional Locations (2)</summary> - [`sim/dex.ts#L487-L494`](https://github.com/smell-of-curry/pokebedrock-showdown/blob/d79a615c2d3854a38cac8bce44c23dafa3e6220e/sim/dex.ts#L487-L494) - [`sim/dex.ts#L217-L221`](https://github.com/smell-of-curry/pokebedrock-showdown/blob/d79a615c2d3854a38cac8bce44c23dafa3e6220e/sim/dex.ts#L217-L221) </details> <p><a href="https://cursor.com/open?data=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImJ1Z2JvdC12MiJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9DVVJTT1IiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjQzMTFiYjdlLTIwZDQtNGI4MS04M2Q0LTVhZGIwOWU4YThkZSIsImVuY3J5cHRpb25LZXkiOiJIOGItbUpsRGNPeW03M1J1Rm12RnR5VWd0amM1RHdTaUxSdVg4T2FzS2tVIiwiYnJhbmNoIjoiZ3JlYXRseS1yZWR1Y2UtbWVtb3J5IiwicmVwb093bmVyIjoic21lbGwtb2YtY3VycnkiLCJyZXBvTmFtZSI6InBva2ViZWRyb2NrLXNob3dkb3duIn0sImlhdCI6MTc3MDY4ODIzMywiZXhwIjoxNzczMjgwMjMzfQ.A97ytj4hpGbNk4cGyB_X9xOjefrW-1fkDfNCBv6tnwh2OT7g8W8TaBXTAMYHxrf_94B60GYm3_c53uWHjVxRuSjd63zTIJ1IFpry3yzzAzvxFXfSaHcI9ow2O2pY0VPEdYkqQ7J_bw_flQ-cHgPJTkBTPfmzEYb8wkd-Hh7iqZ2WvQQzS6hcbAT0VVxiBisxV4c-uIdiM2GYMOUJHoSCPhJ9ob4Ibq6Q6_NXUOvO1_BugplbCqCBpCga-l-kqq-G3aVU3s-S61VikW1o-ZxH5tsgAZjbfz_X9IUSMhrw1ohC6HLQyre11wArXHSQdn2HCvx_FqQEWJLISE90XwZB5Q" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-cursor-light.png"><img alt="Fix in Cursor" width="115" height="28" src="https://cursor.com/assets/images/fix-in-cursor-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/agents?data=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImJ1Z2JvdC12MiJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9XRUIiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjQzMTFiYjdlLTIwZDQtNGI4MS04M2Q0LTVhZGIwOWU4YThkZSIsImVuY3J5cHRpb25LZXkiOiJIOGItbUpsRGNPeW03M1J1Rm12RnR5VWd0amM1RHdTaUxSdVg4T2FzS2tVIiwiYnJhbmNoIjoiZ3JlYXRseS1yZWR1Y2UtbWVtb3J5IiwicmVwb093bmVyIjoic21lbGwtb2YtY3VycnkiLCJyZXBvTmFtZSI6InBva2ViZWRyb2NrLXNob3dkb3duIiwicHJOdW1iZXIiOjgsImNvbW1pdFNoYSI6ImQ3OWE2MTVjMmQzODU0YTM4Y2FjOGJjZTQ0YzIzZGFmYTNlNjIyMGUiLCJwcm92aWRlciI6ImdpdGh1YiJ9LCJpYXQiOjE3NzA2ODgyMzMsImV4cCI6MTc3MzI4MDIzM30.gxBqdiMUxrkS9RYdy5jiRW7A1eCl8Smi7PEYr0DIdYsDDnsQRwGPaAvJ9VjRE3B9CmPfh4zpUG_1DFTqBN_wAawokrSdH4pDS6LXDLDi1uXvPfjYdbqc3bzBR2SABaEGRAVDH08RcG5uNY5OTeNPYJtG_88ocp0Ahcb8XzsaFPyXsFofA9O6Llo6TWPQSAx99rwEudOCFrGNEDD6HKOh4Rmrq8ej1J9o_pyZHTZspFdoZn7GuOsucdpnalBhdfm6bZnGRbcXbA-8JF4Ym01gkj3qGNqQOcrbwxG7wAQ_0fuqTUmD9iMYbtzVnZE-bXNnuZ3KvMXq4EdvFvuYn-uL-g" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-web-light.png"><img alt="Fix in Web" width="99" height="28" src="https://cursor.com/assets/images/fix-in-web-dark.png"></picture></a></p>
cursor[bot] (Migrated from github.com) commented 2026-02-10 01:50:33 +00:00

Startup crash: non-gen9 formats require unregistered mods

High Severity

includeMods() now only registers pokebedrock, but config/formats.ts still contains ~10 format entries with mod: 'gen8', 'gen7', 'gen6', 'gen5', 'gen4', and 'gen3'. When formats load, the validation check if (!this.dex.dexes[format.mod]) in dex-formats.ts will throw for each of these since only base, gen9, and pokebedrock exist in dexes. This crashes the server at startup before any battle can occur.

Additional Locations (1)

Fix in Cursor Fix in Web

### Startup crash: non-gen9 formats require unregistered mods **High Severity** <!-- DESCRIPTION START --> `includeMods()` now only registers `pokebedrock`, but `config/formats.ts` still contains ~10 format entries with `mod: 'gen8'`, `'gen7'`, `'gen6'`, `'gen5'`, `'gen4'`, and `'gen3'`. When formats load, the validation check `if (!this.dex.dexes[format.mod])` in `dex-formats.ts` will throw for each of these since only `base`, `gen9`, and `pokebedrock` exist in `dexes`. This crashes the server at startup before any battle can occur. <!-- DESCRIPTION END --> <!-- BUGBOT_BUG_ID: 52b08c9e-3de6-482e-aa47-79a98102e478 --> <!-- LOCATIONS START sim/dex.ts#L537-L539 sim/dex-formats.ts#L628-L631 LOCATIONS END --> <details> <summary>Additional Locations (1)</summary> - [`sim/dex-formats.ts#L628-L631`](https://github.com/smell-of-curry/pokebedrock-showdown/blob/d79a615c2d3854a38cac8bce44c23dafa3e6220e/sim/dex-formats.ts#L628-L631) </details> <p><a href="https://cursor.com/open?data=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImJ1Z2JvdC12MiJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9DVVJTT1IiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjQ4YWZiNWUwLWJjYWEtNDIzZS1iNDYyLThiZmZjZGNiYzA5OSIsImVuY3J5cHRpb25LZXkiOiJjS2gzTFlUaWZVblotNDNFczBPckdGZTdyMWNIYXBSN2VrVnRXRW9XRld3IiwiYnJhbmNoIjoiZ3JlYXRseS1yZWR1Y2UtbWVtb3J5IiwicmVwb093bmVyIjoic21lbGwtb2YtY3VycnkiLCJyZXBvTmFtZSI6InBva2ViZWRyb2NrLXNob3dkb3duIn0sImlhdCI6MTc3MDY4ODIzMywiZXhwIjoxNzczMjgwMjMzfQ.Br2Amukw9RYE88xBxL9ITh9fiyqCTRysTz7vUc2Xx0Bfnkhqwapl-m2y5_h_hvaUgHu_SlOpuKm0BXe1js5kJJRldGzqehRNI2SOyCeynIM4qsjz_uKUa8XOT7cuw1H4oLxUeI6DAskoH9UX9JKeQ-tATX2V5tTWGDfMIOU_saOjBdp2iMCc7Btyg12Aq7NBFgebPnoc3XlKE0dMnOG8JYYX29TANyr5ZI0gXkfKSRBx7I_CPSJfLp6T5RhYGqJcL3CP5492gnknaK7ac1HTKokIOoWsEDB0Cd97rOShorSuJxfnZWej7_mdRF2XtryInzEQpj6KY1lPoQy-H-wbKw" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-cursor-light.png"><img alt="Fix in Cursor" width="115" height="28" src="https://cursor.com/assets/images/fix-in-cursor-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/agents?data=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImJ1Z2JvdC12MiJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9XRUIiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OjQ4YWZiNWUwLWJjYWEtNDIzZS1iNDYyLThiZmZjZGNiYzA5OSIsImVuY3J5cHRpb25LZXkiOiJjS2gzTFlUaWZVblotNDNFczBPckdGZTdyMWNIYXBSN2VrVnRXRW9XRld3IiwiYnJhbmNoIjoiZ3JlYXRseS1yZWR1Y2UtbWVtb3J5IiwicmVwb093bmVyIjoic21lbGwtb2YtY3VycnkiLCJyZXBvTmFtZSI6InBva2ViZWRyb2NrLXNob3dkb3duIiwicHJOdW1iZXIiOjgsImNvbW1pdFNoYSI6ImQ3OWE2MTVjMmQzODU0YTM4Y2FjOGJjZTQ0YzIzZGFmYTNlNjIyMGUiLCJwcm92aWRlciI6ImdpdGh1YiJ9LCJpYXQiOjE3NzA2ODgyMzMsImV4cCI6MTc3MzI4MDIzM30.jD5HbHjyURT7T69AP6QfAEeEVgKhDSF8fo4RosSGwJmeFbtQE-BVW5TyOowYdvz500EeN-j_m0etWPKXMlnGOvik7uKzMbjhlJV5rDHHZtfmh3OZyElxZpdq7UTjx8Ok91UYsRneG2sUwRjwbau-6JxcdjMtUmlGyMTkLQBmr02NYXqxEaclFIdIjG-T3ArIfQcFrgTfzIYCf7FKJaVEgNARSDJrw5qnE38kCB1l2ACZyEtpIGdC7hytvOvYXawakdJkhvgMympsWdezODbAmTftXvHyUDWeQXsHe3hGGA3lyNc_0K5W_76V3qa4aGG0ApvDtET9xc0iJqIwhuXbqQ" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-web-light.png"><img alt="Fix in Web" width="99" height="28" src="https://cursor.com/assets/images/fix-in-web-dark.png"></picture></a></p>
@ -29,3 +1,1 @@
'randomroulette': require('../data/random-battles/randomroulette/teams'),
'sharedpower': require('../data/random-battles/sharedpower/teams'),
}[module];
export const getRandomBattlesModule = (mod: string): { default: any } | undefined => {
cursor[bot] (Migrated from github.com) commented 2026-02-10 01:50:33 +00:00

Exported RandomBattlesMods constant is never imported anywhere

Low Severity

RandomBattlesMods is exported but has zero import sites in the codebase. A grep for its name finds only the definition in random-battles-module-map.ts. This is unused dead code that could be removed.

Fix in Cursor Fix in Web

### Exported `RandomBattlesMods` constant is never imported anywhere **Low Severity** <!-- DESCRIPTION START --> `RandomBattlesMods` is exported but has zero import sites in the codebase. A grep for its name finds only the definition in `random-battles-module-map.ts`. This is unused dead code that could be removed. <!-- DESCRIPTION END --> <!-- BUGBOT_BUG_ID: 805378c9-2216-4c01-b862-17d40670f4b6 --> <!-- LOCATIONS START sim/random-battles-module-map.ts#L1-L2 LOCATIONS END --> <p><a href="https://cursor.com/open?data=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImJ1Z2JvdC12MiJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9DVVJTT1IiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OmQ4YjQ4ZmViLWUyOTYtNGM4OC04Mzc4LWRiOThlNjk5MTdhZSIsImVuY3J5cHRpb25LZXkiOiJDQ3VtQThlZ3MyQUNDQnFHY254aWN0YkhrREF3Y1VkMC0wQXNDaXlrREJJIiwiYnJhbmNoIjoiZ3JlYXRseS1yZWR1Y2UtbWVtb3J5IiwicmVwb093bmVyIjoic21lbGwtb2YtY3VycnkiLCJyZXBvTmFtZSI6InBva2ViZWRyb2NrLXNob3dkb3duIn0sImlhdCI6MTc3MDY4ODIzMywiZXhwIjoxNzczMjgwMjMzfQ.bfCcjdgA74iPxEChvfB3ytpXNEjgp4o12Nl4EGHe4Il7Mw-GyFvUjzRlFEkFLC-siJNeLOW9N0KlhA03rG__D4LMJP6L-LDLYtFVH1e-2_DkxWTBN0OMrdq66O3ynuQiKFr51S2OtnGfTseGG7J97eTp2vRCrjA7geGaOhHKddPz6ICeNhCKMxUAOsgydA-cPzPXDYq2xN7DsYuViFok6crw7Xj--yiVv3L6LLrxR_VIxPDfeCbUqQwqhCIOpdUL3o5WOIFWSOKnlvnbnB-UqNRTx9DRtzcJU46bUXrR95aPQNExI4BWk7CO4rguXvtLOATcZV1QrvTY4_7LCtjU3Q" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-cursor-light.png"><img alt="Fix in Cursor" width="115" height="28" src="https://cursor.com/assets/images/fix-in-cursor-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/agents?data=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImJ1Z2JvdC12MiJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9XRUIiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OmQ4YjQ4ZmViLWUyOTYtNGM4OC04Mzc4LWRiOThlNjk5MTdhZSIsImVuY3J5cHRpb25LZXkiOiJDQ3VtQThlZ3MyQUNDQnFHY254aWN0YkhrREF3Y1VkMC0wQXNDaXlrREJJIiwiYnJhbmNoIjoiZ3JlYXRseS1yZWR1Y2UtbWVtb3J5IiwicmVwb093bmVyIjoic21lbGwtb2YtY3VycnkiLCJyZXBvTmFtZSI6InBva2ViZWRyb2NrLXNob3dkb3duIiwicHJOdW1iZXIiOjgsImNvbW1pdFNoYSI6ImQ3OWE2MTVjMmQzODU0YTM4Y2FjOGJjZTQ0YzIzZGFmYTNlNjIyMGUiLCJwcm92aWRlciI6ImdpdGh1YiJ9LCJpYXQiOjE3NzA2ODgyMzMsImV4cCI6MTc3MzI4MDIzM30.X6bCaAnqQ5NAtHJ9l2nTcYE8DAcc1QRkaHTCF1W9BMLOxVPz6zrx1h7zYgHjZr0TAeacrvRkdderN7_SzcgT2WoMhtIfFTqVxGgBvjBiZDs1OqElxG7B4RhrF3UjdCU_7HLC0NZmlXgxjHIGqQcn6mCWTCNOehgm2yAmUGVZfZJ34mvowqIkSGbXISfJwtwHc_vfvJmbp6SHThTfe-eZlEdprH9BQUymrdHx7Wy2l8201UrpuHMHUSI1BEuEq_5FAcvoc0ghLMLnWOjFXuhbmAxipnJxdYEQrhnmrtpZpmlA1qKouUKDW7IkluvWjsEgs7kfVN5tDskDd1aEK8GnDg" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-web-light.png"><img alt="Fix in Web" width="99" height="28" src="https://cursor.com/assets/images/fix-in-web-dark.png"></picture></a></p>
cursor[bot] commented 2026-02-10 01:53:58 +00:00 (Migrated from github.com)

Bugbot Autofix prepared fixes for 3 of the 3 bugs found in the latest run.

  • ✅ Fixed: Startup crash: non-gen9 formats require unregistered mods
    • Formats loader now defaults unknown mods to gen9 instead of throwing, preventing startup crash.
  • ✅ Fixed: Lazy mod creation crashes on missing DataRegistry entries
    • Dex.mod/forFormat/forGen now fall back to base for unsupported mods, avoiding TypeError from missing DataRegistry entries.
  • ✅ Fixed: Exported RandomBattlesMods constant is never imported anywhere
    • Removed the unused RandomBattlesMods export from random-battles-module-map.ts.
<!-- BUGBOT_AUTOFIX_COMMENT --> [Bugbot Autofix](https://cursor.com/docs/bugbot#autofix) prepared fixes for 3 of the 3 bugs found in the latest run. - ✅ Fixed: **Startup crash: non-gen9 formats require unregistered mods** - Formats loader now defaults unknown mods to gen9 instead of throwing, preventing startup crash. - ✅ Fixed: **Lazy mod creation crashes on missing DataRegistry entries** - Dex.mod/forFormat/forGen now fall back to base for unsupported mods, avoiding TypeError from missing DataRegistry entries. - ✅ Fixed: **Exported `RandomBattlesMods` constant is never imported anywhere** - Removed the unused RandomBattlesMods export from random-battles-module-map.ts.
coderabbitai[bot] (Migrated from github.com) reviewed 2026-02-10 01:57:11 +00:00
coderabbitai[bot] (Migrated from github.com) left a comment

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@sim/random-battles-module-map.ts`:
- Around line 1-8: The return type of getRandomBattlesModule is wrong because
require('../data/random-battles/gen9/teams') yields an object with named exports
(not a default), so update the function signature and callers: change
getRandomBattlesModule(mod: string): { default: any } | undefined to return the
actual exported shape (e.g., Record<string, any> or a proper interface matching
TeamData/BattleFactorySpecies/MoveCounter) or use a dynamic ES import (await
import('../data/random-battles/gen9/teams')) and type it accordingly; ensure
callers of getRandomBattlesModule no longer access .default but use the named
properties (e.g., TeamData) and update any type annotations to reference the
real exported types from teams.ts.
🧹 Nitpick comments (2)
sim/dex.ts (2)

202-208: Silent fallback to base for unknown mods may hide configuration errors.

When an unregistered mod is requested (e.g., 'gen8', 'gen7'), this silently returns gen9 data with no warning. This is intentional per the PR objectives, but a console.warn or debug log would help developers diagnose issues when formats unexpectedly resolve to base data.

💡 Optional: Add a debug warning for unregistered mod fallback
 	mod(mod: string | undefined): ModdedDex {
 		if (!dexes['base'].modsLoaded) dexes['base'].includeMods();
 		const modId = mod || 'base';
 		// Fallback to base data for unsupported/unregistered mods
-		if (!dexes[modId]) return dexes[BASE_MOD].includeData();
+		if (!dexes[modId]) {
+			console.warn(`[Dex] Mod '${modId}' is not registered; falling back to '${BASE_MOD}'`);
+			return dexes[BASE_MOD].includeData();
+		}
 		return dexes[modId].includeData();
 	}

487-507: The catch block for MODULE_NOT_FOUND / ENOENT is now dead code.

Since loadDataFile no longer calls require() (it reads from DataRegistry), the only throws are the explicit TypeErrors on lines 496 and 499, which won't have .code === 'MODULE_NOT_FOUND'. The catch block silently swallows nothing but could mislead future maintainers into thinking dynamic loading still occurs.

🧹 Optional: Remove the stale catch guard
-	loadDataFile(basePath: string, dataType: DataType): AnyObject | void {
-		try {
-			const filePath = basePath + DATA_FILES[dataType];
-			// `@pokebedrock` - use inline data registry to avoid dynamic requires
-			const dataObject = DataRegistry[filePath];
-			// `@pokebedrock` - Only allow silent fallback for the pokebedrock mod
-			// Other mods must be explicitly registered; otherwise, error out
-			if (!dataObject && basePath.includes('mods/pokebedrock')) return;
-			if (!dataObject || typeof dataObject !== 'object') {
-				throw new TypeError(`${filePath}, if it exists, must export a non-null object`);
-			}
-			if (dataObject[dataType]?.constructor?.name !== 'Object') {
-				throw new TypeError(`${filePath}, if it exists, must export an object whose '${dataType}' property is an Object`);
-			}
-			return dataObject[dataType];
-		} catch (e: any) {
-			if (e.code !== 'MODULE_NOT_FOUND' && e.code !== 'ENOENT') {
-				throw e;
-			}
-		}
+	loadDataFile(basePath: string, dataType: DataType): AnyObject | void {
+		const filePath = basePath + DATA_FILES[dataType];
+		// `@pokebedrock` - use inline data registry to avoid dynamic requires
+		const dataObject = DataRegistry[filePath];
+		// `@pokebedrock` - Only allow silent fallback for the pokebedrock mod
+		// Other mods must be explicitly registered; otherwise, error out
+		if (!dataObject && basePath.includes('mods/pokebedrock')) return;
+		if (!dataObject || typeof dataObject !== 'object') {
+			throw new TypeError(`${filePath}, if it exists, must export a non-null object`);
+		}
+		if (dataObject[dataType]?.constructor?.name !== 'Object') {
+			throw new TypeError(`${filePath}, if it exists, must export an object whose '${dataType}' property is an Object`);
+		}
+		return dataObject[dataType];
 	}
**Actionable comments posted: 1** <details> <summary>🤖 Fix all issues with AI agents</summary> ``` In `@sim/random-battles-module-map.ts`: - Around line 1-8: The return type of getRandomBattlesModule is wrong because require('../data/random-battles/gen9/teams') yields an object with named exports (not a default), so update the function signature and callers: change getRandomBattlesModule(mod: string): { default: any } | undefined to return the actual exported shape (e.g., Record<string, any> or a proper interface matching TeamData/BattleFactorySpecies/MoveCounter) or use a dynamic ES import (await import('../data/random-battles/gen9/teams')) and type it accordingly; ensure callers of getRandomBattlesModule no longer access .default but use the named properties (e.g., TeamData) and update any type annotations to reference the real exported types from teams.ts. ``` </details> <details> <summary>🧹 Nitpick comments (2)</summary><blockquote> <details> <summary>sim/dex.ts (2)</summary><blockquote> `202-208`: **Silent fallback to base for unknown mods may hide configuration errors.** When an unregistered mod is requested (e.g., `'gen8'`, `'gen7'`), this silently returns gen9 data with no warning. This is intentional per the PR objectives, but a `console.warn` or debug log would help developers diagnose issues when formats unexpectedly resolve to base data. <details> <summary>💡 Optional: Add a debug warning for unregistered mod fallback</summary> ```diff mod(mod: string | undefined): ModdedDex { if (!dexes['base'].modsLoaded) dexes['base'].includeMods(); const modId = mod || 'base'; // Fallback to base data for unsupported/unregistered mods - if (!dexes[modId]) return dexes[BASE_MOD].includeData(); + if (!dexes[modId]) { + console.warn(`[Dex] Mod '${modId}' is not registered; falling back to '${BASE_MOD}'`); + return dexes[BASE_MOD].includeData(); + } return dexes[modId].includeData(); } ``` </details> --- `487-507`: **The `catch` block for `MODULE_NOT_FOUND` / `ENOENT` is now dead code.** Since `loadDataFile` no longer calls `require()` (it reads from `DataRegistry`), the only throws are the explicit `TypeError`s on lines 496 and 499, which won't have `.code === 'MODULE_NOT_FOUND'`. The catch block silently swallows nothing but could mislead future maintainers into thinking dynamic loading still occurs. <details> <summary>🧹 Optional: Remove the stale catch guard</summary> ```diff - loadDataFile(basePath: string, dataType: DataType): AnyObject | void { - try { - const filePath = basePath + DATA_FILES[dataType]; - // `@pokebedrock` - use inline data registry to avoid dynamic requires - const dataObject = DataRegistry[filePath]; - // `@pokebedrock` - Only allow silent fallback for the pokebedrock mod - // Other mods must be explicitly registered; otherwise, error out - if (!dataObject && basePath.includes('mods/pokebedrock')) return; - if (!dataObject || typeof dataObject !== 'object') { - throw new TypeError(`${filePath}, if it exists, must export a non-null object`); - } - if (dataObject[dataType]?.constructor?.name !== 'Object') { - throw new TypeError(`${filePath}, if it exists, must export an object whose '${dataType}' property is an Object`); - } - return dataObject[dataType]; - } catch (e: any) { - if (e.code !== 'MODULE_NOT_FOUND' && e.code !== 'ENOENT') { - throw e; - } - } + loadDataFile(basePath: string, dataType: DataType): AnyObject | void { + const filePath = basePath + DATA_FILES[dataType]; + // `@pokebedrock` - use inline data registry to avoid dynamic requires + const dataObject = DataRegistry[filePath]; + // `@pokebedrock` - Only allow silent fallback for the pokebedrock mod + // Other mods must be explicitly registered; otherwise, error out + if (!dataObject && basePath.includes('mods/pokebedrock')) return; + if (!dataObject || typeof dataObject !== 'object') { + throw new TypeError(`${filePath}, if it exists, must export a non-null object`); + } + if (dataObject[dataType]?.constructor?.name !== 'Object') { + throw new TypeError(`${filePath}, if it exists, must export an object whose '${dataType}' property is an Object`); + } + return dataObject[dataType]; } ``` </details> </blockquote></details> </blockquote></details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
coderabbitai[bot] (Migrated from github.com) commented 2026-02-10 01:57:10 +00:00

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find the gen9 teams module
echo "=== Finding gen9 teams module ==="
find . -path '*random-battles/gen9/teams*' -type f 2>/dev/null

echo -e "\n=== Checking the gen9 teams module content ==="
find . -path '*random-battles/gen9/teams*' -type f -exec cat -n {} \; 2>/dev/null | head -80

echo -e "\n=== Checking tsconfig files ==="
find . -name 'tsconfig*.json' -type f | head -5

echo -e "\n=== Checking for esModuleInterop in tsconfig ==="
find . -name 'tsconfig*.json' -type f -exec grep -H 'esModuleInterop' {} \;

echo -e "\n=== Checking the module-map file itself ==="
cat -n sim/random-battles-module-map.ts

Repository: smell-of-curry/pokebedrock-showdown

Length of output: 3527


Fix return type: teams module has named exports, not a default export.

The teams.ts module uses named exports (export interface, export class, etc.), not export default. With esModuleInterop: true in TypeScript config, require('../data/random-battles/gen9/teams') returns an object with named properties (e.g., { TeamData, BattleFactorySpecies, MoveCounter, ... }), not { default: any }.

The return type annotation is incorrect and will cause runtime errors if .default is accessed. Update the return type to match the actual exported shape, or refactor to use ES imports instead of require().

🤖 Prompt for AI Agents
In `@sim/random-battles-module-map.ts` around lines 1 - 8, The return type of
getRandomBattlesModule is wrong because
require('../data/random-battles/gen9/teams') yields an object with named exports
(not a default), so update the function signature and callers: change
getRandomBattlesModule(mod: string): { default: any } | undefined to return the
actual exported shape (e.g., Record<string, any> or a proper interface matching
TeamData/BattleFactorySpecies/MoveCounter) or use a dynamic ES import (await
import('../data/random-battles/gen9/teams')) and type it accordingly; ensure
callers of getRandomBattlesModule no longer access .default but use the named
properties (e.g., TeamData) and update any type annotations to reference the
real exported types from teams.ts.
_⚠️ Potential issue_ | _🔴 Critical_ <details> <summary>🧩 Analysis chain</summary> 🏁 Script executed: ```shell #!/bin/bash # Find the gen9 teams module echo "=== Finding gen9 teams module ===" find . -path '*random-battles/gen9/teams*' -type f 2>/dev/null echo -e "\n=== Checking the gen9 teams module content ===" find . -path '*random-battles/gen9/teams*' -type f -exec cat -n {} \; 2>/dev/null | head -80 echo -e "\n=== Checking tsconfig files ===" find . -name 'tsconfig*.json' -type f | head -5 echo -e "\n=== Checking for esModuleInterop in tsconfig ===" find . -name 'tsconfig*.json' -type f -exec grep -H 'esModuleInterop' {} \; echo -e "\n=== Checking the module-map file itself ===" cat -n sim/random-battles-module-map.ts ``` Repository: smell-of-curry/pokebedrock-showdown Length of output: 3527 --- </details> **Fix return type: teams module has named exports, not a default export.** The teams.ts module uses named exports (`export interface`, `export class`, etc.), not `export default`. With `esModuleInterop: true` in TypeScript config, `require('../data/random-battles/gen9/teams')` returns an object with named properties (e.g., `{ TeamData, BattleFactorySpecies, MoveCounter, ... }`), not `{ default: any }`. The return type annotation is incorrect and will cause runtime errors if `.default` is accessed. Update the return type to match the actual exported shape, or refactor to use ES imports instead of `require()`. <details> <summary>🤖 Prompt for AI Agents</summary> ``` In `@sim/random-battles-module-map.ts` around lines 1 - 8, The return type of getRandomBattlesModule is wrong because require('../data/random-battles/gen9/teams') yields an object with named exports (not a default), so update the function signature and callers: change getRandomBattlesModule(mod: string): { default: any } | undefined to return the actual exported shape (e.g., Record<string, any> or a proper interface matching TeamData/BattleFactorySpecies/MoveCounter) or use a dynamic ES import (await import('../data/random-battles/gen9/teams')) and type it accordingly; ensure callers of getRandomBattlesModule no longer access .default but use the named properties (e.g., TeamData) and update any type annotations to reference the real exported types from teams.ts. ``` </details> <!-- fingerprinting:phantom:poseidon:phoenix --> <!-- This is an auto-generated comment by CodeRabbit -->
cursor[bot] (Migrated from github.com) reviewed 2026-02-10 02:06:03 +00:00
cursor[bot] (Migrated from github.com) left a comment

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Cursor Bugbot has reviewed your changes and found 1 potential issue.
@ -628,1 +627,4 @@
// If a format requires a mod that is not registered, fall back to default
// This prevents startup crashes when legacy gens are present in formats list
if (!this.dex.dexes[format.mod]) format.mod = DEFAULT_MOD;
cursor[bot] (Migrated from github.com) commented 2026-02-10 02:06:03 +00:00

Silent mod fallback makes gen9ssb team generator unreachable

High Severity

The [Gen 9] Super Staff Bros Ultimate format in config/formats.ts specifies mod: 'gen9ssb', but includeMods() only registers 'pokebedrock'. During format loading, this.dex.dexes['gen9ssb'] is undefined, so format.mod is silently rewritten to 'gen9'. This makes the mod === 'gen9ssb' check in teams.ts getGenerator unreachable — the SSB-specific random team generator (data/mods/gen9ssb/random-teams) is never loaded, and the format silently falls through to the generic gen9 random team generator instead.

Additional Locations (2)

Fix in Cursor Fix in Web

### Silent mod fallback makes gen9ssb team generator unreachable **High Severity** <!-- DESCRIPTION START --> The `[Gen 9] Super Staff Bros Ultimate` format in `config/formats.ts` specifies `mod: 'gen9ssb'`, but `includeMods()` only registers `'pokebedrock'`. During format loading, `this.dex.dexes['gen9ssb']` is undefined, so `format.mod` is silently rewritten to `'gen9'`. This makes the `mod === 'gen9ssb'` check in `teams.ts` `getGenerator` unreachable — the SSB-specific random team generator (`data/mods/gen9ssb/random-teams`) is never loaded, and the format silently falls through to the generic gen9 random team generator instead. <!-- DESCRIPTION END --> <!-- BUGBOT_BUG_ID: abea89a1-2dd1-400a-9bae-a53acb5e2aad --> <!-- LOCATIONS START sim/dex-formats.ts#L626-L629 sim/teams.ts#L701-L703 sim/dex.ts#L539-L541 LOCATIONS END --> <details> <summary>Additional Locations (2)</summary> - [`sim/teams.ts#L701-L703`](https://github.com/smell-of-curry/pokebedrock-showdown/blob/f2d9258887bb229373a39e1b991693cdd26930bf/sim/teams.ts#L701-L703) - [`sim/dex.ts#L539-L541`](https://github.com/smell-of-curry/pokebedrock-showdown/blob/f2d9258887bb229373a39e1b991693cdd26930bf/sim/dex.ts#L539-L541) </details> <p><a href="https://cursor.com/open?data=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImJ1Z2JvdC12MiJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9DVVJTT1IiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OmZiOGI0MjUwLTFhNjMtNGRiOS1iZWE4LTgwOGEzNzNjODZjZiIsImVuY3J5cHRpb25LZXkiOiIxdjBHb1ExS3FZcTBkY3JlLVdrVV85b2dkY09TTG43cVlXR1J2RXVtU1ZrIiwiYnJhbmNoIjoiZ3JlYXRseS1yZWR1Y2UtbWVtb3J5IiwicmVwb093bmVyIjoic21lbGwtb2YtY3VycnkiLCJyZXBvTmFtZSI6InBva2ViZWRyb2NrLXNob3dkb3duIn0sImlhdCI6MTc3MDY4OTE2MywiZXhwIjoxNzczMjgxMTYzfQ.GoAeurZcliuPtMVtO2H_dGCz-UIQfC4FC2pEe2o5YYOpiizuzFH-EGpD_Cpx6R_NNPNP9gQBtXPdqChfaHtCLl1dAxVNSNyCXASAbumpE-zMCQv013yyXyY6NhBf5catZb4j1ZWirjknDLsdJ4-EuAlcnB-S18JVkterzTqzozx5UTg4Xzm-8XhU_I2ICFUa3fzwdI5WCBCIJJeMFj2-nugDHG_u9HLxnOo7rmwqC6qf208cA9cX7IVPAnbGlWK4ibg_1AzWmIPpDExx8TxRveW0yQTCHXY-1kp2qKkbNy_b4yvX9jI_XqGTxl1XHYBR3l9Fg0KUaK-ucLAtpsI4qw" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-cursor-light.png"><img alt="Fix in Cursor" width="115" height="28" src="https://cursor.com/assets/images/fix-in-cursor-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/agents?data=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImJ1Z2JvdC12MiJ9.eyJ2ZXJzaW9uIjoxLCJ0eXBlIjoiQlVHQk9UX0ZJWF9JTl9XRUIiLCJkYXRhIjp7InJlZGlzS2V5IjoiYnVnYm90OmZiOGI0MjUwLTFhNjMtNGRiOS1iZWE4LTgwOGEzNzNjODZjZiIsImVuY3J5cHRpb25LZXkiOiIxdjBHb1ExS3FZcTBkY3JlLVdrVV85b2dkY09TTG43cVlXR1J2RXVtU1ZrIiwiYnJhbmNoIjoiZ3JlYXRseS1yZWR1Y2UtbWVtb3J5IiwicmVwb093bmVyIjoic21lbGwtb2YtY3VycnkiLCJyZXBvTmFtZSI6InBva2ViZWRyb2NrLXNob3dkb3duIiwicHJOdW1iZXIiOjgsImNvbW1pdFNoYSI6ImYyZDkyNTg4ODdiYjIyOTM3M2EzOWUxYjk5MTY5M2NkZDI2OTMwYmYiLCJwcm92aWRlciI6ImdpdGh1YiJ9LCJpYXQiOjE3NzA2ODkxNjMsImV4cCI6MTc3MzI4MTE2M30.ofJfu0CeS-efqfdSldrvqjMcM6bTZYdW6GTpuriSTkw8ioFv6FD4UtN04BcLmDWrOuV0DqRZ_m-DELs3shaxUSwRRs1IP0INLromUslkuMPfgR1dNa_R5GGX1KK8wlrp6EM_I0U9YjjEnkKWQ-3YLRdRzbou2jBUGCbheFcoggvZ4Gf03pBAb4pmbLYX_o9AcQs-dr5BCiiARiJb_1g3htCfdEhYDfBCnbhDonBwHRGeCLAIKt6BS2o7YV_Jj9fLeQiOz6ILvwgMkkU2O6HdHOYMb1zEVlxHMwry7wJFBT1tMuF5rE_A8Pi0KB6nFUYXVt5O02rvEMFE4TfC_Sfvmg" target="_blank" rel="noopener noreferrer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/fix-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/fix-in-web-light.png"><img alt="Fix in Web" width="99" height="28" src="https://cursor.com/assets/images/fix-in-web-dark.png"></picture></a></p>
coderabbitai[bot] (Migrated from github.com) reviewed 2026-04-26 16:09:49 +00:00
coderabbitai[bot] (Migrated from github.com) left a comment

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
sim/teams.ts (1)

696-719: ⚠️ Potential issue | 🟠 Major

Behavior change: non-gen9 random formats now hard-fail at team generation — confirm intended scope.

With the random-battles map narrowed to gen9-only (per sim/random-battles-module-map.ts), any format with a non-gen9 mod that reaches the fallback at sim/teams.ts:713–715 will throw. This affects 38 gen8 formats still defined with team: 'random', along with gen1–gen7 and other custom mods (e.g., randomroulette, sharedpower). Error handling varies by caller:

  • sim/battle.ts — no try/catch; error propagates into battle init.
  • server/chat-plugins/randombattles/index.ts generateteam — no try/catch; user-facing crash on /genteam [gen8-format].
  • sim/team-validator.ts and server/tournaments/index.ts — already wrap in try/catch, so they degrade gracefully.

Gen8 and legacy modules exist in the filesystem but are unregistered. If gen8 random battles should remain available in production, register them in the module map (mirroring the monkeyspaw → gen9 normalization pattern). Otherwise, disable gen8 random-battle formats explicitly to avoid unintended failures.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sim/teams.ts` around lines 696 - 719, getGenerator currently throws when
getRandomBattlesModule(mod) returns undefined for non-gen9 mods, causing runtime
crashes for legacy random formats; fix by either (A) registering the missing
random-battles modules for those mods in the random-battles-module-map (e.g.,
add gen8 entries or map legacy mods to the correct gen module similar to the
monkeyspaw → gen9 normalization) so getRandomBattlesModule(mod) returns a valid
module, or (B) explicitly disable/mark non-gen9 formats that use team: 'random'
(update their Format entries) so they never reach TeamGenerator creation; update
sim/teams.ts (getGenerator), sim/random-battles-module-map.ts, and the affected
Format definitions accordingly to implement the chosen approach.
🧹 Nitpick comments (3)
sim/teams.ts (1)

711-715: Include format identifier in the error for easier diagnosis.

The thrown error only reports mod, which will almost always be a generic value like gen9 (or the raw format.mod for unsupported gens). Since this branch is the catch-all for any random-battles format that didn’t match the earlier specific cases (gen9ssb, gen9baby, gen9cap, gen9ffa), the failure mode worth knowing in logs is which format triggered it — especially because battle.ts does not wrap Teams.getGenerator in try/catch and the error will surface during battle init.

♻️ Suggested refactor
-			// `@pokebedrock` - use static module map to avoid dynamic requires;
-			// only `gen9` is registered, so non-gen9 random formats throw here.
-			const rbModule = getRandomBattlesModule(mod);
-			if (!rbModule) throw new Error(`Random battles module not found for mod: ${mod}`);
-			TeamGenerator = rbModule.default;
+			// `@pokebedrock` - use static module map to avoid dynamic requires;
+			// only `gen9` is registered, so non-gen9 random formats throw here.
+			const rbModule = getRandomBattlesModule(mod);
+			if (!rbModule) {
+				throw new Error(
+					`Random battles module not found for mod '${mod}' (format: ${format.id || formatID})`
+				);
+			}
+			TeamGenerator = rbModule.default;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sim/teams.ts` around lines 711 - 715, The throw inside the
getRandomBattlesModule branch currently only reports `mod`; update the error to
include the actual format identifier so failures show which format triggered
this path. Locate the block using getRandomBattlesModule(mod) and TeamGenerator
and change the thrown Error to include the format's id/name (e.g., `format.id`
or `format.name`) or the serialized `format` object alongside `mod` so the error
message becomes something like "Random battles module not found for mod: X,
format: Y" for easier diagnosis.
sim/dex.ts (2)

57-73: Optional: type DataRegistry more precisely.

Record<string, any> opts the registry out of TS type checking. A keyed type (or Record<string, Readonly<Record<string, unknown>>>) would catch typos in keys/exports at compile time and protect future edits to the registry.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sim/dex.ts` around lines 57 - 73, The DataRegistry variable is typed as
Record<string, any>, which disables useful type checking; replace the any with a
stricter module type (for example define a DataModule = Readonly<Record<string,
unknown>> or a literal union of the exact import keys) and then type
DataRegistry as Record<string, DataModule> (or as a mapping of the explicit keys
to DataModule) so TypeScript can catch typos in keys/exports and prevent
accidental mutations; update the declaration of DataRegistry and the new
DataModule/type alias and ensure each entry (e.g., DataAbilities, DataMoves,
ModPBPokedex, ModPBScripts) conforms to that type.

487-501: Tighten the pokebedrock-path check.

basePath.includes('mods/pokebedrock') is a substring match without a trailing slash, so a future sibling mod path (e.g. mods/pokebedrock-test/...) would also be matched and silently accept missing registry entries instead of throwing. Since the registered dataDir is always '../data/mods/pokebedrock', the check can be made exact.

Suggested change
-		// `@pokebedrock` - Only allow silent fallback for the pokebedrock mod
-		// Other mods must be explicitly registered; otherwise, error out
-		if (!dataObject && basePath.includes('mods/pokebedrock')) return;
+		// `@pokebedrock` - Only allow silent fallback for the pokebedrock mod
+		// Other mods must be explicitly registered; otherwise, error out
+		if (!dataObject && basePath.startsWith(`${MODS_DIR}/pokebedrock/`)) return;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sim/dex.ts` around lines 487 - 501, The silent fallback for the pokebedrock
mod currently uses a substring match (basePath.includes('mods/pokebedrock'))
which can incorrectly match sibling paths; in loadDataFile replace that includes
check with an exact match to the registered dataDir (e.g. compare basePath ===
'../data/mods/pokebedrock' or whatever the canonical registered value is) so
only the intended pokebedrock data directory is allowed the silent return; keep
references to DataRegistry, DATA_FILES and the existing TypeError guards
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@sim/dex.ts`:
- Around line 210-215: forGen currently silently falls back to the Gen 9 base
mod for gen < 9; update the forGen(gen: number) path that returns
dexes[BASE_MOD].includeData() to emit a console.warn (or processLogger.warn if
available) when gen is provided and < 9, including the requested gen and that it
is returning the Gen 9/base mod data; locate the logic in the forGen method and
add the warning immediately before the return, referencing forGen, dexes,
BASE_MOD, mod, and includeData to ensure the fallback is observable.

---

Outside diff comments:
In `@sim/teams.ts`:
- Around line 696-719: getGenerator currently throws when
getRandomBattlesModule(mod) returns undefined for non-gen9 mods, causing runtime
crashes for legacy random formats; fix by either (A) registering the missing
random-battles modules for those mods in the random-battles-module-map (e.g.,
add gen8 entries or map legacy mods to the correct gen module similar to the
monkeyspaw → gen9 normalization) so getRandomBattlesModule(mod) returns a valid
module, or (B) explicitly disable/mark non-gen9 formats that use team: 'random'
(update their Format entries) so they never reach TeamGenerator creation; update
sim/teams.ts (getGenerator), sim/random-battles-module-map.ts, and the affected
Format definitions accordingly to implement the chosen approach.

---

Nitpick comments:
In `@sim/dex.ts`:
- Around line 57-73: The DataRegistry variable is typed as Record<string, any>,
which disables useful type checking; replace the any with a stricter module type
(for example define a DataModule = Readonly<Record<string, unknown>> or a
literal union of the exact import keys) and then type DataRegistry as
Record<string, DataModule> (or as a mapping of the explicit keys to DataModule)
so TypeScript can catch typos in keys/exports and prevent accidental mutations;
update the declaration of DataRegistry and the new DataModule/type alias and
ensure each entry (e.g., DataAbilities, DataMoves, ModPBPokedex, ModPBScripts)
conforms to that type.
- Around line 487-501: The silent fallback for the pokebedrock mod currently
uses a substring match (basePath.includes('mods/pokebedrock')) which can
incorrectly match sibling paths; in loadDataFile replace that includes check
with an exact match to the registered dataDir (e.g. compare basePath ===
'../data/mods/pokebedrock' or whatever the canonical registered value is) so
only the intended pokebedrock data directory is allowed the silent return; keep
references to DataRegistry, DATA_FILES and the existing TypeError guards
unchanged.

In `@sim/teams.ts`:
- Around line 711-715: The throw inside the getRandomBattlesModule branch
currently only reports `mod`; update the error to include the actual format
identifier so failures show which format triggered this path. Locate the block
using getRandomBattlesModule(mod) and TeamGenerator and change the thrown Error
to include the format's id/name (e.g., `format.id` or `format.name`) or the
serialized `format` object alongside `mod` so the error message becomes
something like "Random battles module not found for mod: X, format: Y" for
easier diagnosis.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5d3a465e-b351-4124-a93d-6e7b0c49c6ba

📥 Commits

Reviewing files that changed from the base of the PR and between f2d9258887 and 45ff0ad3cc.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • package.json
  • sim/dex.ts
  • sim/teams.ts
✅ Files skipped from review due to trivial changes (1)
  • package.json
**Actionable comments posted: 1** > [!CAUTION] > Some comments are outside the diff and can’t be posted inline due to platform limitations. > > > > <details> > <summary>⚠️ Outside diff range comments (1)</summary><blockquote> > > <details> > <summary>sim/teams.ts (1)</summary><blockquote> > > `696-719`: _⚠️ Potential issue_ | _🟠 Major_ > > **Behavior change: non-gen9 random formats now hard-fail at team generation — confirm intended scope.** > > With the random-battles map narrowed to gen9-only (per `sim/random-battles-module-map.ts`), any format with a non-gen9 `mod` that reaches the fallback at `sim/teams.ts:713–715` will throw. This affects 38 gen8 formats still defined with `team: 'random'`, along with gen1–gen7 and other custom mods (e.g., randomroulette, sharedpower). Error handling varies by caller: > > - `sim/battle.ts` — no try/catch; error propagates into battle init. > - `server/chat-plugins/randombattles/index.ts` `generateteam` — no try/catch; **user-facing crash on `/genteam [gen8-format]`**. > - `sim/team-validator.ts` and `server/tournaments/index.ts` — already wrap in try/catch, so they degrade gracefully. > > Gen8 and legacy modules exist in the filesystem but are unregistered. If gen8 random battles should remain available in production, register them in the module map (mirroring the `monkeyspaw → gen9` normalization pattern). Otherwise, disable gen8 random-battle formats explicitly to avoid unintended failures. > > <details> > <summary>🤖 Prompt for AI Agents</summary> > > ``` > Verify each finding against the current code and only fix it if needed. > > In `@sim/teams.ts` around lines 696 - 719, getGenerator currently throws when > getRandomBattlesModule(mod) returns undefined for non-gen9 mods, causing runtime > crashes for legacy random formats; fix by either (A) registering the missing > random-battles modules for those mods in the random-battles-module-map (e.g., > add gen8 entries or map legacy mods to the correct gen module similar to the > monkeyspaw → gen9 normalization) so getRandomBattlesModule(mod) returns a valid > module, or (B) explicitly disable/mark non-gen9 formats that use team: 'random' > (update their Format entries) so they never reach TeamGenerator creation; update > sim/teams.ts (getGenerator), sim/random-battles-module-map.ts, and the affected > Format definitions accordingly to implement the chosen approach. > ``` > > </details> > > </blockquote></details> > > </blockquote></details> <details> <summary>🧹 Nitpick comments (3)</summary><blockquote> <details> <summary>sim/teams.ts (1)</summary><blockquote> `711-715`: **Include format identifier in the error for easier diagnosis.** The thrown error only reports `mod`, which will almost always be a generic value like `gen9` (or the raw `format.mod` for unsupported gens). Since this branch is the catch-all for any random-battles format that didn’t match the earlier specific cases (gen9ssb, gen9baby, gen9cap, gen9ffa), the failure mode worth knowing in logs is which `format` triggered it — especially because `battle.ts` does not wrap `Teams.getGenerator` in try/catch and the error will surface during battle init. <details> <summary>♻️ Suggested refactor</summary> ```diff - // `@pokebedrock` - use static module map to avoid dynamic requires; - // only `gen9` is registered, so non-gen9 random formats throw here. - const rbModule = getRandomBattlesModule(mod); - if (!rbModule) throw new Error(`Random battles module not found for mod: ${mod}`); - TeamGenerator = rbModule.default; + // `@pokebedrock` - use static module map to avoid dynamic requires; + // only `gen9` is registered, so non-gen9 random formats throw here. + const rbModule = getRandomBattlesModule(mod); + if (!rbModule) { + throw new Error( + `Random battles module not found for mod '${mod}' (format: ${format.id || formatID})` + ); + } + TeamGenerator = rbModule.default; ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against the current code and only fix it if needed. In `@sim/teams.ts` around lines 711 - 715, The throw inside the getRandomBattlesModule branch currently only reports `mod`; update the error to include the actual format identifier so failures show which format triggered this path. Locate the block using getRandomBattlesModule(mod) and TeamGenerator and change the thrown Error to include the format's id/name (e.g., `format.id` or `format.name`) or the serialized `format` object alongside `mod` so the error message becomes something like "Random battles module not found for mod: X, format: Y" for easier diagnosis. ``` </details> </blockquote></details> <details> <summary>sim/dex.ts (2)</summary><blockquote> `57-73`: **Optional: type `DataRegistry` more precisely.** `Record<string, any>` opts the registry out of TS type checking. A keyed type (or `Record<string, Readonly<Record<string, unknown>>>`) would catch typos in keys/exports at compile time and protect future edits to the registry. <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against the current code and only fix it if needed. In `@sim/dex.ts` around lines 57 - 73, The DataRegistry variable is typed as Record<string, any>, which disables useful type checking; replace the any with a stricter module type (for example define a DataModule = Readonly<Record<string, unknown>> or a literal union of the exact import keys) and then type DataRegistry as Record<string, DataModule> (or as a mapping of the explicit keys to DataModule) so TypeScript can catch typos in keys/exports and prevent accidental mutations; update the declaration of DataRegistry and the new DataModule/type alias and ensure each entry (e.g., DataAbilities, DataMoves, ModPBPokedex, ModPBScripts) conforms to that type. ``` </details> --- `487-501`: **Tighten the pokebedrock-path check.** `basePath.includes('mods/pokebedrock')` is a substring match without a trailing slash, so a future sibling mod path (e.g. `mods/pokebedrock-test/...`) would also be matched and silently accept missing registry entries instead of throwing. Since the registered dataDir is always `'../data/mods/pokebedrock'`, the check can be made exact. <details> <summary>Suggested change</summary> ```diff - // `@pokebedrock` - Only allow silent fallback for the pokebedrock mod - // Other mods must be explicitly registered; otherwise, error out - if (!dataObject && basePath.includes('mods/pokebedrock')) return; + // `@pokebedrock` - Only allow silent fallback for the pokebedrock mod + // Other mods must be explicitly registered; otherwise, error out + if (!dataObject && basePath.startsWith(`${MODS_DIR}/pokebedrock/`)) return; ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against the current code and only fix it if needed. In `@sim/dex.ts` around lines 487 - 501, The silent fallback for the pokebedrock mod currently uses a substring match (basePath.includes('mods/pokebedrock')) which can incorrectly match sibling paths; in loadDataFile replace that includes check with an exact match to the registered dataDir (e.g. compare basePath === '../data/mods/pokebedrock' or whatever the canonical registered value is) so only the intended pokebedrock data directory is allowed the silent return; keep references to DataRegistry, DATA_FILES and the existing TypeError guards unchanged. ``` </details> </blockquote></details> </blockquote></details> <details> <summary>🤖 Prompt for all review comments with AI agents</summary> ``` Verify each finding against the current code and only fix it if needed. Inline comments: In `@sim/dex.ts`: - Around line 210-215: forGen currently silently falls back to the Gen 9 base mod for gen < 9; update the forGen(gen: number) path that returns dexes[BASE_MOD].includeData() to emit a console.warn (or processLogger.warn if available) when gen is provided and < 9, including the requested gen and that it is returning the Gen 9/base mod data; locate the logic in the forGen method and add the warning immediately before the return, referencing forGen, dexes, BASE_MOD, mod, and includeData to ensure the fallback is observable. --- Outside diff comments: In `@sim/teams.ts`: - Around line 696-719: getGenerator currently throws when getRandomBattlesModule(mod) returns undefined for non-gen9 mods, causing runtime crashes for legacy random formats; fix by either (A) registering the missing random-battles modules for those mods in the random-battles-module-map (e.g., add gen8 entries or map legacy mods to the correct gen module similar to the monkeyspaw → gen9 normalization) so getRandomBattlesModule(mod) returns a valid module, or (B) explicitly disable/mark non-gen9 formats that use team: 'random' (update their Format entries) so they never reach TeamGenerator creation; update sim/teams.ts (getGenerator), sim/random-battles-module-map.ts, and the affected Format definitions accordingly to implement the chosen approach. --- Nitpick comments: In `@sim/dex.ts`: - Around line 57-73: The DataRegistry variable is typed as Record<string, any>, which disables useful type checking; replace the any with a stricter module type (for example define a DataModule = Readonly<Record<string, unknown>> or a literal union of the exact import keys) and then type DataRegistry as Record<string, DataModule> (or as a mapping of the explicit keys to DataModule) so TypeScript can catch typos in keys/exports and prevent accidental mutations; update the declaration of DataRegistry and the new DataModule/type alias and ensure each entry (e.g., DataAbilities, DataMoves, ModPBPokedex, ModPBScripts) conforms to that type. - Around line 487-501: The silent fallback for the pokebedrock mod currently uses a substring match (basePath.includes('mods/pokebedrock')) which can incorrectly match sibling paths; in loadDataFile replace that includes check with an exact match to the registered dataDir (e.g. compare basePath === '../data/mods/pokebedrock' or whatever the canonical registered value is) so only the intended pokebedrock data directory is allowed the silent return; keep references to DataRegistry, DATA_FILES and the existing TypeError guards unchanged. In `@sim/teams.ts`: - Around line 711-715: The throw inside the getRandomBattlesModule branch currently only reports `mod`; update the error to include the actual format identifier so failures show which format triggered this path. Locate the block using getRandomBattlesModule(mod) and TeamGenerator and change the thrown Error to include the format's id/name (e.g., `format.id` or `format.name`) or the serialized `format` object alongside `mod` so the error message becomes something like "Random battles module not found for mod: X, format: Y" for easier diagnosis. ``` </details> <details> <summary>🪄 Autofix (Beta)</summary> Fix all unresolved CodeRabbit comments on this PR: - [ ] <!-- {"checkboxId": "4b0d0e0a-96d7-4f10-b296-3a18ea78f0b9"} --> Push a commit to this branch (recommended) - [ ] <!-- {"checkboxId": "ff5b1114-7d8c-49e6-8ac1-43f82af23a33"} --> Create a new PR with the fixes </details> --- <details> <summary>ℹ️ Review info</summary> <details> <summary>⚙️ Run configuration</summary> **Configuration used**: defaults **Review profile**: CHILL **Plan**: Pro **Run ID**: `5d3a465e-b351-4124-a93d-6e7b0c49c6ba` </details> <details> <summary>📥 Commits</summary> Reviewing files that changed from the base of the PR and between f2d9258887bb229373a39e1b991693cdd26930bf and 45ff0ad3cceffa8e58ed7af5c0313f26ad03746c. </details> <details> <summary>⛔ Files ignored due to path filters (1)</summary> * `package-lock.json` is excluded by `!**/package-lock.json` </details> <details> <summary>📒 Files selected for processing (3)</summary> * `package.json` * `sim/dex.ts` * `sim/teams.ts` </details> <details> <summary>✅ Files skipped from review due to trivial changes (1)</summary> * package.json </details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
coderabbitai[bot] (Migrated from github.com) commented 2026-04-26 16:09:48 +00:00

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find call sites that pass non-9 gens to forGen, which would now silently
# get gen9 data.
rg -nP --type=ts -C2 '\bforGen\s*\('

Repository: smell-of-curry/pokebedrock-showdown

Length of output: 2419


Add warning to forGen() fallback for unsupported gens to prevent silent data mismatches.

The code silently returns gen 9 data when forGen() is called with gen < 9. This affects real validation code: data/rulesets.ts explicitly calls forGen(5) and iterates through forGen(gen) with decremented gen values (lines 141, 536, 1696) to fetch historical gen-specific item and move data. Silent fallback causes data mismatch—these validators would incorrectly receive gen 9 data instead of the requested gen's rules.

Add a console warning to make the fallback observable:

Suggested change
 forGen(gen: number) {
   if (!gen) return this;
-  // Only Gen 9 (base) is supported; fallback for older gens
-  if (gen >= 9) return this.mod(`gen${gen}`);
-  return dexes[BASE_MOD].includeData();
+  // Only Gen 9 is supported; warn on unsupported gens so silent
+  // fallbacks don't corrupt validation/sim output.
+  if (gen >= 9) return this.mod(`gen${gen}`);
+  if (typeof console !== 'undefined') {
+    console.warn(`Dex.forGen(${gen}): only gen 9 is supported; falling back to gen 9 data.`);
+  }
+  return dexes[BASE_MOD].includeData();
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	forGen(gen: number) {
		if (!gen) return this;
		// Only Gen 9 is supported; warn on unsupported gens so silent
		// fallbacks don't corrupt validation/sim output.
		if (gen >= 9) return this.mod(`gen${gen}`);
		if (typeof console !== 'undefined') {
			console.warn(`Dex.forGen(${gen}): only gen 9 is supported; falling back to gen 9 data.`);
		}
		return dexes[BASE_MOD].includeData();
	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sim/dex.ts` around lines 210 - 215, forGen currently silently falls back to
the Gen 9 base mod for gen < 9; update the forGen(gen: number) path that returns
dexes[BASE_MOD].includeData() to emit a console.warn (or processLogger.warn if
available) when gen is provided and < 9, including the requested gen and that it
is returning the Gen 9/base mod data; locate the logic in the forGen method and
add the warning immediately before the return, referencing forGen, dexes,
BASE_MOD, mod, and includeData to ensure the fallback is observable.
_⚠️ Potential issue_ | _🟡 Minor_ <details> <summary>🧩 Analysis chain</summary> 🏁 Script executed: ```shell #!/bin/bash # Find call sites that pass non-9 gens to forGen, which would now silently # get gen9 data. rg -nP --type=ts -C2 '\bforGen\s*\(' ``` Repository: smell-of-curry/pokebedrock-showdown Length of output: 2419 --- </details> **Add warning to `forGen()` fallback for unsupported gens to prevent silent data mismatches.** The code silently returns gen 9 data when `forGen()` is called with gen < 9. This affects real validation code: `data/rulesets.ts` explicitly calls `forGen(5)` and iterates through `forGen(gen)` with decremented gen values (lines 141, 536, 1696) to fetch historical gen-specific item and move data. Silent fallback causes data mismatch—these validators would incorrectly receive gen 9 data instead of the requested gen's rules. Add a console warning to make the fallback observable: <details> <summary>Suggested change</summary> ```diff forGen(gen: number) { if (!gen) return this; - // Only Gen 9 (base) is supported; fallback for older gens - if (gen >= 9) return this.mod(`gen${gen}`); - return dexes[BASE_MOD].includeData(); + // Only Gen 9 is supported; warn on unsupported gens so silent + // fallbacks don't corrupt validation/sim output. + if (gen >= 9) return this.mod(`gen${gen}`); + if (typeof console !== 'undefined') { + console.warn(`Dex.forGen(${gen}): only gen 9 is supported; falling back to gen 9 data.`); + } + return dexes[BASE_MOD].includeData(); } ``` </details> <!-- suggestion_start --> <details> <summary>📝 Committable suggestion</summary> > ‼️ **IMPORTANT** > Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements. ```suggestion forGen(gen: number) { if (!gen) return this; // Only Gen 9 is supported; warn on unsupported gens so silent // fallbacks don't corrupt validation/sim output. if (gen >= 9) return this.mod(`gen${gen}`); if (typeof console !== 'undefined') { console.warn(`Dex.forGen(${gen}): only gen 9 is supported; falling back to gen 9 data.`); } return dexes[BASE_MOD].includeData(); } ``` </details> <!-- suggestion_end --> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against the current code and only fix it if needed. In `@sim/dex.ts` around lines 210 - 215, forGen currently silently falls back to the Gen 9 base mod for gen < 9; update the forGen(gen: number) path that returns dexes[BASE_MOD].includeData() to emit a console.warn (or processLogger.warn if available) when gen is provided and < 9, including the requested gen and that it is returning the Gen 9/base mod data; locate the logic in the forGen method and add the warning immediately before the return, referencing forGen, dexes, BASE_MOD, mod, and includeData to ensure the fallback is observable. ``` </details> <!-- fingerprinting:phantom:poseidon:nectarine:211e4753-ac3c-444b-8c7d-ff56946c7e49 --> <!-- 4e71b3a2 --> <!-- This is an auto-generated comment by CodeRabbit -->
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
pokebedrock/pokebedrock-showdown!8
No description provided.