Commit History
-
submit: raise concurrency_limit to 16 so submissions run in parallel
Michael Rabinovich +1: Cursorhandle_submit blocks for the whole eval (dispatch + poll). With Gradio's default concurrency of 1, submissions serialized and a single stuck eval froze the Submit button for everyone. Allow up to 16 concurrent. Co-authored-by: Cursor <cursoragent@cursor.com>770de2c
-
Drop mesh-file submissions; STEP-only candidates
Michael Rabinovich +1: CursorRemove the triangle-mesh submission path (and its OpenSCAD framing) from the submit gate, UI copy, and metrics page; candidates are STEP/BREP only. Pin the eval image's cadgenbench to a47c951. Co-authored-by: Cursor <cursoragent@cursor.com>04e4262
-
Accept mesh candidates in leaderboard submissions
Michael Rabinovich0f9004d
-
Gallery: show GT "answer-key" edit-diff for editing fixtures
Michael Rabinovich +1: CursorThe ground-truth row now renders the blue edit-diff turntable (the correct change vs the input) for editing fixtures instead of a plain GT turntable, so the reference reads the same way as the candidate red/amber diff in the same column. Adds a gt_diff_resolver pointing at the one-time GT-dataset webp (<fixture>/renders/edit_diff_gt.webp, via the existing /gt proxy) and updates the compare modal caption/legend. tools/generate_gt_edit_diff.py renders/uploads those webps for the 32 editing fixtures (one-time, per data revision). Co-authored-by: Cursor <cursoragent@cursor.com>49e27be -
Add missing header logo PNG and tighten title spacing
Michael Rabinovich +1: CursorThe deployed app.py already references assets/logo.png (via _logo_data_uri), but the binary was never committed, so the Space build crashed with FileNotFoundError. Commit the transparent, content-cropped wordmark and snug up the title block (smaller logo height + collapsed flex gap) so it sits directly above the tabs. Co-authored-by: Cursor <cursoragent@cursor.com>ae4b377 -
Update leaderboard Space URL after rename to CADGenBench
Michael Rabinovich +1: CursorThe Space moved from HuggingAI4Engineering/cadgenbench-leaderboard to HuggingAI4Engineering/CADGenBench; point the hardcoded references at the new URL. Co-authored-by: Cursor <cursoragent@cursor.com>7922a9c -
Rename fixture-named result keys to sample-named keys
Michael Rabinovich +1: CursorRead/write per_sample_scores, per_sample_breakdown, n_samples, per_sample_results across submit/gallery/admin and tools. Also link the canonical submission docs from the Submit tab. Co-authored-by: Cursor <cursoragent@cursor.com>be6fa3d -
feat(admin): hide the entire admin panel from non-admins
Michael Rabinovich +1: CursorThe Admin tab previously showed everyone the table + (disabled) controls. Actions were already gated server-side (is_admin re-check in every handler), but the UI and the read-only table were visible to all, which looked unprofessional and streamed submission rows to non-admins. Wrap all admin UI in a Column that stays hidden unless the logged-in user is in CADGENBENCH_ADMINS; non-admins (and logged-out visitors) now see only the login/logout button and a status line. The table starts empty and the load/refresh/timer handlers return an empty frame for non-admins, so no submission data is sent behind the hidden panel. Server-side gating on the mutating handlers is unchanged (defense in depth). Co-authored-by: Cursor <cursoragent@cursor.com>335cdfa
-
leaderboard: reclaim Gradio chrome + responsive mobile gallery
Michael Rabinovich +1: Cursor- Hide the Gradio footer and tighten outer padding (the unused space between Refresh and the footer) and grow the gallery box to use it, so more rows fit in one viewport. - Mobile: the 4-sample matrix no longer clips. On narrow screens the table scrolls horizontally (swipe), the rank column is dropped, the Submission column is frozen to the left, and the score breakdown is hidden -- so the renders are actually visible and you can tell which model each belongs to, with the header + GT row still pinned. Co-authored-by: Cursor <cursoragent@cursor.com>2ec97dd -
leaderboard: squeeze header/caption, grow gallery to show more rows
Michael Rabinovich +1: Cursor- Drop the gallery caption and collapse the Gradio title to a single compact line, and cut the gallery body padding (removes the dead gap between the last row and the Refresh button). - With that freed vertical space, lower the box chrome reserve and raise the cap so the gallery shows as many rows as fit in one viewport while staying a single scroll (harness-verified across screen sizes). Co-authored-by: Cursor <cursoragent@cursor.com>882faa0 -
leaderboard: add Metrics tab/page + report deep-links
Michael Rabinovich +1: CursorNew self-contained Metrics explainer (metrics_page.py) served at /metrics and embedded in a Metrics tab: validity gate, the three axes, editing renormalization, with formulas and the interface mating-group illustration (vendored under assets/metrics/ via LFS, served by the /metrics-assets route). Submit's merge path passes the submission name and the /metrics base URL to the report generator so hosted reports title themselves and their metric pills deep-link to the explainer. Co-authored-by: Cursor <cursoragent@cursor.com>28e0081 -
fix(oauth): use real HF OAuth on this Docker Space instead of mock login
Michael Rabinovich +1: CursorGradio's get_space() only returns truthy when SYSTEM=="spaces", which HF sets on Gradio-SDK Spaces but not on sdk: docker Spaces like this one. Without it, mount_gradio_app wired up Gradio's MOCK OAuth routes: they never contact hf.co and log every visitor in as the container token's owner (our HF_TOKEN account). Because that account is in CADGENBENCH_ADMINS, this leaked the "Logout (michaelr27)" identity to all visitors and granted admin to anyone who completed the (mock) login. Set SYSTEM=spaces when running on a Space (SPACE_ID present) so the real hf_oauth: true flow runs; left unset locally so the local mock login still works for dev. Co-authored-by: Cursor <cursoragent@cursor.com>f17ac64 -
leaderboard: make the gallery the single scroller
Michael Rabinovich +1: CursorSizing the iframe to a fixed 80vh left two scrollbars (the iframe body and the outer Gradio page), which was confusing. Now fitIframe measures the available height from the iframe's own top down to the bottom of the viewport (via the same-origin parent) and sizes the iframe to min(content, available), reserving room for the Refresh button. Short content shrinks the iframe (nothing scrolls); tall content fills the viewport so only the iframe body scrolls and the sticky header + GT row stay locked. The outer page no longer needs its own scrollbar. Co-authored-by: Cursor <cursoragent@cursor.com>5eaf6b8 -
leaderboard: lock GT row via in-iframe scroll capped by max-height
Michael Rabinovich +1: CursorThe previous attempt capped the gallery scroll box from JS using window.parent.innerHeight, but inside HF's nested iframes that is not the browser viewport, so the cap came out huge: the box never scrolled, the iframe grew to full height, and the page scrolled the GT row away. Instead, scroll inside the iframe itself (the column header + GT row are sticky against the iframe viewport, which reliably works) and cap the iframe with `max-height: 80vh` in app.py, where vh is the Gradio doc viewport. fitIframe still shrinks the iframe to content for a compact page when there are few rows; once content exceeds the cap the iframe body scrolls and the GT row stays pinned. Drops the unreliable JS cap and the parent-aware modal positioning (back to plain fixed centering). Co-authored-by: Cursor <cursoragent@cursor.com>a0462d9
-
leaderboard: fixed 4-sample gallery, auto-size iframe, center modal
Michael Rabinovich +1: CursorReplace the gallery's interactive fixture picker with a fixed comparison sheet: two generation + two editing samples, one Medium and one Hard per task. Difficulty is chosen once from the Claude Opus 4.8 baseline's per-sample CAD scores (median = Medium, 20th percentile = Hard) and frozen into FIXED_FIXTURES; the GUI no longer recomputes it as the leaderboard evolves, trading a moving ground truth for a simple, stable interface. Adds tools/pick_gallery_fixtures.py to regenerate the constant. Size the gallery iframe to its content (no more 90vh fixed box / nested scrollbar) and pin the compare modal to the visible part of the iframe so it opens centered in view instead of far below the fold. Co-authored-by: Cursor <cursoragent@cursor.com>08eae45
-
leaderboard: admin rescore (selected + all) reusing the eval pipeline
Michael Rabinovich +1: CursorAdd a maintainer-only rescore that re-evaluates submissions against the current ground truth/data, reusing the submit worker end to end: each target row is reset to the pending regime (scores cleared, submitted_at preserved) and _spawn_worker is re-dispatched, which re-renders the gallery, regenerates reports/<id>.{html,json}, and recomputes the score. - rescore_rows(ids): selected rows; LookupError on unknown id before any write. rescore_all(): every row with a stored zip that isn't pending (skips legacy zip-less seed rows + in-flight evals). - Bulk dispatch is staggered on a background thread so a board-wide rescore doesn't fire N run_job calls at once; fully re-runnable, so an interrupted rescore converges on a retry. - UI in the Admin tab: "Rescore selected" behind a confirm checkbox and "Rescore ALL" behind a type-to-confirm phrase, both admin-gated with a server-side re-check and disarmed after firing / on load. Co-authored-by: Cursor <cursoragent@cursor.com>2893b22 -
leaderboard: rename tabs, relabel fixtures as samples, inline gallery row stats
Michael Rabinovich +1: Cursor- Rename the visual "Gallery" tab to "Leaderboard" and the table tab to "Detailed View" (order unchanged); update the smoke test accordingly. - Replace user-facing "fixture" wording with "sample" across the gallery, task browser, submit instructions, and submitter status/error messages. Internal data keys, routes, CSS, and identifiers are unchanged. - Drop the gallery's "more numbers" expander: surface Generation/Editing inline under the aggregate score and move Download ZIP under the name. - Link each gallery submission title to its hosted report (same /reports/<id>.html the Detailed View table uses); drop the date line. Co-authored-by: Cursor <cursoragent@cursor.com>461547b -
leaderboard: serve GT report assets via proxy; link them in hosted report
Michael Rabinovich +1: CursorAdd a /gt/{fixture}/{relpath} proxy route that streams the private GT view PNGs + PDF (token-holding), and pass gt_base_url/input_base_url to generate_html in the merge path so the hosted report links GT/input/overlay (lazy) instead of base64-inlining them. Bump CADGENBENCH_SHA to 25943a0. Co-authored-by: Cursor <cursoragent@cursor.com>5140b0a -
leaderboard: serve renders from the public bucket, not the dataset proxy
Michael Rabinovich +1: CursorCandidate renders (turntables + edit-diff WebP) now live in the public HF Storage Bucket under renders/<id>/, uploaded once by the eval job. The gallery grid and the hosted report reference them by anonymous bucket URL, so the Space is out of the render read path and the binary renders stop bloating the submissions dataset / its commit queue. - leaderboard: HF_RENDER_BUCKET + render URL/path/prefix helpers. - app: render resolvers return public bucket URLs; the two render proxy routes + fetchers are retired. Only the private GT render keeps its token-held proxy. - submit: merge passes render_base_url to generate_html and commits report-only; dispatched job gets CADGENBENCH_RENDER_BUCKET/HF_ENDPOINT. - admin: delete also purges the bucket renders/<id>/ prefix (previously orphaned). - Dockerfile: bump cadgenbench pin to 3d49822 (render_base_url support). Co-authored-by: Cursor <cursoragent@cursor.com>d2161b1
-
leaderboard: show edit-diff turntable in gallery grid for editing fixtures
Michael Rabinovich +1: CursorThe gallery grid tile for an editing fixture now serves the ghost edit-diff WebP (renders/<id>/<fixture>/edit_diff.webp) instead of the plain candidate turntable, so a small edit is legible at a glance. Generation tiles, the GT column, and the cell-click modal are unchanged (the modal keeps the plain aligned output via img; the grid uses a new gridImg). - gallery: per-cell gridImg + gridRenderFor hook; build/render take a diff_resolver. - app: _fetch_render_diff + /render-diff proxy route + resolver. A miss 404s to the dashed cell (no fallback to rotating.webp). Co-authored-by: Cursor <cursoragent@cursor.com>e611f15 -
leaderboard: move Tasks tab after Leaderboard
Michael Rabinovich +1: CursorCo-authored-by: Cursor <cursoragent@cursor.com>31854f7 -
leaderboard: add Tasks tab to browse benchmark fixtures
Michael Rabinovich +1: CursorA read-only task browser that mirrors the per-submission report's summary-table -> detail-card navigation (j/k, Esc, Prev/Next, deep-linkable) but shows only the prompt + input (drawing for generation, starting-shape renders for editing) with no scores or ground truth. Fixtures come from each <fixture>/description.yaml in the inputs dataset; input images are proxied through the Space's read token via /task-input and lazy-loaded. Co-authored-by: Cursor <cursoragent@cursor.com>f4924d6 -
Serve rotating WebP turntables + GT generator
Michael Rabinovich +1: CursorPoint the gallery and proxy routes at rotating.webp (submissions and GT), publish the full per-fixture renders folder, and add a reusable one-time GT turntable generator that renders from the cached GT mesh. Co-authored-by: Cursor <cursoragent@cursor.com>c1cb5e4 -
leaderboard: open reports in new tab
Michael RabinovichNow that the Space is public, link completed submissions directly to their proxied HTML reports instead of inlining large report payloads through the row-click detail panel.5fb3ebc -
gallery: searchable fixture picker, URL-persisted picks, cached render proxies
Michael Rabinovich +1: CursorReplace the always-open fixture chip grid with the compact reference UI: current picks as removable pills + an "Add fixture" button opening a searchable, grouped (Generation/Editing) dropdown, capped at 3 with a "remove one to add another" note. Persist the 3 picks in ?fixtures= so shared links reproduce the view; URL read/replaceState are try/catch guarded for sandboxed iframes. Drop the external Google Fonts @import for system font stacks so the page never errors in a sandboxed frame. Serve thumbnails as lazy-loaded, hard-cached /render and /gt-render proxy URLs (loading="lazy" + decoding="async" + CSS-constrained width) instead of base64-inlining every tile, so only the ~33 visible thumbnails load and fixture swaps / repeat visits hit cache. Requires the Space to be public. Fix a stale test expecting the old 6-tuple _admin_delete signature. Co-authored-by: Cursor <cursoragent@cursor.com>4a9408a -
admin: stop pending jobs before delete
Michael RabinovichAdd an admin action that cancels matching in-flight HF Jobs before deleting submissions, and keep the admin table refreshed so pending rows stay visible.c4b5d70 -
submit: retry Hub commits on 429/5xx + persistent status panel
Michael Rabinovich +1: CursorWrap every Space-side commit (zip upload, results.jsonl RMW, report + gallery uploads, shard cleanup) in a backoff-with-jitter retry that honors Retry-After, so a rate-limited submissions repo delays rather than fails a submit. Make handle_submit a generator streaming a durable status panel (validating -> uploading -> queued, or the rejection reason) instead of relying on transient toasts. Co-authored-by: Cursor <cursoragent@cursor.com>b224eee
-
submit: allow missing fixture outputs
Michael Rabinovichdc8ff2a -
gallery: refresh after admin changes
Michael Rabinovichdaae24c -
admin: refresh table on auth load
Michael Rabinovich02751ff
-
gallery: stop negative-caching render fetches
Michael Rabinovich +1: CursorRenders land after boot (a submission completes, or an existing row is backfilled), so lru_cache was pinning boot-time 404s and keeping thumbnails dashed until the next restart. Drop the memoization on the render byte-fetchers; hf_hub_download keeps its own per-revision disk cache, so re-fetching an unchanged thumbnail stays cheap. Also picks up the 3 baseline rows' just-backfilled renders on this redeploy. Co-authored-by: Cursor <cursoragent@cursor.com>8eb8954 -
add visual Gallery tab (top-10 verified, sticky GT, fixture picker)
Michael Rabinovich +1: CursorVisual-first leaderboard as a new default tab. Self-contained HTML (gallery.py) inlined into an iframe srcdoc with base64 thumbnails, so it works on the private Space where HF's edge 404s in-browser custom-route fetches (same constraint the report viewer's srcdoc path already handles). Top-10 verified only, teal sticky ground-truth row, 3-fixture picker (drop-oldest, global re-render), dashed cell for invalid/missing fixtures, per-row generation/editing/validity expander, and a GT-vs-output compare modal per thumbnail. Existing Leaderboard / Submit / About / Admin tabs unchanged. Co-authored-by: Cursor <cursoragent@cursor.com>01d67e9 -
leaderboard: drop silent fallback; boot resilient on Hub read failure
Michael RabinovichThe leaderboard previously fell back to a bundled/local results.jsonl on any Hub error, which let an under-scoped Space HF_TOKEN silently serve stale baked-in rows that looked up-to-date. Remove the fallback: the live results.jsonl is the single source of truth and any read failure raises LeaderboardDataError. To stay robust rather than crash the Space at construction time, app.py wraps the readers (_safe_load_split / _safe_load_admin): a failed read yields empty, correctly-shaped tables plus a loud, persistent banner and a gr.Warning toast on refresh / Timer tick, and is logged via logger.exception. No stale or cached data is ever shown in place of a failed read. Also git rm the bundled results.jsonl and add regression tests for the no-fallback contract and the boot-resilience wrappers.a662bfa
-
license: add apache-2.0 header to space modules
Michael Rabinovichb048bc2 -
app: use a colon in the submit-tab system-agnostic note
Michael Rabinovich8a21dae -
app: default the admin validation_method to manual
Michael Rabinovichmanual (we re-ran the agent ourselves) is the common case for the maintainer team, so preselect it on the promote radio.46e3a72 -
app: credit Mecado as CAD data source in About tab
Michael Rabinovich +1: CursorCo-authored-by: Cursor <cursoragent@cursor.com>0c44305 -
app: admin tab as a multi-select table with delete
Michael Rabinovichreplaces the single-row dropdown with an editable table: one row per submission, a leading select checkbox the only editable column, the rest read-only context. promote, demote and delete now act on every ticked row at once. promote applies the chosen validation_method to the whole selection. delete sits in a danger-zone accordion behind a confirm checkbox that arms the button, and clears companion artifacts plus the row. a live count line reports how many rows are selected.58ce093 -
app: add admin tab for promoting and demoting rows
Michael Rabinovichnew admin tab with a login button, a submission dropdown, a validation_method radio, and mark validated / mark unvalidated buttons. the controls are gated on membership in the CADGENBENCH_ADMINS set via a blocks.load handler, mirroring the submit button's login gate; the promote and demote handlers re-check admin rights server-side and refresh the dropdown plus both leaderboard tables after a write.47c86cf
-
leaderboard: format submitted_at as `YYYY-MM-DD HH:MM UTC`; lock tables read-only
Michael RabinovichTable cells were editable (gradio_leaderboard inherits gr.Dataframe's interactive default); add interactive=False to both Validated and Unvalidated widgets so cell contents aren't accidentally typed over. submitted_at column rendered as raw ISO-8601 ("2026-05-28T07:13:16Z"); apply the same _fmt_timestamp helper the detail panel already uses so the table reads as "2026-05-28 07:13 UTC". Helper moved into leaderboard.py (formatter module) and re-imported by app.py.c4e21b3 -
submit: serialize cadgenbench evaluate to dodge cpu-upgrade contention
Michael RabinovichEVAL_WORKER_COUNT goes from "8" to "1". Removes the debug /debug/render-bench route added in the previous commit. Why: on the Space's cpu-upgrade tier today, a single headless- Chromium render takes ~7s; five in parallel collapse the host and each individual render blows past its 120s subprocess timeout. Same renderer, same fixtures, same Playwright version run on a laptop in ~5s per render with no slowdown under 5-way parallelism. The slow path is HF's shared host, not our renderer. Sequential eval (one fixture at a time, one render at a time) gives each Chromium the whole box. Five fixtures finish in ~30-60s wall time, far under the 15-minute outer EVAL_TIMEOUT_SECONDS budget. Tradeoff: total eval wall time grows linearly with fixture count. For today's five fixtures that's a few seconds slower than the healthy-host parallel case, and a huge cliff better than a failed eval. For the 100-fixture launch this becomes ~10 minutes per submission, which is the limit of this approach: a r…6e3ab50 -
debug: add /debug/render-bench route for one-shot Chromium timing
Michael RabinovichRead-only FastAPI endpoint mounted on the Space's parent app. Sequentially times `render_step` against each fixture's input.step in cadgenbench-data and returns per-fixture seconds + view count. Used to compare per-render cost on the Space's container vs a local reference when eval has been timing out at the 120s render_step ceiling but nothing on the render path changed in our code. Curl-fetchable under Bearer auth (the Space is private): curl -H "Authorization: Bearer $HF_TOKEN" \ https://<space>.hf.space/debug/render-bench Not user-visible (no UI), no side effects, no row writes. Safe to remove once the diagnosis lands.37e45d8 -
submit+app: gate Submit on HF OAuth; populate hf_username from profile
Michael RabinovichBundle 1+2 C10. Login-required submit shaped per the bundle spec. submit.py: - `handle_submit` grows a `profile: gr.OAuthProfile | None` arg. Gradio dependency-injects the visitor's profile based on the signature. None -> immediate `gr.Error("Please log in via the HF button before submitting.")` so a UI mishap can't write an anonymous row. - `_build_pending_row` grows an `hf_username=None` kwarg. `handle_submit` passes `profile.username` through so the row carries the canonical HF identity (not a free-text claim in meta.json's submitter_name). app.py: - New `gr.LoginButton()` in the Submit tab above the zip dropzone. - Submit button starts `interactive=False`; new `_enable_submit_when_logged_in(profile)` reads the visitor's OAuth profile via `blocks.load` and flips the button on / off per page load. Server-side gate in `handle_submit` mirrors this so a logged-out user who somehow bypasses the disabled-button UI still gets rejected. requirements.txt: - `gradio…c87b253 -
submit+app: toast-based feedback (validating / queued / refreshed)
Michael RabinovichBundle 1+2 C9. Replaces the static markdown reply on the Submit tab with gr.Info / gr.Error toasts, and adds a refresh toast on the manual Refresh button (the Timer auto-refresh stays silent - a toast every 10s would be noise). submit.py: - handle_submit no longer returns a markdown string. It side- effects: gr.Info("Validating submission...") at the top of the validation stage, gr.Info("Submission <id> queued ...") after the row + zip are on the Hub and the worker has been spawned. Every rejection path raises gr.Error so the user gets a red toast and the handler aborts; the outer try/finally still runs cleanup. Internal _ValidationError + _HubWriteError sentinels preserved. - _validate_form returns a plain message (no `**Error:**` markdown wrap; the caller wraps into gr.Error). - All four rejection paths covered: 1. Form (no zip attached). 2. Validation gate (extract / meta / fixtures / steps). 3. Dedup gate (sha256 match on existing row). 4. Hub write…6facf47
-
leaderboard+app: combined CSV download with validation_status discriminator
Michael RabinovichBundle 1+2 C8. One file, both tiers, downloaded via `gr.DownloadButton` next to the existing Refresh button. leaderboard.py: - New `CSV_COLUMNS` constant (wider than the on-screen table: raw aggregate_score / validity_rate, plus provenance fields like submission_sha256 + cadgenbench_data_revision + notes + failure_reason). `validation_status` is the discriminator that lets a reader grep the file for one tier or the other. - New `build_combined_csv()` reads the same rows the leaderboard reader does, applies the same status / validation_status defaults, projects to CSV_COLUMNS, sort: validated rows on top (highest score first) then unvalidated, then writes to a unique /tmp file and returns the path. Fresh on every click so the export reflects the latest data, not a snapshot captured at boot. app.py: - Imports `build_combined_csv`. The Refresh button and the new `gr.DownloadButton("Download CSV", size="sm")` live in a single `gr.Row` so they sit side-by-side unde…f585077 -
app: Citation + Validation Guidelines accordions, validation link in About
Michael RabinovichBundle 1+2 C7. Two collapsed accordions above the leaderboard tables plus a validation-policy bullet on the About tab. - Validation Guidelines accordion (collapsed by default, sits above the tables). Carries the two-tier story in two lines (unvalidated -> validated, four evidence types) plus a link to the canonical policy doc in the main repo at `cadgenbench/docs/benchmark/validation.md`. Bundle 4 creates the file; the link will 404 until that lands, then resolves. - Citation accordion (collapsed by default, below Validation Guidelines). Carries the verbatim BibTeX entry locked in space-setup/bundles/1-2-space-ux.md (cite key cadgenbench2026, Space URL as howpublished). Rendered in a `gr.Code` with language=None (no BibTeX highlighter ships with gradio) and show_line_numbers off so the entry stays copy-paste tidy. - About tab picks up a new bullet linking the same validation doc. VALIDATION_DOC_URL is centralised at module level so the Validation Guidelines markdo…97b9a4a -
app: render reports inline via iframe srcdoc (private-Space safe)
Michael RabinovichPolish follow-up on C6. Reports now render inside the Space, inside the same iframe HF uses to host the leaderboard, with no second HTTP request leaving the browser. Why: the Space is private, and HF's edge gates same-origin pathname navigations on a short-lived __sign JWT that browsers don't carry forward when a user clicks a relative link. The previous design (submission_name -> /reports/<id>.html) worked server-side under Bearer auth (verified) but 404'd in the browser. Confirmed via external review and reproduced with a requests.Session cookie test. This commit: - Drops the submission_name -> /reports/<id>.html link wrapping from the rendered table; the cell stays plain text. The underlying `report_url` column (relative URL to the proxy) is still computed for the modern-pipeline gate but no longer surfaced as a clickable cell. - Adds a `gr.HTML` viewer below the detail panel. Row-click triggers `_format_detail_and_report`, which returns (detail_markdown, report_ifram…0e3b21f -
app+leaderboard: link submission_name to a Space-side report proxy
Michael RabinovichPolish follow-up #2 on C6. Three user-visible changes plus the plumbing required to make them work. 1. Drop the `report` and `zip` columns from the rendered table. `submission_name` becomes the report's deep link (typical HF leaderboard pattern: the system / model name doubles as the link target; cf. Open LLM Leaderboard, DABstep, BigCodeBench). Modern completed rows get `[<name>](/reports/<sid>.html)`; pending, failed, and legacy seed rows fall back to plain text so there's no broken click. The hidden `submission_blob_url` and the computed `report_url` ride along in the DataFrame and surface in the row-click detail panel only. 2. Rename the agent-URL column from `agent` to `model details (optional)`. Missing cells render as italic `_None_` so the optionality is explicit instead of a blank. "Agent" was confusing; the schema lets `agent_url` be code OR paper OR a blog post and "agent" reads narrow. 3. Add a Space-side proxy for the per-submission H…77edebf -
app+leaderboard: detail panel polish (rename link columns, fix broken report links)
Michael RabinovichPolish follow-up on C6, three fixes after the first detail-panel commit landed: 1. Rename display columns from snake_case schema names to clean short headers. `agent_url` -> `agent`, `submission_blob_url` -> `zip`, `report_url` -> `report`. The rename happens at projection time via `df.rename`, so the schema in results.jsonl is unchanged. Headers now read as plain English ("agent", "zip", "report") rather than a python dict. 2. The `agent` column shows the URL itself (scheme stripped, truncated past 40 chars) as link text instead of a fixed "code" label. The schema says agent_url can be code OR paper; the shortened URL is the only honest hint about what's behind the click. Missing values render as italic `_None_` rather than a blank cell, so the optionality is explicit. 3. The `report` link is now gated on the row's `submission_sha256` being non-null in addition to status == "completed". Legacy seed rows pre-date the modern submit pipeline (which …1a8f331 -
app: row-click detail panel below the leaderboard tables
Michael RabinovichBundle 1+2 C6. Single shared `gr.Markdown` panel below both Leaderboard widgets; either table's `.select(...)` event populates it with the clicked row's notes, agent_url, submitted_at, submission zip + report links (always), and failure_reason (failed rows only). Spec'd shape: one panel, two select sources. leaderboard.py: - LEADERBOARD_COLS + VALIDATED_LEADERBOARD_COLS each grow by three hidden detail-only fields (submission_id, notes, failure_reason). They ride in the underlying DataFrame so the select handler can read them out directly without a parallel state cache. - New LEADERBOARD_HIDE_COLUMNS constant lists the columns hidden from view; both Leaderboard widgets in app.py consume it. - `_project_and_format` now fills missing columns with None (legacy rows can lack optional fields like notes; the panel needs the column-set to be stable regardless of source-row shape). app.py: - pandas imported (for the helper's pd.isna check). - New `_format_detail(df, evt)` helper …3112173