Skip to content

Commit a43fc91

Browse files
authored
fix(results): harden static report publishing (#1373)
1 parent 8ceb028 commit a43fc91

4 files changed

Lines changed: 172 additions & 1 deletion

File tree

apps/cli/src/commands/results/report.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ export function renderResultsReport(
124124
serializeReportResult(result, sourceFile, records[index], benchmarkEvalFile),
125125
);
126126
const dataJson = JSON.stringify(rows).replace(/<\//g, '<\\/');
127-
return RESULTS_REPORT_TEMPLATE.replace('__DATA_PLACEHOLDER__', dataJson);
127+
return RESULTS_REPORT_TEMPLATE.replace('__DATA_PLACEHOLDER__', () => dataJson);
128128
}
129129

130130
export async function writeResultsReport(

apps/cli/test/commands/results/report.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,27 @@ describe('results report', () => {
148148
expect(html).not.toContain('Grader Results');
149149
});
150150

151+
it('embeds result text containing replacement tokens without corrupting the inline script', async () => {
152+
const runDir = path.join(tempDir, 'run');
153+
await writeArtifactsFromResults(
154+
[
155+
makeResult({
156+
output: "literal replacement tokens: $' $& $` $$",
157+
}),
158+
],
159+
runDir,
160+
{ evalFile: 'evals/demo.eval.yaml' },
161+
);
162+
163+
const { outputPath } = await writeResultsReport(runDir, undefined, tempDir);
164+
const html = readFileSync(outputPath, 'utf8');
165+
166+
expect(html.match(/<\/script>/g)).toHaveLength(1);
167+
expect(html).toContain("literal replacement tokens: $' $& $` $$");
168+
expect(html).toContain('<script>');
169+
expect(html).toContain('</script>');
170+
});
171+
151172
it('emits an inline report script that parses successfully', async () => {
152173
const runDir = path.join(tempDir, 'run');
153174
await writeArtifactsFromResults([makeResult()], runDir, { evalFile: 'evals/demo.eval.yaml' });

apps/web/src/content/docs/docs/tools/results.mdx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,31 @@ What it shows:
5454
- **Expandable details** — unified assertions with pass/fail indicators and type badges, collapsible input/output
5555
- **Criteria column** — shows the test prompt or description inline for quick scanning
5656

57+
### Publish a static report with GitHub Pages
58+
59+
The generated file is self-contained HTML: no Dashboard server, API endpoint, or external asset host is required after it is written. That makes it a good fit for public result repositories served by GitHub Pages.
60+
61+
One minimal publication workflow is:
62+
63+
```bash
64+
# 1. Run an eval and sync or copy the run workspace into your public results repo.
65+
agentv eval evals/demo.eval.yaml --output .agentv/results/runs/demo-live
66+
67+
# 2. In the public results repo, render the report into the Pages source directory.
68+
agentv results report .agentv/results/runs/demo-live --out docs/index.html
69+
70+
# 3. Review the generated HTML before publishing.
71+
grep -RInE 'sk-[A-Za-z0-9]|Bearer |localhost|127\.0\.0\.1|/home/|/Users/|/tmp/' docs/index.html
72+
73+
# 4. Commit the run artifacts and docs/index.html, then enable GitHub Pages
74+
# for the repository's docs/ directory or the branch used for Pages.
75+
git add .agentv/results/runs/demo-live docs/index.html README.md
76+
git commit -m "docs(results): publish static AgentV report"
77+
git push
78+
```
79+
80+
Use `--out docs/<name>.html` when a repository should publish multiple runs. Link those files from the result repository README so readers can browse a dashboard-like report from GitHub Pages instead of running `agentv dashboard` or opening raw JSONL.
81+
5782
<Image src={resultsReportDetails} alt="AgentV results report showing an expanded failing test case with unified assertions, deterministic type badges, pass/fail indicators, evidence text, and collapsible input/output" />
5883

5984
| Option | Description |
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
---
2+
date: 2026-06-14
3+
topic: static-results-dashboard
4+
type: recommendation
5+
---
6+
7+
# Static Results Dashboard Recommendation
8+
9+
## Summary
10+
11+
AgentV should keep `agentv results report` focused on one run and add any future multi-run GitHub Pages export as a separate `agentv results dashboard` command. The dashboard should be a read-only static index over existing run artifacts, with relative links to single-run reports for drill-down.
12+
13+
---
14+
15+
## Problem Frame
16+
17+
Public benchmark repositories need a URL that explains quality movement over time without asking readers to clone artifacts, run `agentv dashboard`, or interpret raw `index.jsonl`. The existing single-run report solves the case-level review problem, but it does not answer longitudinal questions such as whether pass rate drifted, which target regressed, or whether a release improved a benchmark pack.
18+
19+
AgentV already has the core primitives for those questions: canonical run workspaces, `agentv trend` for score drift, `agentv compare` for pairwise and target matrix deltas, and Dashboard analytics for run lists, score distribution, normalized gain, tag heatmaps, and trend charts. The static dashboard should compose those existing primitives into a publishable artifact rather than creating a second hosted Dashboard.
20+
21+
---
22+
23+
## Key Decisions
24+
25+
- **New command, not `results report` mode expansion.** `results report` has a clear one-run contract and one default output file. A multi-run dashboard has different source semantics, writes an index plus optional per-run pages, and should not add a second mode to the report command.
26+
- **Run artifacts remain canonical.** The static dashboard reads existing `.agentv/results/runs/**/index.jsonl` and summary artifacts from public result repos. It does not introduce a committed database, service worker, or new canonical index.
27+
- **Static-first output.** The primary artifact is `docs/index.html` with inline data and no backend. Optional drill-down pages use safe relative links, such as `docs/runs/<run-slug>.html`.
28+
- **Graceful sparse data.** Legal currently has one published live run, while financial has multiple useful runs. Trend and comparison panels should render when data supports them and otherwise show an explanatory empty state.
29+
30+
---
31+
32+
## Requirements
33+
34+
**Inputs**
35+
36+
- R1. The dashboard command accepts one or more result repo roots, run workspace directories, or `index.jsonl` manifests.
37+
- R2. The command discovers canonical run workspaces under `.agentv/results/runs/` when given a repo root.
38+
- R3. The command uses existing run metadata and `index.jsonl` rows without requiring a live Dashboard or remote API.
39+
- R4. Optional filtering supports suite, target, experiment, tags, and latest-N run selection when those fields exist in artifacts.
40+
41+
**Output**
42+
43+
- R5. The default output is a GitHub Pages-friendly `docs/index.html` that is read-only and self-contained.
44+
- R6. Per-run drill-down links are relative and can point to generated single-run report pages.
45+
- R7. The generated HTML uses the existing Dashboard/report visual language: dark surface hierarchy, summary cards, pass/fail tones, score distribution, run table, and expandable details through linked reports.
46+
- R8. The output includes no external scripts, no external stylesheets, no local endpoint references, and no local filesystem paths.
47+
48+
**Analysis**
49+
50+
- R9. The dashboard summarizes total runs, latest run, pass rate, mean score, failures, errors, duration, token usage, and cost when present.
51+
- R10. The dashboard shows pass-rate and mean-score trend lines across runs when at least two comparable runs exist.
52+
- R11. The dashboard shows score distributions for the selected run set.
53+
- R12. The dashboard shows target/model comparison tables when multiple targets are present.
54+
- R13. The dashboard surfaces release/regression signals by highlighting latest-run deltas against a selected baseline or previous run.
55+
56+
**Publication**
57+
58+
- R14. The command supports a public results repository workflow where `docs/index.html` is committed with run artifacts and served by GitHub Pages.
59+
- R15. The command can optionally generate single-run report pages for every included run by reusing the existing report renderer.
60+
- R16. The command emits enough terminal output for automation to record the generated files and source run count.
61+
62+
---
63+
64+
## MVP for Legal and Financial Demos
65+
66+
The first useful version does not need a full Dashboard clone. It needs:
67+
68+
1. `agentv results dashboard <results-repo-root> --out docs/index.html --reports docs/runs/`
69+
2. A static overview with cards for runs, tests, latest pass rate, mean score, failures, and errors.
70+
3. A run table with date, experiment/run ID, target, tests, pass rate, mean score, and a relative `runs/<slug>.html` report link.
71+
4. A score distribution histogram over the selected runs.
72+
5. A pass-rate trend chart when at least two comparable runs exist.
73+
6. A target comparison table when at least two targets exist.
74+
7. Empty states that explain why legal has no trend yet if only one legal run is published.
75+
76+
For the current legal and financial publication task, the existing `agentv results report` primitive is enough: publish `docs/index.html` in the legal results repo, and publish `docs/index.html` plus `docs/dexter-baseline.html` in the financial results repo. The multi-run dashboard should be a follow-up because it would add a new command, source discovery rules, and aggregation behavior beyond this issue's smallest GitHub Pages-ready path.
77+
78+
---
79+
80+
## URL and Layout Shape
81+
82+
```text
83+
docs/
84+
index.html # multi-run static dashboard
85+
runs/
86+
<experiment>-<timestamp>.html # generated with the single-run report renderer
87+
```
88+
89+
Suggested tabs or sections for `docs/index.html`:
90+
91+
- **Overview** — cards, latest run, selected filters, and publication timestamp.
92+
- **Trends** — pass-rate and mean-score lines, with sparse-data empty states.
93+
- **Compare** — target/model matrix and latest-vs-baseline deltas.
94+
- **Runs** — sortable run table with relative links to generated single-run reports.
95+
96+
---
97+
98+
## Scope Boundaries
99+
100+
- Do not build a second live Dashboard app.
101+
- Do not require a server, database, API route, or GitHub Actions service to view the output.
102+
- Do not commit a generated SQLite database or append-only aggregate index as canonical state.
103+
- Do not replace `agentv trend`, `agentv compare`, or Dashboard analytics; reuse their concepts and data shapes.
104+
- Do not add statistical claims beyond descriptive trend/delta summaries in the MVP.
105+
106+
---
107+
108+
## Acceptance Examples
109+
110+
- AE1. **Covers R1, R2, R5.** Given a public results repo root, when the command runs with `--out docs/index.html`, then a static dashboard file is generated from discovered run workspaces.
111+
- AE2. **Covers R6, R15.** Given `--reports docs/runs/`, when the command includes a run, then the run table links to a relative single-run report page.
112+
- AE3. **Covers R10.** Given fewer than two comparable legal runs, when the dashboard renders, then the trend panel explains that more runs are required instead of showing a misleading chart.
113+
- AE4. **Covers R8, R14.** Given the generated `docs/` directory is scanned, then no external scripts, local endpoints, local filesystem paths, or secrets are present.
114+
- AE5. **Covers R12, R13.** Given financial runs include multiple targets or a baseline/candidate pair, when the dashboard renders, then target comparison or latest-vs-baseline deltas are visible without running the live Dashboard.
115+
116+
---
117+
118+
## Sources
119+
120+
- `apps/cli/src/commands/results/report.ts` — existing one-run static HTML report writer.
121+
- `apps/cli/src/commands/results/report-template.ts` — existing Dashboard-themed static report visual language.
122+
- `apps/cli/src/commands/trend/index.ts` — existing multi-run trend analysis over run manifests.
123+
- `apps/cli/src/commands/compare/index.ts` — existing pairwise and target-matrix comparison logic.
124+
- `apps/web/src/content/docs/docs/tools/dashboard.mdx` — current Dashboard analytics behavior to mirror at static-export scope.
125+
- `apps/web/src/content/docs/docs/tools/results.mdx` — current single-run report docs and GitHub Pages workflow.

0 commit comments

Comments
 (0)