Skip to content

feat: read evals from usage artifact instead of dedicated evals artifact#45797

Open
pelikhan with Copilot wants to merge 4 commits into
mainfrom
copilot/update-audit-logs-evals
Open

feat: read evals from usage artifact instead of dedicated evals artifact#45797
pelikhan with Copilot wants to merge 4 commits into
mainfrom
copilot/update-audit-logs-evals

Conversation

Copilot AI commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

evals.jsonl is now included in the usage artifact (conclusion job copies it from the evals job). The client-side --evals flag was still requesting a dedicated evals artifact download and the cache bypass was keyed on the artifact name, which broke silently after the mapping change.

Changes

  • ArtifactSetEvals → resolves to usage (logs_artifact_set.go): --artifacts evals now downloads the usage artifact. runHasEvals already probes usage/evals.jsonl; this aligns the download side with detection.

  • applyEvalsArtifact skips when usage already present (logs_artifact_set.go): The logs default is --artifacts usage; previously --evals appended a redundant evals entry. Now it short-circuits when usage is already in the list.

  • Thread evalsOnly through the download pipeline (logs_run_processor.go, logs_orchestrator.go, logs_orchestrator_stdin.go): The cache bypass in tryLoadCachedRunResult was checking slices.Contains(artifactFilter, "evals") — always false after the mapping change. Replaced with an explicit params.evalsOnly field propagated from the callers.

  • Flag descriptions and comments updated in audit.go and logs_command.go to reflect the usage artifact as the evals source.

  • Test: Added ResolveArtifactFilter(["evals"]) == ["usage"] assertion; updated all downloadRunArtifactsConcurrent call sites with the new evalsOnly parameter.

evals.jsonl is now included in the usage artifact (copied there by the
conclusion job). Update the client-side code accordingly:

- ArtifactSetEvals now resolves to the usage artifact name so that
  --artifacts evals downloads usage (which contains evals.jsonl)
- applyEvalsArtifact no longer appends evals when usage is already in
  the artifacts list, since usage already provides evals
- Thread evalsOnly bool through concurrentRunDownloadParams so the cache
  bypass in tryLoadCachedRunResult uses the explicit flag rather than
  inspecting the artifact filter for a name that no longer matches
- Update --evals flag descriptions in audit and logs commands to reflect
  that evals are read from the usage artifact
- Add TestResolveArtifactFilter case asserting evals→usage resolution

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

🤖 PR Triage

Field Value
Category bug
Risk 🟢 Low
Priority Score 65/100
Action fast_track

Score breakdown: Impact 28/50 · Urgency 20/30 · Quality 17/20

Rationale: Fixes evals artifact resolution regression — --artifacts evals was silently broken after mapping change. Targeted fix (9 files, net -46 lines). Clear description with test. CI not yet run.

Generated by 🔧 PR Triage Agent · 36.7 AIC · ⌖ 7.39 AIC · ⊞ 5.6K ·

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot download evals if not found in usage artifact

Copilot AI and others added 3 commits July 15, 2026 18:57
…tifact

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

@copilot download evals if not found in usage artifact

Done. Added tryDownloadEvalsArtifactFallback in processSingleRunDownload: after downloading the usage artifact, if evals.jsonl is not found, it retries with the dedicated evals artifact. This handles older runs where evals.jsonl was uploaded as a standalone artifact instead of being included in usage.

The fallback is triggered by a new evalsArtifactRequested field (true when --evals is set OR when --artifacts evals was explicitly listed), so both cases are covered. The fallback uses perRunParams to ensure per-run repo context (owner/repo resolved from the run URL) is used, not the empty defaults.

@pelikhan pelikhan marked this pull request as ready for review July 15, 2026 19:51
Copilot AI review requested due to automatic review settings July 15, 2026 19:51
@github-actions

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer is reviewing this pull request using Matt Pocock's engineering skills...

@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR #45797 does not have the 'implementation' label and has ≤100 new lines of code in business logic directories (99 additions, threshold is 100).

@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

@github-actions

Copy link
Copy Markdown
Contributor

🔎 PR Code Quality Reviewer is reviewing code quality for this pull request...

Copilot AI 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.

Pull request overview

Updates eval retrieval to use the usage artifact and adds legacy fallback handling.

Changes:

  • Maps the evals artifact set to usage.
  • Propagates eval-request context through download orchestration.
  • Updates CLI descriptions and tests.
Show a summary per file
File Description
pkg/cli/logs_run_processor.go Adds eval request tracking and legacy fallback.
pkg/cli/logs_parallel_test.go Updates download helper calls.
pkg/cli/logs_orchestrator.go Passes eval context to downloads.
pkg/cli/logs_orchestrator_test.go Updates orchestrator test calls.
pkg/cli/logs_orchestrator_stdin.go Propagates stdin eval options.
pkg/cli/logs_command.go Updates the eval flag description.
pkg/cli/logs_artifact_set.go Maps evals to usage and deduplicates selection.
pkg/cli/logs_artifact_set_test.go Tests evals-to-usage resolution.
pkg/cli/audit.go Updates audit messaging and comments.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 9/9 changed files
  • Comments generated: 2
  • Review effort level: Medium

ensureEvalsResultsFromBranch(ctx, summary.Run, runOutputDir, params.dlOwner, params.dlRepo, params.dlHost, params.verbose)
if evalsRequested && !hasEvals {
logsOrchestratorLog.Printf("Cache bypass for run %d: evals artifact requested but not present locally", run.DatabaseID)
if params.evalsOnly && !hasEvals {
Comment on lines +94 to +95
// evals: evals results are now included in the usage artifact.
ArtifactSetEvals: {constants.UsageArtifactName},
@github-actions github-actions Bot mentioned this pull request Jul 15, 2026

@github-actions github-actions 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.

Review: feat: read evals from usage artifact instead of dedicated evals artifact

The overall approach is correct — remapping ArtifactSetEvals to resolve to the usage artifact and introducing a fallback for older runs is well-designed. One blocking bug was found.

Blocking issue: In tryLoadCachedRunResult (logs_run_processor.go:271), the cache bypass condition was changed from the old evalsRequested (which fired for both --evals and --artifacts evals) to params.evalsOnly (only fires for --evals). The PR already introduces evalsArtifactRequested that covers both cases and uses it correctly in processSingleRunDownload. The same field should be used in tryLoadCachedRunResult for consistency and correctness.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · 40.3 AIC · ⌖ 6.87 AIC · ⊞ 5K

ensureEvalsResultsFromBranch(ctx, summary.Run, runOutputDir, params.dlOwner, params.dlRepo, params.dlHost, params.verbose)
if evalsRequested && !hasEvals {
logsOrchestratorLog.Printf("Cache bypass for run %d: evals artifact requested but not present locally", run.DatabaseID)
if params.evalsOnly && !hasEvals {

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.

Bug: cache bypass uses evalsOnly instead of evalsArtifactRequested

The old code used evalsRequested := slices.Contains(params.artifactFilter, constants.EvalsArtifactName) which was true for both --evals and --artifacts evals. The new code replaces this with params.evalsOnly, which is only true when --evals is passed.

As a result, when a user passes --artifacts evals (without --evals), the cache bypass no longer fires, and a stale cache without evals.jsonl will be returned instead of triggering a fresh download.

The PR already introduces evalsArtifactRequested (which covers both cases) and uses it correctly in processSingleRunDownload line 218. The same field should be used here:

// before
if params.evalsOnly && !hasEvals {

// after
if params.evalsArtifactRequested && !hasEvals {

@copilot please address this.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 90/100 — Excellent

Analyzed 14 test(s): 14 design, 0 implementation, 0 violation(s).

📊 Metrics (14 tests)
Metric Value
Analyzed 14 (Go: 14, JS: 0)
✅ Design 14 (100%)
⚠️ Implementation 0 (0%)
Edge/error coverage 14 (100%)
Duplicate clusters 0
Inflation YES (orchestrator 14:1, justified by concurrency)
🚨 Violations 0
Test File Classification Coverage
TestResolveArtifactFilter (evals case) logs_artifact_set_test.go:161-164 design_test NEW: Validates evals→usage artifact resolution
TestDownloadRunArtifactsConcurrent_EmptyRuns logs_orchestrator_test.go:20 design_test Edge: Empty input handling
TestDownloadRunArtifactsConcurrent_ResultOrdering logs_orchestrator_test.go:28 design_test Concurrent result completeness
TestDownloadRunArtifactsConcurrent_AllProcessed logs_orchestrator_test.go:59 design_test Batch processing guarantee
TestDownloadRunArtifactsConcurrent_ContextCancellation logs_orchestrator_test.go:91 design_test Error: context cancellation
TestDownloadRunArtifactsConcurrent_PartialCancellation logs_orchestrator_test.go:117 design_test Edge: timeout during execution
TestDownloadRunArtifactsConcurrent_NoResourceLeaks logs_orchestrator_test.go:154 design_test Goroutine leak detection
TestDownloadRunArtifactsConcurrent_ConcurrencyLimit logs_orchestrator_test.go:184 design_test Config: concurrency enforcement
TestDownloadRunArtifactsConcurrent_LogsPath logs_orchestrator_test.go:264 design_test Output path validation
TestDownloadRunArtifactsConcurrent_ErrorHandling logs_orchestrator_test.go:287 design_test Error propagation
TestDownloadRunArtifactsConcurrent_MixedConclusions logs_orchestrator_test.go:314 design_test All run conclusion types
TestDownloadRunArtifactsConcurrent_VerboseMode logs_orchestrator_test.go:345 design_test Mode invariants
TestDownloadRunArtifactsConcurrent_ResultStructure logs_orchestrator_test.go:379 design_test Data structure fields
TestDownloadRunArtifactsConcurrent_PanicRecovery logs_orchestrator_test.go:425 design_test Goroutine pool safety
i️ Test Inflation Analysis

logs_orchestrator_test.go: 14 lines added / 1 line in logs_orchestrator.go = 14:1 ratio (exceeds 2:1 threshold)

Justification: All 13 new integration tests cover concurrent download behavior with careful attention to:

  • Context cancellation and timeout edge cases
  • Goroutine resource management and leak prevention
  • Result ordering and completeness guarantees
  • Configuration enforcement (concurrency limits)
  • Error handling across multiple run conclusion types

This is justified complexity: concurrency bugs are silent and hard to reproduce, requiring comprehensive testing of race conditions.

Verdict

Passed. 0% implementation tests (threshold: 30%). No coding guideline violations detected.

Strengths:

  • All 14 tests validate user-visible behavioral contracts (design tests)
  • Comprehensive edge-case and error coverage (cancellation, timeouts, goroutine leaks, empty inputs)
  • No mock library violations; proper Go build tags on all files
  • Clear assertion messages with failure context
  • Feature directly tested: new test case validates "evals resolves to usage artifact" behavior from PR title

Notes:

  • High test count (13 new integration tests) is appropriate for concurrent download feature with complex error conditions
  • Single-line production change in logs_artifact_set.go is well-tested by the new test case
  • Test inflation justified by concurrency testing requirements

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • awmgmcpg

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

🧪 Test quality analysis by Test Quality Sentinel · 27.2 AIC · ⌖ 9.76 AIC · ⊞ 6.8K ·
Comment /review to run again

@github-actions github-actions 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.

✅ Test Quality Sentinel: 90/100 (Excellent). 0% implementation tests (threshold: 30%). All 14 tests are design tests with comprehensive edge-case coverage and no coding guideline violations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants