BAR type-error cleanup: coordinated merge
PRs
Stacked — merge bottom-up. Each PR's own diff is scoped to its layer; stack navigation is on each PR.
Important: Do not run just bar::fmt-mig until fmt has merged. Running it earlier reformats the entire codebase on your branch (~200k lines).
Branch topology (6 leaves + 3 rollups)
Leaves — each targets master, mergeable independently
| Branch |
Command |
What it does |
| fmt |
stylua |
stylua across the entire codebase |
| mig-bracket |
bar-lua-codemod bracket-to-dot |
x["y"] → x.y, ["y"]= → y= via full_moon AST rewrite |
| mig-rename-aliases |
bar-lua-codemod rename-aliases |
deprecated Spring API aliases (GetMyTeamID → GetLocalTeamID, etc.) |
| mig-detach-bar-modules |
bar-lua-codemod detach-bar-modules |
Spring.{I18N,Utilities,Debug,Lava,GetModOptionsCopy} → BAR.{…} namespace |
| mig-integration-tests |
<hand curated> |
luaui/Tests + luaui/TestsExamples → return-table shape; dbg_test_runner reads hooks from the returned table |
| mig-busted-types |
<hand curated> |
vendored LuaCATS/busted + LuaCATS/luassert type annotations under types/ (pending lumen-oss/lux#953) |
Rollups — composite branches stacking the leaves and (for fmt-llm) the env + LLM layers
| Branch |
Notes |
| mig |
all leaves combined; deterministic rebuild from master |
| fmt-llm-source |
human-curated env layer (.emmyrc.json, types/* stubs, explicit type ignores, CI gate, manual fixes) |
| fmt-llm |
fmt-llm-source + one LLM triage commit |
Regenerated deterministically by just bar::fmt-mig-generate.
Commit-by-commit breakdown (12 commits)
Commits
| # |
Commit |
What it does |
| 1 |
00dbca64ed test(builders): rename Spring* builders to Engine*, own Engine/BAR wiring |
— |
| 2 |
0aa6075833 gen(stylua): initial formatting of entire codebase |
stylua across the entire codebase |
| 3 |
8488baa262 env: expose detached BAR modules to widget/gadget sandbox |
expose detached BAR modules to widget/gadget sandbox |
| 4 |
2f6fe55c1f gen(hand): integration tests return-table shape |
luaui/Tests + luaui/TestsExamples → return-table shape; dbg_test_runner reads hooks from the returned table |
| 5 |
76b48c7f0d gen(hand): inline luassert and busted LuaCATS types |
vendored LuaCATS/busted + LuaCATS/luassert type annotations under types/ (pending lumen-oss/lux#953) |
| 6 |
a677acb3df gen(bar_codemod): bracket-to-dot |
x["y"] → x.y, ["y"]= → y= via full_moon AST rewrite |
| 7 |
c9fdae6d2b gen(bar_codemod): rename-aliases |
deprecated Spring API aliases (GetMyTeamID → GetLocalTeamID, etc.) |
| 8 |
21541c7c59 gen(bar_codemod): detach-bar-modules |
Spring.{I18N,Utilities,Debug,Lava,GetModOptionsCopy} → BAR.{…} namespace |
| 9 |
45b9c4c167 env(llm): fmt-llm-source preparation for the LLM run |
.emmyrc.json globals, types/* stubs, busted mock, CI gate, manual fixes |
| 10 |
b6d7a65c47 env(llm): declare assertEqual, forward-decls, revert orphaned kikito i18n loader |
.emmyrc.json globals, types/* stubs, busted mock, CI gate, manual fixes |
| 11 |
1d0edf933e gen(llm): type-error triage (56 → 2 errors) |
parallel LLM workers applying SKILL.md fix recipes per file chunk |
| 12 |
01e45a5710 git-blame-ignore-revs: add transform commits |
register transform commits with git blame |
For contributors — after fmt merges, update your open branches:
just bar::fmt-mig # transform your branch first
git commit -am "apply code transforms" # squashed away when PR merges
git merge origin/master # conflicts are now real conflicts only
See the BAR-Devtools README for setup.
What this contains
- Automated script (
just bar::fmt-mig-generate) that rebuilds all branches deterministically from master
- Updated Recoil with new extractor + missing type decorators
- New PR gate: "Type Check" (
just bar::check)
- Replaced LuaLS/Sumneko with EmmyLua (~100x faster). Never use the Sumneko VS Code plugin.
New developer commands
just bar::check → type-check (EmmyLua)
just bar::fmt → format (StyLua)
just bar::test → unit + integration tests
just bar::lint → lint (luacheck)
just setup::editor → editor integration (language servers, extensions, settings)
just bar::fmt-mig → replay all transforms onto your branch
Generation pipeline: just bar::fmt-mig-generate --update-prs
- Fetch origin and rebase prereq branches onto master.
- Deterministic text transformations — ~99.9% mistake-free once I've validated a transform, basically free to re-run.
- Non-deterministic pass (LLM + rules to categorize type errors with relatively simple heuristics). This targets the ~106 type errors remaining after the globals are cleaned up, and crucially, most of them are actual bugs that'll improve code quality once fixed.
- Update PRs with output.
The upshot
- (1) is basically free and VERY reliable.
- (2) just requires we read it, test it, make any fixes, then either update our rules or merge ASAP.
Step 2 detail
Step 2 is the interesting part. I arrived at these rules by dispatching cheap subagents in parallel, then having an orchestrator agent refine the rules and re-run until the cheaper models covered all the edge cases. Because all of these fixes are well below the waterline for an Opus-calibre agent to explain to a GPT 5.4 Mini class of agent, this works. It gives us cheap, repeatable, and mostly idempotent execution on top of master.
Really effective for this sort of problem — in the past it would've been a month of hand editing and hating my life to get to zero, plus another month agonizing over which problems were worth a deterministic transform vs. just grinding through. =D
Closing thoughts
- I think this will let us actually use the formal type system to fuller effect (because people treat it as a real signal) and will greatly increase code quality in BAR over time.
- The more formal verification we wire in, the better our parsers and LLM agents get and the faster we can move on systemic problems.
- This makes the argument made in Game Economy more compelling (and I confess that's what led me here). The idea of moving subsystem by subsystem out of the engine and into Lua modules (that may or may not live in the game) makes waaaaaaay more sense when you have types enforced. Suddenly Lua can express its own design patterns under type checking — both where the engine has no stake (most of the game outside the sim) and where it does, by wrapping the engine API in typed abstractions instead of leaking it everywhere. cc @sprunk
Credits
- @rhys_vdw — thanks for the fantastic foundation in lua-doc-extractor and recoil-lua-library. Doing all of those decorators by hand must've been unbelievably labor intensive and there is not a snowball's chance in hell I would've even started this project unless that work already existed.
- @ThuLe — super enabled by BAR-Devtools existing, shout out for getting that ball rolling. SHARED CROSS REPO SCRIPTING LAYER!!!!!
BAR type-error cleanup: coordinated merge
PRs
Stacked — merge bottom-up. Each PR's own diff is scoped to its layer; stack navigation is on each PR.
zkbranchbarbarianbranchBranch topology (6 leaves + 3 rollups)
Leaves — each targets
master, mergeable independentlystyluabar-lua-codemod bracket-to-dotbar-lua-codemod rename-aliasesbar-lua-codemod detach-bar-modules<hand curated><hand curated>Rollups — composite branches stacking the leaves and (for
fmt-llm) the env + LLM layersmaster.emmyrc.json,types/*stubs, explicit type ignores, CI gate, manual fixes)fmt-llm-source+ one LLM triage commitRegenerated deterministically by
just bar::fmt-mig-generate.Commit-by-commit breakdown (12 commits)
Commits
00dbca64edtest(builders): rename Spring* builders to Engine*, own Engine/BAR wiring0aa6075833gen(stylua): initial formatting of entire codebase8488baa262env: expose detached BAR modules to widget/gadget sandbox2f6fe55c1fgen(hand): integration tests return-table shape76b48c7f0dgen(hand): inline luassert and busted LuaCATS typesa677acb3dfgen(bar_codemod): bracket-to-dotc9fdae6d2bgen(bar_codemod): rename-aliases21541c7c59gen(bar_codemod): detach-bar-modules45b9c4c167env(llm): fmt-llm-source preparation for the LLM runb6d7a65c47env(llm): declare assertEqual, forward-decls, revert orphaned kikito i18n loader1d0edf933egen(llm): type-error triage (56 → 2 errors)01e45a5710git-blame-ignore-revs: add transform commitsFor contributors — after
fmtmerges, update your open branches:See the BAR-Devtools README for setup.
What this contains
just bar::fmt-mig-generate) that rebuilds all branches deterministically frommasterjust bar::check)New developer commands
just bar::check→ type-check (EmmyLua)just bar::fmt→ format (StyLua)just bar::test→ unit + integration testsjust bar::lint→ lint (luacheck)just setup::editor→ editor integration (language servers, extensions, settings)just bar::fmt-mig→ replay all transforms onto your branchGeneration pipeline:
just bar::fmt-mig-generate --update-prsThe upshot
Step 2 detail
Step 2 is the interesting part. I arrived at these rules by dispatching cheap subagents in parallel, then having an orchestrator agent refine the rules and re-run until the cheaper models covered all the edge cases. Because all of these fixes are well below the waterline for an Opus-calibre agent to explain to a GPT 5.4 Mini class of agent, this works. It gives us cheap, repeatable, and mostly idempotent execution on top of master.
Really effective for this sort of problem — in the past it would've been a month of hand editing and hating my life to get to zero, plus another month agonizing over which problems were worth a deterministic transform vs. just grinding through. =D
Closing thoughts
Credits