Repository navigation
Export evaluation run reports (JSON, HTML, Markdown) and Copy as Markdown - #621
Merged
Merged
Conversation
…y piece as Markdown A complete run comes back out as the version-1 envelope the collector at <mount>/api/evaluation_reports takes, so it moves to another install with one POST, and posting it back is an identical retry: - GET <mount>/api/evaluation_reports/:run_id (ingest key, tenant-scoped like the POST). An imported run exports under its published run_id, a dashboard run under dashboard-run-<id>-<created_at>. EvaluationReportImport accepts a run's own export as identical to it. - ActiveAgent::Evals::Publisher.envelope builds the envelope for both the publisher and the export (EvaluationReportExport). - The dashboard's run report adds report.json and report.md (one piece with ?part=verdict|fix_items|scenario), and ?download=1 on any format. - rake action_agent:evaluations:export / :import. Report#to_markdown now carries the HTML page's content in GitHub-flavored Markdown (ReportMarkdown): the verdict, What to fix from fix_items, and each scenario's answers in a <details> block, with table cells escaped. Its pieces are public and back "Copy as Markdown" in the dashboard and in the standalone HTML page, which gains one inline script for it. Downloads sit next to "Open standalone" and on the suite's run header. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhpgqyUrmSDK8cLDSheH3W
GET <mount>/api/evaluation_reports/:run_id?format=html returns the self-contained page run_report renders, with no theme (it follows the viewer) and its fix actions linking into the dashboard by absolute path, so a CLI can fetch a run's report with the ingest key. download=1 sends any format as an attachment named like the dashboard's downloads; an unknown format is a 422. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhpgqyUrmSDK8cLDSheH3W
…t key The collector takes reports from an install with no ingest key, a mount a host keeps off the network. A read of a stored run is different: its prompts, answers and judge text would be open under a guessable run_id to anyone who reaches the mount. GET /api/evaluation_reports/:run_id now answers 401 on a single-tenant install until ActionAgent.ingest_api_key is set; a multi-tenant install authenticates the tenant's key already. The HTML and Markdown formats also refuse an incomplete run (422) as the envelope did, instead of rendering a partial page. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FVSMckjfmJy2QWSb4wRrGh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A complete evaluation run can now leave the dashboard in three formats, and any piece of its report can be copied as Markdown for an issue or a pull request.
JSON export that round-trips through the existing import
GET <mount>/api/evaluation_reports/:run_id: authenticated with the ingest key (IngestAuthentication) and scoped to the tenant exactly likePOST. It returns the version-1 envelope thePOSTtakes. 404 for another tenant's run, 422 for a run that isn't complete or an unknownformat.?format=htmlreturns the self-contained pagerun_reportrenders (text/html). It takes no theme, so it follows the viewer's preference, and its fix actions link into the dashboard by absolute path (request.script_name). The CLI draft (Add the activeagent CLI: evals, catalogs, agents and traces, with JSON import/export between installs #620,evals report --format html) calls this.?format=mdreturns the Markdown (text/markdown).?download=1sends any format as an attachment with the same file names as the dashboard's downloads.:run_idresolves:run_idit was published under.dashboard-run-<id>-<created_at YYYYMMDDhhmmss UTC>. The timestamp keeps two installs' run Active Agent generate with stream #12 from colliding on a third install.ActiveAgent::Evals::Publisher.envelopebuilds the envelope for both the publisher and the export (ActionAgent::EvaluationReportExport), so the hash layout lives in one place.EvaluationRun#to_report(estimate: false)with the recorded run-level judge usage, so the same run always exports the same envelope. The DBrunid is left out of the metadata.EvaluationReportImporttreats a run's own export as an identical retry (200,duplicate: true). It covers both cases:run_id, so posting it back creates nothing.Different content under the
run_idis still a 409. The receipt'srun_idis the exported one.POST /api/evaluation_reportsitself is unchanged.Dashboard run report
…/runs/:run_id/report.jsonserves the same envelope to a dashboard session.report.mdserves the Markdown.?part=verdict|fix_items[&model=]|scenario&scenario=serves one piece of it.?download=1on any format sendsContent-Disposition: attachmentwith a file name like<evaluation-slug>-run-<n>.html|json|md.UI
allow="clipboard-write".show_run'sfix_items[].markdown);Markdown (
ActiveAgent::Evals::ReportMarkdown)Report#to_markdownnow has the HTML page's content in GitHub-flavored Markdown:fix_items, which replaces the old Recommendations list;<details><summary>…block with a per-model table (status, score, tools, fault, cost) and the answers quoted.|and fold line breaks. Text in summaries and answers escapes</>.verdict_markdown,fix_items_markdown(model:),fix_item_markdown(item)andscenario_markdown(key). The CLI, the endpoints, the dashboard buttons and the standalone HTML page all use these methods.execCommand("copy")when the Clipboard API is refused. Nothing is loaded from outside the page.Rake
action_agent:evaluations:export RUN=<run_id> | EVALUATION=<id> RUN=<id> FORMAT=json|html|md [FILE=path]writes to standard output when noFILEis given.action_agent:evaluations:import FILE=path [ACCOUNT_ID=…]goes throughEvaluationReportImportand printsStored: …orAlready stored (identical retry): ….Tests
actionagent/test/evaluation_report_export_test.rb:run_idvalues with dots work;format=htmlpage is the same pagerun_reportrenders, with absolute fix links,text/htmland no theme;download=1on json/html/md, and an unknown format is a 422;.json/.md/download=1headers and file names, and the Markdown pieces;fix_items[].markdown;test/evals/report_test.rb:<details>blocks, pipe/newline escaping and per-model What to fix;test/evals/publisher_test.rb:Publisher.envelopeis what#callsends.reportExport.test.mjs(URLs, ClipboardItem path and fallback) andreportExportViews.test.mjs(the rendered buttons and links).Results:
format=html,download=1): engine suite 1794 runs, 0 failures, 0 errors;test/evals245 runs, 0 failures.bin/test(gem + engine): 4056 runs, 0 failures, 5 errors. All 5 areRubyLLMIntegrationTest, which calls OpenAI live wheneverOPENAI_API_KEYis set, and the local placeholder key gets a 401. The same 5 fail on a cleanorigin/maincheckout with the same.env.test. CI names that keyOPEN_AI_API_KEY, so the file skips there.bin/lint: no offenses.npm test: 698 pass.npm run buildwas rerun and its output committed.🤖 Generated with Claude Code
https://claude.ai/code/session_01KhpgqyUrmSDK8cLDSheH3W