This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Wheelson is a World of Warcraft addon (Lua, WoW API) that forms balanced Mythic+ dungeon groups from guild members using a wheel-spin reveal animation. It uses AceAddon-3.0 framework and communicates between guild members via AceComm.
luacheck src/ tests/bustedTests use the busted framework. Config is in .busted — tests live in tests/ with the test_ prefix pattern.
busted tests/test_models.luabash scripts/build.shChecks that the .toc file exists and all source files listed in it are present on disk.
The addon registers itself as Wheelson via AceAddon in src/Config.lua, stored in _G.Wheelson. Every other source file accesses it via local WHLSN = _G.Wheelson and attaches methods/data to it. There is no module system — all files share the single WHLSN table.
- Config.lua — Creates the addon object, defines constants (roles, spec→role mapping, session states, saved variable defaults)
- Models.lua —
WHLSN.PlayerandWHLSN.Groupclasses (metatables with:New(),:ToDict(),.FromDict()serialization) - GroupCreator.lua — Group formation algorithm (port of
parallelGroupCreator.ts). Assigns tanks → lust → brez → healers → ranged → remaining DPS with duplicate-avoidance across runs - Core.lua — Addon lifecycle (
OnInitialize/OnEnable), slash commands (/wheelson), session state machine (lobby → spinning → completed), addon comm message handling, session timeout - Services/ —
SpecService(local player spec detection, realm name stripping),GuildService(roster queries),PartyService(party invites) - UI/ —
MainFrame.xml+MainFrame.lua(window shell, view switching),Lobby.lua(player list + join/spin),Wheel.lua(animated group reveal),GroupDisplay.lua(final results with invite/post/copy actions)
WHLSN.session.status: nil → "lobby" → "spinning" → "completed". The host broadcasts state to guild via AceComm (GUILD channel, prefix WHLSN). Non-hosts send JOIN_REQUEST/LEAVE_REQUEST messages.
GroupCreator.lua is a direct port of parallelGroupCreator.ts from a companion TypeScript project. It fills groups in priority order: tanks, lust providers, brez providers, healers, ranged DPS, remaining DPS. It tracks previous group compositions per guild to avoid repeat teammate assignments.
Tests stub WoW APIs and LibStub at the top of each file, then dofile() the source files in load order. Only non-UI logic is tested (Models, GroupCreator, GuildService, SpecService). The test stubs pattern is consistent across all test files — copy from an existing test when adding new ones.
- Never push directly to
main. Always create a feature branch, push there, and open a PR. - When using
/commit-push, push to the current feature branch (notorigin main). - Use
/ship-itto create the PR, get reviews, and merge.
This addon targets WoW 12.0 (Midnight) (## Interface: 120001). Use the modern C_ namespaced APIs — do not use their deprecated predecessors:
| Deprecated (do NOT use) | Use instead |
|---|---|
GetSpecialization() |
C_SpecializationInfo.GetSpecialization() |
GetSpecializationInfo() |
C_SpecializationInfo.GetSpecializationInfo() |
SendChatMessage() |
C_ChatInfo.SendChatMessage() |
InviteUnit() |
C_PartyInfo.InviteUnit() |
When adding new WoW API calls, check Warcraft Wiki API changes to confirm the function hasn't been removed or moved to a C_ namespace in 12.0.
- Lua 5.1 target (
std = "lua51"in.luacheckrc), 120 char line limit - Roles are strings:
"tank","healer","ranged","melee" - Utilities are strings:
"brez","lust" - Player identity comparison uses
Player:Equals()(name-based) - Serialization for addon comms uses
:ToDict()/.FromDict()pattern on model classes - Table append idiom:
t[#t + 1] = value(nottable.insert) - External libraries (Ace3, LibStub, etc.) are fetched at release time by BigWigsMods packager per
.pkgmeta— thelibs/dir is gitignored except.gitkeep - CI job naming constraint:
.github/workflows/ci-shared.ymlis a reusable workflow (workflow_callonly) that defines three jobs:Lint,Build,Test. It is called by.github/workflows/ci.yml(trigger:pull_requestonly) via a calling job with IDCI. GitHub Actions names reusable workflow checks as<calling_job_id> / <reusable_job_id>, producingCI / Lint,CI / Build,CI / Test— which branch protection requires. Do not rename the calling job ID inci.ymlor the job IDs inci-shared.yml, and do not add extra triggers toci.yml. - Never
git add -fgitignored files. If a path is in.gitignore(e.g.docs/superpowers/), respect that — do not force-add or force-commit it. Those files are local-only by design.