Skip to content

Let a parallel child hand back a verdict it reached on time - #75

Open
jessie1111101 wants to merge 2 commits into
kubernetes-sigs:mainfrom
jessie1111101:fix-parallel-child-handoff
Open

Let a parallel child hand back a verdict it reached on time#75
jessie1111101 wants to merge 2 commits into
kubernetes-sigs:mainfrom
jessie1111101:fix-parallel-child-handoff

Conversation

@jessie1111101

@jessie1111101 jessie1111101 commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

A converging objective whose children poll for something that never appears is scored error, not fail.

Root cause

_run_parallel hands its children the same deadline its own futures_wait uses. A child that polls to the very end overshoots it slightly — poll_until clamps its final sleep but then re-checks the predicate once more before giving up. The parent stopped waiting at exactly the deadline, so the two raced, and a child that lost kept the pre-seeded placeholder:

disruption-and-scaling  error  w=0.3334
  [0] failed: evaluation did not complete before the deadline;
  [1] failed: evaluation did not complete before the deadline

Both children had in fact reached a verdict. They just could not hand it back.

Why it matters

rollup.py drops an errored entry from both the numerator and the denominator, so an objective the agent genuinely failed is deleted rather than counted — and the score goes up.

Seen live on deploy-hello-app. The agent created neither a PodDisruptionBudget nor a HorizontalPodAutoscaler; I confirmed that directly against the cluster mid-run (0 pdb, 0 hpa). Both children errored on the deadline:

c OutcomeScore
as scored (error, excluded) 3.0833 / 3.6666 = 0.8409 0.9170
counting the observation 3.0833 / 4.0 = 0.7708 0.8780

Same failure shape as #74: an observation the harness did make, discarded as if it had not been.

The change

The converge wait now allows a one second handoff window past the deadline.

The asymmetry is deliberate and preserved. A genuinely hung child must keep erroring, because a stuck kubectl under assert mode must never read as an observed safeguard violation — that could zero a run through the catastrophic gate. One second is wide enough to collect a result that landed on time and far too narrow to rescue a hung child; the two existing hung-child tests (a 3.0s sleep against a 1.2s deadline, and the single-shot ceiling path) pass unchanged, which is what pins that boundary.

single_shot is untouched.

Tests

One new regression test reproducing the real scenario: two children that poll just past a converge deadline and each reach a genuine "not there" verdict. Verified it actually catches the bug — reverting the fix fails exactly this test and nothing else.

The budget must clear _MIN_LEAF_BUDGET_SECONDS in that test, otherwise the leaves are short-circuited before they run and the race is never exercised. My first attempt made that mistake and passed for the wrong reason.

1194 tests pass; ruff and boilerplate clean.

Summary by CodeRabbit

  • Bug Fixes
    • Improved parallel evaluation handling near time limits.
    • Preserved accurate child failure verdicts and reasons instead of incorrectly reporting deadline errors.
    • Ensured groups report the correct overall failure status when evaluations finish at the deadline.

Fixes #67.

A converging objective whose children poll for something that never appears
was scored "error", not "fail". The children are handed the same deadline the
parent's futures_wait uses, and a child that polls to the very end overshoots
it slightly: poll_until clamps its final sleep but then re-checks the
predicate once more before giving up. The parent stopped waiting at exactly
the deadline, so the two raced, and a child that lost was recorded as never
observed even though it had reached a verdict.

That inflates the score. rollup drops an errored entry from both sides of the
correctness fraction, so an objective the agent genuinely failed is deleted
rather than counted.

Seen on deploy-hello-app's disruption-and-scaling: the agent created neither a
PodDisruptionBudget nor a HorizontalPodAutoscaler, confirmed against the live
cluster, and both children errored on the deadline. Scored as an error the run
was 0.9170; counting the observation it is 0.8780.

The wait now allows a one second handoff window past the deadline. That is
wide enough to collect a result that landed on time and far too narrow to
rescue a genuinely hung child, which must keep erroring so a stuck kubectl
under assert mode never reads as an observed safeguard violation.

Signed-off-by: Jessie Liu <jssl@google.com>
@kubernetes-prow
kubernetes-prow Bot requested a review from janetkuo August 3, 2026 23:05
@kubernetes-prow

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: jessie1111101
Once this PR has been reviewed and has the lgtm label, please assign janetkuo for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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 cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Aug 3, 2026
@kubernetes-prow

Copy link
Copy Markdown

Hi @jessie1111101. 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 the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Aug 3, 2026
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Parallel convergence waits now allow a one-second child handoff period after the shared deadline. Single-shot waits keep their existing limit. A regression test verifies that child failure verdicts and reasons remain preserved.

Changes

Parallel deadline handoff

Layer / File(s) Summary
Parallel handoff and verdict preservation
devops_bench/verification/runner.py, tests/unit/verification/test_runner.py
Converge-mode parallel waits add a one-second grace interval. Single-shot waits keep their existing ceiling. The regression test verifies that child failures retain their statuses and actual reasons.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested labels: kind/bug

Suggested reviewers: geojaz, eugeneng04, janetkuo

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 clearly describes the main change: allowing a parallel child to return a verdict reached before the deadline.
✨ 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.

@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: 3

🤖 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/verification/runner.py`:
- Line 88: Update the module-level constant _CHILD_HANDOFF_GRACE_SEC with an
explicit float type annotation while preserving its current value and behavior.
- Line 546: Update the wait_timeout calculation in _run_parallel() to cap the
handoff at the absolute deadline plus _CHILD_HANDOFF_GRACE_SEC, rather than
adding the grace period after clamping negative remaining time. Ensure late
starts receive only the remaining time until that absolute handoff deadline,
while preserving the one-second grace window.
- Around line 546-547: Update the parallel-child result handling around
futures_wait and _PARALLEL_INCOMPLETE_REASON so children not actually evaluated
by the deadline retain status="error" instead of being overwritten by the
default deadline-exhausted fail result. Preserve fail for checks that genuinely
completed evaluation, and add coverage for workloads exceeding
_MAX_PARALLEL_WORKERS to verify the conjunction remains unevaluated.
🪄 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 Plus

Run ID: 1ba26655-1249-4081-be94-425409cb2bd0

📥 Commits

Reviewing files that changed from the base of the PR and between 4670d76 and 2fb95f8.

📒 Files selected for processing (2)
  • devops_bench/verification/runner.py
  • tests/unit/verification/test_runner.py

Comment thread devops_bench/verification/runner.py Outdated
Comment thread devops_bench/verification/runner.py Outdated
Comment thread devops_bench/verification/runner.py Outdated
@janetkuo janetkuo 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 Aug 11, 2026
Per review. Adding the grace to the time remaining meant a group entered after
its deadline waited a full grace period from that late start, so the handoff
could finish well past deadline plus grace and outlive the parent wait. A
nested parallel node reached late is exactly that case.

Measuring back from the absolute handoff deadline caps it: a group starting on
time still gets its full window, and one entered late gets whatever is left of
it, down to nothing.

Also annotates the constant as float per the repository typing rule.

Signed-off-by: Jessie Liu <jssl@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parallel verification discards a child's real result when it lands at the shared deadline

2 participants