Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
b449009
codemod: crate skeleton — span-edit framework over emmylua_parser
keithharvey Jul 22, 2026
b3aaf8a
codemod: bracket-to-dot transform
keithharvey Jul 22, 2026
176b83b
codemod: rename-aliases transform
keithharvey Jul 22, 2026
93a9270
codemod: detach-bar-modules transform
keithharvey Jul 22, 2026
a9e2fc7
bar: emmylua type-check integration and editor wiring
keithharvey Jul 22, 2026
ed50303
bar: codemod recipes and the migrate::stylua-cleanup replay
keithharvey Jul 22, 2026
6fad424
migrate: stylua-cleanup skips the .styluaignore set
keithharvey Jul 22, 2026
ac2c2bf
lua: extract Sim/Units/Scripts docs in lua::library
keithharvey Jul 23, 2026
e4ffc56
llm: type-error triage pipeline — workers, prompts, rulebook
keithharvey Jul 22, 2026
e703f38
migrate: generation pipeline with the LLM capstone
keithharvey Jul 22, 2026
cc93715
migrate: pipeline codemod runs skip the .styluaignore set
keithharvey Jul 22, 2026
136e5ea
migrate: gh stack link resolves gh on the host
keithharvey Jul 22, 2026
792b46f
migrate: chain PRs move to same-repo heads (#8395–#8398)
keithharvey Jul 22, 2026
d278529
migrate: every pipeline branch hosts on the canonical repo
keithharvey Jul 22, 2026
a24724c
migrate: leaf PRs move to same-repo heads (#8401–#8405)
keithharvey Jul 22, 2026
670cbf4
migrate: PR edits omit --base when it already matches
keithharvey Jul 22, 2026
ca3dd11
migrate: Bulk Migrations doc link follows its same-repo PR (#8410)
keithharvey Jul 22, 2026
0ddda19
migrate: tracking-issue checklist follows the same-repo PRs
keithharvey Jul 22, 2026
38c97b8
migrate: the engine rename waits for spring-split — prefix branch dro…
keithharvey Jul 25, 2026
4fc415b
lua: clean before mkdir — clean_dir removes the dir itself
keithharvey Jul 25, 2026
3ec64f8
migrate: museum links point at the canonical repo; prereq description…
keithharvey Jul 25, 2026
75fdb57
migrate: unquoted apostrophe broke the prereq description
keithharvey Jul 25, 2026
fa28232
migrate: push implies update-prs — museum SHAs and branches move as o…
keithharvey Jul 25, 2026
d46024e
bar: restack recipe — root-first rebase of a stacked branch chain
keithharvey Jul 23, 2026
65f26c2
migrate: blame-ignore revs read off the branch, not the build loop
keithharvey Jul 29, 2026
bcc9893
skills: a type fix may change types and names, never behavior
keithharvey Jul 29, 2026
51c3c12
bar: pre-commit hook checks staged Lua instead of rewriting the tree
keithharvey Jul 29, 2026
5370151
skills: templated Lua is not Lua, and a set holds true
keithharvey Jul 29, 2026
5f45dcb
bar: pre-commit checks staged blobs, not the working tree
keithharvey Jul 29, 2026
900d75f
migrate: run stylua on the host, where git writes
keithharvey Jul 29, 2026
64d3fb4
remove noise: drop the bifurcated-types scratch doc, widen build ignores
keithharvey Jul 29, 2026
209136e
migrate: never push a branch that sits on its PR base
keithharvey Jul 29, 2026
aa3048a
migrate: tracking issue picks up the mission kit and the hook
keithharvey Jul 29, 2026
ea3c894
bar: drop restack, superseded by repos::restack
keithharvey Jul 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .claude/skills/type-fixes-preserve-behavior/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
name: type-fixes-preserve-behavior
description: A type-error fix may change types and names — never behavior. Use when clearing emmylua_check errors in the Beyond-All-Reason tree, or on any pass that renames locals, adopts a namespace (Spring.X -> BAR.X), or edits a file to satisfy the analyzer. It encodes the gui_chat.lua regression that shipped a widget that would not load.
---

# Type fixes preserve behavior

`emmylua_check` reports a *type* problem. The fix is a type annotation, a declaration, or a name — never a restructured function, never a dropped field, never an inlined recomputation. A green analyzer on a widget that no longer loads is worse than the error it replaced.

## The rule

**Every edit is reversible into "same program, better typed."** If you cannot state the change as a rename, an annotation, or a declaration, you are no longer fixing a type error.

## Renames are total or they are not done

Renaming a local means renaming *every* reader in the file, in one pass. Count the references before and after — they must match.

```lua
-- state table renamed I18N -> i18nStrings
local i18nStrings = state.i18nStrings -- renamed
...
local modeText = I18N.everyone -- NOT renamed: now a nil global
```

A partial rename is silent at load and crashes on the first draw. `grep -c` the old name after the edit; the answer is 0.

## A namespace prefix is not noise

`Spring.I18N(...)` -> `BAR.I18N(...)` is the migration. `BAR.I18N(...)` -> `I18N(...)` is a bug, unless the file declares `local I18N = BAR.I18N` — and if it does, that declaration must be in the same edit.

Bare `I18N(` reads as a local alias. Grep the file for the `local ... = BAR.` line before assuming one exists.

## Never drop a table field

A key removed from a constructor is a runtime nil at every read site. Two keys (`channelScopeAll`, `label`) went missing from a table while its readers stayed — both would have returned nil forever.

Diff the constructor key-set before and after. It only grows.

## Never introduce shadowing recomputation

Do not re-declare inside a closure what the enclosing function already computed. Fifteen such lines were inserted into a `glCreateList(function() ... end)`, recomputing `isCmd` *without* the `isLabel` branch the outer scope had — a behavior regression the analyzer is blind to.

If a closure needs a value, it already has it as an upvalue.

## Not every .lua file is Lua

`mapgenerator/mapinfo_template.lua` is a `${PLACEHOLDER}` template. A bare
`${START_POSITIONS}` inside a table is a parse error, and commenting it out
silences the analyzer while breaking every generated map — the substituted
block lands behind a `--`.

A file the analyzer cannot parse for a structural reason belongs in
`.emmyrc.json` `workspace.ignoreDir`, not in your edit set. Ask what the file
*is* before treating a diagnostic on it as a defect.

## Repair to the intent, not to whatever is in scope

`stompableDefs[udid] = v` — `v` leaked from a previous loop and was nil, so the
table was always empty. `ud` is in scope and makes the error go away; `true` is
what the code meant, because the only read is `if stompableDefs[unitDefID]`.

When a table is used as a set, the value is `true`. Look at the read sites
before choosing the write.

## Verify before committing

- `luajit -bl <file> >/dev/null` — syntax.
- `git diff <pre-pass-commit> -- <file>` — every changed line is a rename, an annotation, or a declaration. Line count does not grow.
- Load the game and read `infolog.txt` for `Failed to load:`. The analyzer cannot see a nil global that is only called at load.
7 changes: 7 additions & 0 deletions .emmyrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"workspace": {
"ignoreDir": [
".devtools"
]
}
}
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@ bar_debug_launcher
repos.local.conf
.env

# Build artifacts
target/
bar-mission-kit/vscode/server/bar-mission-kit

# Runtime / editor state
tasks/
.devtools/
.backups/
*.log
bar-lua-codemod/target/
.claude/settings.local.json
.claude/projects/
.claude/todos/
Expand Down
40 changes: 15 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# BAR Devtools

Local development environment for [Beyond All Reason](https://www.beyondallreason.info/) -- spins up **Teiserver** (lobby server), **PostgreSQL**, **SPADS** (autohost), and **bar-lobby** (game client) with a single command.

Everything server-side runs in Docker. The game client runs natively.
Shared development environment for [Beyond All Reason](https://www.beyondallreason.info/) — game code (Lua), engine (C++), lobby server (Elixir), and autohost (Perl) all from one repo.

## Quickstart (Linux)

Expand Down Expand Up @@ -164,6 +162,14 @@ just bar::lx-shell # interactive lx shell for package work
# (`lx add <pkg>`, `lx sync`, `lx install`, etc.)
```

> **⚠️ Merge conflicts with master?** The project ships deterministic code transforms (formatting, API renames, Spring split) that can be replayed onto any branch. Transform your branch first, then merge:
> ```bash
> just bar::migrate::stylua-cleanup # 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
> ```
> This is idempotent — safe to run multiple times. Includes `bar::fmt`, so no need to run it separately.

### Teiserver development

Tests run in a separate container with `MIX_ENV=test`, so they work whether or not `services::up` is running. The test database is independent from the dev database.
Expand Down Expand Up @@ -243,6 +249,7 @@ just services::down # stop everything
just services::logs teiserver # tail logs
just services::shell teiserver # open bash inside the running container
```
The SPADS bot account (`spadsbot` / `password`) is created automatically during Teiserver init.

## Requirements

Expand Down Expand Up @@ -306,32 +313,15 @@ This runs a read-only check of your system dependencies, environment, ports, rep

**Port 5432/5433 conflict with host PostgreSQL:**
Either stop your local PostgreSQL (`sudo systemctl stop postgresql`) or change the port:
**Port conflict with host PostgreSQL:**
```bash
BAR_POSTGRES_PORT=5434 just services::up
```

**Teiserver takes forever on first run:**
The initial database seeding includes generating fake data. Follow progress with:
```bash
just services::logs teiserver
```
**Teiserver takes forever on first run:** Initial DB seeding generates fake data. Follow progress with `just services::logs teiserver`.

**SPADS fails with "No Spring map/mod found":**
Game data download may have failed. Check logs and retry:
```bash
just services::logs spads
just services::down
just services::up spads
```
**SPADS "No Spring map/mod found":** Game data download may have failed. `just services::down && just services::up spads`.

**Docker permission denied:**
```bash
sudo usermod -aG docker $USER
# Then log out and back in
```
**Docker permission denied:** `sudo usermod -aG docker $USER` then log out and back in.

**Nuclear option -- start completely fresh:**
```bash
just services::reset
just services::up
```
**Nuclear option:** `just services::reset && just services::up`
Loading