Skip to content

Add concrete judge metric families - #34

Merged
kubernetes-prow[bot] merged 3 commits into
kubernetes-sigs:mainfrom
eugeneng04:add-concrete-metrics
Jul 21, 2026
Merged

Add concrete judge metric families#34
kubernetes-prow[bot] merged 3 commits into
kubernetes-sigs:mainfrom
eugeneng04:add-concrete-metrics

Conversation

@eugeneng04

@eugeneng04 eugeneng04 commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Adds the five judge metric families and wires them into the scoring surface.

Metric families (devops_bench/metrics/)

  • grounding.py — documentation-grounding scoring and doc-retrieval rate.
  • tool_invocation.py — tool-invocation correctness metric.
  • checklist.py — checklist extraction and scoring.
  • outcome_validity.py — outcome-validity metric.
  • chaos_metrics.py — chaos-scenario scoring.

Each family self-registers into the METRICS registry on import. pipeline.py
imports them for those registration side effects and re-exports the checklist
helpers, and the package __init__ now exposes the full scoring surface
(evaluate_metrics_batch, the judge accessors, and the per-family builders).

Unit tests are co-located under tests/unit/metrics/: the existing
test_metrics_pipeline.py gains the concrete-family coverage alongside the
stub-based dispatch tests, and new tests cover grounding, chaos, and the skill
loaders.

Summary by CodeRabbit

  • New Features

    • Added checklist-based evaluation of critical requirements.
    • Added outcome validity and tool-invocation scoring.
    • Added documentation grounding and retrieval-rate metrics.
    • Added chaos diagnosis, recovery, and performance evaluation.
    • Added batch processing across all applicable metrics with isolated failures.
    • Expanded the metrics API with additional evaluation helpers and model access.
  • Tests

    • Added comprehensive coverage for metric scoring, filtering, aggregation, ordering, and error handling.

@kubernetes-prow kubernetes-prow Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 21, 2026
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The metrics package adds checklist, outcome-validity, tool-invocation, grounding, retrieval, chaos, and batch evaluators. It expands public exports, normalizes pipeline contexts, preserves score ordering, isolates metric failures, and adds unit coverage for evaluator behavior and packaged criteria loading.

Changes

Metrics evaluation framework

Layer / File(s) Summary
Metric builders and public contracts
devops_bench/metrics/__init__.py, devops_bench/metrics/outcome_validity.py, devops_bench/metrics/tool_invocation.py, tests/unit/metrics/test_metrics_skills.py
Packaged criteria loaders, GEval builders, registered evaluators, generation-only handling, and package-level exports are added and tested.
Checklist, grounding, and chaos scoring
devops_bench/metrics/checklist.py, devops_bench/metrics/grounding.py, devops_bench/metrics/chaos_metrics.py, tests/unit/metrics/test_metrics_grounding.py, tests/unit/metrics/test_metrics_chaos.py, tests/unit/metrics/test_metrics_pipeline.py
Checklist extraction and aggregation, documentation retrieval and grounding aggregation, chaos diagnosis/recovery scoring, performance passthroughs, and related unit tests are added.
Batch metric orchestration
devops_bench/metrics/pipeline.py, tests/unit/metrics/test_metrics_pipeline.py
Batch evaluation resolves MCP settings, builds normalized contexts, orders registered evaluators, records scores, warns on missing expected output, and isolates evaluator failures.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested labels: kind/feature, approved

Suggested reviewers: janetkuo, itssimrank

Sequence Diagram(s)

sequenceDiagram
  participant DetailedResults
  participant evaluate_metrics_batch
  participant METRICS
  participant MetricEvaluator
  participant Scores
  DetailedResults->>evaluate_metrics_batch: provide result and judge model
  evaluate_metrics_batch->>METRICS: select ordered evaluators
  METRICS->>MetricEvaluator: evaluate applicable MetricContext
  MetricEvaluator->>Scores: return MetricScore entries
  evaluate_metrics_batch->>DetailedResults: store scores
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.09% 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 reflects the main change: adding several concrete judge metric families.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@kubernetes-prow
kubernetes-prow Bot requested a review from janetkuo July 21, 2026 18:34
@kubernetes-prow kubernetes-prow Bot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Jul 21, 2026
@kubernetes-prow

Copy link
Copy Markdown

Hi @eugeneng04. Thanks for your PR.

I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Tip

We noticed you've done this a few times! Consider joining the org to skip this step and gain /lgtm and other bot rights. We recommend asking approvers on your previous PRs to sponsor you.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@kubernetes-prow kubernetes-prow Bot added needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Jul 21, 2026
@janetkuo

Copy link
Copy Markdown
Member

/ok-to-test

@kubernetes-prow kubernetes-prow Bot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Jul 21, 2026
@eugeneng04
eugeneng04 marked this pull request as ready for review July 21, 2026 19:41
@kubernetes-prow kubernetes-prow Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 21, 2026
Adds the five judge metric families that self-register into the METRICS
registry: grounding, tool-invocation, checklist, outcome-validity, and
chaos metrics. The batch pipeline imports them for their registration
side effects and re-exports the checklist helpers, and the package
__init__ exposes the full scoring surface.

Signed-off-by: Eugene Ng <ngeugene@google.com>
@eugeneng04
eugeneng04 force-pushed the add-concrete-metrics branch from 0ce150b to 0435f13 Compare July 21, 2026 19:49

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (6)
devops_bench/verification/spec.py (2)

42-56: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

json_schema() embeds each member's own $defs instead of hoisting them to a shared root.

Each m.model_json_schema() call returns a self-contained document with its own local $defs. Placing these raw dicts directly inside anyOf (rather than $ref-pointing into a shared root-level $defs) means any future verifier with a nested BaseModel field would produce a $ref: "#/$defs/X" that resolves against the outer combined document root, not its own nested $defs — breaking ref resolution for schema consumers. Pydantic's own multi-model combination helper avoids exactly this by hoisting $defs to the top level and using $ref pointers in anyOf.

♻️ Proposed fix using `models_json_schema`
+from pydantic.json_schema import models_json_schema
+
 def json_schema() -> dict[str, Any]:
     members = list(VERIFIERS.values())
-    return {
-        "title": "VerificationSpec",
-        "anyOf": [m.model_json_schema() for m in members],
-        "discriminator": {"propertyName": "type"},
-    }
+    _, top_level_schema = models_json_schema(
+        [(m, "validation") for m in members], title="VerificationSpec"
+    )
+    top_level_schema["anyOf"] = [
+        {"$ref": f"`#/`$defs/{m.__name__}"} for m in members
+    ]
+    top_level_schema["discriminator"] = {"propertyName": "type"}
+    return top_level_schema

Since this touches pydantic's schema-combination API, please confirm the exact models_json_schema signature/behavior for the pydantic version pinned in this repo before applying.

🤖 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 `@devops_bench/verification/spec.py` around lines 42 - 56, Update json_schema()
to combine VERIFIERS models using Pydantic’s version-pinned models_json_schema
helper rather than embedding each model_json_schema() result directly in anyOf.
Confirm the helper’s exact signature and output for the repository’s Pydantic
version, then return its combined schema with shared root-level $defs and
correctly resolved anyOf references while preserving the VerificationSpec title
and type discriminator.

144-190: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Untrusted type_key is f-string-interpolated into a PydanticCustomError message template.

_validation_error builds messages like f"unknown verifier type {type_key!r}; ..." and hands the already-interpolated string to PydanticCustomError as its template. Since that template is documented to be rendered with {curly_brace} placeholders, a type value containing literal braces (e.g. "{oops}") would leave an unmatched placeholder in the template, risking a rendering error instead of the intended ValidationError. Pydantic's documented pattern is to pass the raw value via the context dict instead of pre-formatting it into the template.

🛡️ Proposed fix passing values via context
-        raise _validation_error(
-            "verification_spec_unknown_type",
-            (f"unknown verifier type {type_key!r}; registered: {sorted(VERIFIERS.keys())}"),
-            input_value=data,
-        ) from exc
+        raise _validation_error(
+            "verification_spec_unknown_type",
+            "unknown verifier type {type_key!r}; registered: {registered!r}",
+            input_value=data,
+            context={"type_key": type_key, "registered": sorted(VERIFIERS.keys())},
+        ) from exc

(with _validation_error extended to accept and forward a context dict to PydanticCustomError.)

Please confirm this rendering behavior against the pydantic-core version pinned in this repo.

🤖 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 `@devops_bench/verification/spec.py` around lines 144 - 190, Update the
unknown-type handling in the verifier validation flow and _validation_error so
untrusted type_key values are passed to PydanticCustomError through its context
rather than interpolated into the message template. Extend _validation_error to
accept and forward context, use a static template with a named placeholder for
the verifier type, and preserve the resulting ValidationError behavior for
values containing literal braces. Confirm the implementation matches the pinned
pydantic-core API.
tests/unit/verification/test_base.py (1)

22-66: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test functions are missing return type annotations. Both files' test functions omit -> None, the shared root cause being no consistent return-type annotation on any test function in this PR's verification test suite.

  • tests/unit/verification/test_base.py#L22-L66: add -> None to test_default_fields_match_contract, test_compound_result_carries_children_not_raw, test_leaf_result_carries_raw_not_children, and test_no_details_field.
  • tests/unit/verification/test_verifier_registry.py#L33-L114: add -> None to test_dummy_verifier_parses_without_union_edit, test_unknown_type_lists_registered_keys_in_error, test_already_parsed_unregistered_basemodel_is_rejected, and test_unregistered_basemodel_as_checks_child_is_rejected.

As per path instructions, tests/**/*.py should "Ensure test functions have proper type annotations and clean structure."

🤖 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 `@tests/unit/verification/test_base.py` around lines 22 - 66, Add -> None
return annotations to test_default_fields_match_contract,
test_compound_result_carries_children_not_raw,
test_leaf_result_carries_raw_not_children, and test_no_details_field in
tests/unit/verification/test_base.py, and to
test_dummy_verifier_parses_without_union_edit,
test_unknown_type_lists_registered_keys_in_error,
test_already_parsed_unregistered_basemodel_is_rejected, and
test_unregistered_basemodel_as_checks_child_is_rejected in
tests/unit/verification/test_verifier_registry.py; make no other changes.

Source: Path instructions

devops_bench/verification/runner.py (1)

152-204: 🩺 Stability & Availability | 🔵 Trivial

Design note: parallel worker threads can outlive the returned result if a leaf ignores its timeout budget.

ex.shutdown(wait=False, cancel_futures=True) only drops queued-but-not-started futures; in-flight workers keep running after _run_parallel returns. This is fine as documented, contingent on every BaseVerifier.verify honoring timeout_sec. If a future leaf implementation blocks past its budget (e.g. a raw blocking call with no internal timeout), the non-daemon ThreadPoolExecutor threads can hold the process open past the point this function already reported a timeout. Worth keeping an eye on as new leaf verifiers are added, since this file can't enforce that contract on their behalf.

🤖 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 `@devops_bench/verification/runner.py` around lines 152 - 204, Ensure every
leaf verifier invoked through _run_parallel and its _run path strictly honors
the provided deadline/timeout budget, including blocking operations such as
kubectl wait or poll_until. Audit BaseVerifier.verify implementations and add
bounded timeouts where needed; preserve the existing parallel result handling
while preventing in-flight worker threads from outliving the returned timeout
result.
tests/unit/verification/test_verifier_registry.py (1)

36-68: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test cleanup reaches into Registry._items (private attribute).

Popping VERIFIERS._items directly couples this test to the registry's internal representation. A public Registry.unregister()/context-manager, or a pytest fixture with yield+teardown, would keep the cleanup robust if Registry's internals change, and would better satisfy the path instruction to ensure "clean structure" for test fixtures.

As per path instructions, tests/**/*.py should have "proper type annotations and clean structure," which suggests this cleanup could use a public API or fixture instead of a private-attribute reach-through.

🤖 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 `@tests/unit/verification/test_verifier_registry.py` around lines 36 - 68,
Replace the direct VERIFIERS._items mutation in the test cleanup with the
registry’s public unregister or scoped-registration mechanism; if unavailable,
add a pytest yield fixture that performs supported teardown. Keep the
dummy_check registration isolated and ensure cleanup still runs after both
verification scenarios without relying on Registry internals.

Source: Path instructions

tests/unit/metrics/test_metrics_pipeline.py (1)

33-394: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test functions lack return-type annotations across all three new test modules. None of the new test functions (nor their mocker/caplog fixture parameters) carry type hints, the shared root cause for all three files below.

  • tests/unit/metrics/test_metrics_pipeline.py#L33-L394: annotate each def test_*(...) with -> None and type the mocker/caplog fixture parameters (e.g. mocker: MockerFixture).
  • tests/unit/metrics/test_metrics_chaos.py#L33-L86: annotate test_chaos_records_geval_and_perf/test_chaos_defaults_fault_and_survives_eval_error with -> None and type mocker.
  • tests/unit/metrics/test_metrics_grounding.py#L34-L213: annotate all test_* functions with -> None and type mocker on the GEval-mocked tests.

As per path instructions, tests/**/*.py should "Ensure test functions have proper type annotations and clean structure."

🤖 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 `@tests/unit/metrics/test_metrics_pipeline.py` around lines 33 - 394, Add ->
None return annotations to every test_* function in
tests/unit/metrics/test_metrics_pipeline.py (lines 33-394),
tests/unit/metrics/test_metrics_chaos.py (lines 33-86), and
tests/unit/metrics/test_metrics_grounding.py (lines 34-213); annotate each
mocker fixture parameter with MockerFixture and each caplog fixture parameter
with the appropriate logging capture fixture type, adding required imports. Keep
non-fixture parameters and test behavior unchanged.

Source: Path instructions

🤖 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 `@devops_bench/metrics/chaos_metrics.py`:
- Around line 26-31: Update the chaos GEval metric definitions diag_metric and
rec_metric to pass GEVAL_PASS_THRESHOLD explicitly to their threshold
configuration, matching sibling metrics and preserving consistent success
evaluation.

In `@devops_bench/metrics/grounding.py`:
- Around line 67-84: Update the retrieval-rate logic around accessed_docs so
each documentation entry matched in the trajectory increments the accessed count
directly, rather than storing doc_name values in a set. Preserve the existing
doc_name and URL matching guards, and calculate the rate from the number of
matched documentation entries.

In `@devops_bench/metrics/outcome_validity.py`:
- Around line 73-99: Apply complete type annotations across the metrics and test
surfaces: annotate the model parameter in build_outcome_validity_metric within
devops_bench/metrics/outcome_validity.py lines 73-99 and the corresponding model
parameter in devops_bench/metrics/tool_invocation.py lines 59-79; annotate all
helpers, fixture parameters, and test functions with return types including None
in tests/unit/metrics/test_metrics_geval.py lines 26-124; and annotate stub
methods, helpers, nested fake-resource methods, and tests in
tests/unit/metrics/test_metrics_skills.py lines 31-150.

In `@devops_bench/verification/spec.py`:
- Around line 122-134: Update the parse_node doctest to use a verifier type
registered in the repository, or explicitly import the registration path before
constructing the pod_healthy example. Keep the example’s discriminator behavior
and bare-list rejection assertions unchanged, and ensure doctest can resolve the
selected type without relying on unavailable registration.

In `@tests/unit/verification/test_package_import.py`:
- Line 27: Update test_import_pulls_no_heavy_sdks with the required return type
hint and a concise docstring describing what the test verifies, while preserving
its existing test behavior.

---

Nitpick comments:
In `@devops_bench/verification/runner.py`:
- Around line 152-204: Ensure every leaf verifier invoked through _run_parallel
and its _run path strictly honors the provided deadline/timeout budget,
including blocking operations such as kubectl wait or poll_until. Audit
BaseVerifier.verify implementations and add bounded timeouts where needed;
preserve the existing parallel result handling while preventing in-flight worker
threads from outliving the returned timeout result.

In `@devops_bench/verification/spec.py`:
- Around line 42-56: Update json_schema() to combine VERIFIERS models using
Pydantic’s version-pinned models_json_schema helper rather than embedding each
model_json_schema() result directly in anyOf. Confirm the helper’s exact
signature and output for the repository’s Pydantic version, then return its
combined schema with shared root-level $defs and correctly resolved anyOf
references while preserving the VerificationSpec title and type discriminator.
- Around line 144-190: Update the unknown-type handling in the verifier
validation flow and _validation_error so untrusted type_key values are passed to
PydanticCustomError through its context rather than interpolated into the
message template. Extend _validation_error to accept and forward context, use a
static template with a named placeholder for the verifier type, and preserve the
resulting ValidationError behavior for values containing literal braces. Confirm
the implementation matches the pinned pydantic-core API.

In `@tests/unit/metrics/test_metrics_pipeline.py`:
- Around line 33-394: Add -> None return annotations to every test_* function in
tests/unit/metrics/test_metrics_pipeline.py (lines 33-394),
tests/unit/metrics/test_metrics_chaos.py (lines 33-86), and
tests/unit/metrics/test_metrics_grounding.py (lines 34-213); annotate each
mocker fixture parameter with MockerFixture and each caplog fixture parameter
with the appropriate logging capture fixture type, adding required imports. Keep
non-fixture parameters and test behavior unchanged.

In `@tests/unit/verification/test_base.py`:
- Around line 22-66: Add -> None return annotations to
test_default_fields_match_contract,
test_compound_result_carries_children_not_raw,
test_leaf_result_carries_raw_not_children, and test_no_details_field in
tests/unit/verification/test_base.py, and to
test_dummy_verifier_parses_without_union_edit,
test_unknown_type_lists_registered_keys_in_error,
test_already_parsed_unregistered_basemodel_is_rejected, and
test_unregistered_basemodel_as_checks_child_is_rejected in
tests/unit/verification/test_verifier_registry.py; make no other changes.

In `@tests/unit/verification/test_verifier_registry.py`:
- Around line 36-68: Replace the direct VERIFIERS._items mutation in the test
cleanup with the registry’s public unregister or scoped-registration mechanism;
if unavailable, add a pytest yield fixture that performs supported teardown.
Keep the dummy_check registration isolated and ensure cleanup still runs after
both verification scenarios without relying on Registry internals.
🪄 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: Pro

Run ID: 601f6829-fcce-4fd8-813d-33110a924ecb

📥 Commits

Reviewing files that changed from the base of the PR and between 5432011 and 0ce150b.

📒 Files selected for processing (21)
  • devops_bench/metrics/__init__.py
  • devops_bench/metrics/_skills.py
  • devops_bench/metrics/chaos_metrics.py
  • devops_bench/metrics/checklist.py
  • devops_bench/metrics/geval.py
  • devops_bench/metrics/grounding.py
  • devops_bench/metrics/outcome_validity.py
  • devops_bench/metrics/pipeline.py
  • devops_bench/metrics/tool_invocation.py
  • devops_bench/verification/__init__.py
  • devops_bench/verification/base.py
  • devops_bench/verification/runner.py
  • devops_bench/verification/spec.py
  • tests/unit/metrics/test_metrics_chaos.py
  • tests/unit/metrics/test_metrics_geval.py
  • tests/unit/metrics/test_metrics_grounding.py
  • tests/unit/metrics/test_metrics_pipeline.py
  • tests/unit/metrics/test_metrics_skills.py
  • tests/unit/verification/test_base.py
  • tests/unit/verification/test_package_import.py
  • tests/unit/verification/test_verifier_registry.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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: 5

🧹 Nitpick comments (6)
devops_bench/verification/spec.py (2)

42-56: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

json_schema() embeds each member's own $defs instead of hoisting them to a shared root.

Each m.model_json_schema() call returns a self-contained document with its own local $defs. Placing these raw dicts directly inside anyOf (rather than $ref-pointing into a shared root-level $defs) means any future verifier with a nested BaseModel field would produce a $ref: "#/$defs/X" that resolves against the outer combined document root, not its own nested $defs — breaking ref resolution for schema consumers. Pydantic's own multi-model combination helper avoids exactly this by hoisting $defs to the top level and using $ref pointers in anyOf.

♻️ Proposed fix using `models_json_schema`
+from pydantic.json_schema import models_json_schema
+
 def json_schema() -> dict[str, Any]:
     members = list(VERIFIERS.values())
-    return {
-        "title": "VerificationSpec",
-        "anyOf": [m.model_json_schema() for m in members],
-        "discriminator": {"propertyName": "type"},
-    }
+    _, top_level_schema = models_json_schema(
+        [(m, "validation") for m in members], title="VerificationSpec"
+    )
+    top_level_schema["anyOf"] = [
+        {"$ref": f"`#/`$defs/{m.__name__}"} for m in members
+    ]
+    top_level_schema["discriminator"] = {"propertyName": "type"}
+    return top_level_schema

Since this touches pydantic's schema-combination API, please confirm the exact models_json_schema signature/behavior for the pydantic version pinned in this repo before applying.

🤖 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 `@devops_bench/verification/spec.py` around lines 42 - 56, Update json_schema()
to combine VERIFIERS models using Pydantic’s version-pinned models_json_schema
helper rather than embedding each model_json_schema() result directly in anyOf.
Confirm the helper’s exact signature and output for the repository’s Pydantic
version, then return its combined schema with shared root-level $defs and
correctly resolved anyOf references while preserving the VerificationSpec title
and type discriminator.

144-190: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Untrusted type_key is f-string-interpolated into a PydanticCustomError message template.

_validation_error builds messages like f"unknown verifier type {type_key!r}; ..." and hands the already-interpolated string to PydanticCustomError as its template. Since that template is documented to be rendered with {curly_brace} placeholders, a type value containing literal braces (e.g. "{oops}") would leave an unmatched placeholder in the template, risking a rendering error instead of the intended ValidationError. Pydantic's documented pattern is to pass the raw value via the context dict instead of pre-formatting it into the template.

🛡️ Proposed fix passing values via context
-        raise _validation_error(
-            "verification_spec_unknown_type",
-            (f"unknown verifier type {type_key!r}; registered: {sorted(VERIFIERS.keys())}"),
-            input_value=data,
-        ) from exc
+        raise _validation_error(
+            "verification_spec_unknown_type",
+            "unknown verifier type {type_key!r}; registered: {registered!r}",
+            input_value=data,
+            context={"type_key": type_key, "registered": sorted(VERIFIERS.keys())},
+        ) from exc

(with _validation_error extended to accept and forward a context dict to PydanticCustomError.)

Please confirm this rendering behavior against the pydantic-core version pinned in this repo.

🤖 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 `@devops_bench/verification/spec.py` around lines 144 - 190, Update the
unknown-type handling in the verifier validation flow and _validation_error so
untrusted type_key values are passed to PydanticCustomError through its context
rather than interpolated into the message template. Extend _validation_error to
accept and forward context, use a static template with a named placeholder for
the verifier type, and preserve the resulting ValidationError behavior for
values containing literal braces. Confirm the implementation matches the pinned
pydantic-core API.
tests/unit/verification/test_base.py (1)

22-66: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test functions are missing return type annotations. Both files' test functions omit -> None, the shared root cause being no consistent return-type annotation on any test function in this PR's verification test suite.

  • tests/unit/verification/test_base.py#L22-L66: add -> None to test_default_fields_match_contract, test_compound_result_carries_children_not_raw, test_leaf_result_carries_raw_not_children, and test_no_details_field.
  • tests/unit/verification/test_verifier_registry.py#L33-L114: add -> None to test_dummy_verifier_parses_without_union_edit, test_unknown_type_lists_registered_keys_in_error, test_already_parsed_unregistered_basemodel_is_rejected, and test_unregistered_basemodel_as_checks_child_is_rejected.

As per path instructions, tests/**/*.py should "Ensure test functions have proper type annotations and clean structure."

🤖 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 `@tests/unit/verification/test_base.py` around lines 22 - 66, Add -> None
return annotations to test_default_fields_match_contract,
test_compound_result_carries_children_not_raw,
test_leaf_result_carries_raw_not_children, and test_no_details_field in
tests/unit/verification/test_base.py, and to
test_dummy_verifier_parses_without_union_edit,
test_unknown_type_lists_registered_keys_in_error,
test_already_parsed_unregistered_basemodel_is_rejected, and
test_unregistered_basemodel_as_checks_child_is_rejected in
tests/unit/verification/test_verifier_registry.py; make no other changes.

Source: Path instructions

devops_bench/verification/runner.py (1)

152-204: 🩺 Stability & Availability | 🔵 Trivial

Design note: parallel worker threads can outlive the returned result if a leaf ignores its timeout budget.

ex.shutdown(wait=False, cancel_futures=True) only drops queued-but-not-started futures; in-flight workers keep running after _run_parallel returns. This is fine as documented, contingent on every BaseVerifier.verify honoring timeout_sec. If a future leaf implementation blocks past its budget (e.g. a raw blocking call with no internal timeout), the non-daemon ThreadPoolExecutor threads can hold the process open past the point this function already reported a timeout. Worth keeping an eye on as new leaf verifiers are added, since this file can't enforce that contract on their behalf.

🤖 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 `@devops_bench/verification/runner.py` around lines 152 - 204, Ensure every
leaf verifier invoked through _run_parallel and its _run path strictly honors
the provided deadline/timeout budget, including blocking operations such as
kubectl wait or poll_until. Audit BaseVerifier.verify implementations and add
bounded timeouts where needed; preserve the existing parallel result handling
while preventing in-flight worker threads from outliving the returned timeout
result.
tests/unit/verification/test_verifier_registry.py (1)

36-68: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test cleanup reaches into Registry._items (private attribute).

Popping VERIFIERS._items directly couples this test to the registry's internal representation. A public Registry.unregister()/context-manager, or a pytest fixture with yield+teardown, would keep the cleanup robust if Registry's internals change, and would better satisfy the path instruction to ensure "clean structure" for test fixtures.

As per path instructions, tests/**/*.py should have "proper type annotations and clean structure," which suggests this cleanup could use a public API or fixture instead of a private-attribute reach-through.

🤖 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 `@tests/unit/verification/test_verifier_registry.py` around lines 36 - 68,
Replace the direct VERIFIERS._items mutation in the test cleanup with the
registry’s public unregister or scoped-registration mechanism; if unavailable,
add a pytest yield fixture that performs supported teardown. Keep the
dummy_check registration isolated and ensure cleanup still runs after both
verification scenarios without relying on Registry internals.

Source: Path instructions

tests/unit/metrics/test_metrics_pipeline.py (1)

33-394: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test functions lack return-type annotations across all three new test modules. None of the new test functions (nor their mocker/caplog fixture parameters) carry type hints, the shared root cause for all three files below.

  • tests/unit/metrics/test_metrics_pipeline.py#L33-L394: annotate each def test_*(...) with -> None and type the mocker/caplog fixture parameters (e.g. mocker: MockerFixture).
  • tests/unit/metrics/test_metrics_chaos.py#L33-L86: annotate test_chaos_records_geval_and_perf/test_chaos_defaults_fault_and_survives_eval_error with -> None and type mocker.
  • tests/unit/metrics/test_metrics_grounding.py#L34-L213: annotate all test_* functions with -> None and type mocker on the GEval-mocked tests.

As per path instructions, tests/**/*.py should "Ensure test functions have proper type annotations and clean structure."

🤖 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 `@tests/unit/metrics/test_metrics_pipeline.py` around lines 33 - 394, Add ->
None return annotations to every test_* function in
tests/unit/metrics/test_metrics_pipeline.py (lines 33-394),
tests/unit/metrics/test_metrics_chaos.py (lines 33-86), and
tests/unit/metrics/test_metrics_grounding.py (lines 34-213); annotate each
mocker fixture parameter with MockerFixture and each caplog fixture parameter
with the appropriate logging capture fixture type, adding required imports. Keep
non-fixture parameters and test behavior unchanged.

Source: Path instructions

🤖 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 `@devops_bench/metrics/chaos_metrics.py`:
- Around line 26-31: Update the chaos GEval metric definitions diag_metric and
rec_metric to pass GEVAL_PASS_THRESHOLD explicitly to their threshold
configuration, matching sibling metrics and preserving consistent success
evaluation.

In `@devops_bench/metrics/grounding.py`:
- Around line 67-84: Update the retrieval-rate logic around accessed_docs so
each documentation entry matched in the trajectory increments the accessed count
directly, rather than storing doc_name values in a set. Preserve the existing
doc_name and URL matching guards, and calculate the rate from the number of
matched documentation entries.

In `@devops_bench/metrics/outcome_validity.py`:
- Around line 73-99: Apply complete type annotations across the metrics and test
surfaces: annotate the model parameter in build_outcome_validity_metric within
devops_bench/metrics/outcome_validity.py lines 73-99 and the corresponding model
parameter in devops_bench/metrics/tool_invocation.py lines 59-79; annotate all
helpers, fixture parameters, and test functions with return types including None
in tests/unit/metrics/test_metrics_geval.py lines 26-124; and annotate stub
methods, helpers, nested fake-resource methods, and tests in
tests/unit/metrics/test_metrics_skills.py lines 31-150.

In `@devops_bench/verification/spec.py`:
- Around line 122-134: Update the parse_node doctest to use a verifier type
registered in the repository, or explicitly import the registration path before
constructing the pod_healthy example. Keep the example’s discriminator behavior
and bare-list rejection assertions unchanged, and ensure doctest can resolve the
selected type without relying on unavailable registration.

In `@tests/unit/verification/test_package_import.py`:
- Line 27: Update test_import_pulls_no_heavy_sdks with the required return type
hint and a concise docstring describing what the test verifies, while preserving
its existing test behavior.

---

Nitpick comments:
In `@devops_bench/verification/runner.py`:
- Around line 152-204: Ensure every leaf verifier invoked through _run_parallel
and its _run path strictly honors the provided deadline/timeout budget,
including blocking operations such as kubectl wait or poll_until. Audit
BaseVerifier.verify implementations and add bounded timeouts where needed;
preserve the existing parallel result handling while preventing in-flight worker
threads from outliving the returned timeout result.

In `@devops_bench/verification/spec.py`:
- Around line 42-56: Update json_schema() to combine VERIFIERS models using
Pydantic’s version-pinned models_json_schema helper rather than embedding each
model_json_schema() result directly in anyOf. Confirm the helper’s exact
signature and output for the repository’s Pydantic version, then return its
combined schema with shared root-level $defs and correctly resolved anyOf
references while preserving the VerificationSpec title and type discriminator.
- Around line 144-190: Update the unknown-type handling in the verifier
validation flow and _validation_error so untrusted type_key values are passed to
PydanticCustomError through its context rather than interpolated into the
message template. Extend _validation_error to accept and forward context, use a
static template with a named placeholder for the verifier type, and preserve the
resulting ValidationError behavior for values containing literal braces. Confirm
the implementation matches the pinned pydantic-core API.

In `@tests/unit/metrics/test_metrics_pipeline.py`:
- Around line 33-394: Add -> None return annotations to every test_* function in
tests/unit/metrics/test_metrics_pipeline.py (lines 33-394),
tests/unit/metrics/test_metrics_chaos.py (lines 33-86), and
tests/unit/metrics/test_metrics_grounding.py (lines 34-213); annotate each
mocker fixture parameter with MockerFixture and each caplog fixture parameter
with the appropriate logging capture fixture type, adding required imports. Keep
non-fixture parameters and test behavior unchanged.

In `@tests/unit/verification/test_base.py`:
- Around line 22-66: Add -> None return annotations to
test_default_fields_match_contract,
test_compound_result_carries_children_not_raw,
test_leaf_result_carries_raw_not_children, and test_no_details_field in
tests/unit/verification/test_base.py, and to
test_dummy_verifier_parses_without_union_edit,
test_unknown_type_lists_registered_keys_in_error,
test_already_parsed_unregistered_basemodel_is_rejected, and
test_unregistered_basemodel_as_checks_child_is_rejected in
tests/unit/verification/test_verifier_registry.py; make no other changes.

In `@tests/unit/verification/test_verifier_registry.py`:
- Around line 36-68: Replace the direct VERIFIERS._items mutation in the test
cleanup with the registry’s public unregister or scoped-registration mechanism;
if unavailable, add a pytest yield fixture that performs supported teardown.
Keep the dummy_check registration isolated and ensure cleanup still runs after
both verification scenarios without relying on Registry internals.
🪄 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: Pro

Run ID: 601f6829-fcce-4fd8-813d-33110a924ecb

📥 Commits

Reviewing files that changed from the base of the PR and between 5432011 and 0ce150b.

📒 Files selected for processing (21)
  • devops_bench/metrics/__init__.py
  • devops_bench/metrics/_skills.py
  • devops_bench/metrics/chaos_metrics.py
  • devops_bench/metrics/checklist.py
  • devops_bench/metrics/geval.py
  • devops_bench/metrics/grounding.py
  • devops_bench/metrics/outcome_validity.py
  • devops_bench/metrics/pipeline.py
  • devops_bench/metrics/tool_invocation.py
  • devops_bench/verification/__init__.py
  • devops_bench/verification/base.py
  • devops_bench/verification/runner.py
  • devops_bench/verification/spec.py
  • tests/unit/metrics/test_metrics_chaos.py
  • tests/unit/metrics/test_metrics_geval.py
  • tests/unit/metrics/test_metrics_grounding.py
  • tests/unit/metrics/test_metrics_pipeline.py
  • tests/unit/metrics/test_metrics_skills.py
  • tests/unit/verification/test_base.py
  • tests/unit/verification/test_package_import.py
  • tests/unit/verification/test_verifier_registry.py
🛑 Comments failed to post (5)
devops_bench/metrics/chaos_metrics.py (1)

26-31: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Chaos GEval metrics should use the project threshold.

diag_metric and rec_metric omit threshold=GEVAL_PASS_THRESHOLD, so they fall back to DeepEval’s default 0.5 while sibling metrics use 0.8. That makes the chaos success flags looser and inconsistent with the rest of the metric suite.

🤖 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 `@devops_bench/metrics/chaos_metrics.py` around lines 26 - 31, Update the chaos
GEval metric definitions diag_metric and rec_metric to pass GEVAL_PASS_THRESHOLD
explicitly to their threshold configuration, matching sibling metrics and
preserving consistent success evaluation.
devops_bench/metrics/grounding.py (1)

67-84: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Retrieval rate undercounts when docs share an empty/missing doc_name.

accessed_docs is a set keyed by doc_name. When two or more documentation entries lack a doc_name (or happen to share one) but are matched via distinct URLs, they all collapse into the same set entry, so len(accessed_docs) undercounts the actually-accessed guide count. E.g. two docs with only url set, both found in the trajectory, yield len(accessed_docs) == 1 instead of 2, silently deflating DocRetrievalRate.

Count matches directly instead of deduplicating by a non-unique name.

🐛 Proposed fix
-    accessed_docs = set()
+    accessed_count = 0
     for doc in documentation:
-        doc_name = doc.get("doc_name") or ""
-        doc_name_lower = doc_name.lower()
+        doc_name_lower = (doc.get("doc_name") or "").lower()
         url_lower = (doc.get("url") or "").lower()
-        found_in_trajectory = False
         for step_str in step_strs:
             # Guard both substrings on truthiness so a missing name/url (now "")
             # does not spuriously match every step (``"" in s`` is always True).
             if (doc_name_lower and doc_name_lower in step_str) or (
                 url_lower and url_lower in step_str
             ):
-                found_in_trajectory = True
+                accessed_count += 1
                 break
-        if found_in_trajectory:
-            accessed_docs.add(doc_name)
 
-    return len(accessed_docs) / len(documentation)
+    return accessed_count / len(documentation)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    accessed_count = 0
    for doc in documentation:
        doc_name_lower = (doc.get("doc_name") or "").lower()
        url_lower = (doc.get("url") or "").lower()
        for step_str in step_strs:
            # Guard both substrings on truthiness so a missing name/url (now "")
            # does not spuriously match every step (``"" in s`` is always True).
            if (doc_name_lower and doc_name_lower in step_str) or (
                url_lower and url_lower in step_str
            ):
                accessed_count += 1
                break

    return accessed_count / len(documentation)
🤖 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 `@devops_bench/metrics/grounding.py` around lines 67 - 84, Update the
retrieval-rate logic around accessed_docs so each documentation entry matched in
the trajectory increments the accessed count directly, rather than storing
doc_name values in a set. Preserve the existing doc_name and URL matching
guards, and calculate the rate from the number of matched documentation entries.
devops_bench/metrics/outcome_validity.py (1)

73-99: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add the required type annotations across the new metrics surface.

  • devops_bench/metrics/outcome_validity.py#L73-L99: annotate model.
  • devops_bench/metrics/tool_invocation.py#L59-L79: annotate model.
  • tests/unit/metrics/test_metrics_geval.py#L26-L124: annotate helpers and every test function, including fixture parameters and -> None.
  • tests/unit/metrics/test_metrics_skills.py#L31-L150: annotate stub methods, helpers, nested fake-resource methods, and tests.

As per coding guidelines, “All Python code must include type hints.” As per path instructions, “Ensure test functions have proper type annotations.”

📍 Affects 4 files
  • devops_bench/metrics/outcome_validity.py#L73-L99 (this comment)
  • devops_bench/metrics/tool_invocation.py#L59-L79
  • tests/unit/metrics/test_metrics_geval.py#L26-L124
  • tests/unit/metrics/test_metrics_skills.py#L31-L150
🤖 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 `@devops_bench/metrics/outcome_validity.py` around lines 73 - 99, Apply
complete type annotations across the metrics and test surfaces: annotate the
model parameter in build_outcome_validity_metric within
devops_bench/metrics/outcome_validity.py lines 73-99 and the corresponding model
parameter in devops_bench/metrics/tool_invocation.py lines 59-79; annotate all
helpers, fixture parameters, and test functions with return types including None
in tests/unit/metrics/test_metrics_geval.py lines 26-124; and annotate stub
methods, helpers, nested fake-resource methods, and tests in
tests/unit/metrics/test_metrics_skills.py lines 31-150.

Sources: Coding guidelines, Path instructions

devops_bench/verification/spec.py (1)

122-134: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if doctests are executed in CI/pytest config, and confirm "pod_healthy" registration.
rg -n "doctest" pyproject.toml setup.cfg pytest.ini tox.ini 2>/dev/null
rg -n 'register\("pod_healthy"\)' -g '*.py'

Repository: kubernetes-sigs/devops-bench

Length of output: 166


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- file list ---\n'
git ls-files | rg '^(devops_bench/verification/spec\.py|pyproject\.toml|setup\.cfg|pytest\.ini|tox\.ini|\.github/workflows/.*\.ya?ml)$'

printf '\n--- spec.py outline ---\n'
ast-grep outline devops_bench/verification/spec.py --view expanded || true

printf '\n--- search for pod_healthy and registration patterns ---\n'
rg -n '"pod_healthy"|pod_healthy|register\(' devops_bench -g '*.py'

printf '\n--- test config mentions doctest ---\n'
rg -n "doctest|pytest" pyproject.toml setup.cfg pytest.ini tox.ini .github/workflows -g '!**/node_modules/**' || true

Repository: kubernetes-sigs/devops-bench

Length of output: 257


🏁 Script executed:

#!/bin/bash
set -euo pipefail
git ls-files | rg '^(devops_bench/verification/spec\.py|pyproject\.toml|setup\.cfg|pytest\.ini|tox\.ini|\.github/workflows/.*\.ya?ml)$'

Repository: kubernetes-sigs/devops-bench

Length of output: 215


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- devops_bench/verification/spec.py (around doctest) ---'
sed -n '1,220p' devops_bench/verification/spec.py

echo
echo '--- pyproject.toml ---'
sed -n '1,260p' pyproject.toml

echo
echo '--- search for pod_healthy registration and verifier imports ---'
rg -n '"pod_healthy"|pod_healthy|register\(' devops_bench -g '*.py'

echo
echo '--- search for doctest / pytest config ---'
rg -n 'doctest|pytest' pyproject.toml setup.cfg pytest.ini tox.ini .github/workflows -g '!**/node_modules/**' || true

Repository: kubernetes-sigs/devops-bench

Length of output: 11174


Doctest needs a registered verifier. This example uses pod_healthy, but that type isn’t registered anywhere in this repo, so doctest runs will fail unless the example imports the registration path or switches to a registered verifier.

🤖 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 `@devops_bench/verification/spec.py` around lines 122 - 134, Update the
parse_node doctest to use a verifier type registered in the repository, or
explicitly import the registration path before constructing the pod_healthy
example. Keep the example’s discriminator behavior and bare-list rejection
assertions unchanged, and ensure doctest can resolve the selected type without
relying on unavailable registration.
tests/unit/verification/test_package_import.py (1)

27-27: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add the required type hint and docstring.

As per coding guidelines, Python code must include type hints and public functions must have concise docstrings; the tests/**/*.py path instructions also require typed test functions.

Suggested fix
-def test_import_pulls_no_heavy_sdks():
+def test_import_pulls_no_heavy_sdks() -> None:
+    """Verify verification imports without loading provider SDKs."""
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

def test_import_pulls_no_heavy_sdks() -> None:
    """Verify verification imports without loading provider SDKs."""
🤖 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 `@tests/unit/verification/test_package_import.py` at line 27, Update
test_import_pulls_no_heavy_sdks with the required return type hint and a concise
docstring describing what the test verifies, while preserving its existing test
behavior.

Sources: Coding guidelines, Path instructions

- chaos GEval metrics (DiagnosisAccuracy, GracefulRecovery) now pass the
  shared GEVAL_PASS_THRESHOLD, matching the other judge metrics instead of
  deepeval's looser default
- doc-retrieval rate counts each matched documentation entry directly
  rather than deduplicating by a possibly-shared or empty doc_name, which
  undercounted the accessed fraction
- annotate the judge model parameter on the outcome-validity and
  tool-invocation metric builders
- add return-type and fixture annotations to the metric unit tests

Signed-off-by: Eugene Ng <ngeugene@google.com>
Comment thread devops_bench/metrics/checklist.py Outdated
extract_checklist_items used lstrip("- "), a character-class strip that
also removed a leading "--" on flag requirements ("- --dry-run flag" ->
"dry-run flag"). Remove just the single leading "- " bullet via regex and
cover it with a regression test.

Signed-off-by: Eugene Ng <ngeugene@google.com>

@janetkuo janetkuo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

/lgtm

@kubernetes-prow kubernetes-prow Bot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jul 21, 2026
@kubernetes-prow

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: eugeneng04, janetkuo

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubernetes-prow kubernetes-prow Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jul 21, 2026
@kubernetes-prow
kubernetes-prow Bot merged commit 1cc3022 into kubernetes-sigs:main Jul 21, 2026
7 checks passed
pradeepvrd pushed a commit to gke-labs/devops-bench that referenced this pull request Jul 22, 2026
Flip the entries at blob parity with upstream, by upstream PR:
- kubernetes-sigs/devops-bench#32 (model clients + CLI agent harnesses):
  agents/cli/gemini_cli/**, agents/cli/__init__.py
- kubernetes-sigs/devops-bench#31 (chaos package): chaos/spec.py,
  chaos/__init__.py
- kubernetes-sigs/devops-bench#29 (verification base + metrics judge):
  verification/base.py, verification/__init__.py, its base/package
  tests, metrics/geval.py, metrics/_skills.py,
  tests/unit/metrics/test_metrics_geval.py
- kubernetes-sigs/devops-bench#30 (deployer abstraction + default
  stack): deployers/base.py, deployers/__init__.py, deployers/noop.py,
  both engine tests
- kubernetes-sigs/devops-bench#34 (concrete judge metric families):
  metrics/__init__.py

Drifted entries stay commented until gke-labs and upstream reconcile.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants