diff --git a/apps/web/src/content/docs/docs/evaluation/experiments.mdx b/apps/web/src/content/docs/docs/evaluation/experiments.mdx index c0e381891..7e852eac7 100644 --- a/apps/web/src/content/docs/docs/evaluation/experiments.mdx +++ b/apps/web/src/content/docs/docs/evaluation/experiments.mdx @@ -269,19 +269,22 @@ Do not set both `repeat` and `runs` in the same runtime block. ## Result Layout -Eval runs write to the selected result group: +Eval runs write to the selected result bucket: ```text -.agentv/results/// +.agentv/results/// ``` -CLI `--experiment` sets the result group explicitly. Without that flag, AgentV -derives the group from the eval input: a single eval uses the eval metadata -`name` when present or the eval filename otherwise, and multiple eval files use -`multi-eval`. Inline `experiment.name` does not currently select the result -group. +CLI `--experiment` sets the bucket explicitly. Without that flag, AgentV uses +`experiment.name` from the eval file, then `default`. The experiment remains the +comparison and runtime-policy label for a run condition; folder names are only +storage allocation and must not define result semantics. Imported source suite metadata appears in `run_manifest.jsonl` rows and manifests. Use `run_manifest.jsonl` fields such as `eval_path`, `test_id`, `target`, and `result_dir` for identity and artifact discovery instead of reconstructing paths from suite names or wrapper layout. + +For the complete result file contract, including why row metadata is semantic +truth and directories are storage allocation, see +[Result Artifact Contract](/docs/reference/result-artifacts/). diff --git a/apps/web/src/content/docs/docs/evaluation/running-evals.mdx b/apps/web/src/content/docs/docs/evaluation/running-evals.mdx index b8709faad..639ae6298 100644 --- a/apps/web/src/content/docs/docs/evaluation/running-evals.mdx +++ b/apps/web/src/content/docs/docs/evaluation/running-evals.mdx @@ -17,7 +17,9 @@ AgentV picks the experiment bucket from `--experiment`, then timestamped run bundle. Each line is a JSON object with one result per test case, and the run workspace also stores the manifest and related artifacts. Use this generated run folder as the portable audit surface: copy or sync the run -directory, not a hand-authored parallel bundle. +directory, not a hand-authored parallel bundle. See the +[Result Artifact Contract](/docs/reference/result-artifacts/) for the complete +run layout and reader rules. Each `scores[]` entry includes per-grader timing: @@ -104,7 +106,8 @@ agentv eval evals/my-eval.yaml --output ./my-results ``` `--output` is a run directory, not a file path. The canonical manifest is always -`/run_manifest.jsonl`. +`/run_manifest.jsonl`; the aggregate summary is +`/summary.json`. ### Read Results from the Run Manifest @@ -135,7 +138,7 @@ my-results/ grading.json metrics.json timing.json - transcript.json + transcript.jsonl transcript-raw.jsonl outputs/answer.md task/ @@ -154,6 +157,9 @@ case directories are still useful for organizing bulky prompts, fixtures, or tests while authoring an eval, but they are optional input organization rather than a separate artifact schema. +For the full root layout, per-attempt sidecars, pointer rules, and integration +guidance, use the [Result Artifact Contract](/docs/reference/result-artifacts/). + Use repo-relative `eval_path`, `test_id`, and `target` as the source identity for a result row. `suite` and `name` are display metadata only; do not use them to infer storage paths or pick a Dashboard detail row. diff --git a/apps/web/src/content/docs/docs/index.mdx b/apps/web/src/content/docs/docs/index.mdx index 11ed92d8e..5855bd2b6 100644 --- a/apps/web/src/content/docs/docs/index.mdx +++ b/apps/web/src/content/docs/docs/index.mdx @@ -52,7 +52,7 @@ Use this topic map when you are an AI agent trying to decide which primitive or | Run or resume evals | [Running evals](/docs/evaluation/running-evals/) → [WIP checkpoints](/docs/tools/wip-checkpoints/) | Covers `agentv eval`, concurrency, `--resume`, `--rerun-failed`, and remote partial-run recovery. | | Choose graders | [Rubrics](/docs/evaluation/rubrics/) → [Code graders](/docs/graders/code-graders/) → [LLM graders](/docs/graders/llm-graders/) | Keeps deterministic checks, rubric scoring, and LLM judgment separate. | | Evaluate tool use or agents | [Tool trajectory](/docs/graders/tool-trajectory/) → [Coding agents](/docs/targets/coding-agents/) → [CLI provider](/docs/targets/cli-provider/) | Shows how targets, transcripts, and tool-call assertions compose. | -| Share and inspect results | [Results](/docs/tools/results/) → [Dashboard](/docs/tools/dashboard/) | Explains local artifacts, reports, remote result repositories, and Dashboard review flows. | +| Share and inspect results | [Result artifact contract](/docs/reference/result-artifacts/) → [Results](/docs/tools/results/) → [Dashboard](/docs/tools/dashboard/) | Explains canonical run bundles, local artifacts, reports, remote result repositories, and Dashboard review flows. | | Compare runs | [Compare](/docs/tools/compare/) → [Dashboard Analytics](/docs/tools/dashboard/#analytics) | Use CLI metrics for automation and Dashboard analytics for interactive inspection. | | Govern or improve an agent workflow | [Agent eval layers](/docs/guides/agent-eval-layers/) → [Skill improvement workflow](/docs/guides/skill-improvement-workflow/) → [Enterprise governance](/docs/guides/enterprise-governance/) | Moves from primitive eval design to iterative agent improvement and governance checks. | diff --git a/apps/web/src/content/docs/docs/reference/result-artifacts.mdx b/apps/web/src/content/docs/docs/reference/result-artifacts.mdx new file mode 100644 index 000000000..d5a453c2f --- /dev/null +++ b/apps/web/src/content/docs/docs/reference/result-artifacts.mdx @@ -0,0 +1,249 @@ +--- +title: Result Artifact Contract +description: The canonical AgentV run output layout, manifest roles, and integration contract. +sidebar: + order: 1 +--- + +AgentV writes each eval invocation as a portable run bundle. The bundle is the +source of truth for Dashboard, reports, compare/trend tooling, CI gates, and +external adapters. + +The contract is run-centric: + +- `summary.json` owns aggregate run facts. +- `index.jsonl` owns row-level discovery and filtering. +- Per-case sidecars own detailed payloads such as grading, metrics, transcripts, + timing, generated files, and raw provider evidence. +- Dashboard, search, SQLite, HTML reports, and vendor exports are rebuildable + projections over the bundle. + +:::note +This page names the intended canonical row index as `index.jsonl`. During the +transition from the temporary `run_manifest.jsonl` filename, readers should +accept either filename when inspecting existing bundles. New contract examples +and integrations should converge on `index.jsonl`. +::: + +## Directory Layout + +The default local layout is: + +```text +.agentv/results/ + / + / + summary.json + index.jsonl + tags.json # optional mutable Dashboard tags + / + summary.json # optional per-case aggregate, especially repeats + task/ # optional generated task bundle + EVAL.yaml + targets.yaml + files/ + graders/ + run-1/ + result.json + grading.json + metrics.json + timing.json + transcript.jsonl + transcript-raw.jsonl + outputs/ + answer.md + run-2/ + result.json + grading.json + metrics.json + timing.json + transcript.jsonl + transcript-raw.jsonl + outputs/ + answer.md +``` + +The `` and `` directories are storage allocation. They help +AgentV put completed runs somewhere predictable, but readers must not infer +semantic truth from folder names. Use fields in `summary.json` and `index.jsonl` +for experiment, target, variant, attempt, eval path, case identity, timing, +scores, and artifact paths. + +`experiment` remains the comparison and runtime-policy concept: it is how users +label a condition such as `baseline`, `candidate`, `with_skills`, or +`without_skills`. The folder segment is a convenient bucket for that concept, +not an alternate schema. If a bundle is copied, combined, published, or imported +under a different directory, its rows still carry the facts consumers should +query. + +## File Roles + +| File or field | Owns | Use it for | +| --- | --- | --- | +| `summary.json` | Aggregate run metadata and rollups: run id, experiment metadata, counts, pass rate, score summaries, duration, token/cost totals, and writer metadata. | Listing runs, CI summaries, quick dashboards, trend cards, and validating that a run is complete enough to inspect. | +| `index.jsonl` | Canonical row index: one row per result, attempt, or case-level aggregate, with identity fields, filter metadata, scores, status, and explicit run-relative paths to sidecars. | Filtering, compare/trend inputs, Dashboard detail routing, rerun/resume lookup, export adapters, and artifact discovery. | +| `result.json` | Compact per-attempt manifest for one attempt directory. | Loading one attempt without scanning the whole run index. | +| `grading.json` | Grader outputs, assertions, rubric evidence, execution-metric grader facts, and scoring provenance. | Explaining why a row passed or failed. | +| `metrics.json` | Derived executor behavior summary, such as tool calls, files touched, shell commands, errors, turns, and output sizes. | Dashboard behavior views, metric-style graders, adapter projections, and lightweight analysis. | +| `timing.json` | Duration, token usage, cost usage, and source labels such as `provider_reported`, `token_estimated`, `aggregate`, or `unavailable`. | Cost/latency reporting and provider-accounting audits. | +| `transcript.jsonl` | AgentV-normalized transcript/timeline rows. | Portable human review, replay, transcript-aware graders, and tool-trajectory analysis. | +| `transcript-raw.jsonl` | Native provider or harness evidence when available. | Parser debugging, forensic review, and preserving source bytes without making provider schemas public AgentV fields. | +| `task/` | Generated task bundle for the exact eval slice and target settings that produced a row. | Audit, external review, and rerun workflows that should not depend on a mutable source checkout. | +| `artifact_pointers` | Offload indirection for large detached payload bytes. | Finding payloads published outside the primary metadata/control-plane branch, such as transcript bytes on `agentv/artifacts/v1`. | + +`summary.json` and `index.jsonl` are complementary, not redundant. A run list +should not scan every row just to show pass rate or total duration, and a row +reader should not parse aggregate summary structures to find one case's grading +or transcript. Keep aggregate questions on `summary.json`; keep row and artifact +discovery on `index.jsonl`. + +## Row Contract + +Each `index.jsonl` line is a JSON object. The exact field set grows as AgentV +adds providers and projections, but stable rows follow these rules: + +- Field names are `snake_case`. +- Identity and filter fields live on the row, not only in directory names. +- Sidecar references are explicit path fields, relative to the run directory. +- Large detached payloads may also have `artifact_pointers`, but ordinary + sidecars should still be discoverable through path fields. +- Unknown fields should be preserved by adapters when they rewrite or project + rows. + +Example row: + +```json +{ + "timestamp": "2026-06-30T08:15:00.000Z", + "run_id": "2026-06-30T08-15-00-000Z", + "experiment": "with_skills", + "eval_path": "evals/support/refunds.eval.yaml", + "test_id": "refund-eligibility", + "target": "codex-gpt5", + "variant": "skills-v2", + "attempt": 1, + "execution_status": "ok", + "score": 0.92, + "duration_ms": 184200, + "result_dir": "refund-eligibility/run-1", + "summary_path": "refund-eligibility/summary.json", + "grading_path": "refund-eligibility/run-1/grading.json", + "metrics_path": "refund-eligibility/run-1/metrics.json", + "timing_path": "refund-eligibility/run-1/timing.json", + "transcript_path": "refund-eligibility/run-1/transcript.jsonl", + "transcript_raw_path": "refund-eligibility/run-1/transcript-raw.jsonl", + "output_path": "refund-eligibility/run-1/outputs/answer.md", + "answer_path": "refund-eligibility/run-1/outputs/answer.md", + "task_dir": "refund-eligibility/task" +} +``` + +Rows can represent repeated attempts, multi-target runs, imported suites, +manual `prepare`/`grade` attempts, or imported provider sessions. That is why +`experiment`, `eval_path`, `test_id`, `target`, `variant`, `attempt`, and +source metadata belong in `index.jsonl`: tools can filter dynamically without +requiring every run to be pre-split into semantic folders. + +## Reader Rules + +Consumers should read a bundle in this order: + +1. Resolve the run directory from either a directory path or an `index.jsonl` + path. +2. Load `summary.json` for aggregate metadata and run-level display. +3. Stream `index.jsonl` for row identity, filters, status, scores, and sidecar + paths. +4. Resolve sidecar paths relative to the run directory. +5. Rebuild any local cache, search index, SQLite table, static report, or + vendor projection from `summary.json`, `index.jsonl`, and sidecars. + +Do not reconstruct paths from `suite`, `name`, `test_id`, `target`, or +directory names. `result_dir` is readable when possible, but it is still an +opaque run-local allocation that may be suffixed or otherwise changed to avoid +collisions. + +Do not treat derived artifacts as canonical: + +- Dashboard indexes are caches over the run bundle. +- Search indexes are caches over rows and sidecars. +- SQLite databases are query accelerators. +- HTML reports are renderings. +- Vendor-neutral projection bundles are adapter handoffs. +- Phoenix, Langfuse, Opik, or other backend views are external projections or + correlations, not AgentV's source of truth. + +## User Examples + +Run an eval and inspect the portable bundle: + +```bash +agentv eval evals/support/refunds.eval.yaml --experiment with_skills +ls .agentv/results/with_skills/ +cat .agentv/results/with_skills//summary.json +cat .agentv/results/with_skills//index.jsonl +``` + +Find failed rows without loading every sidecar: + +```bash +jq -r 'select(.execution_status != "ok" or .score < 0.5) | + [.eval_path, .test_id, .target, .grading_path] | @tsv' \ + .agentv/results/with_skills//index.jsonl +``` + +Compare two completed runs by their row indexes: + +```bash +agentv compare \ + .agentv/results/baseline//index.jsonl \ + .agentv/results/candidate//index.jsonl +``` + +Generate a shareable report from the same canonical bundle: + +```bash +agentv results report .agentv/results/with_skills/ +``` + +## Integration Author Examples + +An adapter that exports run results should treat `index.jsonl` as the row +catalog: + +```ts +import { createReadStream } from "node:fs"; +import path from "node:path"; +import { createInterface } from "node:readline"; + +export async function* rows(runDir: string) { + const rl = createInterface({ + input: createReadStream(path.join(runDir, "index.jsonl"), "utf8"), + crlfDelay: Infinity, + }); + + for await (const line of rl) { + if (!line.trim()) continue; + yield JSON.parse(line) as Record; + } +} + +for await (const row of rows(".agentv/results/with_skills/2026-run")) { + const gradingPath = row.grading_path; + if (typeof gradingPath === "string") { + console.log(path.join(".agentv/results/with_skills/2026-run", gradingPath)); + } +} +``` + +Adapter guidance: + +- Preserve unknown row fields when possible. +- Prefer path fields such as `grading_path`, `metrics_path`, `timing_path`, + `transcript_path`, and `transcript_raw_path` over ad hoc path construction. +- Use `artifact_pointers` only for detached payload lookup; do not make pointers + the discovery path for ordinary sidecars that are present in the run tree. +- If you build a database or search index, store enough source metadata to + rebuild it from the run bundle and invalidate it when `summary.json` or + `index.jsonl` changes. +- Keep backend-specific anonymization, upload, and schema mapping in the adapter + layer. AgentV's canonical bundle remains backend-neutral. diff --git a/apps/web/src/content/docs/docs/tools/results.mdx b/apps/web/src/content/docs/docs/tools/results.mdx index 788bd5360..93564d223 100644 --- a/apps/web/src/content/docs/docs/tools/results.mdx +++ b/apps/web/src/content/docs/docs/tools/results.mdx @@ -13,6 +13,9 @@ The `results` command family works on existing local AgentV run workspaces and ` Remote result repository exchange is intentionally not part of `agentv results`. New eval runs publish completed artifacts to a configured results repo or branch; `auto_push: true` additionally pushes that branch to the remote. Manual remote status and sync are Dashboard/API workflows. See [Dashboard Remote Results](/docs/tools/dashboard/#remote-results) for configuration and sync behavior, and [WIP checkpoints](/docs/tools/wip-checkpoints/) for recovering in-progress runs before final publish. +For the canonical run output structure, file roles, and integration contract, +start with [Result Artifact Contract](/docs/reference/result-artifacts/). + ## Subcommands | Subcommand | Purpose | @@ -98,6 +101,11 @@ agentv results export [--out ] [--dup This is useful when a manifest needs to be materialized into a predictable artifact tree for other tooling, review, or archiving. The run workspace is also where generated task bundles live: `run_manifest.jsonl` rows may point to per-result `task_dir`, `eval_path`, `targets_path`, `files_path`, and `graders_path` entries. Keep those generated artifacts with the run when sharing or auditing results. +The export source is still the canonical run bundle described in the +[Result Artifact Contract](/docs/reference/result-artifacts/): `summary.json` +for aggregate run facts, the row manifest for row discovery, and sidecars for +detailed payloads. + Each exported trace sidecar and `run_manifest.jsonl` row includes a stable `projection_identity` derived from AgentV-owned fields: `run_id`, `suite` or `eval_path`, `test_id`, `target`, `source_target`, `attempt`, `variant`, `envelope_id`, `trace_id`, `root_span_id`, and the projection format/version. Retrying the same completed run keeps the same projection ID even when you choose a different `--out` directory, because `run_id` comes from the source run directory or source manifest name rather than the export destination. Duplicate policy is explicit: diff --git a/docs/adr/0011-result-output-artifact-contract.md b/docs/adr/0011-result-output-artifact-contract.md new file mode 100644 index 000000000..fd8ddb392 --- /dev/null +++ b/docs/adr/0011-result-output-artifact-contract.md @@ -0,0 +1,229 @@ +# 11. Result output artifact contract is run-centric and manifest-first + +Date: 2026-06-30 + +## Status + +Accepted + +Extends: + +- [ADR 0006](0006-separate-experiments-from-eval-definitions.md), which keeps + experiment runtime inline in eval YAML. +- [ADR 0008](0008-normalized-transcript-artifact-contract.md), which defines + raw and normalized transcript sidecars. +- [ADR 0009](0009-eval-path-result-identity-and-default-experiment.md), which + keeps result identity in `index.jsonl` rows and uses `default` as the fallback + result experiment. + +## Context + +AgentV needs a result output contract that works for local runs, CI gates, +Dashboard inspection, static reports, comparisons, repeated attempts, imported +suites, manual prepare/grade attempts, and downstream adapters. The contract +must remain portable across repositories and machines without requiring a +hosted database or an external observability system. + +Several pressures make directory-derived semantics brittle: + +- A single CLI invocation can run multiple targets or imported suites. +- Repeated attempts can create multiple attempts for one case. +- Two suites can reuse the same test ID. +- Dashboard and compare tools need dynamic filters across experiment, target, + variant, source eval, attempt, status, score, and metadata. +- Result bundles can be copied, combined, published, imported, or projected into + another storage location. +- Future schema evolution should add row fields or sidecars without requiring a + directory migration. + +The product direction also keeps AgentV-owned run bundles, traces, transcripts, +datasets, experiments, indexes, and Git-backed artifacts outside Phoenix and +other hosted systems. AgentV can correlate with external traces through safe +metadata, but AgentV's run bundle remains the source of truth. + +## Decision + +An AgentV result output is a run-centric bundle with this root contract: + +```text +.agentv/results/// + summary.json + index.jsonl + tags.json # optional mutable overlay + / + summary.json # optional case aggregate, especially repeats + task/ # optional generated task bundle + run-1/ + result.json + grading.json + metrics.json + timing.json + transcript.jsonl + transcript-raw.jsonl + outputs/ +``` + +`summary.json` and `index.jsonl` are complementary: + +- `summary.json` owns aggregate run metadata and rollups: counts, pass rate, + score summaries, duration, token/cost totals, writer metadata, and run-level + display fields. Run listings, CI summaries, and quick Dashboard cards should + use it. +- `index.jsonl` owns row-level truth: one row per result, attempt, or + case-level aggregate, with identity fields, filter metadata, status, scores, + and explicit run-relative paths to sidecars. Dashboard detail routing, + compare/trend tooling, rerun lookup, and adapters should use it. + +This is not redundant storage. It avoids forcing aggregate consumers to scan +every row and avoids forcing row consumers to reverse-engineer case details from +aggregate summaries. + +`index.jsonl` is the canonical row index for a run. It is the discovery path for +ordinary per-case sidecars through explicit fields such as `result_dir`, +`summary_path`, `grading_path`, `metrics_path`, `timing_path`, +`transcript_path`, `transcript_raw_path`, `answer_path`, `output_path`, +`task_dir`, `eval_path`, `targets_path`, `files_path`, and `graders_path` when +those artifacts exist. + +During the transition away from the temporary `run_manifest.jsonl` filename, +readers may accept both `run_manifest.jsonl` and `index.jsonl` for existing +bundles. The contract name for new examples and integration guidance is +`index.jsonl`. + +`artifact_pointers` remain an offload indirection for large detached payload +bytes. They are not the discovery path for ordinary sidecars that live in the +run tree. + +Dashboard search indexes, SQLite caches, static HTML reports, comparison +outputs, and vendor-neutral projection bundles are rebuildable projections over +`summary.json`, `index.jsonl`, and sidecars. They must not become the canonical +source for run identity or artifact discovery. + +## Directory Paths Are Allocation + +The `.agentv/results///` path is storage allocation. It +gives AgentV a predictable place to write and discover completed bundles, but +the path does not define semantic truth. + +The experiment remains AgentV's comparison and runtime-policy concept. Users +can label run conditions such as `baseline`, `candidate`, `with_skills`, or +`without_skills`, and tools can use that label for grouping and comparison. +However, readers must use row and summary metadata for semantics. If a run is +copied under a different folder, combined with another run, synced to a results +branch, or imported from another machine, the manifest fields still carry the +truth. + +AgentV must not use a semantic `experiments//...` folder hierarchy as the +source of truth. A repository may keep wrapper eval YAML files under a directory +named `experiments/`, but that is user-owned organization for ordinary eval +files. It does not define result identity, runtime behavior, or Dashboard +routing. + +`result_dir` is also allocation. It should stay readable when possible, but it +can be suffixed or otherwise allocated to avoid collisions. The public row +identity is the manifest data, not the directory spelling. + +## Row Metadata Owns Filtering + +Experiment, target, variant, attempt, source eval, source target, imported suite +metadata, repeat policy results, execution status, and artifact path fields +belong in result rows because consumers need to filter after the run is written. + +This supports: + +- multi-target runs where one bundle contains rows for several candidates; +- repeated attempts where one logical case has multiple attempt records; +- imported suites where source suite metadata differs from wrapper eval + metadata; +- Dashboard filters and detail routing without pre-splitting folders for every + view; +- comparison tools that group by experiment, target, variant, attempt, or eval + path; +- adapter projections that can evolve by preserving unknown fields and adding + new sidecar path fields; +- future schema evolution where a new metadata dimension does not require a + directory migration. + +The row contract follows AgentV's wire-format convention: on-disk fields are +`snake_case`, and TypeScript internals translate at the boundary. + +## Margin Evals Alignment + +This aligns with Margin Evals' manifest-first and run-centric lessons: + +- completed runs should have a portable bundle that can be copied or published; +- row manifests should carry enough metadata to reconstruct views and exports; +- dashboards and search tables should be projections, not the source of truth; +- directory layout should be convenient for humans without becoming the query + model. + +AgentV does not copy Margin Evals' exact layout. AgentV keeps its own +`summary.json` plus `index.jsonl` split, AgentV transcript sidecars, repeat-run +attempt folders, generated task bundles, Git-backed result branch model, and +optional detached `artifact_pointers`. + +## Consequences + +Positive: + +- A run bundle remains inspectable with ordinary file tools. +- Dashboard, reports, compare, trend, and adapters can share one canonical + contract. +- Copying or publishing a run does not destroy semantics. +- New filter dimensions can be added as row fields instead of directory + migrations. +- Derived indexes can be deleted and rebuilt from canonical artifacts. + +Negative: + +- Readers must parse `index.jsonl` instead of relying on folder names. +- Docs and examples must teach the summary/index split clearly. +- Some directory names may look meaningful but remain non-authoritative, which + requires discipline in Dashboard and adapter code. + +## Alternatives Considered + +### Semantic experiment folder hierarchy + +Rejected. A hierarchy such as +`experiments/////...` makes simple cases +look organized, but it turns every new filter dimension into a storage decision. +It also breaks down for multi-target runs, imported suites, repeated attempts, +manual grading, combined bundles, and copied result repositories. + +### Single aggregate manifest only + +Rejected. A single `summary.json` with embedded row data would force row +consumers to parse and rewrite a large aggregate document. It would also make +append-mostly result sync and streaming row readers worse. + +### Row index only + +Rejected. A run list should not need to stream every row and hydrate sidecars to +show total tests, pass rate, duration, and cost. `summary.json` is the cheap +aggregate entrypoint. + +### Database as source of truth + +Rejected. SQLite, search tables, Dashboard caches, and hosted backends are +useful projections, but AgentV's zero-infra local and CI path needs portable +files as the canonical contract. + +## Non-Goals + +- Defining a new hosted results store. +- Replacing the normalized transcript contract. +- Projecting AgentV-owned runs, transcripts, datasets, experiments, or indexes + into Phoenix. +- Requiring a semantic `experiments/` directory. +- Removing compatibility readers for older bundles in this ADR. +- Freezing every possible row field. This ADR defines ownership and discovery; + field additions remain additive and versioned. + +## References + +- Strategy: [STRATEGY.md](../../STRATEGY.md) +- Roadmap: [ROADMAP.md](../../ROADMAP.md) +- Product boundary: [.agents/product-boundary.md](../../.agents/product-boundary.md) +- Technical conventions: [.agents/conventions.md](../../.agents/conventions.md) +- Public docs: [Result Artifact Contract](../../apps/web/src/content/docs/docs/reference/result-artifacts.mdx)