Skip to content

feat(evaluator): add ATIF trace and log read handles for evidence - #432

Merged
arpitsardhana merged 2 commits into
mainfrom
aalgo-258-p0-evidence-metrics/arpsingh
Jun 30, 2026
Merged

feat(evaluator): add ATIF trace and log read handles for evidence#432
arpitsardhana merged 2 commits into
mainfrom
aalgo-258-p0-evidence-metrics/arpsingh

Conversation

@arpitsardhana

@arpitsardhana arpitsardhana commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds the portable trace/log read layer for agent-eval evidence so metrics can score off what the agent actually did (its trace and logs), independent of the producing runtime. Rebased onto main after the filesystem handle / run_verifier / taskset work landed via #447, so this PR is now scoped to trace and log read handles only.

This PR ingests traces in ATIF (Agent Trajectory Interchange Format; RFC 0001). It does not normalize foreign formats — producers are responsible for emitting conformant ATIF, and the SDK validates on read and exposes typed handles.

  • Lightweight ATIF read models (values/atif.py): Trajectory / Step / ToolCall / Metrics / FinalMetrics — a permissive (extra="ignore") read view over just the subset of ATIF the evaluator consumes, rather than vendoring the full reference schema (avoids dependency/licensing bloat and stays forward-compatible).
  • Ingest = validate-on-read (values/evidence.py): parse_atif validates a payload as a Trajectory (raises ValidationError if non-conformant). Trace evidence is persisted in its raw producer form; nothing is normalized at persist time.
  • Read handles: CandidateEvidence.trace()TraceHandle (trace / steps / tool_calls / token_usage) and .logs()LogHandle (list_files / read_text / tail), both async and per-trial cached so sibling metrics share a materialized handle.
  • Well-known keys: WellKnownEvidenceKey Literal (initial_state / trace / logs / final_state / verifier_logs).
  • Example reference metric (examples/run_agent_eval/example_metrics.py, example-only): inefficient_retry_loop scoring off TraceHandle (consecutive-streak detection over a canonical tool-call key).
  • Vendored SDK mirror synced via make vendor.

Test plan

  • ruff check + ruff format --check clean on changed files
  • ty check — no new diagnostics in changed files
  • pytest packages/nemo_evaluator_sdk/tests/agent_eval/ → 67 passed (trace/log handle reads, ATIF validation, example retry-loop metric)
  • make vendor regenerated mirror, no drift
  • CI green

Notes

  • Additions live in values/evidence.py + values/atif.py (no separate value module) per review preference.
  • Ingest-only: no normalization of NAT/OTel/OpenInference. Traces persist raw and are validated lazily by TraceHandle on first read.
  • agent_eval/evaluator.py and agent_eval/trials.py are intentionally not modified by this PR — trace evidence is persisted as-is and read via TraceHandle.

@github-actions github-actions Bot added the feat label Jun 24, 2026
@arpitsardhana arpitsardhana changed the title feat(evaluator): P0 evidence handles, ATIF traces, and taskset feat(evaluator): filesystem extension, Evidence handles, ATIF traces, and taskset Jun 24, 2026
@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 22154/29335 75.5% 60.3%
Integration Tests 12772/28015 45.6% 19.0%

@arpitsardhana
arpitsardhana force-pushed the aalgo-258-p0-evidence-metrics/arpsingh branch 3 times, most recently from 55ce862 to 15882d4 Compare June 24, 2026 22:04
Comment thread packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/evidence.py Outdated
Comment thread packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/evidence.py Outdated
@arpitsardhana
arpitsardhana force-pushed the aalgo-258-p0-evidence-metrics/arpsingh branch 2 times, most recently from 948dc8a to 9c8325f Compare June 26, 2026 06:55
@arpitsardhana arpitsardhana changed the title feat(evaluator): filesystem extension, Evidence handles, ATIF traces, and taskset feat(evaluator): ATIF trace normalization and trace/log evidence read handles Jun 26, 2026
@arpitsardhana arpitsardhana changed the title feat(evaluator): ATIF trace normalization and trace/log evidence read handles feat(evaluator): Evidence handles, ATIF traces and trace normalisation Jun 26, 2026
@arpitsardhana
arpitsardhana marked this pull request as ready for review June 26, 2026 07:00
@arpitsardhana
arpitsardhana requested review from a team as code owners June 26, 2026 07:00
@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds Pydantic ATIF data models (ToolCall, Step, Trajectory, etc.), lazy TraceHandle and LogHandle evidence accessors on CandidateEvidence, a parse_atif helper, and a new InefficientRetryLoopMetric example metric. NoTestCheatingMetric drops configurable evidence name parameters; TestsPassMetric switches to EVIDENCE_FINAL_STATE.

Changes

ATIF trace evidence and retry metrics

Layer / File(s) Summary
ATIF data models
src/nemo_evaluator_sdk/values/atif.py
New module with Pydantic models for ToolCall, Metrics, FinalMetrics, Step, and Trajectory; validates schema_version starts with "ATIF-".
Trace and log evidence handles
src/nemo_evaluator_sdk/values/evidence.py, src/nemo_evaluator_sdk/values/__init__.py
parse_atif, TraceHandle (lazy load/validate trajectory, expose steps/tool_calls/token_usage), and LogHandle (list/read/tail log bundle) are added; CandidateEvidence gets cached trace()/logs() accessors; all new types re-exported from the values package.
Example metrics updates and InefficientRetryLoopMetric
examples/run_agent_eval/example_metrics.py
Imports switch to SDK evidence constants; NoTestCheatingMetric removes initial_name/final_name params (hardcodes EVIDENCE_INITIAL_STATE/EVIDENCE_FINAL_STATE); InefficientRetryLoopMetric added to detect repeated consecutive tool calls in traces.
Evidence and metrics tests
tests/agent_eval/test_evidence.py, tests/agent_eval/test_example_metrics.py
Tests cover TraceHandle/LogHandle caching and correctness, ValidationError on invalid ATIF payloads, verifier timeout PID polling refactor, and InefficientRetryLoopMetric with looping vs. clean traces.

Possibly related PRs

  • NVIDIA-NeMo/nemo-platform#339: Introduces the core EvidenceDescriptor/CandidateEvidence/LocalFilesystemEvidence foundation that this PR extends with trace/log handles.
  • NVIDIA-NeMo/nemo-platform#447: Modifies the same example_metrics.py file around TestsPassMetric/NoTestCheatingMetric signatures.

Suggested reviewers

  • SandyChapman
  • ngoncharenko
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.90% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding trace and log read handles for evidence.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch aalgo-258-p0-evidence-metrics/arpsingh

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

♻️ Duplicate comments (1)
packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/trials.py (1)

161-168: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

This strips source format for file-based traces.

standard_evidence_descriptors() can now only emit atif or json, so OTEL/OpenInference exports passed via trace_path can never hit their normalizers on this path. This needs an explicit trace-format input instead of filename heuristics.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/trials.py`
around lines 161 - 168, The trace descriptor normalization is using filename
heuristics in standard_evidence_descriptors() / the trace_path handling, which
causes file-based OTEL/OpenInference traces to lose their original format.
Update the evidence-building flow to accept an explicit trace-format input and
pass that through when constructing the EvidenceDescriptor for EVIDENCE_TRACE,
instead of inferring “atif” vs “json” from is_atif or the path name. Ensure
normalize_trace_descriptor and the caller in trials.py preserve the source
format so the correct normalizer can run.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/nemo_evaluator_sdk/examples/run_agent_eval/example_metrics.py`:
- Around line 19-21: The retry detection in the example metrics logic is
counting global frequency instead of consecutive repeats, so update the relevant
code in example_metrics.py to measure the longest streak of identical calls in
the trace rather than total occurrences. In the call-counting path around the
metrics computation (the logic that uses EVIDENCE_TRACE), canonicalize nested
args before comparing so semantically equivalent dicts with different insertion
order map to the same payload, and keep the streak bounded to adjacent entries
only. Use the existing symbols EVIDENCE_TRACE, EVIDENCE_INITIAL_STATE, and
EVIDENCE_FINAL_STATE to locate the trace-processing code and adjust the retry
metric accordingly.

In `@packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/evidence.py`:
- Around line 490-510: normalize_trace() currently drops any list-shaped payload
unless source_format is explicitly otel/openinference, which can erase live
evaluator trajectory evidence. Update normalize_trace() in evidence.py to
preserve unknown list traces by either routing them through the appropriate
list-based normalizer or explicitly validating and rejecting unsupported list
shapes instead of returning an empty AtifTrace(). Keep the existing dict
handling for steps/events and ensure the fallback path for bare lists is handled
safely rather than silently discarding data.
- Around line 534-541: The ref-handling in `_local_filesystem_ref()` / the
`descriptor.ref is not None` branch currently raises for remote refs before the
`is_file()` no-op path can run, which conflicts with the documented behavior.
Update the logic so non-local or unresolvable refs are detected and returned
unchanged in `descriptor.model_copy` flow, and only call
`_local_filesystem_ref()` after confirming the ref is local or otherwise safe to
resolve. Keep the existing `normalize_trace` and `.atif.json` write path for
local files, but preserve the unchanged descriptor behavior for remote refs.
- Around line 671-682: The `Evidence.trace()` accessor is currently using
`self.require(name)` without verifying the descriptor kind, so a non-trace entry
can be wrapped as a `TraceHandle` and look valid. Update `trace()` to enforce
`kind="trace"` before constructing the handle, matching the stricter contract
already implied by `TraceHandle` and the existing `filesystem()`/`logs()`
accessors. Keep the cache behavior in `_trace_cache`, but ensure only true trace
descriptors are accepted and anything else fails immediately.

In `@packages/nemo_evaluator_sdk/tests/agent_eval/test_evidence.py`:
- Around line 5-7: The process cleanup assertion in test_evidence.py is using a
fixed 200 ms wait, which can make the test flaky if the child is briefly a
zombie on a busy runner. Update the test around the cleanup check to poll
`os.kill(pid, 0)` until a short deadline instead of sleeping once, so the
assertion waits for reaping to complete. Use the existing process-tree
cleanup/test logic in `test_evidence` to locate the affected check and keep the
polling window small.

---

Duplicate comments:
In `@packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/trials.py`:
- Around line 161-168: The trace descriptor normalization is using filename
heuristics in standard_evidence_descriptors() / the trace_path handling, which
causes file-based OTEL/OpenInference traces to lose their original format.
Update the evidence-building flow to accept an explicit trace-format input and
pass that through when constructing the EvidenceDescriptor for EVIDENCE_TRACE,
instead of inferring “atif” vs “json” from is_atif or the path name. Ensure
normalize_trace_descriptor and the caller in trials.py preserve the source
format so the correct normalizer can run.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 739e49cd-e370-4b40-991d-c3b8b5189fc5

📥 Commits

Reviewing files that changed from the base of the PR and between e1ac31b and 9c8325f.

⛔ Files ignored due to path filters (4)
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/evaluator.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/trials.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/values/__init__.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/values/evidence.py is excluded by !sdk/**
📒 Files selected for processing (7)
  • packages/nemo_evaluator_sdk/examples/run_agent_eval/example_metrics.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/evaluator.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/trials.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/__init__.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/evidence.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_evidence.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_example_metrics.py

Comment thread packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/evidence.py Outdated
Comment thread packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/evidence.py Outdated
Comment thread packages/nemo_evaluator_sdk/tests/agent_eval/test_evidence.py
Comment thread packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/evidence.py Outdated
@arpitsardhana
arpitsardhana force-pushed the aalgo-258-p0-evidence-metrics/arpsingh branch from 9c8325f to 2da7a67 Compare June 26, 2026 07:52
Comment thread packages/nemo_evaluator_sdk/examples/run_agent_eval/example_metrics.py Outdated
Comment thread packages/nemo_evaluator_sdk/examples/run_agent_eval/example_metrics.py Outdated
Comment thread packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/evidence.py Outdated
Comment thread packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/evaluator.py Outdated
Comment thread packages/nemo_evaluator_sdk/examples/run_agent_eval/example_metrics.py Outdated
Comment thread packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/evidence.py Outdated
@arpitsardhana
arpitsardhana force-pushed the aalgo-258-p0-evidence-metrics/arpsingh branch from 2da7a67 to 8975314 Compare June 30, 2026 05:57

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/evidence.py`:
- Around line 520-522: Reject non-local trace refs before caching the
TraceHandle in the trace lookup flow, so self.require(name, kind="trace") cannot
store a handle that will later fail in TraceHandle._load_payload() via
_local_filesystem_ref(). Update the relevant trace-loading path and any shared
helper used by the trace cache (including the related logic around
normalize_trace_descriptor() and the affected duplicate block) to validate the
ref is local first, and raise a trace-level contract error instead of letting a
filesystem ValueError surface on first read.
- Around line 368-380: The trace validation logic in the descriptor
normalization path is skipping any descriptor already stamped with
format="atif", which allows malformed inline or local ATIF payloads to bypass
validation. Update the validation branch in evidence.py so resolvable ATIF
descriptors (including those with descriptor.format already set to "atif" and a
local ref or inline data) still flow through
parse_atif(_read_trace_payload(descriptor)) before returning, while preserving
the existing early return for non-trace descriptors and non-local refs. Keep the
behavior in the same validation helper that currently uses
_local_filesystem_ref, _read_trace_payload, and parse_atif so persist-time
validation remains enforced consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: e6403cd5-6d4a-45fc-8998-122585081f5e

📥 Commits

Reviewing files that changed from the base of the PR and between 2da7a67 and 8975314.

⛔ Files ignored due to path filters (5)
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/evaluator.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/trials.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/values/__init__.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/values/atif.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/values/evidence.py is excluded by !sdk/**
📒 Files selected for processing (10)
  • packages/nemo_evaluator_sdk/examples/run_agent_eval/example_metrics.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/evaluator.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/trials.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/__init__.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/atif.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/evidence.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_evaluator.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_evidence.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_example_metrics.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_trials.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/init.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/trials.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/evaluator.py

Comment thread packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/evidence.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/evaluator.py`:
- Line 47: The evaluator is still persisting sample["trajectory"] with
format="atif" even though it is no longer normalized, which can break later
parsing in TraceHandle.trace(). Update the logic around
EvidenceDescriptor/CandidateEvidence creation to either normalize the trajectory
before saving or validate its shape and reject non-ATIF payloads; do not label
raw NAT/OpenTelemetry/OpenInference traces as ATIF unless they are actually
converted to that contract.

In `@packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/trials.py`:
- Line 17: The trace-path handling in trials.py is hard-coding format="atif" for
every trace file, which bypasses the existing normalization/validation flow.
Update the trace-path helper that feeds TraceHandle to use the normalizer again,
and only preserve ATIF after validating the trace content rather than stamping
all inputs as ATIF. Make the fix in the trace_path-related logic and the related
import/use site so non-ATIF JSON traces are not persisted with the wrong
contract.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 4c1f389a-2329-494d-abd7-212ca86c1fc4

📥 Commits

Reviewing files that changed from the base of the PR and between 8975314 and 599051d.

⛔ Files ignored due to path filters (4)
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/evaluator.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/trials.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/values/__init__.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/values/evidence.py is excluded by !sdk/**
📒 Files selected for processing (5)
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/evaluator.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/trials.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/__init__.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/evidence.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_evidence.py
💤 Files with no reviewable changes (3)
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/init.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_evidence.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/evidence.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/evaluator.py`:
- Line 47: The evaluator is still persisting sample["trajectory"] with
format="atif" even though it is no longer normalized, which can break later
parsing in TraceHandle.trace(). Update the logic around
EvidenceDescriptor/CandidateEvidence creation to either normalize the trajectory
before saving or validate its shape and reject non-ATIF payloads; do not label
raw NAT/OpenTelemetry/OpenInference traces as ATIF unless they are actually
converted to that contract.

In `@packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/trials.py`:
- Line 17: The trace-path handling in trials.py is hard-coding format="atif" for
every trace file, which bypasses the existing normalization/validation flow.
Update the trace-path helper that feeds TraceHandle to use the normalizer again,
and only preserve ATIF after validating the trace content rather than stamping
all inputs as ATIF. Make the fix in the trace_path-related logic and the related
import/use site so non-ATIF JSON traces are not persisted with the wrong
contract.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 4c1f389a-2329-494d-abd7-212ca86c1fc4

📥 Commits

Reviewing files that changed from the base of the PR and between 8975314 and 599051d.

⛔ Files ignored due to path filters (4)
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/evaluator.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/trials.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/values/__init__.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/values/evidence.py is excluded by !sdk/**
📒 Files selected for processing (5)
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/evaluator.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/trials.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/__init__.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/evidence.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_evidence.py
💤 Files with no reviewable changes (3)
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/init.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_evidence.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/evidence.py
🛑 Comments failed to post (2)
packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/evaluator.py (1)

47-47: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Don't relabel unnormalized inline traces as ATIF.

This path stopped normalizing sample["trajectory"] but still persists it with format="atif". Any NAT / OpenTelemetry / OpenInference payload will now be stored under the ATIF contract and fail later when TraceHandle.trace() parses it. Normalize or validate before writing the descriptor.

Proposed fix
-from nemo_evaluator_sdk.values.evidence import CandidateEvidence, EvidenceDescriptor
+from nemo_evaluator_sdk.values.evidence import (
+    CandidateEvidence,
+    EvidenceDescriptor,
+    normalize_trace_descriptor,
+)
...
-        # Persist the producer's trajectory as-is (ATIF); TraceHandle validates on read.
-        trace = EvidenceDescriptor(kind="trace", format="atif", data=sample["trajectory"])
+        trace = normalize_trace_descriptor(
+            EvidenceDescriptor(kind="trace", data=sample["trajectory"])
+        )

Also applies to: 329-331

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/evaluator.py`
at line 47, The evaluator is still persisting sample["trajectory"] with
format="atif" even though it is no longer normalized, which can break later
parsing in TraceHandle.trace(). Update the logic around
EvidenceDescriptor/CandidateEvidence creation to either normalize the trajectory
before saving or validate its shape and reject non-ATIF payloads; do not label
raw NAT/OpenTelemetry/OpenInference traces as ATIF unless they are actually
converted to that contract.
packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/trials.py (1)

17-17: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Don't stamp every trace_path as ATIF.

TraceHandle only reads ATIF. This helper now sets format="atif" for any trace file without normalizing or validating it first, so non-ATIF JSON traces will be persisted with the wrong contract and blow up when metrics read them. Restore the normalizer here instead of hard-coding the format.

Proposed fix
-from nemo_evaluator_sdk.values.evidence import CandidateEvidence, EvidenceDescriptor
+from nemo_evaluator_sdk.values.evidence import (
+    CandidateEvidence,
+    EvidenceDescriptor,
+    normalize_trace_descriptor,
+)
...
-        # Persist the producer-written trace as-is (ATIF); TraceHandle validates on read.
-        descriptors[EVIDENCE_TRACE] = EvidenceDescriptor(
-            kind="trace",
-            format="atif",
-            ref=str(trace_path),
-        )
+        descriptors[EVIDENCE_TRACE] = normalize_trace_descriptor(
+            EvidenceDescriptor(kind="trace", ref=str(trace_path))
+        )

Also applies to: 159-163

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/trials.py` at
line 17, The trace-path handling in trials.py is hard-coding format="atif" for
every trace file, which bypasses the existing normalization/validation flow.
Update the trace-path helper that feeds TraceHandle to use the normalizer again,
and only preserve ATIF after validating the trace content rather than stamping
all inputs as ATIF. Make the fix in the trace_path-related logic and the related
import/use site so non-ATIF JSON traces are not persisted with the wrong
contract.

@arpitsardhana arpitsardhana changed the title feat(evaluator): Evidence handles, ATIF traces and trace normalisation feat(evaluator): Add Evidence handles for logs and traces Jun 30, 2026
@arpitsardhana
arpitsardhana force-pushed the aalgo-258-p0-evidence-metrics/arpsingh branch from 599051d to 5998f9f Compare June 30, 2026 06:42
@arpitsardhana arpitsardhana changed the title feat(evaluator): Add Evidence handles for logs and traces feat(evaluator): add ATIF trace and log read handles for evidence Jun 30, 2026
Comment thread packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/evidence.py Outdated
Add read handles over candidate evidence for agent-eval metrics:

- TraceHandle exposes a trace descriptor as an ATIF Trajectory with
  step/tool-call/token-usage views; lightweight ATIF read models live in
  values/atif.py (validated on read via parse_atif, raw payload persisted,
  no normalization — producers emit conformant ATIF).
- LogHandle for log-bundle access and LocalFilesystemEvidence helpers
  (diff, unified_diff, run_verifier with symlink hardening).
- WellKnownEvidenceKey literal and example metrics updates.

Vendored mirror synced via make vendor.

Signed-off-by: Arpit Singh (SW-CLOUD) <arpsingh@nvidia.com>
@arpitsardhana
arpitsardhana force-pushed the aalgo-258-p0-evidence-metrics/arpsingh branch from 5998f9f to c94721e Compare June 30, 2026 18:37
@arpitsardhana
arpitsardhana enabled auto-merge June 30, 2026 18:53
- Restore the symlink-safety comment in run_verifier explaining why
  copytree(symlinks=True) is safe (the ignore hook drops escaping links).
- Reference AgentEvalTrial (not AgentEvalAttempt) in the CandidateEvidence
  docstring.

Vendored mirror synced via make vendor.

Signed-off-by: Arpit Singh (SW-CLOUD) <arpsingh@nvidia.com>
@arpitsardhana
arpitsardhana force-pushed the aalgo-258-p0-evidence-metrics/arpsingh branch from c94721e to fcd211d Compare June 30, 2026 19:34
@arpitsardhana
arpitsardhana added this pull request to the merge queue Jun 30, 2026
Merged via the queue into main with commit 3dd6a44 Jun 30, 2026
52 checks passed
@arpitsardhana
arpitsardhana deleted the aalgo-258-p0-evidence-metrics/arpsingh branch June 30, 2026 19:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants