Skip to content

Contributing

Chronic Tinkerer edited this page May 6, 2026 · 1 revision

Contributing

Thanks for poking around. LibCodex is MIT-licensed — patches, data corrections, new modules, and bug reports all welcome.

Filing issues

The repo has structured issue forms for the four common cases:

  • Bug report — runtime errors, taint, wrong API behavior, crashes.
  • Data correction — a row in a catalog has a wrong or missing field. Citation required so corrections are verifiable.
  • Feature request — new module, new field, new helper API, or new adapter source.
  • Comments / chatter — CurseForge, Wago, WoWInterface comments are linked from the issue chooser. Use those for "how do I use X?" rather than filing an issue.

For bugs, please attach the full !BugGrabber / BugSack output. For data corrections, please cite a source (Wowhead URL, in-game screenshot, DBC dump). Citations get fixes merged faster.

Repository layout

LibCodex-1.0/
├── LibCodex-1.0.lua            -- core library, registration plumbing, typed accessors
├── LibCodex-1.0.toc            -- core TOC (Retail; siblings for Mists / TBC / Vanilla / XPTR)
├── LibCodex-1.0.xml            -- aggregator XML for embed consumers
├── Modules/
│   ├── Common.lua              -- collection factory (used by every module)
│   ├── Enums/<Name>.lua        -- Tier 1: small, hand-curated reference data
│   └── Catalog/<Name>.lua      -- Tier 2: large, runtime-growing catalogs
├── Adapters/
│   └── Runtime.lua             -- built-in event-driven capture adapter
├── Libs/                       -- vendored third-party libs (LibStub, LibEditMode)
├── Log.lua                     -- log window, used by /codex and consumers
├── SlashCommand.lua            -- /codex registration
├── LibCodex-1.0-<Module>/      -- 73 LoadOnDemand sibling addons (one per module)
│   ├── LibCodex-1.0-<Module>.toc
│   └── Data/<Module>.lua       -- bake-tool output (bundled seed)
├── .pkgmeta                    -- BigWigs Packager build manifest
├── .dev/                       -- dev-only tooling (gitignored)
│   ├── release.ps1             -- the release tool (bumps version, tags, pushes)
│   ├── tools/                  -- bake.py and friends
│   └── *-import.lua            -- import sources for the bake step
├── CHANGELOG.md                -- Keep a Changelog format, sequential build-number headers
└── LICENSE

The root TOC is the standalone-install entrypoint. Embed consumers reference LibCodex-1.0\LibCodex-1.0.xml from their own TOC's ## libs: line.

Editor configs are not committed

.vscode/, .idea/, and similar editor metadata are not tracked. If you've cloned the repo and your editor created one of these, it's already excluded from .gitignore. Don't add committed editor config; project-level settings should be portable enough that any contributor can open the repo without local pollution.

Adding a data correction

For a one-row fix that goes straight into the bundled seed:

  1. Open the relevant LibCodex-1.0-<Module>/Data/<Module>.lua.
  2. Locate the row by ID.
  3. Edit the field. Mark it _handcrafted = true (or add _locked = { "fieldName" }) so future bakes don't overwrite your fix.
  4. Run the bake tool to confirm the file still parses (see below).
  5. Bump CHANGELOG.md [Unreleased] with a one-liner under ### Fixed.
  6. PR.

For a bulk correction (re-baking a whole module from updated import data), open the import-side files in .dev/ and re-run bake.py — the corrected handcrafted rows will survive the rebake automatically.

The bake tool

.dev/tools/bake.py reads import sources (Blizzard cache dumps, Wowhead scrapes, Wago snapshots, emulator imports) and emits each module's Data/<Module>.lua. It's chunked: large modules emit multiple _FeedBundledRowsLazy calls so no single Lua function blows the constant-pool limit.

Defaults are tuned for most modules; modules with nested-table rows (TaxiPaths, EncounterCreatures) override the chunk size in _CHUNK_SIZE_OVERRIDES inside the script.

After running bake.py, always:

  • Verify the file count and row count look reasonable.
  • Spot-check a known row by id to confirm the round-trip is intact.
  • Don't trust wc -l from a fresh bash session if the file was just written via the file API — the mount cache can lag. Use Read (or open the file) to verify content.

Running the test suite

There's no full unit-test framework yet. In-game validation goes through Forge_Console: paste or save a Lua snippet under Forge/.dev/tests/<scenario>.lua and run it. The convention is print lines that read PASS: / FAIL: so you can scan results.

For changes touching Common.lua or LibCodex-1.0.lua, please run at least:

  • LC:VersionString() — confirms registration is intact.
  • LC:CountAll() — confirms every module loaded its seed.
  • LC:NPCs():Get(<known-id>) — confirms a :Get round-trip works.
  • LC:Items():Search("rune", { quality = 4 }) — confirms :Search walks lazy chunks correctly.

Releasing (maintainers)

Pre-release manual step. Roll CHANGELOG.md's [Unreleased] section into a new heading for the upcoming build number. release.ps1 does not touch the changelog — keep them in sync by hand before kicking the release.

.dev/release.ps1 "<commit message>" is the release driver. It:

  1. Reads the current ## Version: integer from the primary TOC and computes +1 as the new build number.
  2. Rewrites ## Version: in the five root flavor TOCs (LibCodex-1.0.toc, _Mists, _TBC, _Vanilla, _XPTR) and LIB_MINOR in LibCodex-1.0.lua.
  3. Discovers every nested per-module TOC under LibCodex-1.0-*/ and bumps each one's ## Version: in lockstep (~365 files including all flavor TOCs across 73 sub-addons).
  4. Validates every file matches its pattern exactly once before touching anything.
  5. git add -A, commits with your message, creates an annotated tag (git tag -a — never lightweight, because VSCode "Push (Follow Tags)" silently skips lightweight tags).
  6. Pushes HEAD and the tag separately.
  7. The tag push triggers the BigWigs Packager workflow on GitHub Actions, which publishes to CurseForge, Wago, and WoWInterface using the IDs in the root TOC's X-Curse-Project-ID / X-Wago-ID / X-WoWI-ID fields.

Useful flags:

  • -DryRun — preview changes without touching files or running git.
  • -NoPush — bump, commit, and tag locally without pushing.

Run from any working directory inside the repo:

.\.dev\release.ps1 "fix: NPCs catalog handles 0-id rows"

Vendored libraries (Libs/LibStub, Libs/LibEditMode) are NOT touched — the bump pattern is anchored to local LIB_MINOR exclusively, which only matches in LibCodex-1.0.lua.

Code conventions

  • Comments are documentation. Header comment on every file explains what the file does and why. Function-level comments explain non-obvious choices.
  • Anonymous frames for adapters. CreateFrame("Frame") with no name. Named frames trip ADDON_ACTION_FORBIDDEN in modern Retail when registering certain events.
  • Validate events before registering. C_EventUtils.IsEventValid is your friend. Never pcall-wrap a RegisterEvent call expecting to catch taint — the taint is set before the error fires.
  • No raw CreateFrame for UI. All UI in Steven's WoW addons goes through Cairn-Gui. LibCodex's only UI surface is the Log window, which is plain Blizzard frame primitives because Cairn isn't an embedded dep.
  • Sequential build numbers. LIB_MINOR is a small integer, +1 per release. Don't manually edit it; let release.ps1 do it.
  • String formatting. LIB_MINOR is a number, but format with %s (and tostring if needed) for safety. The old YYMMDDHHMM convention required this; the current sequential-int convention doesn't strictly need it but the habit is harmless.

Contributor License

By submitting a PR you agree your contribution is MIT-licensed. There's no separate CLA.

Clone this wiki locally