carlos / todomvc-bakeoff Public
feat: bakeoff record --note; Spinel load results
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5 files changed,
+20
−3
harness/apps.go+2 −1harness/cmd/bakeoff/main.go+1 −0harness/harness_test.go+9 −0harness/results.go+5 −1results/spinel.json+3 −1
diff --git a/harness/apps.go b/harness/apps.go| index 0e93631..c64b471 100644 |
| --- a/harness/apps.go |
| +++ b/harness/apps.go |
| @@ -43,4 +43,5 @@ func Host(slug string) string { |
| // load), and a used database can't be reset, so it was measured on a third |
| // fresh instance (2026-10-24). |
| var hostOverride = map[string]string{"spinel": "todo-spinel-3.bfj.oncarlos.com"} |
| -func URL(slug string) string { return "https://" + Host(slug) } |
| + |
| +func URL(slug string) string { return "https://" + Host(slug) } |
diff --git a/harness/cmd/bakeoff/main.go b/harness/cmd/bakeoff/main.go| index a523a56..4a11a06 100644 |
| --- a/harness/cmd/bakeoff/main.go |
| +++ b/harness/cmd/bakeoff/main.go |
| @@ -45,6 +45,7 @@ func main() { |
| fs.StringVar(&rec.Version, "version", "", "record: deployed version") |
| fs.StringVar(&rec.Stack, "stack", "", "record: one-line stack summary") |
| fs.StringVar(&rec.Source, "source", "", "record: source URL") |
| + fs.StringVar(&rec.Note, "note", "", "record: a note shown in the app's section (added once)") |
| recURL := fs.String("app-url", "", "record: live URL") |
| replies := fs.String("replies", "", "readability: comma-separated files, one scorer reply each") |
| fs.Parse(os.Args[2:]) |
diff --git a/harness/harness_test.go b/harness/harness_test.go| index 413ced9..3d93025 100644 |
| --- a/harness/harness_test.go |
| +++ b/harness/harness_test.go |
| @@ -322,3 +322,12 @@ func TestKneeStopsAtErrors(t *testing.T) { |
| t.Fatalf("got %+v: want slow-down 64 (last clean step), errors from 128, peak from clean steps only", k) |
| } |
| } |
| + |
| +func TestApplyRecordAppendsNoteOnce(t *testing.T) { |
| + r := AppResult{} |
| + ApplyRecord(&r, Record{Note: "exits under load"}) |
| + ApplyRecord(&r, Record{Note: "exits under load"}) |
| + if len(r.Notes) != 1 || r.Notes[0] != "exits under load" { |
| + t.Fatalf("got %q", r.Notes) |
| + } |
| +} |
diff --git a/harness/results.go b/harness/results.go| index 8e810ad..0d12ee8 100644 |
| --- a/harness/results.go |
| +++ b/harness/results.go |
| @@ -6,6 +6,7 @@ import ( |
| "io/fs" |
| "os" |
| "path/filepath" |
| + "slices" |
| ) |
| // ResultsDir is where results/<slug>.json live, relative to the repo root. |
| @@ -75,7 +76,7 @@ func Update(slug string, f func(*AppResult)) error { return UpdateIn(ResultsDir, |
| // Record is a partial update of an app's identity fields; empty fields |
| // leave the stored value alone. |
| -type Record struct{ Language, Status, URL, Version, Stack, Source string } |
| +type Record struct{ Language, Status, URL, Version, Stack, Source, Note string } |
| // ApplyRecord copies the non-empty fields of rec into r. |
| func ApplyRecord(r *AppResult, rec Record) { |
| @@ -90,4 +91,7 @@ func ApplyRecord(r *AppResult, rec Record) { |
| set(&r.Version, rec.Version) |
| set(&r.Stack, rec.Stack) |
| set(&r.Source, rec.Source) |
| + if rec.Note != "" && !slices.Contains(r.Notes, rec.Note) { |
| + r.Notes = append(r.Notes, rec.Note) |
| + } |
| } |
diff --git a/results/spinel.json b/results/spinel.json| index 2d26765..c7d65f8 100644 |
| --- a/results/spinel.json |
| +++ b/results/spinel.json |
| @@ -102,5 +102,7 @@ |
| "[correctness] `apps/spinel/patches/2-tep-bakeoff.patch:330` — URL decoding turns `%00` into a NUL inside a C string, which is then truncated when copied into Ruby. Posting `title=before%00after` silently stores `before`; editing with `title=%00after` deletes the todo. Preserve decoded string lengths so input cannot silently become a different title or action.", |
| "[spec] `apps/spinel/Makefile:130` — `clean-deps` deletes only the local SQLite and tep artifacts. The arm64 build still links precompiled OpenSSL, zlib and zstd libraries from the shared toolchain root (`scripts/arm64-cc:21`), so the next build does not compile every third-party library from scratch as required. Build those dependencies into the app’s own cache and include them in `clean-deps`." |
| ], |
| - "Notes": null |
| + "Notes": [ |
| + "Its server process exited (status 0) 10 times during the load test, and Carloku restarted it each time; the edge answered 502 in between." |
| + ] |
| } |