The builder could only create games; nothing noticed when a live template
stopped working, and there was no way to tell whether a builder change made
it better or worse.
- repair -id ID: boots an existing template as nodes run it; if it fails,
the same investigation as for a draft runs and the model changes only what
the diagnosis says. The worker handles "repair" jobs (gameId from the
panel) and opens "fix(games): repair ..." on draft/<id>; a template that
boots as it is reports "nothing to repair" and opens no PR. The boot and
fix loop is now shared by builds and repairs.
- validate.yml runs weekly and boot-tests every game; failed games are sent
to the panel (X-GBR-Event: games_boot_failed) to queue repairs.
- eval -ids all: builds games that already have a template from scratch,
blind, and scores each draft against it (boots, same image and app, ports,
ready line, settings found) into eval.md and eval.json.
- research skips our own sites, so neither research nor eval reads our
templates back.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- research: searches SearXNG, reads the best pages through the reader, has the
model list the server's variants, then checks every Docker image and Steam
app it named for real before an admin sees it.
- build: first boot of the variant's images (skipping ones that need root),
a draft by the model, then the draft deployed with the node-agent's
BootTest like CI does; crashes, error lines and saves outside /server go
back to the model, three boots at most.
- worker: polls the panel's builder queue (outbound only), runs research or
build in a fresh clone, streams the output as the job log, and opens the
result as a pull request from the bot account.
- Dockerfile.builder, a workflow publishing gbr-builder:latest, and
BUILDER.md. Everything about where it runs comes from environment
variables; deployment files live outside this public repo.
draft now keeps its conversation in a drafter, so build can send boot
failures back to the same model session. The boot-test runner comment no
longer names its VM.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Validate took ~10 minutes, of which ~10 seconds was work: setup-go's
cache restore and save each waited ~4.7 minutes for a connect timeout,
because the runners' built-in cache server sits on a network job
containers can't reach. Turn off setup-go caching (three small modules
aren't worth it) and the game-test runner's cache server, so any cache
step skips at once.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only games whose folder changed are boot-tested (against the previous
main commit, or against main on branches; manual runs pick games). Each
one is deployed by the node-agent's real deploy code on a dedicated
game-test runner, in a network that can reach the internet but not the
LAN. Publishing to the panel runs only if they all booted.
- boottest-payload builds the DEPLOY_SERVER message the panel would send
- readyPattern/failPatterns in game.yaml; readyExample in test.yaml is
checked against the pattern during validation
- secrets in test.yaml come from CI; a game missing one is skipped
- Minecraft gets a ready pattern; Dragonwilds needs DRAGONWILDS_OWNER_ID
- RUNNER.md + scripts/runner: runner, isolated network, systemd unit
Also fixes newline values ("\n" separators/footers) that yaml.v3 wrote
as "" on import, which would have broken ARK and Dragonwilds config
files once synced, and adds a round-trip test for the importer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds `gbrgames export`, which builds the games_published payload from
every game.yaml, and a CI step that posts it to the panel webhook after
validation on main. Unlike the node-agent notify, a failed publish fails
the run so stale templates in the panel never go unnoticed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Public game templates for GBR Hosting, one games/<id>/game.yaml per game,
imported from the panel. A Go tool validates them against JSON Schemas and
checks for credentials, private addresses and consents that default to
accepted; CI runs it on every push.
Admin/RCON passwords are no longer shared defaults: they are blank with
x-generate so the panel creates one per server, and Palworld/ARK no longer
publish their RCON/REST ports.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>