Repository navigation
feat(metric-benchmark): compute coverage through an Eval Author adapter - #96
Conversation
7851fb5 to
18545f7
Compare
18545f7 to
d25167c
Compare
d25167c to
8ff20b2
Compare
8ff20b2 to
99d7cbc
Compare
Defines an experimental benchmark for evaluating how well our coverage metric predicts evaluation effectiveness through mutation testing. The concise [root README](https://github.com/NVIDIA-NeMo/eval-author/blob/docs/metric-benchmark-design/labs/metric-benchmark/README.md) describes the project, its work-in-progress status, and the expectation that case examples will grow, change, or be dropped as we build in plain sight. Prep is external to this repository; runs consume prepared case examples, fixed subset manifests, and a YAML benchmark definition. The [stage descriptions](https://github.com/NVIDIA-NeMo/eval-author/blob/docs/metric-benchmark-design/labs/metric-benchmark/docs/stages.md) focus on four executable stages: run mutants × eval tasks, compute mutant scores, compute coverage, and correlate the score pairs. The first execution script will be a basic local Harbor loop; NeMo Helix support is planned afterward. The [architecture and both SVG figures](https://github.com/NVIDIA-NeMo/eval-author/blob/docs/metric-benchmark-design/labs/metric-benchmark/docs/architecture.md) explain the inputs, component boundaries, shared results directory, and statistical comparison. This is the documentation-only base of the stack. Implementation PRs #94 → #105 → #106 → #95 → #96 → #97 → #99 inherit the overview and design unchanged. Their detailed CLI guide lives separately in `docs/tools.md`. Validation: the five files in this PR are Markdown/SVG only. Local links and anchors, Markdown fences, headers, SVG XML, and whitespace checks pass; the updated figure was rendered and visually inspected. Restacking preserves all source and test files byte-for-byte. No live evaluations or model calls were made.
99d7cbc to
77563fe
Compare
94337c1 to
d03ec69
Compare
16cb2fb to
d0c0f82
Compare
d0c0f82 to
1da40aa
Compare
0dbdd96 to
aca169c
Compare
40223c4 to
b8219a2
Compare
| Completed subset requests have file-digest receipts. Resume verifies those files | ||
| and inputs before reuse. `--cached-only` prohibits new invocations. A command | ||
| failure preserves its private diagnostic workspace without a completion receipt. | ||
| On POSIX, timeout cancellation kills the command's process group, including its |
There was a problem hiding this comment.
POSIX call out needed here (have we tried any of this on windows haha)?
There was a problem hiding this comment.
Agreed, yea. My move for this is to always say use "WSL" fwiw. :-)
| return False | ||
|
|
||
|
|
||
| def compute_eval_author(request_path: Path) -> Score: |
There was a problem hiding this comment.
minor - might rename this since it's audit specifc
There was a problem hiding this comment.
Agreed, done
aleckhoury
left a comment
There was a problem hiding this comment.
Overall sound. Verified:
- Mutant outcomes never reach coverage requests. Requests carry only the case description, the subset's task IDs, copied baseline evidence with its digests, and the coverage settings.
- Cached responses are reused only when the request digest, the config digest and every saved file match the receipt.
- The adapter builds argv lists (no shell). The
measure.py/report.pyflags and output layout matchskills/eval-author-audit/scripts/audit_spec.
At this head: 158 passed, 1 skipped; ruff is clean. I'd fix the score_scope gate before merge. The other two inline items are smaller.
| for details in sorted(Path("measurements").glob("task=*/run=*/*/details.json")): | ||
| if _unjudged(read_json(details)): | ||
| return Score( | ||
| value=None, reason=f"Eval Author evidence requires missing or unsupported judgments: {details}" | ||
| ) |
There was a problem hiding this comment.
This gate ignores score_scope. Any details.json with unjudged or unsupported evidence nulls the score, even when the score covers a single item kind.
Repro with eval_author_example(non_tool=True): score_scope: tool, and the audit has capability items but no capability judgments.
- Default
methods(all three): every subset is null. methods: [tool_calls]: the same tool-scope score comes out 0.5 / 0.5 / 0.0.
So whether a score is available depends on which extra methods ran, and correlation (#97) then drops those subsets or errors. The required_kinds check below is already scoped this way. Suggest skipping details whose item_kind doesn't match scope when scope != "overall".
There was a problem hiding this comment.
Agreed, done.
| files = file_manifest(workspace) | ||
| score = Score.model_validate(read_json(workspace / "response.json")) | ||
| if any(files.get(name) != digest for name, digest in inputs.items()): | ||
| raise ValueError("coverage system modified its supplied evidence") |
There was a problem hiding this comment.
Diagnostics are kept only for a nonzero exit or a timeout. If the command exits 0 but response.json is missing or invalid, or the command modified its supplied evidence, the exception raised here lets the TemporaryDirectory cleanup delete the whole workspace: the request, authored observations, the bad response and the captured stdout/stderr.
Repro: an adapter that writes authored.txt, prints diag and writes {"value": "oops"} leaves the work root empty. stages.md lists invalid responses and modified inputs as stage failures alongside nonzero exits. Suggest sending these through the same path as lines 142-146: write the logs and rename the workspace to failed-*.
There was a problem hiding this comment.
Agreed, done.
| if not executable.is_absolute(): | ||
| raise ValueError("coverage command must start with an absolute executable path") |
There was a problem hiding this comment.
The docs and fixtures don't reflect this absolute-executable rule:
- The
analysis.ymlexample in benchmark-format.md usescommand: [python, /path/to/coverage-adapter.py], and the nearby text (~131-134) only says "nonempty command argument list". tests/fixtures/metric_benchmark/analysis.ymluses the samepythonform.- compute-coverage.md doesn't mention the rule; only eval-author-coverage.md does.
Copying the documented example passes load_analysis and sha-sign, then fails here. Suggest an absolute interpreter in the example (e.g. [/usr/bin/env, python3, ...], as in the smoke example) and stating the rule in benchmark-format.md and compute-coverage.md.
There was a problem hiding this comment.
Agreed, done.
347fc29 to
44c3225
Compare
…tifacts Signed-off-by: mstaats <mstaats@nvidia.com>
Signed-off-by: mstaats <mstaats@nvidia.com>
Signed-off-by: mstaats <mstaats@nvidia.com>
44c3225 to
9ed018a
Compare
Signed-off-by: mstaats <mstaats@nvidia.com>
|
Agreed, updated. |
Signed-off-by: mstaats <mstaats@nvidia.com>
Compute coverage for each fixed subset using baseline evidence and the case description. Preserve requests, authored observations, response artifacts and receipts; reject stale cached responses. Mutant outcomes are excluded from coverage requests.
compute_coverage.pyis a thin CLI overinvoke_coverage. It accepts cases and analysis configuration, the case ID, saved execution root, work directory and output path. Saved case identities are checked without requiring executable agent bundles or task environments. Command parsing andmain()live in the CLI scripts.The Eval Author adapter invokes the configured author command, then native measurement and reporting scripts through
compute_audit_coverage. Missing judgments affect only the selected score scope. Authoring and semantic judgments may use models; experiment orchestration does not. Invalid responses and modified input evidence retain diagnostic workspaces and logs. Cache errors identify the affected subset. Linux/POSIX behavior, WSL guidance and absolute executable requirements are documented.Usage and artifact contracts:
labs/metric-benchmark/docs/compute-coverage.mdandlabs/metric-benchmark/docs/eval-author-coverage.md.Validation at
11313b3: 3,436 passed, 36 skipped locally; focused coverage/adapter tests 24 passed. Ruff/format, Python 3.12/3.13 type checks, copyright, license and whitespace checks passed. Skips include optional Docker, live-model, external-runtime and platform-specific checks. No new live model or Docker trials were run for these review fixes. Hosted CI passed, including the full Python 3.12 and 3.13 jobs.Earlier pressure testing exercised six real Harbor trials (baseline and one mutant across three tasks), native Eval Author tool-only coverage, cached resume, standalone/coordinator parity and analysis without executable inputs. Constant mutant scores correctly produced unavailable correlation. That exercise validates the pipeline behavior, not scientific metric validity.
Stack after merged #95: main → #96 coverage → #97 correlation → #99 coordinator.