Repository navigation
Conversation
❌ 1 Tests Failed:
View the top 3 failed test(s) by shortest run time
To view more test analytics, go to the Test Analytics Dashboard |
ebursztein
added a commit
that referenced
this pull request
Oct 7, 2026
Link assigned issue #342 and source PRs #338, #339 and #340. Keep completed parser components available while removing Inspect VM/workload and Dockerfile/Compose phases from this agent sprint. Shared 0.7 includes all carried code and latest main; complete integration and runtime/package qualification remain Pierre’s work.
tholop
force-pushed
the
feat/sdk-typed-helpers
branch
from
October 8, 2026 13:07
c1ff8c7 to
cb10270
Compare
tholop
force-pushed
the
feat/inspect-capsem
branch
from
October 8, 2026 13:07
6f9656f to
8708553
Compare
This was referenced Oct 8, 2026
…ration Port the inspect-capsem Inspect AI SandboxEnvironment integration onto the 0.7 Python SDK surface in VM-only mode (container/image execution deferred to the follow-up container commit): - Split the implementation across focused modules under integrations/inspect-ai/inspect_capsem/ (config.py, _cleanup.py, _controller.py, _exec.py, _files.py, _lifecycle.py, _registry.py, _tools.py, _transfer.py, sandbox.py) with every module under 300 lines at 100 columns. - Encapsulate private CapsemSandboxEnvironment state inside sandbox.py, return SandboxConnection(type="capsem", command="capsem shell <id>"), and bound process-owned VM teardown at interpreter exit. - Derive staged file transfer part sizes from MAX_REQUEST_BODY_BYTES, scope VM cleanup to exact managed-by + prefix labels, and clean up unnamed VMs on 504 CreateTimeoutError via CreateTimeoutError.vm_id. - Harden non-root user environment reset when id -un prints numeric UID to stdout and exits 1 or pwd.getpwuid raises KeyError in minimal containers. - Wire integrations/inspect-ai into capsem-gate, CI scope routing, installed wheel/sdist entry-point proof (image_package_acceptance.py), and live VM ironbank acceptance (live_acceptance.py + test_sdk_live.py). Proves #310 / #342 acceptance criteria: - [x] `inspect_capsem` registers cleanly as an `inspect_ai` `SandboxEnvironment` entry point (`@sandboxenv(name="capsem")`) from an installed `inspect-capsem-sandbox` wheel and sdist in an isolated prefix (`integrations/inspect-ai/tests/image_package_acceptance.py`). - [x] `sample_init`, `exec` (`ExecTarget.VM` with non-zero exit, signal, and timeout), `read_file`/`write_file` (text, binary, non-workspace), Inspect's `self_check` suite, `eval_async` with `SandboxEnvironmentSpec("capsem", ...)`, `sample_cleanup`, `task_cleanup`, and prefix-scoped `cli_cleanup` run against the live service with session ledger (`history(layer=EXEC)` + `session.db` `exec_events`) and zero leaked VMs.
tholop
force-pushed
the
feat/inspect-capsem
branch
from
October 9, 2026 15:49
8708553 to
ec91d32
Compare
tholop
force-pushed
the
feat/sdk-typed-helpers
branch
from
October 9, 2026 15:49
cb10270 to
1c64f61
Compare
tholop
marked this pull request as draft
October 9, 2026 15:56
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the Inspect AI sandbox provider (
@sandboxenv(name="capsem")inintegrations/inspect-ai, distributioninspect-capsem-sandbox, moduleinspect_capsem) on top of the0.7Python SDK in VM mode, superseding #291 (tracking issue #310, handoff issue #342). Each Inspect sample runs in a fresh ephemeral Capsem micro-VM with bounded file transfers and label-scoped cleanup; OCI container execution (#339) and opt-in hostDockerfilebuilds (#340) stack on top. Stacked on #337.Changes
integrations/inspect-ai/inspect_capsem/):__init__.py,config.py,sandbox.py,_lifecycle.py,_cleanup.py,_controller.py,_exec.py,_files.py,_transfer.py,_tools.py,_registry.py) plus the committedintegrations/inspect-ai/uv.lock.persistent=False, labeledmanaged-by=inspect-capsemplus optionalinspect-capsem-prefix/inspect-capsem-taskand a per-createinspect-capsem-nonce), and scopestask_cleanupandcli_cleanup(inspect sandbox cleanup capsem) strictly to matchingpersistent=Falselabeled VMs.0.7SDK surface from feat(service,sdk): attach labels to VMs at create and expose them in list #336 and feat(sdk,service): add typed ErrorCode enum, timeout/error helpers, and discovery #337 (Hypervisor.connect,discover_gateway,VmLifecycleState, and typedVmNotFoundError/CreateTimeoutError/ExecTimeoutError, cleaning up half-created VMs on HTTP 504CreateTimeoutErrorviaCreateTimeoutError.vm_idor the per-create nonce label).connection()asSandboxConnection(type="capsem", command="capsem shell <vm_id>")._files.py,_transfer.py,_exec.py):SandboxEnvironmentLimits.MAX_EXEC_OUTPUT_SIZE(10 MiB per stream) andSandboxEnvironmentLimits.MAX_READ_FILE_SIZE.[ -f ]) on reads, derives staged transfer chunk sizes fromMAX_REQUEST_BODY_BYTES, and caps guest reads atlimit + 1bytes while streaming (head -c+ per-part accounting in_transfer._staged_download).capsem-servicestores verbatim (_DIRECT_REL_RE) through the direct Files API and falls back to stagedexec(shlex.quote) for paths containing spaces or special characters.config/gate.toml,build_system/,tests/ironbank/test_sdk_live.py):0.7's interiminspect-extractionownership with standalone[integrations_inspect_ai]package ownership and[[surface]] id = "integrations"under lint, typecheck, 300-line limit, and coverage enforcement.fast.integrations.inspect-ai.{lint,types,tests,build}andintegrations.inspect-ai.prewarmintocapsem-gate(ONLINE_FAST), CI scope routing, offline wheel + sdist entry-point verification (integrations/inspect-ai/tests/image_package_acceptance.py), a portable macOStimeouttest shim (integrations/inspect-ai/tests/conftest.py), and the live VM gate lane (tests/ironbank/test_sdk_live.pyrunningintegrations/inspect-ai/tests/live_acceptance.py).--basetempperCAPSEM_TEST_RUN_IDinintegrations/inspect-ai/tests/conftest.pyandsdk/python/tests/conftest.pyso parallel gate pytest steps cannot collide withfast.citadel'sbasetempdirectory.Mapping to Elie's #291 Review
Every item from the #291 review, and where it is resolved in the stack:
integrations/not in[boundary.scripts].roots; 6 files over)#338) + PR 3 (#339)integrations/inspect-aiadded toroots; VM-mode (_cleanup.py,_lifecycle.py, etc.) and container modules split by responsibility and stay under 300 lines._staged_downloadno byte cap,/dev/zero,_save_built_image_to_cache)#338) + PR 3 (#339)_files.read_guest_filerequires a regular file ([ ! -f ] -> NOT_REGULAR),_staged_downloadruns[ -f ] && head -c <limit+1> | splitand stops atlimit + 1while joining parts. The in-guest image cache that owned_save_built_image_to_cacheis deleted with the0.6dockerd backend in PR 3.#336) + PR 2b (#338)persistent=FalseVMs withmanaged-by=inspect-capsem.inspect-capsem-prefix")#338)persistent=False(vm-Ndisplay names, UUID IDs), so scoping is bypersistent=False+ label (managed-by=inspect-capsemand matchinginspect-capsem-prefixwhenCAPSEM_VM_PREFIXis set);inspect sandbox cleanup capsem <id>on any persistent or non-matching VM logs a warning and leaves it alone.environment: [KEY], bind volumes)#339)0.7's carry in PR 3: default-deny host environment interpolation (SAMPLE_METADATA_*allowlist with.envspoofing rejection) andos.path.realpathproject-root containment of bind sources.capsem>=0.6.3while using newer APIs)#338)integrations/inspect-ai/pyproject.tomldeclarescapsem>=0.7.0, matchingsdk/python/pyproject.toml.sanitize_file_path, error-text parsing)#337) + PR 2b (#338)discover_gateway/Hypervisor.connect, structuredErrorResponse.code+ typed exceptions; PR 2b consumes them.#291's character-stripping_sanitize_file_pathhelper is replaced by a direct-Files-API eligibility check (_DIRECT_REL_REin_transfer.py) that routes only pathscapsem-servicestores verbatim through the direct Files API and falls back to stagedexec(shlex.quote) for paths containing spaces or special characters (becausecrates/capsem-service/src/fs_utils.rssanitize_file_pathcurrently strips characters outside[A-Za-z0-9._\-/]with HTTP 200 rather than returning HTTP 400). Nore.searchover error text ininspect_capsem/.#338) + PR 3 (#339)tests/ironbank/test_sdk_live.pyinstalls built wheel + sdist offline into clean prefixes outside the repo and runsintegrations/inspect-ai/tests/live_acceptance.pyin the VM lane without opt-in flags.X as Xre-exports inbuildschema.py0.7(kept under Pierre's authorship);test_qualification_schema_reexports_keep_one_model_identityon0.7assertsbuildschema.X is qualifyschema.X, i.e. the re-exports are now pinned by upstream's own test.SourcePackageConfig, only the next commit uses it0.7already carriesSourcePackageConfigand tests it (_source_package_type). PR 2b is the first consumer ([integrations_inspect_ai]inconfig/gate.toml).sdkchecks.pyinstead ofisinstance/ fallback branches#338)sdkchecks.pytakessettings: SourcePackageConfigexplicitly; noisinstancefallback remains.assertin production code (sandbox.py)#338)assertstatements ininspect_capsem/.0.7; VM-mode sandbox -> PR 2b (#338); OCI container mode -> PR 3 (#339); SDK/service prerequisites -> PR#341/ PR 1 (#336) / PR 2a (#337); opt-in hostDockerfile/ Composebuild:(HostBuildGrant) -> PR 4 (#340), stacked on#339for #342 step 4.ModulesConfig.transition: TransitionSettingsconflict inqualifyschema.py0.7qualifyschema.py:70on0.7@upstream, so there is no conflict to resolve.Qualification (#342)
integrations/inspect-ai/tests,linux/x86_64, Python3.12.14):ruff check,ruff format --check,ty check --error-on-warning --python-platform all, andpytest integrations/inspect-ai/tests -q(68 passed on#338VM-only), plus builtcapsem-0.7.0andinspect_capsem_sandbox-0.1.0wheel and sdist archives.tests/ironbank/test_sdk_live.py::test_inspect_ai_live_vm_sandbox_acceptance): passed across both offline-installed wheel and sdist consumers (python -I), emittingSDK_IMAGE_PACKAGE_ACCEPTANCE_OKandINSPECT_CAPSEM_VM_ACCEPTANCE_OK, with43/43Inspectself_checkpass (test_read_and_write_large_file_binaryskipped), liveeval_asyncVM task (accuracy=1.000,4s), verifiedhistory(layer=EXEC)+session.dbexec_events(target="vm"), foreignpersistent=TrueVM survival, orphan ephemeral sweep, and0leaked managed VMs.Stack Overview (Supersedes #291, Rebased on
0.7)feat/shared-vm-name-rule) — shared VM-name validation rule acrosscapsem-apiandcapsem-servicefeat/sdk-vm-labels) — VM labels on create, fork, and listfeat/sdk-typed-helpers) — structuredErrorCodeenum, timeout/lookup exceptions, and gateway discoveryfeat/inspect-capsem) (this PR) — VM-modeinspect-capsemSandboxEnvironmentintegrationfeat/inspect-capsem-containers) — OCI container execution mode and reconciled0.7Compose parserfeat/inspect-capsem-host-build) — default-off, operator-granted hostdocker build(HostBuildGrant) and hermetic live gate acceptance (Integrate and qualify Inspect AI on current 0.7 (Pierre handoff) #342 step 4)