feat: add a file explorer to trial results - #244
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a49f4691-6bee-4479-98d8-adf6e8f60d38
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The workspace loader currently excludes files whose names match excluded directories and has an apparent off-by-one depth limit, plus a test that may be flaky due to high parallel file creation.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review tier: Lite
Findings: 3
New issues introduced by this change (3)
| Severity | Finding |
|---|---|
website/src/workspace-files.test.ts — This test creates 2,001 files using Promise.all, which can open a large number of file… |
|
website/src/workspace-files.ts — MAX_DEPTH is described as “50 directory levels”, but the current depth >= MAX_DEPTH guard stops… |
|
website/src/workspace-files.ts — The exclusion filter drops any entry whose name matches an excluded directory, even when that entry… |
What changed in this PR
Adds a new website-only “Code” tab to benchmark/experiment trial results that renders a read-only, keyboard-accessible file tree and UTF-8 previews for the saved workspace (artifacts.workspaceDirectory) at build time (static-export friendly).
Changes:
- Introduces workspace loading + safety/limits (path containment, symlink handling, byte/entry/depth caps) and wires it into run details.
- Adds a new FileExplorer UI component and integrates it as a new tab in the run details page.
- Adds Vitest coverage for workspace loading edge cases and documents the feature/limits in the website README.
| File | Description |
|---|---|
| website/src/workspace-files.ts | New loader that reads and bounds workspace file trees + previews from result artifacts. |
| website/src/workspace-files.test.ts | Tests for workspace loading, limits, symlink/path safety, and integration into experiment run details. |
| website/src/runs.ts | Plumbs workspaceDirectory through normalized experiment output results. |
| website/src/run-details.ts | Integrates getWorkspaceFiles into benchmark/experiment run details; factors artifact resolution into shared helper. |
| website/src/artifacts.ts | New shared artifact path resolution/containment helpers. |
| website/src/app/components/RunDetailsPage.tsx | Adds the new “Code” tab and renders the explorer per trial (reset via key). |
| website/src/app/components/FileExplorer.tsx | New client component rendering the file tree and read-only previews. |
| website/src/app/components/FileExplorer.module.css | Responsive two-pane layout styling for tree + preview. |
| website/README.md | Documents the new Code tab behavior, exclusions, and preview/tree limits. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a49f4691-6bee-4479-98d8-adf6e8f60d38
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
Workspace candidate resolution returns early on some invalid candidates, preventing fallback to later valid candidates and causing incorrect “unavailable” outcomes in certain relocation/legacy scenarios.
Review tier: Lite
Findings: None
Issues resolved since last review (3)
| Severity | Finding |
|---|---|
website/src/workspace-files.ts — The exclusion filter drops any entry whose name matches an excluded directory, even when that entry… View resolved comment |
|
website/src/workspace-files.ts — MAX_DEPTH is described as “50 directory levels”, but the current depth >= MAX_DEPTH guard stops… View resolved comment |
|
website/src/workspace-files.test.ts — This test creates 2,001 files using Promise.all, which can open a large number of file… View resolved comment |
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
website/src/workspace-files.ts:145
- Inside the
for (const candidate ...)loop, returning immediately on an out-of-root resolution (or a non-directory) prevents trying later candidates fromgetArtifactCandidates()(e.g., legacy vs relocated artifacts). This can cause false negatives when the first candidate is invalid but a subsequent candidate is valid; it also differs fromgetArtifactDataUrl, which continues to other candidates on failure. Consider tracking these failure modes and only returning an unavailable reason after all candidates have been tried.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a49f4691-6bee-4479-98d8-adf6e8f60d38
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The changes are cohesive, well-tested, and the workspace previewing path includes appropriate safety/limit handling for static and server rendering.
Review tier: Lite
Findings: None
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a49f4691-6bee-4479-98d8-adf6e8f60d38
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
FileExplorer uses workspace file paths directly in DOM id attributes, which can be invalid (e.g., whitespace) and break TreeView accessibility/behavior.
Review tier: Lite
Findings: None
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
Suppressed comments (2)
Previously missed (1) — in code that hasn't changed since the last review.
website/src/app/components/FileExplorer.tsx:22
TreeView.Itemuses anidderived fromentry.path. Workspace paths can contain spaces (and other whitespace), which makes the resulting HTMLidinvalid and can break TreeView’s ARIA relationships / keyboard navigation for those entries. Encode/sanitize the path portion before using it as a DOM id.
This issue also appears on line 35 of the same file.
website/src/app/components/FileExplorer.tsx:35
TreeView.Itemuses anidderived fromentry.path. Workspace paths can contain spaces (and other whitespace), which makes the resulting HTMLidinvalid and can break TreeView’s ARIA relationships / keyboard navigation for those entries. Encode/sanitize the path portion before using it as a DOM id.
id={`${id}-${entry.path}`}

This PR adds a Code tab to benchmark and experiment trial results so we can inspect the generated workspace without downloading the result bundle.
The explorer shows the final saved workspace, including starter files, rather than a diff of the agent's changes. File previews are highlighted on the server and exported as individual JSON assets, so the explorer also works on GitHub Pages.
Changelog
New
Changed
dist.Removed
None.
Review notes
This is a website-only change and does not change the published
@primer/agent-evalAPI or result format. No changeset is needed.Previews are limited to 256 KiB per file and 2 MiB per workspace. The tree is limited to 2,000 entries and 50 directory levels. Dependency/build directories and Git metadata are omitted; symbolic links are not followed. Review workspace contents before publishing, since previewable files are included in the website.
The initial Server Component implementation eagerly serialized previews for every trial, producing approximately 109 MB of HTML for the saved design-system run. The same run now exports approximately 4.3 MB of HTML with no highlighting tokens. Previews use statically exported GET responses instead of Server Component slots, avoiding that work during the initial run render while keeping highlighting out of the browser.
Verification
ci.yml.Before / After
These screenshots compare the plain-text explorer at
310b122with Shiki highlighting. Both versions use the same representative local trial fixtures (not real evaluation runs). On-demand loading preserves the highlighted preview's appearance.Experiment results
Benchmark results
Dark mode