Skip to content

Run Level 2 validation probes - #1181

Open
burtenshaw wants to merge 15 commits into
mainfrom
ben/rfc008-l2-03-runtime
Open

burtenshaw wants to merge 15 commits into
mainfrom
ben/rfc008-l2-03-runtime

Conversation

@burtenshaw

Copy link
Copy Markdown
Collaborator

This PR runs local Level 2 probes, grades startup/reward/observation/state, and records replayable evidence with explicit skips for unfinished checks. Builds on #1179; third of three stacked PRs tracked in #1177.

@burtenshaw
burtenshaw added this pull request to stack #1183 September 16, 2026 10:17
@burtenshaw
burtenshaw marked this pull request as ready for review September 16, 2026 10:20
@burtenshaw burtenshaw mentioned this pull request Sep 16, 2026
13 tasks
@burtenshaw burtenshaw added feature size: extra-large Extra-large pull request labels Sep 16, 2026 — with Cursor

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Schema worker truncates Unicode payloads
    • The grader now serializes worker payloads without ASCII escaping, with a regression test covering Unicode traces within the wire budget.

Create PR

Or push these changes by commenting:

@cursor push c8f6b6ffb8
Preview (c8f6b6ffb8)
diff --git a/src/openenv/validation/graders/runtime/basic.py b/src/openenv/validation/graders/runtime/basic.py
--- a/src/openenv/validation/graders/runtime/basic.py
+++ b/src/openenv/validation/graders/runtime/basic.py
@@ -143,7 +143,10 @@
         try:
             checked = subprocess.run(
                 [sys.executable, "-I", str(worker)],
-                input=json.dumps({"schema": schema, "observations": observations}),
+                input=json.dumps(
+                    {"schema": schema, "observations": observations},
+                    ensure_ascii=False,
+                ),
                 capture_output=True,
                 text=True,
                 timeout=5,

diff --git a/tests/test_validation/test_runtime_grading.py b/tests/test_validation/test_runtime_grading.py
--- a/tests/test_validation/test_runtime_grading.py
+++ b/tests/test_validation/test_runtime_grading.py
@@ -219,6 +219,45 @@
     )
 
 
+def test_unicode_trace_within_wire_budget_reaches_schema_worker_intact(tmp_path):
+    text = "\U0001f600" * 150_000
+    rows = []
+    for index in range(6):
+        operation = "reset" if index == 0 else "step"
+        rows.append(
+            WireExchange(
+                operation,
+                json.dumps({"type": operation}),
+                json.dumps(
+                    {
+                        "type": "observation",
+                        "data": {
+                            "observation": {"counter": index, "text": text},
+                            "reward": None if index == 0 else 0,
+                            "done": False,
+                        },
+                    },
+                    ensure_ascii=False,
+                ),
+            )
+        )
+    assert (
+        sum(
+            len(row.request_json.encode()) + len(row.response_json.encode())
+            for row in rows
+        )
+        < 8 * 1024 * 1024
+    )
+    assert len(json.dumps([text] * len(rows))) > 10 * 1024 * 1024
+    schema = copy.deepcopy(OBSERVATION_SCHEMA)
+    schema["properties"]["text"] = {"type": "string"}
+    schema["required"].append("text")
+
+    result = ObservationSchemaGrader().run(subject_with(tmp_path, rows, schema=schema))
+
+    assert result.status is CheckStatus.PASS
+
+
 @pytest.mark.parametrize(
     "field,value", [("done", None), ("done", "false"), ("done", 0), ("observation", [])]
 )

You can send follow-ups to the cloud agent here.

Comment thread src/openenv/validation/graders/runtime/basic.py

@cursor cursor 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.

Alignment Review Report

Two-tier review of the RFC-008 Level 2 execution slice 3 (startup, reward, observation, state checks). This is a stacked PR (base ben/rfc008-l2-02-docker), so the repo's test/lint workflows don't gate it — the results below are from running the suites locally, plus the dedicated runtime-validation CI job.

Automated Checks

  • Lint: PASS (PR files). ruff format --check, usort check, and ruff check are all clean on the 14 changed .py files. The full-tree lint.sh failure (57 ruff format + usort exit 2) is pre-existing envs/ + test_grid_world.py/test_julia_env.py drift, not introduced here.
  • Debug code: CLEAN. No print/breakpoint/pdb/TODO/FIXME in the PR's src/ files.
  • Tests (run locally): green. 97 new runtime unit tests pass; full tests/test_validation = 292 passed (incl. test_policy, test_schema_sync, test_runner); tests/test_cli/test_validate.py = 11 passed (no regression — contrast slice 1). The Docker integration test (test_runtime_cli.py, @pytest.mark.docker) isn't runnable in this env, but the dedicated "Runtime validation / Linux Docker" CI job passed.

Open RFCs Context

  • RFC 008 — Environment Auto-Validation (Status: In Review, @zkwentz). This PR implements the "Level 2 execution amendment", slice 3, and is faithful to it: bounded public probe loader (65 536 B / depth 32 / 10 000 nodes / 1–100 actions, duplicate-key + non-finite rejection, no seed/episode_id override); a single-session collector recording raw uncoerced request/response strings; reset-reward-may-be-null / step-reward-must-be-a-finite-number-in-range-excluding-booleans; the state identity + step_count contract; policy v2 adding runtime.startup (v1 rejected for runtime); the FAIL/ERROR/SKIP taxonomy; unsupported network/GPU refused before build; an explicit SKIP inventory for not-yet-implemented Level-2 checks; and a redacted evidence bundle.
  • No other RFC (001/002/003/004) is in conflict; RFC 004 rubrics remain leveraged-not-required.

Tier 1: Fixes Required

  • None. No mechanical, type, import, or security defects found.

Tier 2: Alignment Discussion

Principle Conflicts

None identified. The change actively reinforces several invariants — worth affirming:

  • Dual API boundary / agent isolation: the collector drives the Gym-like reset/step/state loop as validation orchestration (agent_boundary: api), never as an agent tool — no agent-facing exposure of simulation control.
  • Client–server separation: validation talks to the subject purely over the wire (httpx/websockets); it imports nothing from server/.
  • Rewards in environment: graders only observe the environment's own reward against the declared range; no external reward computation.
  • No credential exposure: strong throughout — httpx(trust_env=False), LaunchSpec inherits no host env, artifact redaction (secret keys + token regex), failure reasons carry only exception types, and tests assert secrets never reach reports/traces.
  • Security depth (nice work): JSON-Schema evaluation is sandboxed in a disposable python -I subprocess with CPU/AS rlimits + a wall-clock deadline (ReDoS → finding, not hang); non-local $ref/$dynamicRef are rejected and the worker uses an empty referencing.Registry (no SSRF/file retrieval); source_digest opens files O_NOFOLLOW and rejects symlinks.

Three small, non-blocking notes are left inline (report coherence on mid-run source change; --policy exit-code semantics; HTTP /schema vs the WebSocket-only direction).

RFC Conflicts

ALIGNMENT FLAG: Implementation landing while RFC 008 is still In Review

  • Principle/RFC at stake: RFC 008 (Status: In Review) — Level 2 execution amendment
  • The concern: the standing sequencing flag for this stack — the slice freezes real behavior (manifest schema v2, severity policy v2, the validation.execution sidecar contract) against an amendment that is not yet Accepted. The implementation matches the current amendment text; the ask is to confirm those L2 contracts are settled before further slices stack on them. Non-blocking.
  • Suggested reviewer: @zkwentz (RFC author); @Darktex (principles/invariants owner, git blame b1a92e1 on INVARIANTS.md)

Summary

  • 0 mechanical issues to fix (Tier 1)
  • 1 alignment point for human review (RFC-008 In-Review sequencing) + 3 minor non-blocking inline notes
  • 0 hard RFC conflicts — the implementation is faithful to the RFC 008 Level 2 amendment
Open in Web View Automation 

Sent by Cursor Automation: Pre-review

Comment thread src/openenv/validation/runner.py Outdated
Comment thread src/openenv/cli/commands/validate.py
Comment thread src/openenv/validation/runtime/collector.py
@burtenshaw
burtenshaw force-pushed the ben/rfc008-l2-03-runtime branch from c92372e to c7e8989 Compare September 21, 2026 12:31
@bot-ci-comment

Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

@cursor cursor Bot mentioned this pull request Sep 21, 2026

@cursor cursor 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.

Stale comment

Exact-head CI is red on the same inherited failure as #1178: test_write_report_validation_report_only. Fix lands in #1178; please rebase after that greens. Holding deeper Level-2 probe review until then.

View PR

Open in Web View Automation 

Sent by Cursor Automation: Release

@cursor cursor 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.

Stale Bugbot comment from a previous run.

Comment thread src/openenv/validation/runtime/collector.py
Comment thread src/openenv/validation/runtime/collector.py Outdated
Comment thread src/openenv/validation/runtime/schema_worker.py Outdated

@cursor cursor 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.

Stale comment

REQUEST_CHANGES at c7e89896

Still blocked on inherited #1178 CI (test_write_report_validation_report_only). Separately, Bugbot’s High finding on this head is real:

collector treats exceptions from the final close send / WebSocket context exit as collection failures (failure_reason), and runtime graders then FAIL the episode even when reset/step/state already succeeded. Teardown noise must not fail a measured episode.

Also track (Medium):

  1. Schema worker stdin.read(10MB) can truncate large observation batches under the 8MB trace cap
  2. socket.send is not bound by episode_timeout_s (only pre-checked via remaining())

Fix close-failure handling here; rebase after #1178 greens. Not Thursday 0.6.0 cargo.

Open in Web View Automation 

Sent by Cursor Automation: Release

Comment thread src/openenv/validation/runtime/collector.py

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Malformed envelopes crash runtime graders
    • Runtime graders now convert AttributeError from non-object envelope data into a FAIL finding while preserving the collector failure reason.

Create PR

Or push these changes by commenting:

@cursor push ea46021702
Preview (ea46021702)
diff --git a/src/openenv/validation/graders/runtime/basic.py b/src/openenv/validation/graders/runtime/basic.py
--- a/src/openenv/validation/graders/runtime/basic.py
+++ b/src/openenv/validation/graders/runtime/basic.py
@@ -58,7 +58,14 @@
             problems.append(evidence.failure_reason)
         try:
             problems.extend(self.check(subject, evidence))
-        except (ValueError, TypeError, KeyError, RecursionError, OverflowError):
+        except (
+            ValueError,
+            TypeError,
+            KeyError,
+            AttributeError,
+            RecursionError,
+            OverflowError,
+        ):
             problems.append("malformed runtime evidence")
         return CheckResult(
             check_id=self.check_id,

You can send follow-ups to the cloud agent here.

Comment thread src/openenv/validation/graders/runtime/basic.py

@cursor cursor 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.

Stale comment

REQUEST_CHANGES at 2950de74

Inherited #1178 CI is green now. The High teardown issue remains on this head: close/WS-exit exceptions still set failure_reason and fail graders after a successful reset/step/state episode.

Also still open (Medium): schema-worker 10MB stdin truncate; socket.send not bound by episode_timeout_s.

Not Thursday 0.6.0 cargo.

Open in Web View Automation 

Sent by Cursor Automation: Release

Comment thread src/openenv/validation/runtime/collector.py

@cursor cursor 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.

Stale comment

REQUEST_CHANGES at d724b7e5 (High/Medium fixed; Low residual)

Fixed (prior High/Medium):

  • Completed-episode teardown: complete + best-effort close/send no longer sets failure_reason / fails graders; regressions in test_runtime_transport.py cover close-send, close-failure, and genuine in-episode failure precedence.
  • Transport sends are bounded via _bounded_call + raw-socket abort against episode_timeout_s.
  • Schema worker input budget raised / wire JSON preserved (response_json / schema_json) so unicode and compact 1e9 episodes within wire limits no longer truncate.

Still open (Low): graders call data.get(...) after data = response["data"] without isinstance(data, dict). The collector can store a raw exchange then raise on a non-object data envelope; ObservationSchemaGrader / state graders then AttributeError outside the (ValueError, TypeError, …) catch → grader ERROR instead of contract FAIL. Guard with isinstance(data, dict) (or equivalent) before .get.

Holding approval for that guard (+ exact-head CI still in flight). Not Thursday 0.6.0 cargo.

Open in Web View Automation 

Sent by Cursor Automation: Release

Comment thread src/openenv/validation/graders/runtime/basic.py

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

There are 3 total unresolved issues (including 1 from previous review).

Autofix Details

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Episode timeout silently capped at 300s
    • Runtime collection now honors the manifest's validated episode timeout without imposing an unrelated 300-second cap.
  • ✅ Fixed: Schema worker stdin encoding can fail
    • The schema worker subprocess now explicitly encodes text input as UTF-8 regardless of the parent locale.

Create PR

You can send follow-ups to the cloud agent here.

Comment thread src/openenv/validation/runner.py
Comment thread src/openenv/validation/graders/runtime/basic.py

@cursor cursor 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.

Stale comment

REQUEST_CHANGES at d724b7e5 (Bugbot refresh)

Prior High/Medium (teardown / bounded send / schema wire budget) remain fixed.

New Medium: runner.py silently caps collection at min(..., 300.0) while policy bounds allow max_episode_timeout_s=3600. Legal longer episodes can false-FAIL. Use the policy-validated declared timeout (or align the cap with the bound).

Still open Lows:

  1. Malformed non-object data → AttributeError in graders (ERROR vs FAIL).
  2. Schema-worker stdin: parent text=True/ensure_ascii=False vs worker UTF-8 stdin.buffer (locale-dependent).

Bugbot autofix is active — will re-review on the next head. Not Thursday 0.6.0 cargo.

Open in Web View Automation 

Sent by Cursor Automation: Release

Comment thread src/openenv/validation/runner.py Outdated
Comment thread src/openenv/validation/graders/runtime/basic.py
Comment thread src/openenv/validation/graders/runtime/basic.py

@cursor cursor 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.

Stale comment

REQUEST_CHANGES at f405e4ec (autofix progress)

Fixed this head:

  • Medium timeout cap: collection now uses manifest.resources.episode_timeout_s directly; regression asserts 600.0 is passed through.
  • Low schema-worker encoding: parent subprocess.run(..., encoding="utf-8") aligns with UTF-8 stdin.buffer reads.

Still open (Low): graders still call data.get(...) without isinstance(data, dict) after loading a possibly non-object envelope the collector stored before rejecting. That AttributeError escapes the grader catch set → ERROR instead of contract FAIL.

Holding approval for that guard. Exact-head CI still running. Not Thursday 0.6.0 cargo.

Open in Web View Automation 

Sent by Cursor Automation: Release

Comment thread src/openenv/validation/graders/runtime/basic.py
@burtenshaw
burtenshaw force-pushed the ben/rfc008-l2-03-runtime branch from f405e4e to 16d6868 Compare September 21, 2026 13:21

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Startup failures hide provider diagnostics
    • Runtime startup outcomes now retain the sanitized exception details for runtime-plan, startup, and provider failures, with regression coverage for each path.

Create PR

Or push these changes by commenting:

@cursor push 0577dc4585
Preview (0577dc4585)
diff --git a/src/openenv/validation/runner.py b/src/openenv/validation/runner.py
--- a/src/openenv/validation/runner.py
+++ b/src/openenv/validation/runner.py
@@ -185,27 +185,27 @@
             "runtime.startup", CheckStatus.SKIP, str(exc), started=started
         )
         checks = []
-    except RuntimePlanError:
+    except RuntimePlanError as exc:
         result = _outcome(
             "runtime.startup",
             CheckStatus.FAIL,
-            "runtime plan is missing, unsafe or invalid",
+            str(exc),
             started=started,
         )
         checks = []
-    except StartupError:
+    except StartupError as exc:
         result = _outcome(
             "runtime.startup",
             CheckStatus.FAIL,
-            "subject failed build or readiness; inspect the Docker fixture/build inputs",
+            str(exc),
             started=started,
         )
         checks = []
-    except ProviderError:
+    except ProviderError as exc:
         result = _outcome(
             "runtime.startup",
             CheckStatus.ERROR,
-            "provider could not complete a bounded operation",
+            str(exc),
             started=started,
         )
         checks = []

diff --git a/tests/test_validation/test_runtime_execution.py b/tests/test_validation/test_runtime_execution.py
--- a/tests/test_validation/test_runtime_execution.py
+++ b/tests/test_validation/test_runtime_execution.py
@@ -7,7 +7,7 @@
 
 import pytest
 from openenv.validation.policy import load_policy, PolicyError
-from openenv.validation.providers import StartupError
+from openenv.validation.providers import ProviderError, StartupError
 from openenv.validation.report import CheckResult
 from openenv.validation.runner import run_validation, source_digest
 from openenv.validation.runtime.artifacts import write_runtime_bundle
@@ -172,6 +172,8 @@
     provider = FakeRuntimeProvider()
     report = run_validation(package, max_level=Level.RUNTIME, provider=provider)
     assert report.verdict.value == "fail"
+    result = next(r for r in report.results if r.check_id == "runtime.startup")
+    assert "invalid runtime plan" in result.evidence[0]
     assert not provider.builds
 
 
@@ -185,9 +187,23 @@
     report = run_validation(package, max_level=Level.RUNTIME, provider=provider)
     result = next(r for r in report.results if r.check_id == "runtime.startup")
     assert result.status is CheckStatus.FAIL
+    assert result.evidence == ["subject build failed"]
     assert report.verdict.value == "fail"
 
 
+def test_provider_failure_diagnostics_are_visible(package):
+    provider = FakeRuntimeProvider()
+
+    def failed_build(*args):
+        raise ProviderError("provider deadline elapsed")
+
+    provider.build = failed_build
+    report = run_validation(package, max_level=Level.RUNTIME, provider=provider)
+    result = next(r for r in report.results if r.check_id == "runtime.startup")
+    assert result.status is CheckStatus.ERROR
+    assert result.evidence == ["provider deadline elapsed"]
+
+
 @pytest.mark.parametrize("failure", [RuntimeError, KeyboardInterrupt])
 def test_collector_crash_or_cancel_always_tears_down(package, monkeypatch, failure):
     provider = FakeRuntimeProvider()

You can send follow-ups to the cloud agent here.

Comment thread src/openenv/validation/runner.py Outdated

@cursor cursor 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.

Stale comment

REQUEST_CHANGES at 16d68689 (CI green; Bugbot refresh)

Prior High/Medium (teardown, bounded send, schema wire budget, timeout cap, UTF-8 encoding) remain fixed. Exact-head CI is green.

New Medium: runtime.startup swallows sanitized StartupError / RuntimePlanError / ProviderError details into generic strings — authors lose actionable diagnostics. Surface a bounded sanitized reason.

Still open (Low): malformed non-object data → grader AttributeError (ERROR vs FAIL).

Bugbot autofix is active. Not Thursday 0.6.0 cargo.

Open in Web View Automation 

Sent by Cursor Automation: Release

Comment thread src/openenv/validation/runner.py Outdated
Comment thread src/openenv/validation/graders/runtime/basic.py
cursor[bot]
cursor Bot approved these changes Sep 21, 2026 •
cursor[bot]
cursor Bot approved these changes Sep 21, 2026 •
Comment thread tests/test_validation/integration/test_runtime_cli.py

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Teardown failure hides startup findings
    • Teardown failures now only mark cleanup incomplete, preserving the existing runtime startup and collection findings.

Create PR

Or push these changes by commenting:

@cursor push 61b156dfda
Preview (61b156dfda)
diff --git a/src/openenv/validation/runner.py b/src/openenv/validation/runner.py
--- a/src/openenv/validation/runner.py
+++ b/src/openenv/validation/runner.py
@@ -234,12 +234,6 @@
                 cleanup["completed"] = True
             except Exception:
                 cleanup["completed"] = False
-                result = _outcome(
-                    "runtime.startup",
-                    CheckStatus.ERROR,
-                    "subject teardown failed",
-                    started=started,
-                )
     return [result, *checks], attempted, plan, evidence, inspection, cleanup

You can send follow-ups to the cloud agent here.

Comment thread src/openenv/validation/runner.py Outdated

@cursor cursor 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.

Stale comment

REQUEST_CHANGES at eb7a40b1 (Bugbot Medium)

Prior APPROVE at this tip is withdrawn. Autofix is still in flight; do not merge until the teardown overwrite is fixed.

Tier 1

  • src/openenv/validation/runner.py _runtime() finally: when running.stop() fails, the existing runtime.startup result is replaced with a generic teardown ERROR. That discards prior PASS/FAIL/ERROR evidence (provider reason, collection failure_reason, etc.) and contradicts the helper docstring (“retain failure evidence through teardown”).

Required: keep the original result (and its evidence); record cleanup failure via cleanup["completed"] = False and/or append a separate note without overwriting attribution. Add a regression that fails primary startup/collection then fails stop(), asserting the primary finding remains visible.

Not Thursday 0.6.0 cargo until merge.

Open in Web View Automation 

Sent by Cursor Automation: Release

Comment thread src/openenv/validation/runner.py Outdated
cursor[bot]
cursor Bot approved these changes Sep 21, 2026 •
@cursor cursor Bot mentioned this pull request Sep 21, 2026

@cursor cursor 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.

Stale comment

Base retargeted to main after #1179 merge (26c9465e). Tip 29c58015 still has the two Bugbot mediums (uncaught post-run source_digest, teardown KeyboardInterrupt) — REQUEST_CHANGES holds. Watching Autofix / next push.

View PR

Open in Web View Automation 

Sent by Cursor Automation: Release

@cursor cursor Bot mentioned this pull request Sep 22, 2026
21 tasks
@burtenshaw

Copy link
Copy Markdown
Collaborator Author

Rebased onto current main (26c9465e) after #1179 merged and resolved the conflict while preserving both sets of regression tests.

The three latest findings are fixed in ccca191e: source-digest failures and teardown interrupts preserve reports/artifacts, and the reward grader handles non-object envelopes explicitly. All 13 checks, including Linux Docker validation and Bugbot, pass on this commit; 378 local validation tests pass. All review threads are resolved. Ready for re-review; the earlier changes-requested review still needs to be refreshed.

cursor[bot]
cursor Bot approved these changes Sep 22, 2026 •
cursor[bot]
cursor Bot approved these changes Sep 22, 2026 •
Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>

@cursor cursor 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.

Stale Bugbot comment from a previous run.

Comment thread src/openenv/validation/runner.py Outdated
"runtime validation requires policy v2; v1 supports --level static"
)
signature = detect_signature(target)
digest_before = source_digest(target)

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.

Initial digest errors skip the report

Medium Severity

The initial source_digest call is not on the report-preserving path. A symlink or non-regular file now raises before any checks run, so authors get an internal-error exit instead of a report. The same ValueError and OSError cases after collection are caught and recorded.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit bea5115. Configure here.

@cursor cursor 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.

Stale comment

REQUEST_CHANGES at exact tip bea5115d — Bugbot Medium (valid):

Initial source_digest skips the report path. digest_before = source_digest(target) (~L282) is uncaught. Symlink / non-regular-file ValueErrors (and OSError from os.open) abort with an internal error before any checks run. Post-collection source_digest already catches (ValueError, OSError) and records a reportable failure — initial digest should do the same (or otherwise emit a ValidationReport ERROR) for symmetry with the Autofix that landed in ccca191e.

Autofix is already kicked off — will re-review when the tip advances. Keep out of Thursday 0.6.0 cargo until green.

View PR

Open in Web View Automation 

Sent by Cursor Automation: Release

@cursor
cursor Bot force-pushed the ben/rfc008-l2-03-runtime branch from ff538de to 65be5dd Compare September 23, 2026 06:30

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Failed digest still reads rejected source
    • Validation now reports the digest failure without parsing, re-digesting, or running the rejected package source.

You can send follow-ups to the cloud agent here.

Comment thread src/openenv/validation/runner.py

@cursor cursor 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.

Stale comment

REQUEST_CHANGES still holds at 65be5dd8 — prior Autofix fixed the uncaught initial digest, but Bugbot Medium is valid on the new shape:

Failed digest still reads rejected source. Catching source_digest and setting digest_before = "" then continues into parser.parse and _runtime before stamping static.manifest ERROR. Those paths can follow the same symlinks / non-regular files the digest rejected, so host content may enter the report or build context before the ERROR is recorded.

Fail closed: on initial digest (ValueError, OSError), emit a ValidationReport with a reportable ERROR (and empty/"" source_digest) and return without parse/runtime. Keep the regression that asserts no internal-error exit and no private path leakage.

Autofix already kicked off — will re-review when the tip advances. Keep out of Thursday 0.6.0.

View PR

Open in Web View Automation 

Sent by Cursor Automation: Release

cursor[bot]
cursor Bot approved these changes Sep 23, 2026 •
cursor[bot]
cursor Bot approved these changes Sep 23, 2026 •
@cursor
cursor Bot requested a review from zkwentz September 23, 2026 08:10
Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>

@cursor cursor 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.

Stale comment

@zkwentz — Ben wants your review before folding this into Thursday’s 0.6.0 cut. Tip refreshed onto current main (16240f19) so you’re not reviewing a stale branch; CI will re-run on this head.

View PR

Open in Web View Automation 

Sent by Cursor Automation: Release

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Interrupt during close drops episode
    • WebSocket close teardown now swallows KeyboardInterrupt like other best-effort teardown failures, preserving completed or previously failed episode evidence.

You can send follow-ups to the cloud agent here.

Comment thread src/openenv/validation/runtime/collector.py

@cursor cursor 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.

Stale comment

REQUEST_CHANGES at exact tip 16240f19 — Bugbot Medium (valid) after merge-main re-scan:

Interrupt during post-episode websocket close drops a finished episode. _bounded_call re-raises KeyboardInterrupt; the teardown except Exception handlers miss it. A completed collection then surfaces as interrupt: startup → ERROR, graders never run, failure_phase still names the last successful op.

Post-episode close/teardown should treat KeyboardInterrupt as best-effort (same as other teardown failures) once complete is True, or convert to RuntimeCollectionInterrupted without discarding measured evidence. Autofix is already kicked off — will re-review on the new tip.

Hold fold into Thursday 0.6.0 until this is green + Zach’s review.

View PR

Open in Web View Automation 

Sent by Cursor Automation: Release

@cursor cursor 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.

Re-APPROVE at dd59275f (Bugbot Autofix)

Confirmed the Medium was real: post-episode KeyboardInterrupt during _bounded_call close/teardown bypassed except Exception, so a finished collection was surfaced as RuntimeCollectionInterrupted and graders never ran.

Autofix is correct and minimal — teardown except (Exception, KeyboardInterrupt) on both the graceful close send and the socket close — with a focused regression in test_runtime_transport.py. Local transport suite: 10 passed.

Still waiting on @zkwentz for the human gate before folding into Thursday 0.6.0. Exact-head CI is re-running on this tip.

View PR

Open in Web View Automation 

Sent by Cursor Automation: Release

@cursor
cursor Bot force-pushed the ben/rfc008-l2-03-runtime branch from dd59275 to d94f021 Compare September 23, 2026 08:20

@cursor cursor 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.

Re-APPROVE at d94f0218

Autofix force-pushed the same close-interrupt fix (collector teardown catches KeyboardInterrupt; transport suite 10/10). Prior APPROVE was on superseded tip dd59275f (+1 test-line churn only).

Still waiting on @zkwentz + exact-head CI before Thursday 0.6.0 fold.

View PR

Open in Web View Automation 

Sent by Cursor Automation: Release

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Source digest uses Unix-only flags
    • Made O_NONBLOCK optional in source_digest and added a regression test for platforms where the flag is unavailable.

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit f84f8a3. Configure here.

Comment thread src/openenv/validation/runner.py

This branch has not been deployed

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

Labels

feature size: extra-large Extra-large pull request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants