feat(builder): repair existing templates, a weekly check that queues repairs, and eval
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>
This commit is contained in:
1 parent
00cc61aba2
commit
17f6477b71
12 files changed
+535
-20
No files matched your search
+20
-8
@@ -28,6 +28,9 @@ type buildResult struct {
|
||||
Summary string `json:"summary"`
|
||||
// What the builder diagnosed after each failed boot, the fix it made, and how that went
|
||||
Diagnoses []attempt `json:"diagnoses,omitempty"`
|
||||
// Repairs only: the existing template, and whether it already booted as it is (nothing to change)
|
||||
Repair bool `json:"repair,omitempty"`
|
||||
NoChange bool `json:"noChange,omitempty"`
|
||||
}
|
||||
|
||||
const defaultAgentImage = "www.gitea.gbreed.com/gbreed-public/gbr-node-agent:latest"
|
||||
@@ -159,16 +162,26 @@ func buildWithImage(o buildOptions, image string) (*buildResult, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// 3. Boot the draft the way nodes run it. A failure is investigated and diagnosed before the model
|
||||
// changes anything; a fix that changes nothing rules its cause out
|
||||
wantOutside := len(outsideDirs(report)) > 0
|
||||
// 3. Boot the draft the way nodes run it
|
||||
if err := bootAndFix(o, d, res, len(outsideDirs(report)) > 0); err != nil {
|
||||
return res, err
|
||||
}
|
||||
res.Summary = buildSummary(o, res)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// bootAndFix boots the template in games/<id> the way nodes run it, until it passes. A failure is
|
||||
// investigated and diagnosed before the model changes anything, and a fix that changes nothing rules its
|
||||
// cause out. Builds use it on a fresh draft; repairs on an existing template, where a first boot that
|
||||
// passes means there is nothing to repair. wantOutside also checks no files are lost on a restart.
|
||||
func bootAndFix(o buildOptions, d *drafter, res *buildResult, wantOutside bool) error {
|
||||
iv := newInvestigator(d.m, o.name, o.gamesDir, o.id, o.agentImage)
|
||||
lastFailure := ""
|
||||
for boot := 1; boot <= o.bootRounds; boot++ {
|
||||
fmt.Printf("[build] boot %d of the draft with the node-agent\n", boot)
|
||||
fmt.Printf("[build] boot %d of the template with the node-agent\n", boot)
|
||||
bootProblems, notes, err := bootCheck(o.gamesDir, o.id, o.agentImage, wantOutside)
|
||||
if err != nil {
|
||||
return res, err
|
||||
return err
|
||||
}
|
||||
failure := strings.Join(bootProblems, "\n")
|
||||
iv.outcome(len(bootProblems) == 0, lastFailure, failure)
|
||||
@@ -200,7 +213,7 @@ func buildWithImage(o buildOptions, image string) (*buildResult, error) {
|
||||
problems, err := d.refine(o.attempts, fixRequest(failure, diag))
|
||||
res.Rounds = d.rounds
|
||||
if err != nil {
|
||||
return res, err
|
||||
return err
|
||||
}
|
||||
if len(problems) > 0 {
|
||||
res.Problems = problems
|
||||
@@ -211,8 +224,7 @@ func buildWithImage(o buildOptions, image string) (*buildResult, error) {
|
||||
if res.Passed {
|
||||
res.Problems = nil
|
||||
}
|
||||
res.Summary = buildSummary(o, res)
|
||||
return res, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func isSteamCMDImage(image string) bool {
|
||||
|
||||
Reference in new issue
Block a user