Dockerfile: swap vtk for vtk-osmesa so off-screen rendering works headless
Michael Rabinovich+1: Cursor
545c818
The stock pyvista wheel pulls the stock vtk wheel from PyPI, which is
built with vtkXOpenGLRenderWindow. That render window class needs an
X server even in off_screen mode, so it segfaults the eval worker on
the Space's truly-headless container ("DISPLAY=" with no X11 socket).
The parent ProcessPoolExecutor sees the segfault as BrokenProcessPool
six minutes into the eval, which is exactly the failure mode the
first VTK submission hit.
vtk-osmesa is the same VTK build but compiled against Mesa OSMesa
(pure CPU software rasteriser, statically linked, no display server
required). It shares the `import vtk` namespace so pyvista picks it
up transparently. This is the canonical PyVista headless-Docker fix
(per the PyVista docs + the maintainers' own Docker images). The
wheel lives on Kitware's index, not PyPI proper.
Co-authored-by: Cursor <cursoragent@cursor.com>
Dockerfile: bump CADGENBENCH_SHA to b22a53c (ProcessPool spawn fix)
Pairs with cadgenbench 3fd213d (in-process VTK / PyVista renderer).
Dockerfile drops the playwright install + Chromium browser layer
(~200 MB), drops PLAYWRIGHT_BROWSERS_PATH, and adds the Mesa GL
runtime libs VTK needs for off-screen rendering on the Space's
cpu-upgrade tier (libgl1 was already there; libegl1, libegl-mesa0,
libglx-mesa0 are new). CADGENBENCH_SHA bumps to 3fd213d.
EVAL_WORKER_COUNT goes from "1" back to "4": the VTK renderer is
cheap enough that one ProcessPoolExecutor worker per fixture no
longer oversubscribes the host the way the old Chromium subprocess
did.
Co-authored-by: Cursor <cursoragent@cursor.com>
Dockerfile: bump CADGENBENCH_SHA to 056cfbb (invalid-candidate fast path)
Michael Rabinovich
ff674cc
Dockerfile: bump CADGENBENCH_SHA to 9bd02fb (lazy baseline import)
Michael Rabinovich
67fd44c
Picks up the cadgenbench fix that makes `cadgenbench --help` and
`cadgenbench evaluate` work in the eval-only install (no
`[baseline]` extra). Before this bump, the chunk-4 worker's
`python -m cadgenbench.cli evaluate <run_dir>` subprocess died
during argparse setup with `ModuleNotFoundError: No module named
'dotenv'`, flipping every submission to status=failed before any
work happened.
Bumping CADGENBENCH_SHA invalidates the cadgenbench layer in the
Dockerfile cache (Chromium layer + earlier layers stay cached),
so the rebuild is ~2-3 min not the ~5 min cold cycle.
submit: move handle_submit into its own module + add validation pipeline
Michael Rabinovich
0501689
Step 6 (E) chunk 2 of the async submit work. Lifts the UI-only stub
out of app.py into submit.py and grows it into the real cheap-sync
validation pipeline. Still no Hub writes and no eval kick-off; the
handler returns "would queue here" placeholder text. Async write +
worker thread land in later chunks.
Validation gates, in order:
1. Form: zip attached, agree-checkbox ticked.
2. Zip safety: valid zip, no absolute / parent-traversing entry
names, no symlinks (Python 3.12's extractall normalises unsafe
paths silently; we reject so submitters see a clear error).
3. meta.json schema: required keys, types, agree_to_publish is
literal true, notes within the 500-char cap. meta.json is the
source of truth for submitter / submission identity; the other
form fields are advisory for now and kept only so the gr.click
signature stays stable.
4. Fixture set: top-level dirs in the zip equal the fixture set
reported by cadgenbench.common.paths.data_inputs_di…
Dockerfile: bump CADGENBENCH_SHA to ed31274 (parallel evaluate)
Michael Rabinovich
91244c6
Picks up the eval orchestrator's switch to ProcessPoolExecutor across
fixtures (cadgenbench commit ed31274). On the Space's cpu-upgrade
tier (8 vCPU) this should give a near-linear speedup on real-GT-scale
runs; locally on the 5-stub set we saw ~2.4x going from --workers 1
to --workers 4 (1m13s -> 31s). The default worker count is
min(8, os.cpu_count()) so the Space gets the speedup without setting
any env var.
Verified locally: per-fixture cad_score outputs are byte-identical
between sequential and parallel runs (eval is per-fixture independent
+ deterministic).
Dockerfile: copy all Python modules, not just app.py
Michael Rabinovich
f26021f
Previous COPY hardcoded app.py only, which broke the moment app.py
imported sibling leaderboard.py: the new module never made it into the
image and the runtime hit ModuleNotFoundError. Switching to *.py picks
up every Python file in AI4Engineering/ (currently app.py +
leaderboard.py; submit.py lands next), so future module additions
don't need a Dockerfile bump.
Dockerfile: bump CADGENBENCH_SHA to 1747493 (Hub-only fixtures)
Michael Rabinovich
d8207be
cadgenbench main now resolves fixtures exclusively from the Hub
dataset repos: the wheel-bundled _data/ and the in-repo data/ folder
are both gone (commit 1747493). The Space's Settings variables
CADGENBENCH_DATA_REPO and CADGENBENCH_DATA_GT_REPO are already set
(chunk 5), and HF_TOKEN is the existing Space secret, so this rebuild
verifies the end-to-end Hub-only path inside the production runtime.
Dockerfile: bump CADGENBENCH_SHA to 36ac6b4 (Hub-aware paths.py)
Michael Rabinovich
aa1e886
cadgenbench commit 36ac6b4 adds the Hub-dataset resolution branch to
common/paths.py (snapshot_download from $CADGENBENCH_DATA_REPO /
$CADGENBENCH_DATA_GT_REPO when set, falling back to the existing
local/bundled chain otherwise).
The Space's Settings variables CADGENBENCH_DATA_REPO and
CADGENBENCH_DATA_GT_REPO are set in lockstep with this bump
(HuggingAI4Engineering/cadgenbench-data and
HuggingAI4Engineering/cadgenbench-data-gt respectively), so the
runtime now resolves fixtures from the Hub dataset repos instead of
the wheel-bundled fallback.
GT dataset is private; the existing HF_TOKEN Space secret provides
read access (already set during Step 5 for the submissions dataset).
No new secret required.
scrub for the cadgenbench Public flip: drop NIST + remove build secret
Michael Rabinovich+1: Cursor
a80542f
Three changes bundled together so the next Space rebuild lands in the
post-NIST, post-secret end state in one go:
- legacy/nist_*_comparison_3d.html (9 MB each) deleted; these were old
NIST-stub comparison artifacts already labelled legacy, kept around
for visual reference only. Regenerate from the real benchmark
dataset post-launch if useful.
- results.jsonl emptied. The three baseline seed rows it held were
scheduled for pre-launch deletion anyway (per space-setup/migration.md
Phase D), and the same rows were just rewritten on the Hub side of
cadgenbench-submissions to drop the NIST per-fixture entries. The
Space's leaderboard read path uses results.jsonl only as a Hub-fetch
fallback; an empty file just produces an empty table on fallback,
which is the right behaviour for a development Space.
- Dockerfile: dropped the `RUN --mount=type=secret,id=GH_PAT` line and
switched the cadgenbench install URL from the authenticated
`git+https://michaelr27:$(cat /run/secre…
Dockerfile: use actual GH username in classic-PAT URL, not x-access-token
Michael Rabinovich+1: Cursor
12c3a54
Previous push tried 'https://x-access-token:TOKEN@github.com/...'
(GitHub-Actions placeholder convention). GitHub rejected it:
'Invalid username or token. Password authentication is not supported
for Git operations.' Classic PATs over HTTPS Basic Auth need a real
GitHub username as the user half of the URL, even though the username
is ignored once GitHub validates the PAT as the credential.
Switching to 'https://michaelr27:TOKEN@github.com/...' which is the
form GitHub's docs themselves recommend. Hardcoding 'michaelr27' is
acceptable temporary debt: this whole URL goes away when we either
swap GH_PAT for the read-only deploy key (URL becomes git+ssh://) or
when huggingface/cadgenbench flips Public (URL drops auth entirely).
Co-authored-by: Cursor <cursoragent@cursor.com>
Dockerfile: use x-access-token:TOKEN URL form for classic PAT
Michael Rabinovich+1: Cursor
818fd28
Previous URL form 'https://$TOKEN@github.com/...' relied on GitHub's
special-case where fine-grained PATs are accepted as a single-value
username. Classic PATs don't get that special-casing: git parses
'TOKEN@github.com' as username=TOKEN with no password and then prompts
for one, which fails in the non-interactive Docker build with
'No such device or address'.
Switching to 'https://x-access-token:$TOKEN@github.com/...' (GitHub
Actions convention) is the standard explicit-Basic-Auth form and works
uniformly for classic + fine-grained PATs, so the URL stays the same
when we eventually swap GH_PAT for a deploy key (the URL changes to
ssh+git anyway in that case).
Co-authored-by: Cursor <cursoragent@cursor.com>
Dockerfile: point cadgenbench install at huggingface/cadgenbench
Michael Rabinovich+1: Cursor
aa263ac
Switch source from MichaelRabinovich/LeForge to huggingface/cadgenbench
now that the latter has the full history (181 commits, see
space-setup/migration.md Phase C). The pinned commit (d7e0468) exists
on both remotes so this is URL-only; cadgenbench version bumps are a
separate concern handled by ARG CADGENBENCH_SHA.
The GH_PAT secret on the Space is being rotated in lockstep from a
fine-grained PAT scoped to LeForge to a classic PAT with 'repo' scope.
Classic is broader than ideal (gives the PAT read on any private repo
the issuing user can see, not just huggingface/cadgenbench) but it's
the only self-serve option: the huggingface GH org has fine-grained
PATs disabled, and the cadgenbench space-setup user isn't an admin on
the org repo so can't add a per-repo deploy key either. Tracked as
follow-up debt to swap for a deploy key once admin permissions land
(asked Leandro).
Co-authored-by: Cursor <cursoragent@cursor.com>
step 6 (A2): switch space to sdk:docker, install cadgenbench from private LeForge via GH_PAT build secret
Michael Rabinovich+1: Cursor
900c7c1
The HF Spaces Gradio SDK can't substitute Space secrets into requirements.txt
at build time (only at runtime), and embedding the literal token in
requirements.txt is a no-go (would land in git history of the Space).
Switching to sdk: docker collapses two open Step 6 sub-decisions into one
small change:
(A2) private GitHub dep install -- handled by `RUN --mount=type=secret`
in the Dockerfile; the PAT (Space secret GH_PAT) is mounted at
/run/secrets/GH_PAT for that one RUN and never lands in any layer.
(D) Playwright/Chromium for STEP -> PNG rendering -- handled by
`playwright install --with-deps chromium` in the same Dockerfile.
Layer ordering optimises rebuild speed: OS deps + requirements.txt deps
+ Chromium come early (stable), cadgenbench from git comes mid (bumps
on each commit), app.py + results.jsonl come last (changes most).
Front-matter: sdk: gradio -> sdk: docker, drop sdk_version + app_file
(Docker SDK uses Dockerfile CMD), add app_port: 7860. .…