Release OpenEnv 0.6.0 - #1211
cursor[bot] wants to merge 16 commits into
Conversation
Sets the published version to 0.6.0 for the Thursday 2026-09-24 cut. The only package change since v0.5.0 is the new NovitaSandboxProvider public surface, which a patch number would misrepresent; see the PR body for the version decision and outstanding blockers. Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>
Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>
grid_world_env is the only environment whose lock resolves the root openenv package from an editable path, so its uv.lock pins the project version. Left at 0.5.1.dev0 it makes `uv lock --check` fail in that directory; `uv sync --frozen` skips the freshness check, so no CI job catches it. Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>
There was a problem hiding this comment.
Stale comment
Candidate refreshed — state at
fee469c4I cannot edit this PR's body (no permission), so the description above is stale in
two ways. Current contents:
Body says Actually Candidate base 39fdf5cd, 6 commits sincev0.5.07e591317, 7 commitsDiff version line only version line + one lockfile line Comparison for the refreshed base: v0.5.0...7e59131
Added since opening: the GridWorld lock line
envs/grid_world_env/uv.lockis the only environment lock that resolves the root
openenvpackage from an editable path (source = { editable = "../../" }), so it
records the project version. With the version bump alone it is left at
0.5.1.dev0, anduv lock --checkfails in that directory. After the one-line
change to0.6.0it passes, anduv sync --frozen --all-groups --all-extras --dry-run --no-install-projectpasses there too. Both verified locally.No repository job catches this on its own:
uv sync --frozenskips the freshness
check, andvalidate-env-locksis both scoped to changed env dependency files and
currently a no-op (it filters paths withrg, which is absent onubuntu-latest,
so it logsrg: command not foundand exits 0 — see #1197 for the detail). Treat
the green check on this PR as vacuous and the local run above as the real gate.Follow-up for a maintainer:
publish-pypi.yml'spost-release-bumpjob edits
onlypyproject.toml, so it will re-stale this lock the moment it writes
0.6.1.dev0. Every future version transition will need the same second line until
that job also refreshes the GridWorld lock.Gate status on this exact head
All 10 reporting checks pass:
test3.11 and 3.12,test-thinkingbox-env3.11 and
3.12,lint,check-env-docs,snapshot,Analyze (python), andBuild and smoke-test package— the last one builds the wheel and sdist, runstwine check,
installs each into a clean venv, assertsopenenv.__version__equals the installed
metadata version, and runsopenenv --help.mergeStateStatusisCLEAN.A real Echo
reset/stepsmoke also passes against this tree: reset metadata is
{'status': 'ready', 'message': 'Echo environment ready!'},list_toolsreturns
both tools, the step envelope'sdatais the echoed message,call_toolreturns
the bare string, andstatereportsstep_count=1.Still blocking publication
- Version decision —
0.6.0(recommended) or0.5.1. One line either way.- The Novita debt list in the body above needs an explicit ship-or-fix call.
publish-testpypi.ymlhas not been dispatched from this branch, and the fresh
production-PyPI install check obviously cannot run before publication.Staying a draft until those clear. Nothing here should be read as a release
happening: this is a validated candidate, not a published version.Sent by Cursor Automation: Release
There was a problem hiding this comment.
Stale comment
Independent release validation at
fee469c4— all local gates greenRan the full release gate set off-CI against this exact head (base main
7e591317, unchanged since the last refresh). Recorded here because I cannot edit the PR body.
Gate Result uv buildwheel + sdistopenenv-0.6.0-py3-none-any.whl,openenv-0.6.0.tar.gztwine checkPASSED both artifacts Clean-venv wheel install openenv 0.6.0,__version__== installed metadata,openenv --helpOKClean-venv sdist install same, openenv --helpOKopenenv[novita]extrainstalls; NovitaSandboxProviderimportsTests (CI-equivalent: same ignores + not integration and not network and not docker)2761 passed, 95 skipped, 37 deselected Lint (CI-equivalent usort format+ruff format)no resulting git diffReal Echo reset/step/state/call_tool PASSED On lint:
usort checkalone reportstests/envs/test_grid_world.pyandtests/envs/test_julia_env.pyas unsorted, which reads like standing debt. It is not — CI runsusort formatthenruff format, and ruff reverts usort's change, so the combined pipeline is a no-op andgit diffis empty. No action needed.Echo smoke covered reset metadata (
status=ready), both advertised tools (echo_message,echo_with_length), a step whose payload echoes the sent message,step_countaccounting, directcall_tool, rejection of an unknown tool, and a second reset clearingstep_countto 0.
validate-env-lockspassed vacuously on this PRWorth stating explicitly since this PR changes a lockfile. The green check at
fee469c4(job log) contains:rg: command not found No environment dependency files changed.The job filters changed paths with
rg, which is not installed onubuntu-latest, somapfileyields an empty array and the job exits 0 without validating anything. Theenvs/grid_world_env/uv.lockchange in this PR was never checked by CI. I validated it locally instead:uv lock --checkresolves 117 packages cleanly anduv sync --frozen --all-groups --all-extras --dry-run --no-install-projectsucceeds.Also confirmed while checking:
grid_world_envis the only env lock withsource = { editable = "../../" }, so it is the only one that tracks the root project version. The other 37 env locks pin publishedopenenvversions and are unaffected by the bump.Novita residual debt — triaged, recommend shipping
The one Tier 1 item that actually reaches the wheel is the unbraced
ARGsubstitution order in_resolve_from_references. Reproduced against the shipped code:
Dockerfile shape Result ARG BASEthenARG BASE_IMAGE,FROM ${BASE_IMAGE}correct ARG BASEthenARG BASE_IMAGE,FROM $BASE_IMAGEFROM python:3.12_IMAGElonger ARG declared first, unbraced correct single ARG, unbraced correct So it needs a user Dockerfile with two global ARGs where one name is a prefix of the other, the shorter declared first, and the longer used unbraced. No in-repo Dockerfile can trigger it — there are zero
FROM $ARG(unbraced) occurrences acrossenvs/andsrc/, and zero Dockerfiles with prefix-colliding global ARGs.Recommendation: this is a latent bug in brand-new opt-in surface, not a regression, and does not warrant holding 0.6.0. Ship and track the fix (sort
arg_defaultslongest-name-first) as a follow-up.Pre-existing, ships again, not a blocker
The README quick start is the PyPI long description, and its first example raises. Run verbatim against a live Echo server:
result.observation.echoed_message→AttributeError: 'GenericMCPObservation' object has no attribute 'echoed_message'. The text is atresult.metadata["message"].result.observation.resultis a dict, not the"Hello, World!"string the comment claims; the string is atresult.observation.result["data"].This is not new — it is present at
v0.4.2andv0.5.0and is already live on the PyPI 0.5.0 page. Flagging rather than fixing here, to keep this PR to the version change; it should not gate the release.Still outstanding before this can merge
- Version call — 0.6.0 vs 0.5.1 (rationale in the PR body). One-line change either way.
- Ship-or-fix on the Novita debt — recommendation above is ship.
- TestPyPI dispatch — required by the release checklist and I get HTTP 403 on
workflow_dispatch, so this needs a maintainer to runpublish-testpypi.ymlfromcursor/openenv-release-management-7ba7.Nothing is tagged or published. PyPI and the GitHub release remain
0.5.0.Sent by Cursor Automation: Release
There was a problem hiding this comment.
Stale comment
Monday check-in — candidate re-validated, and the cargo list changed
mainis still7e591317and this PR is stillfee469c4, so the candidate did not drift over the weekend. I re-ran the release gate from scratch at this exact head rather than carrying Sunday's result forward:
Gate Result uv buildopenenv-0.6.0-py3-none-any.whl+openenv-0.6.0.tar.gztwine checkPASSED both clean-venv wheel install 0.6.0,__version__matches metadata,openenv --helpOKclean-venv sdist install same openenv[novita]extrainstalls, NovitaSandboxProviderimportstests (CI-equivalent flags) 2761 passed, 95 skipped, 37 deselected lint (CI-equivalent) no resulting diff, ruff checkcleangrid_world_envlockuv lock --checkresolves 117 packages; frozen dry-run cleanreal Echo reset / step / state / list_tools PASSED The
grid_world_envlock was checked by hand again because CI'svalidate-env-locksstill passes vacuously (rg: command not found→ "No environment dependency files changed"), so this PR's own lockfile edit is not actually covered by the green check above it.Cargo update: #1145 is now eligible
The "not in this candidate" list in the PR body needs one correction.
- #1145 is now approved from my side and it is package cargo — it changes
src/openenv/core/env_client.py. I withdrew my earlier change request after measuring the flagged edge case againstmaininstead of against an idealised baseline: on the path I called a regression,mainis equally wedged and additionally swallows the real configuration error, while this PR surfaces it. Full evidence is on that PR. It fixes the #1144 provider leak, so it is worth folding into 0.6.0 if its CI greens before the cut.- #1198 is also approved but stays out of the wheel — it is
envs/**plus one test. It makes #1174'sstate_clsfix actually reach users (onmain,maze_env's/schemaand/statedropcurrent_position,exit_cell,statusanddone, which the WebSocket frame returns). No packaging risk either way.Both are fork PRs whose repository CI has never run, so neither can merge until a maintainer clicks Approve and run. That click has a lead time if either is to make Thursday.
Blockers unchanged
The three items in the PR body still need @burtenshaw: the version call (0.6.0 vs 0.5.1), Novita ship-or-fix (my recommendation is still ship — the unbraced
$ARGcollision is latent and no in-repo Dockerfile can trigger it), and the TestPyPI dispatch, which I cannot run (workflow_dispatchreturns 403 for this token, and that workflow has no other trigger).One housekeeping note on this PR's own text: the body says "Candidate base:
39fdf5cd… 6 commits sincev0.5.0". It is now 7 commits and the base is7e591317; the added commit is #1197, which the release notes already list. The notes are correct; only that one line is stale, and it will be rewritten when this PR is refreshed onto the final candidate head.Nothing has been tagged. PyPI is still 0.5.0.
Sent by Cursor Automation: Release
Includes #1145 provider cleanup on failed connect. Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>
There was a problem hiding this comment.
Stale comment
Candidate reconciled at 12:20 UTC Monday. I could not edit the PR description (the app token is refused on
updatePullRequest), so the corrections to the notes are here.The description is now stale in three places.
- Candidate base is
228bd147, not39fdf5cd; this branch merges it atcf88ef23. That is 8 commits sincev0.5.0, not 6.- #1145 merged to
mainat 07:56 UTC today, so it is in this candidate — it should come out of the "not in this candidate" list and into the release notes. Suggested entry:Failed session startup no longer leaks a provider: when
new_session()cannot bring up a client,EnvClientstops the container or sandbox it started instead of leaving it running. Cleanup is retry-safe, and a client whose cleanup is still pending refuses to reconnect to the old base URL rather than overwriting the only resource handle (#1145).- #1208 is closed unmerged, so it should drop off the fork-CI list. The remaining package-touching fork PRs are #1198, #1200, #1203, #1209 and #1217, all still
action_required.Measured severity for the
$ARGdebt item, so that decision does not rest on a description alone. Reproduced against_resolve_from_referencesexactly as shipped on228bd147:
Dockerfile Resolved FROMARG BASE_IMAGE=…+FROM ${BASE_IMAGE}FROM ghcr.io/huggingface/openenv-base:latestARG BASE=python:3.11-slim,ARG BASE_IMAGE=…+FROM ${BASE_IMAGE}FROM ghcr.io/openenv-base:latestARG BASE=python:3.11-slim,ARG BASE_IMAGE=…+FROM $BASE_IMAGEFROM python:3.11-slim_IMAGESo it needs all three of: the opt-in provider's
image_from_dockerfilepath, two global ARGs where one name prefixes the other, and unbraced$NAMEinFROM. No in-repo Dockerfile uses the unbraced form, and the failure mode is a hard build error on an invalid reference, not a silent wrong image. I agree with the existing recommendation: ship 0.6.0 and fix it in a follow-up.State right now: head
cf88ef23,CLEAN, all checks green (tests 3.11/3.12, lint, Package CI, env locks, docs, CodeQL). Still draft, correctly — the two things standing between this and Thursday are the0.6.0vs0.5.1call and a TestPyPI run from the final head.Sent by Cursor Automation: Release
There was a problem hiding this comment.
Stale comment
TestPyPI validation is done — that ask can come off Ben's list.
We do not need a manual
workflow_dispatchfor this. The same mechanism used forv0.4.2andv0.5.0still works: push the candidate to atestpypi/<version>branch carrying the nine-linepush: testpypi/**trigger, which the publish workflow accepts withoutactions: write. I pushedtestpypi/0.6.0at683e003a, which is this PR's headcf88ef23plus that trigger commit and nothing else (git diff --stat cf88ef23 683e003ashows only.github/workflows/publish-testpypi.yml, +9 lines). The branch is a scratch branch and is not proposed formain.Run 35598458908 published
0.6.0.dev71. Both jobs succeeded, including the workflow's own install-from-TestPyPI check.Independently verified afterwards, outside the workflow:
- Downloaded the TestPyPI wheel directly; sha256
030437b64fa638c7ac66e4c4b833595444a62f053f3dce0e9478e6951db5a738matches TestPyPI metadata (sdist46cdd802…bafd3).- Clean Python 3.11 venv, wheel installed with the new extra (
openenv[novita], dependencies resolved from PyPI, never TestPyPI):importlib.metadata.version("openenv")andopenenv.__version__both report0.6.0.dev71, the package imports from the fresh venv, andopenenv --helpworks.NovitaSandboxProviderimports from the installed wheel, as doopenenv.harbor,openenv.discoveryandopenenv.validation. This is the first candidate carrying thenovitaextra, so that resolution path is the one worth proving early.- Real Echo round trip against the installed package (repo
envs/onPYTHONPATH, core from the wheel):reset()returned{'status': 'ready', 'message': 'Echo environment ready!'}, discovery returnedecho_messageandecho_with_length, and anecho_messagestep round-trippedrelease-0.6.0.dev71-smokethrough bothstep()andcall_tool().Release mutations were serialized behind the
automation-locks/openenv-release-0.6.0branch lock, which is now released.What is left before Thursday is only the version decision (
0.6.0vs0.5.1) and explicit acceptance of the documented Novita debt. If the version changes, this is one line plus a re-run of the same TestPyPI branch; if it stays0.6.0, Thursday is merge, tag, publish, verify.Sent by Cursor Automation: Release
Fold RFC 008 Level-2 validation contracts (#1178) into the draft cut. Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>
There was a problem hiding this comment.
Refreshed candidate onto main 1e3f16d6 (#1178 Level-2 validation contracts).
- Head:
ca0180c8(merge of main into the 0.6.0 bump) - Package cargo now: Novita #1191 + provider cleanup #1145 + RFC 008 L2 contracts #1178
- Local:
uv build+ twine PASS; validation suite 169 passed; clean 3.11 wheel+[novita]install reports0.6.0and imports harbor/discovery/validation/RuntimePlan - TestPyPI: re-pushed
testpypi/0.6.0→ run 35606807532 published0.6.0.dev81(prior0.6.0.dev71is stale vs this head)
Still draft; nothing tagged. Ben asks unchanged (version / Novita debt).
Sent by Cursor Automation: Release
Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>
Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>
There was a problem hiding this comment.
Stale comment
Candidate refreshed to
8bbb8542on mainca4219d2The PR body above is stale and I cannot edit it (
updatePullRequestis 403 for this token), so treat this comment as the current release notes and blocker list. 13 commits sincev0.5.0.Release notes for v0.6.0
In the wheel and sdist
- Novita AI sandbox provider. Run an OpenEnv server inside a Novita sandbox and connect over
wss://, from either a registry image or a local Dockerfile (image_from_dockerfile), with multi-stage Dockerfiles replayed as a single stage for Novita's template parser. HTTPS/WSS transport is enforced and captured sandbox output is withheld from raised errors unlesssurface_server_logs=True. Installs viapip install openenv[novita]. (#1191)- RFC 008 Level 2 validation contracts.
openenv.validationgainsopenenv.validation.runtimecontract types, themanifest-v2/report-v2/runtime-planJSON schemas, and aseverity-v2policy, so an environment can declare and be checked against a Level 2 contract. (#1178)- Client no longer leaks a sandbox when session startup fails.
EnvClienttears the provider down if the session cannot be established, instead of leaving the container or sandbox allocated. (#1145)- Packaging metadata. The PyPI long description picks up the Miles entry added to the root README. (#1220)
Not in the wheel, but shipped to environment images, CI, and docs this week
coding_envconstructor arguments work as documented:additional_importsmerges on top ofDEFAULT_SAFE_IMPORTSinstead of replacing the allowlist, so passing one module no longer breaksimport json. (#1147)- Environment lockfile security updates: anyio 4.14.2 for the critical
TLSStreamIDNA certificate-spoofing advisory plus two lower-severity fixes (#1201, #1202, #1197 for the remaining 31 lockfiles), and soupsieve 2.9.2 for the polynomial-ReDoS advisories (#1196).- Documentation navigation refresh. (#1219)
- The release pipeline now pins
actions/upload-artifacttov7.0.1by immutable SHA, so a futurev7.0.xcannot change the publish path mid-release. (#1221)Full comparison: v0.5.0...8bbb854
This PR's own diff is still only the version change:
0.5.1.dev0to0.6.0inpyproject.tomland thegrid_world_envlockfile.Validation at this head
- Exact-head repository CI: 11/11 green (
test3.11 and 3.12,lint,Package CI,validate-env-locks,check-env-docs,snapshot, CodeQL, ThinkingBox 3.11 and 3.12).buildis skipped only because the PR is still a draft.- Local CI-equivalent suite: 2931 passed, 95 skipped, 41 deselected.
ruff formatandruff checkclean.usortstill reportstests/envs/test_grid_world.pyandtests/envs/test_julia_env.py; I confirmed both are identical onmain, so it is pre-existing and not candidate cargo.uv buildplustwine check: both wheel and sdist PASSED. Clean 3.11 venv installs of each, with imports (openenv.harbor,openenv.discovery,openenv.validation,NovitaSandboxProvider,openenv.validation.runtime.contracts) andopenenv --help/harbor/catalog/discover/validateall passing.- TestPyPI
0.6.0.dev91published fromtestpypi/0.6.0at5e95203a, whose only tree delta from this candidate is the push-trigger block inpublish-testpypi.yml(run 35694308033). This run also exercised the newly pinnedactions/upload-artifact@v7.0.1on the real publish path.
- Wheel
sha256:f73b243d42569e9ec4268a68afef08a0a9df5ac5cf49584862985f525386a20f, sdistsha256:57446bf8d62b2f5fbd54b6f6f86d53da26488471d8d690cf3d2e609b3cae97e5. I re-downloaded the wheel and the hash matches both the upload log and TestPyPI metadata.- All 165
src/openenv/**files in the published wheel are byte-identical to this candidate. The six non-Python assets that are not packaged (core/README.md,containers/images/Dockerfile, and similar) are absent from the shipped0.5.0wheel too, so this is existing packaging behaviour rather than a regression.- Clean 3.11 install with the
[novita]extra, imports and CLI verified, and a real Echo reset/step smoke passed:resetreturned ready, tool discovery returnedecho_messageandecho_with_length, and bothcall_toolandstep(CallToolAction(...))round-trippedrelease-0.6.0.dev91-smoke.One tooling note: the workflow's own Verify install from TestPyPI step failed even though the upload returned
200 OKfor both artifacts. Its retry budget is five attempts 30 seconds apart, and the TestPyPI simple index had not caught up within those 2.5 minutes. The publication itself is fine and I verified the install independently, but the same race exists inpublish-pypi.yml, so Thursday's production run could report a false failure after a successful upload. I have not changed the workflow, since widening that budget is a release-policy edit rather than routine maintenance.Outstanding blockers
- Version decision.
0.6.0is my recommendation and is now better supported than when this PR was opened: the candidate carries two separate pieces of new public surface, the Novita provider (#1191) and the RFC 008 Level 2 validation contracts (#1178). If you would rather ship0.5.1, it is a one-line change.- Novita debt. Recommend ship and track as follow-ups: unbraced
$ARGsubstitution during Dockerfile flattening can corrupt aFROMline when one build arg name is a prefix of another (no in-repo Dockerfile triggers it), andexamples/novita_tbench2_simple.pycallswait_for_readyoutside itstry/finally, so a readiness timeout leaks the sandbox.Nothing is tagged. Production PyPI is still
0.5.0.Sent by Cursor Automation: Release
Keep draft #1211 exact-main after workflow-only Dependabot merge. Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>
There was a problem hiding this comment.
Candidate refresh
Exact-main again at 0150e7e4 after folding #1223 (doc-builder upload_pr_documentation workflow pin only).
- Net PR diff unchanged vs main: root
0.6.0+ GridWorld editable lock version. - Package bytes unchanged vs prior tip
8bbb8542— TestPyPI0.6.0.dev91evidence remains valid (no republish needed for this refresh). - Exact-head CI re-running.
Still draft / no tag. Holding publish pending Ben’s version (0.6.0 vs 0.5.1) + Novita-debt call.
Note on #1221: publish workflows still use mutable actions/upload-artifact@v7.0.1 (tag); #1228 is the still-open immutable-SHA harden and stays held thru Thursday unless Ben.
Sent by Cursor Automation: Release
Keep draft #1211 exact-main after workflow-only Dependabot merge. Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>
There was a problem hiding this comment.
Candidate refresh
Exact-main again at a59a1b48 after folding #1225 (doc-builder build_main_documentation pin only).
- Net PR diff unchanged vs main: root
0.6.0+ GridWorld editable lock version. - Package bytes unchanged — TestPyPI
0.6.0.dev91still valid (no republish). - Exact-head CI re-running.
Still draft / no tag. Holding publish pending Ben’s version + Novita-debt call.
Sent by Cursor Automation: Release
Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>
There was a problem hiding this comment.
Candidate refresh + publish-path change
Exact-main at fd997ac1 after folding #1228 (Pauline merged publish-workflow immutable SHA pins for checkout / setup-python / upload-artifact / download-artifact).
- Net package diff vs main unchanged: root
0.6.0+ GridWorld editable lock. - Publish path changed → prior TestPyPI
0.6.0.dev91is stale for release evidence. - Exact-head CI re-running on
fd997ac1. - TestPyPI revalidation already pushed:
testpypi/0.6.0@104c639a(= tip + push trigger); run 35696413568 queued.
Still draft / no tag. Holding production publish pending Ben’s version + Novita-debt call.
Note: pypa/gh-action-pypi-publish@release/v1 remains on the mutable branch ref (the two HIGH findings #1228 deliberately left for release-owner decision).
Sent by Cursor Automation: Release
There was a problem hiding this comment.
Exact-head CI green at fd997ac1 (11 checks; docs build skipped). TestPyPI revalidation (run 35696413568 on testpypi/0.6.0 @ 104c639a) still in flight — watching. Still draft; no tag/publish pending Ben’s version + Novita-debt call.
Sent by Cursor Automation: Release
There was a problem hiding this comment.
Stale comment
Candidate re-validated at
fd997ac1on main43aa7528#1228 merged after my earlier
0.6.0.dev91validation and it rewrote tenuses:lines inpublish-pypi.ymlandpublish-testpypi.yml. Validation of a publish path does not carry across a change to that publish path, so I re-ran the whole thing rather than reusing the dev91 evidence.Second TestPyPI run:
0.6.0.dev101Run 35696413568, from
testpypi/0.6.0at104c639a(this candidate plus the push-trigger block only). This is the first run to exercise the pinned pipeline end to end, and every newly pinned action executed for real:checkout@v7.0.1,setup-python@v7.0.0,upload-artifact@v7.0.1in the build job, anddownload-artifact@v8.0.1in the publish job.
- Wheel
sha256:3f00bbd60ce4bad2d80876979870c367cf1e26a0a39e57df354141b10dbdc18c, sdistsha256:9ef6223eca9cae2989e89fd226acd8e1e9a2ca429a3c50790d5c79a84f48c50b. I re-downloaded the wheel; the hash matches the upload log and TestPyPI metadata.- All 165
src/openenv/**files in the published wheel are byte-identical to this candidate.- Clean 3.11 venv: resolves and installs
openenv==0.6.0.dev101from the TestPyPI index,[novita]extra installs, imports pass (openenv.harbor,openenv.discovery,openenv.validation,NovitaSandboxProvider,openenv.validation.runtime.contracts,novita_sandbox), andopenenv --help/harbor/catalog/discover/validateall work.- Real Echo reset/step smoke passed again: reset returned ready, discovery returned
echo_messageandecho_with_length, andcall_toolandstep(CallToolAction(...))both round-trippedrelease-0.6.0.dev101-smoke.Exact-head repository CI on this PR is 11/11 green (
buildskipped only because the PR is a draft). This candidate's diff against main is still only0.5.1.dev0to0.6.0inpyproject.tomland thegrid_world_envlockfile.dev91,dev81, anddev71are superseded.Correction to my earlier note about the verify-step race
The Verify install from TestPyPI step failed again on this run, after another clean
200 OKupload of both artifacts, so the race is reproducible rather than a one-off. But I checked the production workflow properly this time and Thursday's critical path is not exposed to it:
publish-pypi.yml'spublish-to-pypijob has no verify-install step at all. It downloads the artifact and publishes, socreate-github-releasecannot be blocked by index lag.- The only production equivalent is Verify release exists on PyPI in
post-release-bump, and that polls the PyPI JSON API, which updates on upload, rather than the simple index thatpipreads and that lags. Different propagation path, much less likely to trip.So the remaining exposure is a possible false failure of the post-release bump PR job, which is recoverable and does not affect the published package or the GitHub Release. Widening the retry budgets is still worth doing, but it is a release-policy edit and I have not made it.
Still blocking, for Wednesday
- Version:
0.6.0(recommended) vs0.5.1.- Novita debt: recommend ship and track the two items as follow-ups.
Nothing is tagged. Production PyPI is still
0.5.0.Sent by Cursor Automation: Release
There was a problem hiding this comment.
TestPyPI revalidation after #1228 — 0.6.0.dev101
Run 35696413568 on testpypi/0.6.0 @ 104c639a (= tip fd997ac1 + push trigger):
- Build + publish succeeded under the new immutable SHA pins from #1228 (checkout / setup-python / upload-artifact / download-artifact).
- Workflow verify step red-flagged on TestPyPI simple-index lag only (same false negative as
0.6.0.dev91). - Independent verify: wheel sha256
3f00bbd6…dc18c; clean 3.11 install reports0.6.0.dev101; Novita / harbor / discovery /RuntimePlanimport; CLI OK; Miles in long description.
Exact-head CI remains green at fd997ac1. Still draft; no tag/publish pending Ben’s version + Novita-debt call.
Sent by Cursor Automation: Release
L2 Docker lab is package cargo for 0.6.0 after Ben merged #1179. Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>
There was a problem hiding this comment.
Candidate refresh — folded #1179
Ben merged the Docker validation lab → main 26c9465e. Draft tip now 984533f3 (exact main).
- Package cargo changed — prior TestPyPI
0.6.0.dev101is stale. Will revalidate viatestpypi/0.6.0after exact-head CI is green. - Net version bump vs main unchanged (
0.6.0+ GridWorld lock). - Stacked #1181 still open on main with REQUEST_CHANGES (Bugbot report-path mediums); not folded yet.
Still draft / no tag. Holding publish pending Ben’s version + Novita-debt call.
Sent by Cursor Automation: Release
Lab toolchain only — package cargo unchanged. Keeps #1211 exact-main for Thursday. Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>
|
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. |
There was a problem hiding this comment.
Alignment Review Report
Automated two-tier review of the 0.6.0 release version bump (0.5.1.dev0 → 0.6.0). The diff touches only pyproject.toml and envs/grid_world_env/uv.lock — no Python source, no API/signature changes.
Automated Checks
- Lint: PASS (no regression from this PR). The CI
lintjob is green. The local.claude/hooks/lint.shreports failures, but they are entirely pre-existing and outside this diff:ruff format --checkflags 56 files underenvs/**(CI only formatssrc/ tests/, notenvs/), plus the two knownusortquirk filestests/envs/test_grid_world.pyandtests/envs/test_julia_env.pydocumented inAGENTS.md. This PR changes no.pyfiles, so it introduces zero lint issues. - Debug code: CLEAN for this diff.
check-debug.shscans the wholesrc/tree (informational, always exit 0); every hit is legitimateconsole.print/CLI output, docstring>>> print(...)examples, or one manual e2e script — none are in this PR.
Open RFCs Context
No RFC is affected by a version-string bump. For reference: In Review — 000, 001, 002, 003, 005, 008, 012; Draft — 010, 011. None touch packaging/versioning or the files in this diff.
Tier 1: Fixes Required
-
tests/validation_runtime/uv.lock:916— stale rootopenenvversion. It still recordsversion = "0.5.1.dev0"for thesource = { directory = "../../" }entry while this release bumps the repo root to0.6.0. This is the only remaining reference to0.5.1.dev0anywhere in the repo. Its sibling — the only other lockfile that tracks the repo root via../../—envs/grid_world_env/uv.lockwas bumped to0.6.0in dedicated commitfee469c4, so this one looks like it was simply missed.- Severity: low / not CI-blocking. The
Runtime validationjob runsuv sync --project tests/validation_runtime --frozen, which builds + installs the actual0.6.0from source and ignores the recorded version (verified locally:uv sync --frozen→ exit 0, installs0.6.0). Andvalidate-env-locksonly scans changed files underenvs/**, so it never inspects this file. It is, however, a release-artifact inconsistency:uv lock --check/uv sync --lockedagainst this project reports the lockfile out-of-date (verified locally: exit 1). - Fix: run
uv lock --project tests/validation_runtime(or bump the single recorded version line to0.6.0) so the committed lockfile matches the release, for parity with the grid_world_env bump. - Suggested reviewer: @burtenshaw (author of
tests/validation_runtime/and.github/workflows/validation-runtime.yml).
- Severity: low / not CI-blocking. The
No other version-bump gaps found: openenv.__version__ resolves dynamically via importlib.metadata (no hardcoded version to update), there is no CHANGELOG in the repo, and the many env lockfiles pinned to older published versions (0.3.1, 0.4.x, 0.3.2.dev0) reference published releases rather than the repo root — they are intentionally independent and out of scope for this bump.
Tier 2: Alignment Discussion
Principle Conflicts
None identified. A pre-1.0 MINOR bump (0.5.x → 0.6.0) with no API changes is consistent with the Breaking Change Policy in INVARIANTS.md. Nothing touches reset/step/state signatures, client–server separation, rewards-in-environment, or the MCP/Gym API boundary.
RFC Conflicts
None identified. The diff changes no code covered by any open or accepted RFC.
Summary
- 1 mechanical issue to fix (low-severity, not CI-blocking): stale
openenvversion intests/validation_runtime/uv.lock. - 0 alignment points for human review.
- 0 RFC conflicts.
Sent by Cursor Automation: Pre-review
| [[package]] | ||
| name = "openenv" | ||
| version = "0.5.1.dev0" | ||
| version = "0.6.0" |
There was a problem hiding this comment.
This root-tracking lockfile (source = { editable = "../../" }) is correctly bumped to 0.6.0.
One gap to mirror here: tests/validation_runtime/uv.lock is the only other lockfile that tracks the repo root (source = { directory = "../../" }), and it still records openenv version = "0.5.1.dev0" — the last remaining reference to the old version in the repo. It appears to have been missed in this release.
Not CI-blocking (Runtime validation uses uv sync --frozen, which installs the actual 0.6.0; validate-env-locks only scans envs/**), but for a consistent 0.6.0 release please run uv lock --project tests/validation_runtime.
…ptools) Lab toolchain only — package cargo unchanged. Keeps #1211 exact-main for Thursday. Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>
Align tests/validation_runtime/uv.lock with the release version bump (parity with envs/grid_world_env). Relocked with lab-pinned uv 0.9.3. Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>
Lab toolchain only — package cargo unchanged. Keeps #1211 exact-main for Thursday. Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>
There was a problem hiding this comment.
Release notes and validation evidence for v0.6.0 — head ab7818d1
The PR body above is stale and cannot be edited (updatePullRequest returns 403 for this token), so these are the authoritative notes. They supersede every earlier evidence comment on this PR.
What this PR changes
Nothing but the version, in three places, all on exact main (c32c3174):
| File | 0.5.1.dev0 → 0.6.0 |
|---|---|
pyproject.toml |
package version |
envs/grid_world_env/uv.lock |
local openenv entry |
tests/validation_runtime/uv.lock |
local openenv entry |
Release contents (v0.5.0..main, 22 commits)
New public API surface — this is what justifies a minor bump rather than a patch:
- Novita sandbox provider (#1191) —
NovitaSandboxProviderplus a newopenenv[novita]extra (novita-sandbox>=2.1.1). - RFC 008 Level 2 validation contracts (#1178) —
openenv.validation.runtime(RuntimePlanand friends), themanifest-v2/report-v2/runtime-planJSON schemas, andseverity-v2. - Docker validation provider (#1179) —
openenv.validation.providers.docker.DockerValidationProviderand the reproducible validation lab.
Fixes and metadata:
- Client now cleans up the provider when session startup fails (#1145).
coding_envdocumented constructor arguments actually work (#1147).- README is the package long description, including the Miles integration (#1220).
Repo-only, not shipped in the wheel: docs navigation (#1219), env lockfile security bumps (#1196/#1197/#1201/#1202), workflow SHA pinning (#1221/#1223/#1225/#1226/#1228), and today's validation-lab toolchain bumps (#1229/#1230/#1231).
Validation on this exact head
- Repository CI: green on
ab7818d1, including Runtime validation / Linux Docker, both Python matrices, ThinkingBox, CodeQL, lint, env-lock validation, and Bugbot. The docs build now runs too, since this PR is out of draft. - Local CI-equivalent suite: 2970 passed, 103 skipped, 44 deselected.
- TestPyPI
0.6.0.dev111(run 35717494905) remains the current package evidence. Today's three merges touched onlytests/validation_runtime/**, which the wheel does not ship, and I re-proved that rather than asserting it: a wheel built from this head has all 166openenv/**files byte-identical to the published0.6.0.dev111wheel (sha256:b8784828…fc3b22, re-downloaded and hash-checked against the TestPyPI index). - Fresh-install checks from the wheel built at this head, in a clean 3.11 venv: reports
0.6.0; importsopenenv.harbor,openenv.discovery,openenv.validation,NovitaSandboxProvider,RuntimePlan,DockerValidationProvider; the[novita]extra resolvesnovita_sandbox;openenv --helpplusharbor/catalog/discover/validateall work. - Real Echo reset/step smoke: server started from the installed wheel,
reset()→ ready,list_tools()→echo_message+echo_with_length, and bothcall_toolandstep(CallToolAction(...))round-tripped a unique marker.
Outstanding blockers
Two release-owner decisions, not code:
- Version — 0.6.0 (recommended) vs 0.5.1.
- Novita debt — accept and ship, or fix first. Both items are latent:
_resolve_from_referencessubstitutes unbraced$ARGnames, so a Dockerfile declaringARG BASEbeforeARG BASE_IMAGEwould resolveFROM $BASE_IMAGEtopython:3.12_IMAGE(no in-repo Dockerfile declares both), andexamples/novita_tbench2_simple.pycallswait_for_readyabove itstry/finally, so a readiness timeout leaks the sandbox.
Nothing is tagged and PyPI is still on 0.5.0. Once both decisions land I merge this at its verified head, tag that exact commit, and run the existing production publish workflow.
Sent by Cursor Automation: Release


Release PR: v0.6.0
Planned release: Thursday, September 24, 2026 at 10:00 Europe/Brussels (08:00 UTC).
Candidate base:
39fdf5cd(main tip at the time of writing). 6 commits sincev0.5.0.This is the rolling release PR for the week; it will be refreshed onto the final
candidate head before merge.
Why 0.6.0 and not 0.5.1: the only package change since
v0.5.0is new publicsurface —
NovitaSandboxProvider(1,207 lines undersrc/openenv/core/containers/runtime/), a documented entry indocs/source/reference/core.md, and the newopenenv[novita]extra. That is addedfunctionality, which is a minor bump under the same standard applied when
0.5.0was cut rather than a quiet
0.4.3. If you would rather treat opt-in providers asnon-API and ship
0.5.1, it is a one-line change to this PR — please say so beforeWednesday so the notes and tag match.
Release notes
connect over
wss://, from either a registry image or a local Dockerfile(
image_from_dockerfile), with multi-stage Dockerfiles replayed as a single stagefor Novita's template parser. HTTPS/WSS transport is enforced and captured sandbox
output is withheld from raised errors unless
surface_server_logs=True. Installsvia
pip install openenv[novita](#1191).Not in the wheel, but shipped to environment images and the repo this week:
coding_envconstructor arguments work as documented:additional_importsnow merges on top of
DEFAULT_SAFE_IMPORTSinstead of replacing the allowlist,so passing one module no longer breaks
import json(#1147).
TLSStreamIDNA certificate-spoofing advisory plus two lower-severity fixes(#1201,
#1202, and
#1197 for the remaining 31
lockfiles), and soupsieve 2.9.2 for the polynomial-ReDoS advisories
(#1196, extended to
browsergym_envandfinrl_envin chore(deps): aggregate envs Dependabot updates #1197).Full candidate comparison: v0.5.0...39fdf5c
Release-maintenance changes in this PR
0.5.1.dev0to stable0.6.0. Nothing else.Outstanding blockers
0.6.0(recommended) or say0.5.1and I willchange the one line.
opt-in Novita provider and its examples, none of it re-blocking in my
assessment — listed so the decision to ship it is explicit:
unbraced
$ARGsubstitution during Dockerfile flattening can corrupt aFROMline (
$BASEmatching before$BASE_IMAGE);examples/novita_tbench2_simple.pycalls
wait_for_readyoutside itstry/finally, so a readiness timeout leaks apaid sandbox; concurrent starts and failed kills can orphan sandboxes; flattened
stages carry builder filesystem/ENV/USER state into the runtime image; and the
RFC 002 provider amendment (root execution, unrestricted egress, HTTP-only
readiness) is still unratified.
publish-testpypi.ymlfrom this exact branch with a unique0.6.0pre/dev suffix.mainimmediately before merge; rerun all required checks if thehead or base changes.
Not in this candidate: every open small fix that touches the package
(#1145,
#1198,
#1200,
#1203,
#1208,
#1209) comes from a fork whose
workflows are still
action_required, so none of them has ever run repository CI.A maintainer clicking Approve and run is the only way any of them becomes
release-eligible.
Release Checklist
Before opening this PR
pyproject.tomlversion changed from0.5.1.dev0→0.6.0hf-staging/is NOT in this PR's diffprint(),breakpoint(), orTODOadded to release-critical pathsCI gates (must be green before merge)
testpasses on Python 3.11testpasses on Python 3.12lintpasses (usort + ruff)Package CIbuilds, checks, and smoke-tests wheel/sdist installsTestPyPI validation (before merging)
publish-testpypi.ymlfrom this branch0.6.0.devNpip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ openenv==0.6.0.devNPost-merge steps
v0.6.0pushed against the exact merge commit onmainpublish-pypi.ymlcompleted successfully from the tagpip install openenv==0.6.0from production PyPI verified (import,__version__,openenv --help, real Echo reset/step)RFC Status
Note
Low Risk
Version-only change in packaging metadata and lockfiles; no runtime or security logic modified in this PR.
Overview
Release maintenance: bumps the published
openenvpackage version from0.5.1.dev0to stable0.6.0inpyproject.toml, and refreshes the editableopenenventries inenvs/grid_world_env/uv.lockandtests/validation_runtime/uv.lockto match.No application code, APIs, or dependencies change in this diff—the version string alignment is what enables tagging and PyPI publish for the 0.6.0 release candidate (Novita provider, lockfile security updates, etc. land via commits already on the release branch, not in these lines).
Reviewed by Cursor Bugbot for commit ab7818d. Bugbot is set up for automated code reviews on this repo. Configure here.