3.7 KiB
festbench-web
Web viewer for FestBench results — LLM benchmark datapoints
submitted by the festbench CLI, displayed in a fast, sortable table.
Stack: Laravel 12 · Livewire 4 + Volt · Flux UI (Pro) · FrankenPHP · MySQL/MariaDB
Features
- Home — every datapoint festbench captures (per-task rows across all runs), server-side sortable and filterable (suite, level, model, pass/fail, search).
- Run detail (
/runs/{run_id}) — full provenance: model identity, engine build, GPU, image digest, validators, suite versions, plus per-task metrics. - Ownership overlay — festbench-submitted data is immutable; owners can add
notes and toggle public/private visibility. Immutability is enforced in the
model (
BenchmarkRun::OVERLAY_FIELDS) and covered by tests. - My Runs — list your own runs, flip visibility, see pass counts.
festbench:import— import a local festbenchbenchmarks.db(SQLite):php artisan festbench:import results/benchmarks.db --user=you@example.com
Visibility rules
Runs are public by default (matching the CLI's redaction philosophy). Guests see public runs only; authenticated users additionally see their own private runs.
Local development
Requirements: frankenphp binary on PATH, Node 20+, Docker/Podman.
docker compose -f docker/develop.compose.yaml up -d # MariaDB on 127.0.0.1:3306
./dev.sh # frankenphp :8080 + vite HMR
Composer runs through frankenphp's embedded PHP (the host php.ini disables most extensions):
frankenphp php-cli $(pwd)/vendor/bin/composer install
frankenphp php-cli $(pwd)/vendor/bin/pest
frankenphp php-cli $(pwd)/vendor/bin/pint
frankenphp php-cli artisan <command>
The dev DB deliberately lives in a container, reached over TCP — the same
topology as production, where MariaDB runs on a nearby host. Point .env
DB_HOST/DB_PORT at wherever the DB actually lives.
Production (Coolify)
Build pack: Dockerfile. The image is a single FrankenPHP process — no nginx, no php-fpm, no supervisor.
Dockerfile— 3 stages: composer (Flux Pro auth as a BuildKit secret), node assets, finaldunglas/frankenphp:1.12-php8.5+install-php-extensions pdo_mysql intl zip opcache.docker/entrypoint.sh— retriesartisan migrate --force, thenartisan optimize, thenexec frankenphp run.docker/Caddyfile— listens on{$SERVER_NAME::8080}; Coolify maps its port to it. Static files served directly by Caddy, Laravel viaphp_server.
Secrets/env to set in Coolify:
| Variable | Notes |
|---|---|
APP_KEY |
generate once, keep stable |
DB_HOST / DB_PORT / DB_DATABASE / DB_USERNAME / DB_PASSWORD |
the nearby MariaDB |
SESSION_DRIVER=database, CACHE_STORE=database |
no redis needed |
Flux Pro authentication: add a secret named composer_auth
(file contents = the project's auth.json) and configure Coolify to build with
--secret id=composer_auth,src=… (or docker build --secret in CI). The
license key is never committed.
Health check: GET /up.
Submitting results (CLI integration — separate session)
The schema (benchmark_runs, run_results) mirrors festbench's SQLite exactly,
promotes the sortable columns, and stores the complete source row as JSON
(run_results.payload) so new festbench fields require no migration. The
authed ingestion endpoint for festbench --submit is future work; the
festbench:import command is the reference implementation of that mapping.
Deferred
scenario_runs(scenariobench's agentic metrics: turns, submissions, oracle verdicts) — intentionally not imported yet.- Worker mode (
FRANKENPHP_CONFIG="worker ...") — available as a one-env-var toggle when throughput demands it.