diff --git a/.github/workflows/local-backends.yml b/.github/workflows/local-backends.yml index 3b08d5c52..c5148cba1 100644 --- a/.github/workflows/local-backends.yml +++ b/.github/workflows/local-backends.yml @@ -142,8 +142,8 @@ jobs: # The slow tier: builds the env images and the echo A2A agent (tst/data/a2a_agent) and deploys # them on the runner's Docker. The tests that need a real model, a remote sandbox, a registered # default A2A agent or MCP server sources from outside this repository skip with the capability reason. - # Its tests run serially, since they share image tags and artifact ids, so it is split across runners - # instead: AGENTENV_TEST_SHARD picks each runner's share, balanced by tst/integration/slow_durations.json + # Each runner runs its files on two workers, a file's tests on one, and AGENTENV_TEST_SHARD picks + # each runner's share of the files, balanced by tst/integration/slow_durations.json # (tst/util/shards.py). The gateway tests are a check of their own, split the same way. Each check passes # when all of its shards do (the integration-local-slow and integration-local-gateway jobs below). integration-local-slow-shard: diff --git a/tst/integration/computer/browser_computer_test.py b/tst/integration/computer/browser_computer_test.py index fa54c53ff..2e1d2529a 100644 --- a/tst/integration/computer/browser_computer_test.py +++ b/tst/integration/computer/browser_computer_test.py @@ -21,17 +21,9 @@ loads for well over a minute after it's ready, but for one Google account check at launch. Routing sites, it goes out only through the shared site proxy's forward port: start tabs on a site over HTTPS and on a .localhost one load through it, an event stream comes through as it's sent, any other host and loopback are refused and logged, the session user can't stop the port, killed it comes back, and -after a reset it serves the sites and refuses the rest again. As a multi env's website browser, ``browser_envs = -[chromium]``, it deploys on a sandbox of its own as one more computer child beside a synthetic site, with no -playwright-mcp: its start tab loads the site by name through the gateway, an agent drives it through the gateway's /mcp -under ``chromium_``, its CDP address asked through ``/svc/chromium/`` names the gateway and reaches the site by name, a -later process reattaches it from the instance store, a universe loaded into the multi env sets its cookies, and -reset_env brings it back after its container is killed and after the gateway restarts; a multi env naming none takes -the run's browser, chromium too, the same way, and ``browser_envs = []`` deploys none; and browser_connect_cdp -hands an agent an address to it at the multi env's gateway, whose relay takes the agent's page to the site by name, -with the multi env's tools hidden from the agent's role. Its log has an entry for every action a CDP agent and an MCP agent take, over CDP, page -tools and pixels, with who, the tab and its URL and no secret either typed or set, and each tab event names the -command that caused it. +after a reset it serves the sites and refuses the rest again. +Its log has an entry for every action a CDP agent and an MCP agent take, over CDP, page tools and pixels, with who, +the tab and its URL and no secret either typed or set, and each tab event names the command that caused it. Needs Docker and the local registry on localhost:5000, and Node 20 or later and npm for the CDP clients.""" @@ -53,28 +45,19 @@ import httpx import pytest from mcp import ClientSession -from mcp.client.streamable_http import streamable_http_client, streamablehttp_client +from mcp.client.streamable_http import streamablehttp_client from PIL import Image from websockets.asyncio.client import connect from agentenv_protocol import client as protocol_v1 -from agentenv_protocol.client import find_extension_method, invoke_extension from agentenv_protocol.computer import COMPUTER_PAGE, COMPUTER_READY from agentenv_protocol.computer.conformance.client import image from agentenv_protocol.tool_context import ROLE_HEADER from agentenv_protocol.website_browser import BROWSER from agent_env.a2a_agent import conversation_store -from agent_env.artifact import EnvironmentUniverseArtifact -from agent_env.artifact.artifacts.environment import EnvironmentArtifact from agent_env.artifact.artifacts.file import FileArtifact -from agent_env.config import get_config -from agent_env.config.runtime import WEBSITE_BROWSER_OVERRIDE, run_env_ids from agent_env.env import Env -from agent_env.env.env import DeployedEnv -from agent_env.env.envs.multi_env import MultiEnv -from agent_env.env.envs.playwright_mcp import PLAYWRIGHT_MCP_ENVIRONMENT_NAME -from agent_env.env.envs.website import WebsiteEnv from agent_env.env.envs.computer.utils import inside from agent_env.env.store import get_env_store from agent_env.providers.sandbox_providers.local_docker.provider import LocalSandboxProvider @@ -84,20 +67,13 @@ from agent_env.task.teardown import teardown_run from agent_env.task_step.context import TaskStepContext from agent_env.task_step.task_steps.browser.connect_cdp import BrowserConnectCdpTaskStep -from agent_env.task_step.task_steps.browser.sign_in import BrowserSignInTaskStep from agent_env.task_step.task_steps.deploy_agent import DeployAgentTaskStep -from agent_env.task_step.task_steps.deploy_env import DeployEnvTaskStep -from agent_env.task_step.task_steps.load_artifact import LoadArtifactTaskStep from agent_env.task_step.task_steps.prompt_agent import PromptAgentTaskStep from agent_env.task_step.task_steps.reset_env import ResetEnvTaskStep from tst.integration.computer.browser_data import SITE as DATA_SITE, check_browser_data, check_browser_data_under_chaos from tst.integration.computer.browser_steps import check_browser_steps from tst.integration.computer.browser_state import check_browser_state, check_browser_state_under_chaos -from tst.integration.computer.multi_env_computers_test import _containers, _gateway, _image -from tst.integration.computer.website_browser_test import _signed_in from tst.integration.computer.start_tabs import host_pages, tabs_of -from tst.integration.store.local_parallel_deploy_test import _seed_bootstrap_envs -from tst.util import local_sandboxes from tst.util.a2a_test_agent import put_test_agent from tst.util.tls_front import tls_front @@ -1198,320 +1174,3 @@ def _trusting(ca: LocalCA) -> ssl.SSLContext: async def _get(deployed, path: str, **kwargs) -> httpx.Response: async with httpx.AsyncClient(timeout=30) as http: return await http.get(f"{deployed.environment_url}{path}", **kwargs) - - -# --- a multi env's website browser (browser_envs) --- - -MULTI_SITE = "https://shop.test/api/health" -MULTI_CHROMIUM = {"sandbox_type": "local", - "env_params": {"form": "container", "app_settings": {"chromium": {"start_urls": [MULTI_SITE]}}}} -#: How often a multi env's browser is asked through the gateway whether it answers again. -ANSWER_POLL_S = 2.0 - - -@pytest.fixture(scope="module") -def shop(browser_computer): - """The gateway's and service-db's envs, and a website whose backend is the small agentenv website, named - shop.test, under a local id, since a multi env naming chromium's local id must be local too.""" - with namespace_routing(): - _seed_bootstrap_envs() - uid = uuid.uuid4().hex[:8] - return WebsiteEnv.put(id=f"@local/~/browsing-{uid}/shop", environment_name="shop", domains=["shop.test"], - backend_docker_image_artifact=_image("agentenv_website", f"browsing-shop-{uid}")) - - -@pytest.fixture -def made(monkeypatch) -> list[str]: - """The ids of the local sandboxes this test's process makes, so it finds and counts only its own.""" - return local_sandboxes.recorded_sandbox_ids(monkeypatch) - - -def _office(shop, browser_envs) -> MultiEnv: - return MultiEnv.put(id=f"@local/~/browsing-{uuid.uuid4().hex[:8]}/office", mcp_server_envs=[], - website_envs=[shop], browser_envs=browser_envs, name="office") - - -async def _drive(deployed) -> dict: - """What an agent sees through the gateway's /mcp: the tools it lists, a screenshot by chromium's name, and the - tabs after it opens the site by name.""" - async with streamable_http_client(deployed.mcp_url) as (read, write, _): - async with ClientSession(read, write) as session: - await session.initialize() - tools = {tool.name for tool in (await session.list_tools()).tools} - shot = await session.call_tool("chromium_computer_screenshot", {}) - opened = await session.call_tool("chromium_computer_navigate", {"url": MULTI_SITE}) - tabs = await session.call_tool("chromium_computer_tabs", {"action": "list"}) - return {"tools": tools, "shot": not shot.isError and any(part.type == "image" for part in shot.content), - "opened": not opened.isError, - "tabs": " ".join(part.text for part in tabs.content if part.type == "text")} - - -async def _answers_again(deployed) -> bool: - """Whether chromium's screenshot answers through the gateway, asked again until it does or ``WAIT_S`` passes.""" - deadline = asyncio.get_running_loop().time() + WAIT_S - while asyncio.get_running_loop().time() < deadline: - try: - async with streamable_http_client(deployed.mcp_url) as (read, write, _): - async with ClientSession(read, write) as session: - await session.initialize() - if not (await session.call_tool("chromium_computer_screenshot", {})).isError: - return True - except Exception: # noqa: BLE001 - the gateway or the browser restarting - pass - await asyncio.sleep(ANSWER_POLL_S) - return False - - -async def _cdp_at_gateway(deployed, browser: DeployedEnv, *, at: str | None = None, user: str = "ada", - origin: str | None = None, ca: LocalCA | None = None) -> dict: - """The CDP address the browser gives ``user``, asked through the gateway's ``/svc/chromium/`` route, at ``at``, a - front before it, else its own address, with the browser's own control token, as agentenv asks a computer child, - naming ``origin`` or not.""" - app = next(child for child in browser.environment_card["children_environments"] if child["name"] == "chromium") - path = protocol_v1.find_extension_method(app, BROWSER, "cdp")["endpoint"] - async with httpx.AsyncClient(timeout=180, verify=_trusting(ca) if ca else True) as http: - answer = await http.post(f"{at or deployed.gateway_url}/svc/chromium{path}", - json={"user": user, **({"origin": origin} if origin else {})}, - headers=browser.control_headers) - assert answer.status_code == 200, answer.text - return answer.json() - - -def _browser_universe(env_id: str, cookies: list[dict]) -> EnvironmentUniverseArtifact: - """An environment universe whose chromium environment holds a browser state setting ``cookies``.""" - run = uuid.uuid4().hex[:8] - state = FileArtifact.put_bytes(id=f"{env_id}-browser-{run}", description="multi env browser e2e", - filename="browser-state.json", content=json.dumps({"cookies": cookies}).encode(), - content_type="application/json") - environment = EnvironmentArtifact.put(id=f"{env_id}-browser-env-{run}", environment_name="chromium", - file_artifacts={"browser-state.json": state}) - return EnvironmentUniverseArtifact.put(id=f"{env_id}-universe-{run}", environment_artifacts=[environment]) - - -async def _browser_op(browser: DeployedEnv, op: str, params: dict) -> dict: - """``op``'s answer from the browser app on ``browser``, a multi env's browser computer, through its own record.""" - app = next(child for child in browser.environment_card["children_environments"] if child["name"] == "chromium") - assert find_extension_method(app, BROWSER, op) is not None, op - return await invoke_extension(browser.environment_url, app, BROWSER, params, 60, method=op, - headers=browser.control_headers) - - -async def _discovery(http_url: str) -> dict: - async with httpx.AsyncClient(timeout=60) as http: - answer = await http.get(f"{http_url.rstrip('/')}/json/version") - assert answer.status_code == 200, answer.text - return answer.json() - - -@pytest.mark.asyncio -async def test_chromium_as_a_multi_envs_browser_runs_on_its_own_sandbox_reached_through_the_gateway( - browser_computer, shop, made): - with namespace_routing(): - office = _office(shop, [Env.get(browser_computer.id)]) - step = DeployEnvTaskStep(id="office", version=None, env_id=office.id, sandbox_type="local", ttl_seconds=900, - child_envs={"chromium": MULTI_CHROMIUM}) - assert step.preflight() == [] - context = TaskStepContext() - try: - [deployed] = (await step.execute(context)).deployed_envs - browser = DeployedEnv.from_dict(deployed.child_envs["chromium"]) - stated = {child.environment_name for child in protocol_v1.children(deployed.environment_card)} - driven = await _drive(deployed) - address = await _cdp_at_gateway(deployed, browser) - discovered = await _discovery(address["http_url"]) - seen = await _cdp_agent_loads(address["ws_url"], [MULTI_SITE]) - reattached = await Env.from_instance_id(deployed.instance_id) - world = _browser_universe(office.id, [{"name": "sid", "value": "ada", "url": MULTI_SITE, "max_age": 3600}]) - await LoadArtifactTaskStep(id="seed", version=None, env_id=office.id, artifact_id=world.id).execute(context) - loaded = await _browser_op(browser, "cookies/get", {"urls": [MULTI_SITE]}) - - subprocess.run(["docker", "kill", *_containers(browser.sandbox_id)], capture_output=True) - await ResetEnvTaskStep(id="reset", version=None, env_id=office.id, fail_task_on_error=True).execute(context) - after_kill = await _answers_again(deployed) - after_kill_tabs = (await _drive(deployed))["tabs"] - - subprocess.run(["docker", "restart", _gateway(deployed, made)], capture_output=True, check=True) - through_restart = await _answers_again(deployed) - await ResetEnvTaskStep(id="reset-2", version=None, env_id=office.id, - fail_task_on_error=True).execute(context) - after_restart = await _answers_again(deployed) - up = _containers(browser.sandbox_id) - finally: - report = await teardown_run(context) - - assert not report.failed and up and _containers(browser.sandbox_id) == [] - # chromium is a computer child on a sandbox of its own, and no playwright-mcp runs. - assert set(deployed.child_envs) == {"chromium"} - assert deployed.sandbox_ids["local"] == {"chromium": browser.sandbox_id} - assert "chromium" in stated and PLAYWRIGHT_MCP_ENVIRONMENT_NAME not in stated, stated - computer = deployed.child_envs["chromium"]["metadata"]["computer"] - assert computer["sites"]["names"]["routes"] == {"shop": ["shop.test"]} - [start_tab] = computer["start_tabs"]["chromium"] - assert (start_tab["url"], start_tab["site"], start_tab["outcome"]) == (MULTI_SITE, "shop", "loaded"), start_tab - # An agent drives it through the gateway, every tool under chromium_. - assert {"chromium_computer_screenshot", "chromium_computer_navigate"} <= driven["tools"], driven - assert not any(name.startswith("computer_") for name in driven["tools"]), driven - assert driven["shot"] and driven["opened"] and MULTI_SITE in driven["tabs"], driven - # Its CDP address names the gateway, its discovery answer too, and an agent there reaches the site by name. - token = address["http_url"].split("/cdp/")[1].strip("/") - assert address["http_url"] == f"{deployed.gateway_url}/browser/chromium/cdp/{token}/", address - assert browser.environment_url.rstrip("/") not in json.dumps([address, discovered]), (address, discovered) - assert discovered["webSocketDebuggerUrl"].startswith( - f"ws{deployed.gateway_url.removeprefix('http')}/browser/chromium/cdp/"), discovered - assert seen[MULTI_SITE]["error"] is None and seen[MULTI_SITE].get("ready") == "complete", seen - # A later process reattaches it from the instance store, and a universe loaded into the multi env sets its cookies. - assert reattached._computers.browser._deployed.sandbox_id == browser.sandbox_id - assert [cookie["value"] for cookie in loaded["cookies"] if cookie["name"] == "sid"] == ["ada"], loaded - # Through a kill and a gateway restart, a reset brings it back. - assert after_kill and MULTI_SITE in after_kill_tabs, after_kill_tabs - assert after_restart, through_restart - - -@pytest.mark.asyncio -async def test_a_multi_env_naming_no_browser_takes_the_runs_and_chromium_runs_as_a_computer_child(browser_computer, - shop): - with namespace_routing(): - office = _office(shop, None) - context = TaskStepContext() - try: - with run_env_ids({WEBSITE_BROWSER_OVERRIDE: browser_computer.id}): - [deployed] = (await DeployEnvTaskStep(id="office", version=None, env_id=office.id, sandbox_type="local", - ttl_seconds=900, child_envs={"chromium": MULTI_CHROMIUM} - ).execute(context)).deployed_envs - stated = {child.environment_name for child in protocol_v1.children(deployed.environment_card)} - finally: - report = await teardown_run(context) - - assert not report.failed and set(deployed.child_envs) == {"chromium"} - assert PLAYWRIGHT_MCP_ENVIRONMENT_NAME not in stated, stated - [start_tab] = deployed.child_envs["chromium"]["metadata"]["computer"]["start_tabs"]["chromium"] - assert (start_tab["url"], start_tab["site"], start_tab["outcome"]) == (MULTI_SITE, "shop", "loaded"), start_tab - - -@pytest.mark.asyncio -async def test_browser_connect_cdp_hands_an_agent_an_address_at_the_multi_envs_gateway_with_its_tools_hidden( - browser_computer, shop): - with namespace_routing(): - agent = put_test_agent(f"cdp-agent-{uuid.uuid4().hex[:8]}") - office = _office(shop, [Env.get(browser_computer.id)]) - context = TaskStepContext() - try: - [deployed] = (await DeployEnvTaskStep(id="office", version=None, env_id=office.id, sandbox_type="local", - ttl_seconds=900, child_envs={"chromium": MULTI_CHROMIUM} - ).execute(context)).deployed_envs - await DeployAgentTaskStep(id="deploy-solver", version=None, env_ids=[], a2a_agent_id=agent.id, - a2a_agent_version=agent.version, agent_name="solver", - sandbox_type="local").execute(context) - await BrowserConnectCdpTaskStep(id="connect", version=None, env_id=office.id, - agent_name="solver").execute(context) - _, title = await _opened_over_cdp(context, "first", url=MULTI_SITE) - tools = await _tool_names(deployed) - async with httpx.AsyncClient(timeout=30) as http: - lines = (await http.get(f"{deployed.gateway_url}/trajectory")).text.splitlines() - relayed = [event for event in map(json.loads, lines) if event.get("event_type") == "browser_connection"] - finally: - report = await teardown_run(context) - - assert not title.startswith("failed"), title - assert tools == [], tools - assert [event["browser"] for event in relayed] and all(event["browser"] == "chromium" for event in relayed), relayed - assert context.metadata["browser_connections"] == [{ - "step_id": "connect", "env_id": office.id, "agent_name": "solver", "browser": "chromium", "name": "chromium", - "keep_tools": False, "role": "default", "tools_hidden": "*"}] - assert not report.failed - - -@pytest.mark.asyncio -async def test_behind_a_front_that_ends_tls_the_multi_envs_gateway_hands_out_https_and_wss_and_an_agent_connects( - browser_computer, shop): - ca = local_ca() - with namespace_routing(): - office = _office(shop, [Env.get(browser_computer.id)]) - context = TaskStepContext() - try: - [deployed] = (await DeployEnvTaskStep(id="office", version=None, env_id=office.id, sandbox_type="local", - ttl_seconds=900, child_envs={"chromium": MULTI_CHROMIUM} - ).execute(context)).deployed_envs - browser = DeployedEnv.from_dict(deployed.child_envs["chromium"]) - gateway = urllib.parse.urlsplit(deployed.gateway_url) - async with tls_front(ca, gateway.hostname, gateway.port) as front: - named = await _cdp_at_gateway(deployed, browser, at=front, origin=front, ca=ca) - unnamed = await _cdp_at_gateway(deployed, browser, at=front, user="bob", ca=ca) - discovered = await _discovered(named["http_url"], ca) - seen = await _cdp_agent_loads(named["ws_url"], [MULTI_SITE], tls=_trusting(ca)) - finally: - report = await teardown_run(context) - - host = front.removeprefix("https://") - assert named["http_url"].startswith(f"{front}/browser/chromium/cdp/"), named - assert named["ws_url"].startswith(f"wss://{host}/browser/chromium/cdp/") and discovered == named["ws_url"], named - assert unnamed["ws_url"].startswith(f"ws://{host}/browser/chromium/cdp/"), unnamed - assert seen[MULTI_SITE]["error"] is None and seen[MULTI_SITE].get("ready") == "complete", seen - assert not report.failed - - -#: A page the site that offers session serves, which says who a request signs in, and chromium starting there. -SESSION_PAGE = "https://shop.test/api/session" -SESSION_CHROMIUM = {**MULTI_CHROMIUM, - "env_params": {"form": "container", "app_settings": {"chromium": {"start_urls": [SESSION_PAGE]}}}} - - -@pytest.fixture(scope="module") -def session_shop(browser_computer): - """A site named shop.test that offers website/v1 session, under a local id, as a multi env naming chromium's local - id must be.""" - with namespace_routing(): - _seed_bootstrap_envs() - uid = uuid.uuid4().hex[:8] - return WebsiteEnv.put(id=f"@local/~/signin-{uid}/shop", environment_name="shop", domains=["shop.test"], - server_docker_image_artifact=_image("session_website", f"signin-shop-{uid}")) - - -@pytest.mark.asyncio -async def test_under_a_chromium_default_a_site_gets_chromium_unnamed_which_browser_sign_in_signs_in_after_each_reset( - browser_computer, session_shop): - config = get_config() - with namespace_routing(): - office = MultiEnv.put(id=f"{session_shop.id.rsplit('/', 1)[0]}/office", mcp_server_envs=[], - website_envs=[session_shop], name="office") - sign_in = BrowserSignInTaskStep(id="in", version=None, env_id=office.id, site=session_shop.id, user="alex") - context = TaskStepContext() - config.default_website_browser_env_id = browser_computer.id # the config's default, not the run's override - try: - [deployed] = (await DeployEnvTaskStep(id="office", version=None, env_id=office.id, sandbox_type="local", - ttl_seconds=900, child_envs={"chromium": SESSION_CHROMIUM} - ).execute(context)).deployed_envs - browser = DeployedEnv.from_dict(deployed.child_envs["chromium"]) - before = await _signed_in(browser) - await sign_in.execute(context) - signed = await _signed_in(browser) - await ResetEnvTaskStep(id="reset", version=None, env_id=office.id, fail_task_on_error=True).execute(context) - after_reset = await _signed_in(browser) - await sign_in.execute(context) - again = await _signed_in(browser) - finally: - config.default_website_browser_env_id = None - report = await teardown_run(context) - - assert not report.failed - assert office.browser_envs is None and set(deployed.child_envs) == {"chromium"} - [start_tab] = deployed.child_envs["chromium"]["metadata"]["computer"]["start_tabs"]["chromium"] - assert (start_tab["url"], start_tab["site"], start_tab["outcome"]) == (SESSION_PAGE, "shop", "loaded"), start_tab - assert (before, signed, after_reset, again) == (None, "alex", None, "alex") - assert context.metadata["browser_steps"]["in"]["names"] == ["shop.test"] - - -@pytest.mark.asyncio -async def test_a_multi_env_naming_no_browser_deploys_none(browser_computer, shop): - with namespace_routing(): - office = _office(shop, []) - context = TaskStepContext() - try: - [deployed] = (await DeployEnvTaskStep(id="office", version=None, env_id=office.id, sandbox_type="local", - ttl_seconds=900).execute(context)).deployed_envs - stated = {child.environment_name for child in protocol_v1.children(deployed.environment_card)} - finally: - report = await teardown_run(context) - - assert not report.failed and not deployed.child_envs - assert "shop" in stated and PLAYWRIGHT_MCP_ENVIRONMENT_NAME not in stated and "chromium" not in stated, stated diff --git a/tst/integration/computer/browser_multi_env_test.py b/tst/integration/computer/browser_multi_env_test.py new file mode 100644 index 000000000..8fc8cd8ed --- /dev/null +++ b/tst/integration/computer/browser_multi_env_test.py @@ -0,0 +1,364 @@ +"""agentenv's chromium as a multi env's website browser, deployed as a computer child on a sandbox of its own and +reached through the multi env's gateway. +Needs Docker and the local registry on localhost:5000, and Node 20 or later and npm for the CDP clients.""" + +import asyncio +import json +import subprocess +import urllib.parse +import uuid + +import httpx +import pytest +from mcp import ClientSession +from mcp.client.streamable_http import streamable_http_client + +from agentenv_protocol import client as protocol_v1 +from agentenv_protocol.client import find_extension_method, invoke_extension +from agentenv_protocol.website_browser import BROWSER + +from agent_env.artifact import EnvironmentUniverseArtifact +from agent_env.artifact.artifacts.environment import EnvironmentArtifact +from agent_env.artifact.artifacts.file import FileArtifact +from agent_env.config import get_config +from agent_env.config.runtime import WEBSITE_BROWSER_OVERRIDE, run_env_ids +from agent_env.env import Env +from agent_env.env.env import DeployedEnv +from agent_env.env.envs.multi_env import MultiEnv +from agent_env.env.envs.playwright_mcp import PLAYWRIGHT_MCP_ENVIRONMENT_NAME +from agent_env.env.envs.website import WebsiteEnv +from agent_env.store.object_store.local.tls import LocalCA, local_ca +from agent_env.store.routing import namespace_routing +from agent_env.task.teardown import teardown_run +from agent_env.task_step.context import TaskStepContext +from agent_env.task_step.task_steps.browser.connect_cdp import BrowserConnectCdpTaskStep +from agent_env.task_step.task_steps.browser.sign_in import BrowserSignInTaskStep +from agent_env.task_step.task_steps.deploy_agent import DeployAgentTaskStep +from agent_env.task_step.task_steps.deploy_env import DeployEnvTaskStep +from agent_env.task_step.task_steps.load_artifact import LoadArtifactTaskStep +from agent_env.task_step.task_steps.reset_env import ResetEnvTaskStep +from tst.integration.computer.browser_computer_test import (WAIT_S, _cdp_agent_loads, _discovered, _opened_over_cdp, + _tool_names, _trusting) +from tst.integration.computer.multi_env_computers_test import _containers, _gateway, _image +from tst.integration.computer.website_browser_test import _signed_in +from tst.integration.store.local_parallel_deploy_test import _seed_bootstrap_envs +from tst.util import local_sandboxes +from tst.util.a2a_test_agent import put_test_agent +from tst.util.tls_front import tls_front + +pytestmark = [pytest.mark.integration, pytest.mark.int_test_slow] + + +MULTI_SITE = "https://shop.test/api/health" +MULTI_CHROMIUM = {"sandbox_type": "local", + "env_params": {"form": "container", "app_settings": {"chromium": {"start_urls": [MULTI_SITE]}}}} +#: How often a multi env's browser is asked through the gateway whether it answers again. +ANSWER_POLL_S = 2.0 + + +@pytest.fixture(scope="module") +def shop(browser_computer): + """The gateway's and service-db's envs, and a website whose backend is the small agentenv website, named + shop.test, under a local id, since a multi env naming chromium's local id must be local too.""" + with namespace_routing(): + _seed_bootstrap_envs() + uid = uuid.uuid4().hex[:8] + return WebsiteEnv.put(id=f"@local/~/browsing-{uid}/shop", environment_name="shop", domains=["shop.test"], + backend_docker_image_artifact=_image("agentenv_website", f"browsing-shop-{uid}")) + + +@pytest.fixture +def made(monkeypatch) -> list[str]: + """The ids of the local sandboxes this test's process makes, so it finds and counts only its own.""" + return local_sandboxes.recorded_sandbox_ids(monkeypatch) + + +def _office(shop, browser_envs) -> MultiEnv: + return MultiEnv.put(id=f"@local/~/browsing-{uuid.uuid4().hex[:8]}/office", mcp_server_envs=[], + website_envs=[shop], browser_envs=browser_envs, name="office") + + +async def _drive(deployed) -> dict: + """What an agent sees through the gateway's /mcp: the tools it lists, a screenshot by chromium's name, and the + tabs after it opens the site by name.""" + async with streamable_http_client(deployed.mcp_url) as (read, write, _): + async with ClientSession(read, write) as session: + await session.initialize() + tools = {tool.name for tool in (await session.list_tools()).tools} + shot = await session.call_tool("chromium_computer_screenshot", {}) + opened = await session.call_tool("chromium_computer_navigate", {"url": MULTI_SITE}) + tabs = await session.call_tool("chromium_computer_tabs", {"action": "list"}) + return {"tools": tools, "shot": not shot.isError and any(part.type == "image" for part in shot.content), + "opened": not opened.isError, + "tabs": " ".join(part.text for part in tabs.content if part.type == "text")} + + +async def _answers_again(deployed) -> bool: + """Whether chromium's screenshot answers through the gateway, asked again until it does or ``WAIT_S`` passes.""" + deadline = asyncio.get_running_loop().time() + WAIT_S + while asyncio.get_running_loop().time() < deadline: + try: + async with streamable_http_client(deployed.mcp_url) as (read, write, _): + async with ClientSession(read, write) as session: + await session.initialize() + if not (await session.call_tool("chromium_computer_screenshot", {})).isError: + return True + except Exception: # noqa: BLE001 - the gateway or the browser restarting + pass + await asyncio.sleep(ANSWER_POLL_S) + return False + + +async def _cdp_at_gateway(deployed, browser: DeployedEnv, *, at: str | None = None, user: str = "ada", + origin: str | None = None, ca: LocalCA | None = None) -> dict: + """The CDP address the browser gives ``user``, asked through the gateway's ``/svc/chromium/`` route, at ``at``, a + front before it, else its own address, with the browser's own control token, as agentenv asks a computer child, + naming ``origin`` or not.""" + app = next(child for child in browser.environment_card["children_environments"] if child["name"] == "chromium") + path = protocol_v1.find_extension_method(app, BROWSER, "cdp")["endpoint"] + async with httpx.AsyncClient(timeout=180, verify=_trusting(ca) if ca else True) as http: + answer = await http.post(f"{at or deployed.gateway_url}/svc/chromium{path}", + json={"user": user, **({"origin": origin} if origin else {})}, + headers=browser.control_headers) + assert answer.status_code == 200, answer.text + return answer.json() + + +def _browser_universe(env_id: str, cookies: list[dict]) -> EnvironmentUniverseArtifact: + """An environment universe whose chromium environment holds a browser state setting ``cookies``.""" + run = uuid.uuid4().hex[:8] + state = FileArtifact.put_bytes(id=f"{env_id}-browser-{run}", description="multi env browser e2e", + filename="browser-state.json", content=json.dumps({"cookies": cookies}).encode(), + content_type="application/json") + environment = EnvironmentArtifact.put(id=f"{env_id}-browser-env-{run}", environment_name="chromium", + file_artifacts={"browser-state.json": state}) + return EnvironmentUniverseArtifact.put(id=f"{env_id}-universe-{run}", environment_artifacts=[environment]) + + +async def _browser_op(browser: DeployedEnv, op: str, params: dict) -> dict: + """``op``'s answer from the browser app on ``browser``, a multi env's browser computer, through its own record.""" + app = next(child for child in browser.environment_card["children_environments"] if child["name"] == "chromium") + assert find_extension_method(app, BROWSER, op) is not None, op + return await invoke_extension(browser.environment_url, app, BROWSER, params, 60, method=op, + headers=browser.control_headers) + + +async def _discovery(http_url: str) -> dict: + async with httpx.AsyncClient(timeout=60) as http: + answer = await http.get(f"{http_url.rstrip('/')}/json/version") + assert answer.status_code == 200, answer.text + return answer.json() + + +@pytest.mark.asyncio +async def test_chromium_as_a_multi_envs_browser_runs_on_its_own_sandbox_reached_through_the_gateway( + browser_computer, shop, made): + with namespace_routing(): + office = _office(shop, [Env.get(browser_computer.id)]) + step = DeployEnvTaskStep(id="office", version=None, env_id=office.id, sandbox_type="local", ttl_seconds=900, + child_envs={"chromium": MULTI_CHROMIUM}) + assert step.preflight() == [] + context = TaskStepContext() + try: + [deployed] = (await step.execute(context)).deployed_envs + browser = DeployedEnv.from_dict(deployed.child_envs["chromium"]) + stated = {child.environment_name for child in protocol_v1.children(deployed.environment_card)} + driven = await _drive(deployed) + address = await _cdp_at_gateway(deployed, browser) + discovered = await _discovery(address["http_url"]) + seen = await _cdp_agent_loads(address["ws_url"], [MULTI_SITE]) + reattached = await Env.from_instance_id(deployed.instance_id) + world = _browser_universe(office.id, [{"name": "sid", "value": "ada", "url": MULTI_SITE, "max_age": 3600}]) + await LoadArtifactTaskStep(id="seed", version=None, env_id=office.id, artifact_id=world.id).execute(context) + loaded = await _browser_op(browser, "cookies/get", {"urls": [MULTI_SITE]}) + + subprocess.run(["docker", "kill", *_containers(browser.sandbox_id)], capture_output=True) + await ResetEnvTaskStep(id="reset", version=None, env_id=office.id, fail_task_on_error=True).execute(context) + after_kill = await _answers_again(deployed) + after_kill_tabs = (await _drive(deployed))["tabs"] + + subprocess.run(["docker", "restart", _gateway(deployed, made)], capture_output=True, check=True) + through_restart = await _answers_again(deployed) + await ResetEnvTaskStep(id="reset-2", version=None, env_id=office.id, + fail_task_on_error=True).execute(context) + after_restart = await _answers_again(deployed) + up = _containers(browser.sandbox_id) + finally: + report = await teardown_run(context) + + assert not report.failed and up and _containers(browser.sandbox_id) == [] + # chromium is a computer child on a sandbox of its own, and no playwright-mcp runs. + assert set(deployed.child_envs) == {"chromium"} + assert deployed.sandbox_ids["local"] == {"chromium": browser.sandbox_id} + assert "chromium" in stated and PLAYWRIGHT_MCP_ENVIRONMENT_NAME not in stated, stated + computer = deployed.child_envs["chromium"]["metadata"]["computer"] + assert computer["sites"]["names"]["routes"] == {"shop": ["shop.test"]} + [start_tab] = computer["start_tabs"]["chromium"] + assert (start_tab["url"], start_tab["site"], start_tab["outcome"]) == (MULTI_SITE, "shop", "loaded"), start_tab + # An agent drives it through the gateway, every tool under chromium_. + assert {"chromium_computer_screenshot", "chromium_computer_navigate"} <= driven["tools"], driven + assert not any(name.startswith("computer_") for name in driven["tools"]), driven + assert driven["shot"] and driven["opened"] and MULTI_SITE in driven["tabs"], driven + # Its CDP address names the gateway, its discovery answer too, and an agent there reaches the site by name. + token = address["http_url"].split("/cdp/")[1].strip("/") + assert address["http_url"] == f"{deployed.gateway_url}/browser/chromium/cdp/{token}/", address + assert browser.environment_url.rstrip("/") not in json.dumps([address, discovered]), (address, discovered) + assert discovered["webSocketDebuggerUrl"].startswith( + f"ws{deployed.gateway_url.removeprefix('http')}/browser/chromium/cdp/"), discovered + assert seen[MULTI_SITE]["error"] is None and seen[MULTI_SITE].get("ready") == "complete", seen + # A later process reattaches it from the instance store, and a universe loaded into the multi env sets its cookies. + assert reattached._computers.browser._deployed.sandbox_id == browser.sandbox_id + assert [cookie["value"] for cookie in loaded["cookies"] if cookie["name"] == "sid"] == ["ada"], loaded + # Through a kill and a gateway restart, a reset brings it back. + assert after_kill and MULTI_SITE in after_kill_tabs, after_kill_tabs + assert after_restart, through_restart + + +@pytest.mark.asyncio +async def test_a_multi_env_naming_no_browser_takes_the_runs_and_chromium_runs_as_a_computer_child(browser_computer, + shop): + with namespace_routing(): + office = _office(shop, None) + context = TaskStepContext() + try: + with run_env_ids({WEBSITE_BROWSER_OVERRIDE: browser_computer.id}): + [deployed] = (await DeployEnvTaskStep(id="office", version=None, env_id=office.id, sandbox_type="local", + ttl_seconds=900, child_envs={"chromium": MULTI_CHROMIUM} + ).execute(context)).deployed_envs + stated = {child.environment_name for child in protocol_v1.children(deployed.environment_card)} + finally: + report = await teardown_run(context) + + assert not report.failed and set(deployed.child_envs) == {"chromium"} + assert PLAYWRIGHT_MCP_ENVIRONMENT_NAME not in stated, stated + [start_tab] = deployed.child_envs["chromium"]["metadata"]["computer"]["start_tabs"]["chromium"] + assert (start_tab["url"], start_tab["site"], start_tab["outcome"]) == (MULTI_SITE, "shop", "loaded"), start_tab + + +@pytest.mark.asyncio +async def test_browser_connect_cdp_hands_an_agent_an_address_at_the_multi_envs_gateway_with_its_tools_hidden( + browser_computer, shop): + with namespace_routing(): + agent = put_test_agent(f"cdp-agent-{uuid.uuid4().hex[:8]}") + office = _office(shop, [Env.get(browser_computer.id)]) + context = TaskStepContext() + try: + [deployed] = (await DeployEnvTaskStep(id="office", version=None, env_id=office.id, sandbox_type="local", + ttl_seconds=900, child_envs={"chromium": MULTI_CHROMIUM} + ).execute(context)).deployed_envs + await DeployAgentTaskStep(id="deploy-solver", version=None, env_ids=[], a2a_agent_id=agent.id, + a2a_agent_version=agent.version, agent_name="solver", + sandbox_type="local").execute(context) + await BrowserConnectCdpTaskStep(id="connect", version=None, env_id=office.id, + agent_name="solver").execute(context) + _, title = await _opened_over_cdp(context, "first", url=MULTI_SITE) + tools = await _tool_names(deployed) + async with httpx.AsyncClient(timeout=30) as http: + lines = (await http.get(f"{deployed.gateway_url}/trajectory")).text.splitlines() + relayed = [event for event in map(json.loads, lines) if event.get("event_type") == "browser_connection"] + finally: + report = await teardown_run(context) + + assert not title.startswith("failed"), title + assert tools == [], tools + assert [event["browser"] for event in relayed] and all(event["browser"] == "chromium" for event in relayed), relayed + assert context.metadata["browser_connections"] == [{ + "step_id": "connect", "env_id": office.id, "agent_name": "solver", "browser": "chromium", "name": "chromium", + "keep_tools": False, "role": "default", "tools_hidden": "*"}] + assert not report.failed + + +@pytest.mark.asyncio +async def test_behind_a_front_that_ends_tls_the_multi_envs_gateway_hands_out_https_and_wss_and_an_agent_connects( + browser_computer, shop): + ca = local_ca() + with namespace_routing(): + office = _office(shop, [Env.get(browser_computer.id)]) + context = TaskStepContext() + try: + [deployed] = (await DeployEnvTaskStep(id="office", version=None, env_id=office.id, sandbox_type="local", + ttl_seconds=900, child_envs={"chromium": MULTI_CHROMIUM} + ).execute(context)).deployed_envs + browser = DeployedEnv.from_dict(deployed.child_envs["chromium"]) + gateway = urllib.parse.urlsplit(deployed.gateway_url) + async with tls_front(ca, gateway.hostname, gateway.port) as front: + named = await _cdp_at_gateway(deployed, browser, at=front, origin=front, ca=ca) + unnamed = await _cdp_at_gateway(deployed, browser, at=front, user="bob", ca=ca) + discovered = await _discovered(named["http_url"], ca) + seen = await _cdp_agent_loads(named["ws_url"], [MULTI_SITE], tls=_trusting(ca)) + finally: + report = await teardown_run(context) + + host = front.removeprefix("https://") + assert named["http_url"].startswith(f"{front}/browser/chromium/cdp/"), named + assert named["ws_url"].startswith(f"wss://{host}/browser/chromium/cdp/") and discovered == named["ws_url"], named + assert unnamed["ws_url"].startswith(f"ws://{host}/browser/chromium/cdp/"), unnamed + assert seen[MULTI_SITE]["error"] is None and seen[MULTI_SITE].get("ready") == "complete", seen + assert not report.failed + + +#: A page the site that offers session serves, which says who a request signs in, and chromium starting there. +SESSION_PAGE = "https://shop.test/api/session" +SESSION_CHROMIUM = {**MULTI_CHROMIUM, + "env_params": {"form": "container", "app_settings": {"chromium": {"start_urls": [SESSION_PAGE]}}}} + + +@pytest.fixture(scope="module") +def session_shop(browser_computer): + """A site named shop.test that offers website/v1 session, under a local id, as a multi env naming chromium's local + id must be.""" + with namespace_routing(): + _seed_bootstrap_envs() + uid = uuid.uuid4().hex[:8] + return WebsiteEnv.put(id=f"@local/~/signin-{uid}/shop", environment_name="shop", domains=["shop.test"], + server_docker_image_artifact=_image("session_website", f"signin-shop-{uid}")) + + +@pytest.mark.asyncio +async def test_under_a_chromium_default_a_site_gets_chromium_unnamed_which_browser_sign_in_signs_in_after_each_reset( + browser_computer, session_shop): + config = get_config() + with namespace_routing(): + office = MultiEnv.put(id=f"{session_shop.id.rsplit('/', 1)[0]}/office", mcp_server_envs=[], + website_envs=[session_shop], name="office") + sign_in = BrowserSignInTaskStep(id="in", version=None, env_id=office.id, site=session_shop.id, user="alex") + context = TaskStepContext() + config.default_website_browser_env_id = browser_computer.id # the config's default, not the run's override + try: + [deployed] = (await DeployEnvTaskStep(id="office", version=None, env_id=office.id, sandbox_type="local", + ttl_seconds=900, child_envs={"chromium": SESSION_CHROMIUM} + ).execute(context)).deployed_envs + browser = DeployedEnv.from_dict(deployed.child_envs["chromium"]) + before = await _signed_in(browser) + await sign_in.execute(context) + signed = await _signed_in(browser) + await ResetEnvTaskStep(id="reset", version=None, env_id=office.id, fail_task_on_error=True).execute(context) + after_reset = await _signed_in(browser) + await sign_in.execute(context) + again = await _signed_in(browser) + finally: + config.default_website_browser_env_id = None + report = await teardown_run(context) + + assert not report.failed + assert office.browser_envs is None and set(deployed.child_envs) == {"chromium"} + [start_tab] = deployed.child_envs["chromium"]["metadata"]["computer"]["start_tabs"]["chromium"] + assert (start_tab["url"], start_tab["site"], start_tab["outcome"]) == (SESSION_PAGE, "shop", "loaded"), start_tab + assert (before, signed, after_reset, again) == (None, "alex", None, "alex") + assert context.metadata["browser_steps"]["in"]["names"] == ["shop.test"] + + +@pytest.mark.asyncio +async def test_a_multi_env_naming_no_browser_deploys_none(browser_computer, shop): + with namespace_routing(): + office = _office(shop, []) + context = TaskStepContext() + try: + [deployed] = (await DeployEnvTaskStep(id="office", version=None, env_id=office.id, sandbox_type="local", + ttl_seconds=900).execute(context)).deployed_envs + stated = {child.environment_name for child in protocol_v1.children(deployed.environment_card)} + finally: + report = await teardown_run(context) + + assert not report.failed and not deployed.child_envs + assert "shop" in stated and PLAYWRIGHT_MCP_ENVIRONMENT_NAME not in stated and "chromium" not in stated, stated diff --git a/tst/integration/slow_durations.json b/tst/integration/slow_durations.json index 4955f5578..8e2ee4535 100644 --- a/tst/integration/slow_durations.json +++ b/tst/integration/slow_durations.json @@ -7,61 +7,65 @@ "tst/integration/env/gateway/gateway_test.py" ], "seconds": { - "packages/agentenv-protocol/tests/test_a2a_agent.py": 1.1, - "packages/agentenv-protocol/tests/test_a2a_agent_examples.py": 0.1, - "packages/agentenv-protocol/tests/test_a2a_cdp_config.py": 0.2, - "packages/agentenv-protocol/tests/test_a2a_object_transfers.py": 0.4, - "packages/agentenv-protocol/tests/test_a2a_peer_agents.py": 3.9, - "packages/agentenv-protocol/tests/test_a2a_proxy.py": 9.0, - "packages/agentenv-protocol/tests/test_a2a_staging.py": 1.4, - "packages/agentenv-protocol/tests/test_a2a_trajectory_log.py": 0.3, - "packages/agentenv-protocol/tests/test_agent_env_environment.py": 0.4, - "packages/agentenv-protocol/tests/test_browser_cdp.py": 0.7, + "packages/agentenv-protocol/tests/test_a2a_agent.py": 1.0, + "packages/agentenv-protocol/tests/test_a2a_agent_examples.py": 0.0, + "packages/agentenv-protocol/tests/test_a2a_cdp_config.py": 0.1, + "packages/agentenv-protocol/tests/test_a2a_object_transfers.py": 0.3, + "packages/agentenv-protocol/tests/test_a2a_peer_agents.py": 3.8, + "packages/agentenv-protocol/tests/test_a2a_proxy.py": 8.3, + "packages/agentenv-protocol/tests/test_a2a_staging.py": 0.9, + "packages/agentenv-protocol/tests/test_a2a_trajectory_log.py": 0.2, + "packages/agentenv-protocol/tests/test_agent_env_environment.py": 0.3, + "packages/agentenv-protocol/tests/test_browser_cdp.py": 2.7, "packages/agentenv-protocol/tests/test_browser_data.py": 0.3, + "packages/agentenv-protocol/tests/test_browser_log.py": 0.1, "packages/agentenv-protocol/tests/test_browser_state.py": 0.1, "packages/agentenv-protocol/tests/test_client.py": 0.1, - "packages/agentenv-protocol/tests/test_computer_app_data.py": 3.1, - "packages/agentenv-protocol/tests/test_computer_app_server.py": 8.4, - "packages/agentenv-protocol/tests/test_computer_conformance.py": 169.6, + "packages/agentenv-protocol/tests/test_computer_app_data.py": 2.9, + "packages/agentenv-protocol/tests/test_computer_app_server.py": 7.4, + "packages/agentenv-protocol/tests/test_computer_conformance.py": 117.2, "packages/agentenv-protocol/tests/test_computer_conformance_checks.py": 1.1, - "packages/agentenv-protocol/tests/test_computer_conformance_page.py": 54.1, - "packages/agentenv-protocol/tests/test_computer_conformance_recording.py": 32.7, - "packages/agentenv-protocol/tests/test_computer_dataplane.py": 3.1, - "packages/agentenv-protocol/tests/test_computer_declare.py": 0.9, - "packages/agentenv-protocol/tests/test_computer_driver.py": 3.5, - "packages/agentenv-protocol/tests/test_computer_extensions.py": 5.7, - "packages/agentenv-protocol/tests/test_computer_frames.py": 5.4, + "packages/agentenv-protocol/tests/test_computer_conformance_page.py": 32.0, + "packages/agentenv-protocol/tests/test_computer_conformance_recording.py": 28.2, + "packages/agentenv-protocol/tests/test_computer_dataplane.py": 2.4, + "packages/agentenv-protocol/tests/test_computer_declare.py": 0.8, + "packages/agentenv-protocol/tests/test_computer_driver.py": 1.9, + "packages/agentenv-protocol/tests/test_computer_driver_keys.py": 0.0, + "packages/agentenv-protocol/tests/test_computer_extensions.py": 5.1, + "packages/agentenv-protocol/tests/test_computer_frames.py": 2.8, "packages/agentenv-protocol/tests/test_computer_macos.py": 0.0, - "packages/agentenv-protocol/tests/test_computer_page.py": 1.9, - "packages/agentenv-protocol/tests/test_computer_queue.py": 15.8, - "packages/agentenv-protocol/tests/test_computer_recording.py": 33.6, + "packages/agentenv-protocol/tests/test_computer_page.py": 0.9, + "packages/agentenv-protocol/tests/test_computer_queue.py": 12.4, + "packages/agentenv-protocol/tests/test_computer_recording.py": 31.7, "packages/agentenv-protocol/tests/test_computer_seed.py": 0.0, "packages/agentenv-protocol/tests/test_computer_serve.py": 0.3, "packages/agentenv-protocol/tests/test_computer_served.py": 0.3, - "packages/agentenv-protocol/tests/test_computer_session_windows.py": 0.4, - "packages/agentenv-protocol/tests/test_computer_spaces.py": 1.2, - "packages/agentenv-protocol/tests/test_computer_svc_forward.py": 8.5, + "packages/agentenv-protocol/tests/test_computer_session_windows.py": 0.5, + "packages/agentenv-protocol/tests/test_computer_spaces.py": 0.9, + "packages/agentenv-protocol/tests/test_computer_svc_forward.py": 6.3, "packages/agentenv-protocol/tests/test_computer_tool_prefix.py": 1.1, + "packages/agentenv-protocol/tests/test_computer_windows_driver.py": 0.1, "packages/agentenv-protocol/tests/test_control_token.py": 0.0, - "packages/agentenv-protocol/tests/test_data_objects.py": 2.9, - "packages/agentenv-protocol/tests/test_errors.py": 0.3, - "packages/agentenv-protocol/tests/test_extension_methods.py": 0.1, + "packages/agentenv-protocol/tests/test_data_objects.py": 2.8, + "packages/agentenv-protocol/tests/test_errors.py": 0.2, + "packages/agentenv-protocol/tests/test_extension_methods.py": 0.0, "packages/agentenv-protocol/tests/test_intake.py": 0.0, "packages/agentenv-protocol/tests/test_manifest.py": 0.0, "packages/agentenv-protocol/tests/test_preflight.py": 0.0, "packages/agentenv-protocol/tests/test_tool_access.py": 0.2, - "packages/agentenv-protocol/tests/test_tool_annotations.py": 0.3, - "packages/agentenv-protocol/tests/test_tool_client.py": 1.1, - "packages/agentenv-protocol/tests/test_tool_context.py": 0.1, - "packages/agentenv-protocol/tests/test_tool_context_fastmcp.py": 0.2, - "packages/agentenv-protocol/tests/test_tool_context_injection.py": 0.3, - "packages/agentenv-protocol/tests/test_website_api.py": 0.7, - "packages/agentenv-protocol/tests/test_website_browser.py": 3.7, - "packages/agentenv-protocol/tests/test_website_conformance.py": 17.5, - "packages/agentenv-protocol/tests/test_website_environment.py": 8.0, - "packages/agentenv-protocol/tests/test_website_mcp.py": 2.0, - "packages/agentenv-protocol/tests/test_website_notes_example.py": 1.7, - "packages/agentenv-protocol/tests/test_website_readiness.py": 0.1, + "packages/agentenv-protocol/tests/test_tool_annotations.py": 0.1, + "packages/agentenv-protocol/tests/test_tool_client.py": 0.9, + "packages/agentenv-protocol/tests/test_tool_context.py": 0.0, + "packages/agentenv-protocol/tests/test_tool_context_fastmcp.py": 0.1, + "packages/agentenv-protocol/tests/test_tool_context_injection.py": 0.2, + "packages/agentenv-protocol/tests/test_website_api.py": 0.5, + "packages/agentenv-protocol/tests/test_website_browser.py": 3.6, + "packages/agentenv-protocol/tests/test_website_conformance.py": 16.9, + "packages/agentenv-protocol/tests/test_website_environment.py": 7.1, + "packages/agentenv-protocol/tests/test_website_live.py": 0.0, + "packages/agentenv-protocol/tests/test_website_mcp.py": 1.8, + "packages/agentenv-protocol/tests/test_website_notes_example.py": 1.6, + "packages/agentenv-protocol/tests/test_website_readiness.py": 0.0, "tst/installer/test_container_journey.py": 162.4, "tst/installer/test_plugin_changes.py::test_a_bare_directory_that_builds_as_agent_env_never_replaces_it[pipx]": 8.6, "tst/installer/test_plugin_changes.py::test_a_bare_directory_that_builds_as_agent_env_never_replaces_it[uv-project]": 10.3, @@ -123,67 +127,73 @@ "tst/installer/test_wheel.py": 0.0, "tst/integration/agent/a2a_agent/a2a_agent_test.py": 0.0, "tst/integration/agent/a2a_agent/agent_triggers_e2e_test.py": 0.0, + "tst/integration/agent/proxy_local_container_test.py": 37.8, "tst/integration/agent/proxy_modal_vm_test.py": 0.0, - "tst/integration/artifact/artifacts/docker_image_artifact_test.py": 18.4, - "tst/integration/cli/bundle_init_images_test.py": 24.8, - "tst/integration/cli/bundle_register_test.py": 43.2, - "tst/integration/cli/cli_test.py": 56.5, - "tst/integration/cli/run_bundle_browser_use_test.py": 196.6, - "tst/integration/cli/run_bundle_built_agents_test.py": 45.7, + "tst/integration/artifact/artifacts/docker_image_artifact_test.py": 36.6, + "tst/integration/cli/bundle_init_images_test.py": 31.7, + "tst/integration/cli/bundle_register_test.py": 46.7, + "tst/integration/cli/cli_test.py": 73.6, + "tst/integration/cli/run_bundle_browser_use_test.py": 115.8, + "tst/integration/cli/run_bundle_built_agents_test.py": 50.7, "tst/integration/cli/run_bundle_built_envs_test.py::test_a_multi_whose_children_name_one_container_is_refused_before_anything_is_built_or_written": 0.2, - "tst/integration/cli/run_bundle_built_envs_test.py::test_a_multi_whose_servers_share_a_tool_name_is_refused_at_deploy_naming_the_tool_and_both_servers": 42.2, - "tst/integration/cli/run_bundle_built_envs_test.py::test_a_script_on_an_envs_host_reaches_it_and_its_mcp_endpoint_at_the_addresses_its_input_gives[gateway]": 46.2, - "tst/integration/cli/run_bundle_built_envs_test.py::test_a_script_on_an_envs_host_reaches_it_and_its_mcp_endpoint_at_the_addresses_its_input_gives[server]": 11.5, - "tst/integration/cli/run_bundle_built_envs_test.py::test_a_server_that_crashes_on_start_fails_its_deploy_naming_it_and_ending_with_what_it_printed": 30.1, - "tst/integration/cli/run_bundle_built_envs_test.py::test_a_stored_mcp_task_imports_as_a_bundle_that_runs_through_the_gateway": 64.5, - "tst/integration/cli/run_bundle_built_envs_test.py::test_a_universe_composed_every_way_seeds_each_server_of_a_multi_and_a_shared_one_seeds_its_server": 48.4, - "tst/integration/cli/run_bundle_built_envs_test.py::test_an_env_folder_is_built_named_by_its_card_deployed_and_rebuilt_only_when_it_changes": 18.7, - "tst/integration/cli/run_bundle_built_envs_test.py::test_an_output_a_bundles_task_wrote_is_written_under_the_folder_that_imports_it": 43.3, - "tst/integration/cli/run_bundle_built_envs_test.py::test_each_kind_of_bundle_env_deploys_through_the_gateway_and_a_child_edit_rewrites_its_multi": 175.7, - "tst/integration/cli/run_bundle_built_envs_test.py::test_environments_and_a_universe_written_from_a_bundle_load_into_an_env_through_the_gateway": 69.2, - "tst/integration/cli/run_bundle_built_envs_test.py::test_the_shipped_echo_mcp_example_runs_by_name_and_a_rerun_writes_nothing": 67.9, - "tst/integration/cli/run_bundle_built_envs_test.py::test_the_shipped_mail_mcp_example_runs_and_a_task_outside_a_bundle_deploys_its_env_by_its_alias": 51.5, - "tst/integration/cli/run_bundle_claude_code_install_test.py": 123.6, - "tst/integration/cli/run_bundle_claude_code_test.py": 323.1, - "tst/integration/cli/run_bundle_cli_folder_test.py": 75.1, - "tst/integration/cli/run_bundle_image_folder_test.py": 43.8, - "tst/integration/cli/run_bundle_image_ref_test.py": 30.7, - "tst/integration/cli/run_bundle_installed_agent_test.py": 22.0, - "tst/integration/cli/run_bundle_openhands_test.py": 237.4, - "tst/integration/cli/run_bundle_pydantic_ai_test.py": 107.9, - "tst/integration/cli/run_bundle_skills_test.py": 25.1, - "tst/integration/cli/run_role_models_test.py": 36.5, - "tst/integration/computer/base_computer_test.py": 83.2, - "tst/integration/computer/browser_computer_test.py": 303.7, - "tst/integration/computer/browser_gateway_test.py": 191.7, + "tst/integration/cli/run_bundle_built_envs_test.py::test_a_multi_whose_servers_share_a_tool_name_is_refused_at_deploy_naming_the_tool_and_both_servers": 35.7, + "tst/integration/cli/run_bundle_built_envs_test.py::test_a_script_on_an_envs_host_reaches_it_and_its_mcp_endpoint_at_the_addresses_its_input_gives[gateway]": 30.6, + "tst/integration/cli/run_bundle_built_envs_test.py::test_a_script_on_an_envs_host_reaches_it_and_its_mcp_endpoint_at_the_addresses_its_input_gives[server]": 17.3, + "tst/integration/cli/run_bundle_built_envs_test.py::test_a_server_that_crashes_on_start_fails_its_deploy_naming_it_and_ending_with_what_it_printed": 51.9, + "tst/integration/cli/run_bundle_built_envs_test.py::test_a_stored_mcp_task_imports_as_a_bundle_that_runs_through_the_gateway": 81.7, + "tst/integration/cli/run_bundle_built_envs_test.py::test_a_universe_composed_every_way_seeds_each_server_of_a_multi_and_a_shared_one_seeds_its_server": 38.4, + "tst/integration/cli/run_bundle_built_envs_test.py::test_an_env_folder_is_built_named_by_its_card_deployed_and_rebuilt_only_when_it_changes": 7.3, + "tst/integration/cli/run_bundle_built_envs_test.py::test_an_output_a_bundles_task_wrote_is_written_under_the_folder_that_imports_it": 71.1, + "tst/integration/cli/run_bundle_built_envs_test.py::test_each_kind_of_bundle_env_deploys_through_the_gateway_and_a_child_edit_rewrites_its_multi": 167.7, + "tst/integration/cli/run_bundle_built_envs_test.py::test_environments_and_a_universe_written_from_a_bundle_load_into_an_env_through_the_gateway": 63.3, + "tst/integration/cli/run_bundle_built_envs_test.py::test_the_shipped_echo_mcp_example_runs_by_name_and_a_rerun_writes_nothing": 52.3, + "tst/integration/cli/run_bundle_built_envs_test.py::test_the_shipped_mail_mcp_example_runs_and_a_task_outside_a_bundle_deploys_its_env_by_its_alias": 61.7, + "tst/integration/cli/run_bundle_claude_code_install_test.py": 167.4, + "tst/integration/cli/run_bundle_claude_code_test.py": 356.4, + "tst/integration/cli/run_bundle_cli_folder_test.py": 66.8, + "tst/integration/cli/run_bundle_image_folder_test.py": 38.1, + "tst/integration/cli/run_bundle_image_ref_test.py": 36.1, + "tst/integration/cli/run_bundle_installed_agent_test.py": 27.2, + "tst/integration/cli/run_bundle_openhands_test.py": 284.7, + "tst/integration/cli/run_bundle_pydantic_ai_test.py": 135.7, + "tst/integration/cli/run_bundle_skills_test.py": 14.1, + "tst/integration/cli/run_bundle_task_image_test.py": 5.2, + "tst/integration/cli/run_role_models_test.py": 71.7, + "tst/integration/computer/base_computer_test.py": 52.5, + "tst/integration/computer/browser_computer_test.py": 421.4, + "tst/integration/computer/browser_gateway_test.py": 96.5, + "tst/integration/computer/browser_multi_env_test.py": 352.8, "tst/integration/computer/builder_modal_vm_test.py": 0.0, - "tst/integration/computer/ca_trust_test.py": 270.4, - "tst/integration/computer/chromium_app_test.py": 552.2, - "tst/integration/computer/computer_app_test.py::test_a_computers_apps_load_export_and_reset_each_through_its_own_data_plane": 111.4, - "tst/integration/computer/computer_app_test.py::test_an_app_deployed_alone_runs_its_service_on_its_settings_on_a_computer_named_after_it_as_its_driver": 66.8, - "tst/integration/computer/computer_app_test.py::test_the_locks_debs_and_wheels_install_from_mounts_and_stay_in_no_layer_of_the_image": 148.4, - "tst/integration/computer/computer_app_test.py::test_through_the_drivers_route_a_websocket_reaches_an_apps_server_and_a_20_mb_answer_streams_whole": 182.4, - "tst/integration/computer/computer_app_test.py::test_two_apps_composed_into_one_computer_env_each_run_on_their_own_settings": 150.5, - "tst/integration/computer/computer_env_test.py": 257.9, - "tst/integration/computer/covered_test.py": 51.0, - "tst/integration/computer/cua_driver_test.py": 73.3, - "tst/integration/computer/desktop_example_test.py": 130.8, - "tst/integration/computer/disk_boot_test.py": 132.1, + "tst/integration/computer/ca_trust_test.py": 271.8, + "tst/integration/computer/chromium_app_test.py": 501.1, + "tst/integration/computer/computer_app_test.py::test_a_computers_apps_load_export_and_reset_each_through_its_own_data_plane": 46.2, + "tst/integration/computer/computer_app_test.py::test_an_app_deployed_alone_runs_its_service_on_its_settings_on_a_computer_named_after_it_as_its_driver": 37.6, + "tst/integration/computer/computer_app_test.py::test_the_locks_debs_and_wheels_install_from_mounts_and_stay_in_no_layer_of_the_image": 110.4, + "tst/integration/computer/computer_app_test.py::test_through_the_drivers_route_a_websocket_reaches_an_apps_server_and_a_20_mb_answer_streams_whole": 118.1, + "tst/integration/computer/computer_app_test.py::test_two_apps_composed_into_one_computer_env_each_run_on_their_own_settings": 74.8, + "tst/integration/computer/computer_env_test.py": 282.5, + "tst/integration/computer/covered_test.py": 32.1, + "tst/integration/computer/cua_driver_test.py": 139.1, + "tst/integration/computer/desktop_example_test.py": 146.9, + "tst/integration/computer/disk_boot_test.py": 94.3, "tst/integration/computer/disk_modal_vm_test.py": 0.0, - "tst/integration/computer/launcher_test.py": 88.0, - "tst/integration/computer/multi_env_computers_test.py": 314.0, - "tst/integration/computer/recording_chaos_test.py": 136.5, - "tst/integration/computer/set_test.py": 151.9, - "tst/integration/computer/tool_prefix_test.py": 91.3, - "tst/integration/computer/website_browser_test.py": 201.7, + "tst/integration/computer/launcher_test.py": 73.5, + "tst/integration/computer/multi_env_computers_test.py": 422.3, + "tst/integration/computer/omarchy_test.py": 0.0, + "tst/integration/computer/recording_chaos_test.py": 253.1, + "tst/integration/computer/set_test.py": 127.3, + "tst/integration/computer/tool_prefix_test.py": 85.9, + "tst/integration/computer/website_browser_test.py": 332.2, "tst/integration/computer/windows_test.py": 0.0, - "tst/integration/env/env_test.py": 15.7, - "tst/integration/env/envs/build_context_local_test.py": 165.7, - "tst/integration/env/envs/multi_env_child_envs_local_test.py": 106.0, - "tst/integration/env/envs/multi_env_local_test.py": 115.9, - "tst/integration/env/envs/playwright_mcp_local_test.py": 88.9, - "tst/integration/env/envs/server_env_local_test.py": 75.4, + "tst/integration/env/env_test.py": 22.2, + "tst/integration/env/envs/build_context_local_test.py": 140.4, + "tst/integration/env/envs/multi_env_child_envs_local_test.py": 120.7, + "tst/integration/env/envs/multi_env_local_test.py": 73.2, + "tst/integration/env/envs/playwright_mcp_local_test.py": 31.8, + "tst/integration/env/envs/server_env_local_test.py": 80.2, "tst/integration/env/envs/server_env_modal_test.py": 0.0, + "tst/integration/env/gateway/gateway_test.py::test_a_site_slower_to_boot_than_the_health_check_allows_deploys_with_a_ready_timeout_and_its_shared_memory[gateway-default]": 78.9, + "tst/integration/env/gateway/gateway_test.py::test_a_site_slower_to_boot_than_the_health_check_allows_deploys_with_a_ready_timeout_and_its_shared_memory[ready-timeout]": 139.4, "tst/integration/env/gateway/gateway_test.py::test_airtable_clock_consumer[agent37]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_airtable_clock_consumer[boat]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_airtable_clock_consumer[boxd]": 0.0, @@ -272,7 +282,7 @@ "tst/integration/env/gateway/gateway_test.py::test_calendar_mcp_clock_consumer[scale]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_calendar_mcp_clock_consumer[tenki]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_calendar_mcp_clock_consumer[tensorlake]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_cardless_environment_resolves_name_from_environment_name": 37.6, + "tst/integration/env/gateway/gateway_test.py::test_cardless_environment_resolves_name_from_environment_name": 38.9, "tst/integration/env/gateway/gateway_test.py::test_clickup_clock_consumer[agent37]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_clickup_clock_consumer[boat]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_clickup_clock_consumer[boxd]": 0.0, @@ -304,7 +314,7 @@ "tst/integration/env/gateway/gateway_test.py::test_crm_clock_consumer[modal_vm]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_crm_clock_consumer[sail_vm]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_crm_clock_consumer[scale]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_crm_clock_consumer[tenki]": 0.3, + "tst/integration/env/gateway/gateway_test.py::test_crm_clock_consumer[tenki]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_crm_clock_consumer[tensorlake]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_eight_sleep_clock_consumer[agent37]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_eight_sleep_clock_consumer[boat]": 0.0, @@ -403,7 +413,7 @@ "tst/integration/env/gateway/gateway_test.py::test_gateway_autonomous_time_trigger[modal]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_autonomous_time_trigger[modal_vm]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_autonomous_time_trigger[sail_vm]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_gateway_autonomous_time_trigger[scale]": 29.4, + "tst/integration/env/gateway/gateway_test.py::test_gateway_autonomous_time_trigger[scale]": 29.8, "tst/integration/env/gateway/gateway_test.py::test_gateway_autonomous_time_trigger[tenki]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_autonomous_time_trigger[tensorlake]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_barrier_orders_a_templated_mirror[agent37]": 0.0, @@ -414,11 +424,11 @@ "tst/integration/env/gateway/gateway_test.py::test_gateway_barrier_orders_a_templated_mirror[modal]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_barrier_orders_a_templated_mirror[modal_vm]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_barrier_orders_a_templated_mirror[sail_vm]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_gateway_barrier_orders_a_templated_mirror[scale]": 29.1, + "tst/integration/env/gateway/gateway_test.py::test_gateway_barrier_orders_a_templated_mirror[scale]": 28.3, "tst/integration/env/gateway/gateway_test.py::test_gateway_barrier_orders_a_templated_mirror[tenki]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_barrier_orders_a_templated_mirror[tensorlake]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_gateway_changes_name_the_request_behind_a_write_through_the_rest_proxy": 28.3, - "tst/integration/env/gateway/gateway_test.py::test_gateway_changes_name_the_role_behind_each_write": 28.3, + "tst/integration/env/gateway/gateway_test.py::test_gateway_changes_name_the_request_behind_a_write_through_the_rest_proxy": 27.8, + "tst/integration/env/gateway/gateway_test.py::test_gateway_changes_name_the_role_behind_each_write": 27.4, "tst/integration/env/gateway/gateway_test.py::test_gateway_clock_extension[agent37]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_clock_extension[boat]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_clock_extension[boxd]": 0.0, @@ -427,7 +437,7 @@ "tst/integration/env/gateway/gateway_test.py::test_gateway_clock_extension[modal]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_clock_extension[modal_vm]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_clock_extension[sail_vm]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_gateway_clock_extension[scale]": 36.4, + "tst/integration/env/gateway/gateway_test.py::test_gateway_clock_extension[scale]": 37.1, "tst/integration/env/gateway/gateway_test.py::test_gateway_clock_extension[tenki]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_clock_extension[tensorlake]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_clock_rate_accuracy[agent37]": 0.0, @@ -438,10 +448,10 @@ "tst/integration/env/gateway/gateway_test.py::test_gateway_clock_rate_accuracy[modal]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_clock_rate_accuracy[modal_vm]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_clock_rate_accuracy[sail_vm]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_gateway_clock_rate_accuracy[scale]": 51.1, + "tst/integration/env/gateway/gateway_test.py::test_gateway_clock_rate_accuracy[scale]": 51.9, "tst/integration/env/gateway/gateway_test.py::test_gateway_clock_rate_accuracy[tenki]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_clock_rate_accuracy[tensorlake]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_gateway_consistent_mode": 50.9, + "tst/integration/env/gateway/gateway_test.py::test_gateway_consistent_mode": 47.2, "tst/integration/env/gateway/gateway_test.py::test_gateway_queued_trigger_is_not_reported_settled[agent37]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_queued_trigger_is_not_reported_settled[boat]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_queued_trigger_is_not_reported_settled[boxd]": 0.0, @@ -450,7 +460,7 @@ "tst/integration/env/gateway/gateway_test.py::test_gateway_queued_trigger_is_not_reported_settled[modal]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_queued_trigger_is_not_reported_settled[modal_vm]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_queued_trigger_is_not_reported_settled[sail_vm]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_gateway_queued_trigger_is_not_reported_settled[scale]": 28.1, + "tst/integration/env/gateway/gateway_test.py::test_gateway_queued_trigger_is_not_reported_settled[scale]": 31.6, "tst/integration/env/gateway/gateway_test.py::test_gateway_queued_trigger_is_not_reported_settled[tenki]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_queued_trigger_is_not_reported_settled[tensorlake]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_time_trigger_extension[agent37]": 0.0, @@ -461,7 +471,7 @@ "tst/integration/env/gateway/gateway_test.py::test_gateway_time_trigger_extension[modal]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_time_trigger_extension[modal_vm]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_time_trigger_extension[sail_vm]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_gateway_time_trigger_extension[scale]": 29.2, + "tst/integration/env/gateway/gateway_test.py::test_gateway_time_trigger_extension[scale]": 32.7, "tst/integration/env/gateway/gateway_test.py::test_gateway_time_trigger_extension[tenki]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_time_trigger_extension[tensorlake]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_trigger_rearms_after_a_failed_mirror[agent37]": 0.0, @@ -472,7 +482,7 @@ "tst/integration/env/gateway/gateway_test.py::test_gateway_trigger_rearms_after_a_failed_mirror[modal]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_trigger_rearms_after_a_failed_mirror[modal_vm]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_trigger_rearms_after_a_failed_mirror[sail_vm]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_gateway_trigger_rearms_after_a_failed_mirror[scale]": 31.6, + "tst/integration/env/gateway/gateway_test.py::test_gateway_trigger_rearms_after_a_failed_mirror[scale]": 31.5, "tst/integration/env/gateway/gateway_test.py::test_gateway_trigger_rearms_after_a_failed_mirror[tenki]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_trigger_rearms_after_a_failed_mirror[tensorlake]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_trigger_registration_is_fail_loud[agent37]": 0.0, @@ -483,7 +493,7 @@ "tst/integration/env/gateway/gateway_test.py::test_gateway_trigger_registration_is_fail_loud[modal]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_trigger_registration_is_fail_loud[modal_vm]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_trigger_registration_is_fail_loud[sail_vm]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_gateway_trigger_registration_is_fail_loud[scale]": 26.1, + "tst/integration/env/gateway/gateway_test.py::test_gateway_trigger_registration_is_fail_loud[scale]": 28.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_trigger_registration_is_fail_loud[tenki]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_trigger_registration_is_fail_loud[tensorlake]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_triggers_extension[agent37]": 0.0, @@ -494,13 +504,13 @@ "tst/integration/env/gateway/gateway_test.py::test_gateway_triggers_extension[modal]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_triggers_extension[modal_vm]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_triggers_extension[sail_vm]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_gateway_triggers_extension[scale]": 37.9, + "tst/integration/env/gateway/gateway_test.py::test_gateway_triggers_extension[scale]": 38.1, "tst/integration/env/gateway/gateway_test.py::test_gateway_triggers_extension[tenki]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_triggers_extension[tensorlake]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_triggers_nl_executor[modal_vm]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_gateway_website_trigger_fires_on_a_request_through_the_website_proxy": 72.2, - "tst/integration/env/gateway/gateway_test.py::test_gateway_with_agentenv_environment": 28.7, - "tst/integration/env/gateway/gateway_test.py::test_gateway_with_multi_env_including_website": 261.8, + "tst/integration/env/gateway/gateway_test.py::test_gateway_website_trigger_fires_on_a_request_through_the_website_proxy": 66.0, + "tst/integration/env/gateway/gateway_test.py::test_gateway_with_agentenv_environment": 28.9, + "tst/integration/env/gateway/gateway_test.py::test_gateway_with_multi_env_including_website": 162.7, "tst/integration/env/gateway/gateway_test.py::test_gateway_with_multi_mcp_server[agent37]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_with_multi_mcp_server[boat]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_with_multi_mcp_server[boxd]": 0.0, @@ -509,12 +519,12 @@ "tst/integration/env/gateway/gateway_test.py::test_gateway_with_multi_mcp_server[modal]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_with_multi_mcp_server[modal_vm]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_with_multi_mcp_server[sail_vm]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_gateway_with_multi_mcp_server[scale]": 192.0, + "tst/integration/env/gateway/gateway_test.py::test_gateway_with_multi_mcp_server[scale]": 100.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_with_multi_mcp_server[tenki]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_gateway_with_multi_mcp_server[tensorlake]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_gateway_with_single_mcp_server": 209.7, - "tst/integration/env/gateway/gateway_test.py::test_gateway_with_single_website_env": 250.4, - "tst/integration/env/gateway/gateway_test.py::test_gateway_with_website_env_v1": 44.4, + "tst/integration/env/gateway/gateway_test.py::test_gateway_with_single_mcp_server": 108.8, + "tst/integration/env/gateway/gateway_test.py::test_gateway_with_single_website_env": 135.5, + "tst/integration/env/gateway/gateway_test.py::test_gateway_with_website_env_v1": 42.5, "tst/integration/env/gateway/gateway_test.py::test_github_clock_consumer[agent37]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_github_clock_consumer[boat]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_github_clock_consumer[boxd]": 0.0, @@ -647,7 +657,7 @@ "tst/integration/env/gateway/gateway_test.py::test_linear_clock_consumer[scale]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_linear_clock_consumer[tenki]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_linear_clock_consumer[tensorlake]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_load_from_snapshot": 42.4, + "tst/integration/env/gateway/gateway_test.py::test_load_from_snapshot": 42.0, "tst/integration/env/gateway/gateway_test.py::test_messaging_clock_consumer[agent37]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_messaging_clock_consumer[boat]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_messaging_clock_consumer[boxd]": 0.0, @@ -836,8 +846,8 @@ "tst/integration/env/gateway/gateway_test.py::test_smart_lock_clock_consumer[scale]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_smart_lock_clock_consumer[tenki]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_smart_lock_clock_consumer[tensorlake]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_snapshot_agent_state_v1_and_fallback": 41.9, - "tst/integration/env/gateway/gateway_test.py::test_snapshot_cli": 56.9, + "tst/integration/env/gateway/gateway_test.py::test_snapshot_agent_state_v1_and_fallback": 32.8, + "tst/integration/env/gateway/gateway_test.py::test_snapshot_cli": 37.3, "tst/integration/env/gateway/gateway_test.py::test_snowflake_async_virtual_clock[agent37]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_snowflake_async_virtual_clock[boat]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_snowflake_async_virtual_clock[boxd]": 0.0, @@ -901,7 +911,7 @@ "tst/integration/env/gateway/gateway_test.py::test_sync_env_clock_step[modal]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_sync_env_clock_step[modal_vm]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_sync_env_clock_step[sail_vm]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_sync_env_clock_step[scale]": 38.8, + "tst/integration/env/gateway/gateway_test.py::test_sync_env_clock_step[scale]": 26.8, "tst/integration/env/gateway/gateway_test.py::test_sync_env_clock_step[tenki]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_sync_env_clock_step[tensorlake]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_system_clock_consumer[agent37]": 0.0, @@ -926,7 +936,7 @@ "tst/integration/env/gateway/gateway_test.py::test_target_clock_consumer[scale]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_target_clock_consumer[tenki]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_target_clock_consumer[tensorlake]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_the_browsers_card_and_recording_through_the_gateway_survive_its_recorder_and_container_restarting": 240.7, + "tst/integration/env/gateway/gateway_test.py::test_the_browsers_card_and_recording_through_the_gateway_survive_its_recorder_and_container_restarting": 152.3, "tst/integration/env/gateway/gateway_test.py::test_ticketmaster_clock_consumer[agent37]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_ticketmaster_clock_consumer[boat]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_ticketmaster_clock_consumer[boxd]": 0.0, @@ -960,8 +970,8 @@ "tst/integration/env/gateway/gateway_test.py::test_trello_clock_consumer[scale]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_trello_clock_consumer[tenki]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_trello_clock_consumer[tensorlake]": 0.0, - "tst/integration/env/gateway/gateway_test.py::test_validate_universe_compatibility": 28.1, - "tst/integration/env/gateway/gateway_test.py::test_verify_universe_roundtrip_export_all_v1_and_fallback": 28.1, + "tst/integration/env/gateway/gateway_test.py::test_validate_universe_compatibility": 46.4, + "tst/integration/env/gateway/gateway_test.py::test_verify_universe_roundtrip_export_all_v1_and_fallback": 40.0, "tst/integration/env/gateway/gateway_test.py::test_walmart_clock_consumer[agent37]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_walmart_clock_consumer[boat]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_walmart_clock_consumer[boxd]": 0.0, @@ -1028,9 +1038,9 @@ "tst/integration/env/gateway/gateway_test.py::test_zillow_clock_consumer[scale]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_zillow_clock_consumer[tenki]": 0.0, "tst/integration/env/gateway/gateway_test.py::test_zillow_clock_consumer[tensorlake]": 0.0, - "tst/integration/env/task_step/task_steps_test.py": 187.9, - "tst/integration/eval/eval_test.py": 1.7, - "tst/integration/openenv/build_app_test.py": 89.8, + "tst/integration/env/task_step/task_steps_test.py": 207.2, + "tst/integration/eval/eval_test.py": 1.9, + "tst/integration/openenv/build_app_test.py": 106.6, "tst/integration/providers/sandbox_providers/agent37_sandbox_smoke_test.py": 0.0, "tst/integration/providers/sandbox_providers/boat_sandbox_smoke_test.py": 0.0, "tst/integration/providers/sandbox_providers/boxd_sandbox_smoke_test.py": 0.0, @@ -1041,592 +1051,604 @@ "tst/integration/providers/sandbox_providers/tenki_sandbox_smoke_test.py": 0.0, "tst/integration/providers/sandbox_providers/tensorlake_sandbox_smoke_test.py": 0.0, "tst/integration/providers/sandbox_providers/vercel_sandbox_smoke_test.py": 0.0, - "tst/integration/providers/sandbox_providers/vm_sandbox_build_test.py": 2.8, + "tst/integration/providers/sandbox_providers/vm_sandbox_build_test.py": 2.0, "tst/integration/providers/sandbox_providers/websockets_live_test.py": 0.0, - "tst/integration/store/local_parallel_deploy_test.py": 51.6, - "tst/integration/task_step/test_advance_to_next_event_hook_local.py": 112.1, - "tst/integration/task_step/test_agent_on_local_sandbox.py": 7.7, + "tst/integration/store/local_parallel_deploy_test.py": 106.2, + "tst/integration/task_step/test_advance_to_next_event_hook_local.py": 62.5, + "tst/integration/task_step/test_agent_on_local_sandbox.py": 18.8, "tst/integration/task_step/test_enable_docker_e2e.py": 0.0, "tst/integration/task_step/test_multiturn_verifier_delivery.py": 0.0, - "tst/integration/task_step/test_next_env_event_hook_local.py": 111.3, - "tst/integration/task_step/test_prompt_agent_notifications_local.py": 115.4, - "tst/integration/task_step/test_register_env_triggers_local.py": 91.2, - "tst/integration/training/harness_test.py": 26.8, - "tst/integration/training/trl_test.py": 32.9, - "tst/integration/utils/docker/prune_test.py": 6.3, - "tst/unit/a2a_agent/add_skill_test.py": 0.9, - "tst/unit/a2a_agent/alias_get_test.py": 0.4, + "tst/integration/task_step/test_next_env_event_hook_local.py": 213.1, + "tst/integration/task_step/test_prompt_agent_notifications_local.py": 129.2, + "tst/integration/task_step/test_register_env_triggers_local.py": 218.8, + "tst/integration/training/harness_test.py": 34.4, + "tst/integration/training/trl_test.py": 39.1, + "tst/integration/utils/docker/prune_test.py": 7.2, + "tst/unit/a2a_agent/add_skill_test.py": 0.7, + "tst/unit/a2a_agent/alias_get_test.py": 0.3, "tst/unit/a2a_agent/cdp_config_test.py": 0.0, - "tst/unit/a2a_agent/context_only_deploy_test.py": 0.7, - "tst/unit/a2a_agent/deploy_cleanup_test.py": 0.1, + "tst/unit/a2a_agent/context_only_deploy_test.py": 0.4, + "tst/unit/a2a_agent/deploy_cleanup_test.py": 0.0, "tst/unit/a2a_agent/negotiate_agent_config_test.py": 0.0, - "tst/unit/a2a_agent/object_transfer_reach_test.py": 0.2, - "tst/unit/a2a_agent/object_transfer_test.py": 0.3, - "tst/unit/a2a_agent/protocol_test.py": 0.3, - "tst/unit/a2a_agent/put_version_test.py": 0.2, + "tst/unit/a2a_agent/object_transfer_reach_test.py": 0.1, + "tst/unit/a2a_agent/object_transfer_test.py": 0.2, + "tst/unit/a2a_agent/protocol_test.py": 0.2, + "tst/unit/a2a_agent/put_version_test.py": 0.1, "tst/unit/a2a_agent/readable_parts_test.py": 0.1, - "tst/unit/a2a_agent/staging_test.py": 2.2, + "tst/unit/a2a_agent/staging_test.py": 1.0, "tst/unit/a2a_agent/store_test.py": 0.0, - "tst/unit/a2a_agent/test_trajectory_follower.py": 0.7, - "tst/unit/a2a_agent/test_validator_changelog_objects.py": 0.2, - "tst/unit/a2a_agent/test_validator_skill_variants.py": 0.1, - "tst/unit/a2a_agent/validator_trajectory_dag_test.py": 0.3, + "tst/unit/a2a_agent/test_trajectory_follower.py": 0.6, + "tst/unit/a2a_agent/test_validator_changelog_objects.py": 0.1, + "tst/unit/a2a_agent/test_validator_skill_variants.py": 0.0, + "tst/unit/a2a_agent/validator_trajectory_dag_test.py": 0.1, "tst/unit/a2a_agent/validator_uri_probes_test.py": 0.0, "tst/unit/a2a_agent/verify_a2a_agent_card_test.py": 0.0, - "tst/unit/agents/browser_use/test_browser_use_agent.py": 1.6, - "tst/unit/agents/claude_code/test_card_contract.py": 1.3, - "tst/unit/agents/claude_code/test_changelog.py": 107.5, - "tst/unit/agents/claude_code/test_claude_bridge_builtin_tools.py": 0.1, - "tst/unit/agents/claude_code/test_claude_bridge_cancel.py": 9.6, - "tst/unit/agents/claude_code/test_claude_bridge_failure_message.py": 0.3, + "tst/unit/agents/browser_use/test_browser_use_agent.py": 1.4, + "tst/unit/agents/claude_code/test_card_contract.py": 1.1, + "tst/unit/agents/claude_code/test_changelog.py": 17.5, + "tst/unit/agents/claude_code/test_claude_bridge_builtin_tools.py": 0.0, + "tst/unit/agents/claude_code/test_claude_bridge_cancel.py": 8.1, + "tst/unit/agents/claude_code/test_claude_bridge_failure_message.py": 0.1, "tst/unit/agents/claude_code/test_claude_bridge_live.py": 0.1, - "tst/unit/agents/claude_code/test_claude_bridge_model.py": 0.1, - "tst/unit/agents/claude_code/test_claude_bridge_retry.py": 0.4, + "tst/unit/agents/claude_code/test_claude_bridge_model.py": 0.0, + "tst/unit/agents/claude_code/test_claude_bridge_retry.py": 0.2, "tst/unit/agents/claude_code/test_claude_bridge_stdin.py": 1.1, - "tst/unit/agents/claude_code/test_cli_env.py": 0.2, - "tst/unit/agents/claude_code/test_ext_mcp_name.py": 0.1, - "tst/unit/agents/claude_code/test_extensions.py": 0.2, - "tst/unit/agents/claude_code/test_image_contract.py": 0.1, - "tst/unit/agents/claude_code/test_install_sh_host_root.py": 0.1, - "tst/unit/agents/claude_code/test_message_contract.py": 1.6, - "tst/unit/agents/claude_code/test_object_transfer.py": 0.5, - "tst/unit/agents/claude_code/test_partial_trajectory.py": 0.2, - "tst/unit/agents/claude_code/test_workspace_snapshot.py": 0.2, + "tst/unit/agents/claude_code/test_cli_env.py": 0.1, + "tst/unit/agents/claude_code/test_ext_mcp_name.py": 0.0, + "tst/unit/agents/claude_code/test_extensions.py": 0.1, + "tst/unit/agents/claude_code/test_image_contract.py": 0.0, + "tst/unit/agents/claude_code/test_install_sh_host_root.py": 0.0, + "tst/unit/agents/claude_code/test_message_contract.py": 1.4, + "tst/unit/agents/claude_code/test_object_transfer.py": 0.3, + "tst/unit/agents/claude_code/test_partial_trajectory.py": 0.1, + "tst/unit/agents/claude_code/test_workspace_snapshot.py": 0.1, "tst/unit/agents/codex/test_card_contract.py": 0.1, "tst/unit/agents/codex/test_codex_bridge_events.py": 0.2, "tst/unit/agents/codex/test_codex_bridge_failure_message.py": 0.2, - "tst/unit/agents/codex/test_codex_bridge_retry.py": 0.5, - "tst/unit/agents/codex/test_codex_bridge_watchdog.py": 0.3, - "tst/unit/agents/codex/test_codex_builtin_tools.py": 1.9, + "tst/unit/agents/codex/test_codex_bridge_retry.py": 0.3, + "tst/unit/agents/codex/test_codex_bridge_watchdog.py": 0.2, + "tst/unit/agents/codex/test_codex_builtin_tools.py": 1.8, "tst/unit/agents/codex/test_codex_executor_outcome.py": 0.2, - "tst/unit/agents/codex/test_codex_snapshot_hardening.py": 0.3, - "tst/unit/agents/codex/test_config_and_mcp.py": 0.3, + "tst/unit/agents/codex/test_codex_snapshot_hardening.py": 0.2, + "tst/unit/agents/codex/test_config_and_mcp.py": 0.2, "tst/unit/agents/codex/test_image_contract.py": 0.1, - "tst/unit/agents/codex/test_install.py": 0.1, + "tst/unit/agents/codex/test_install.py": 0.0, "tst/unit/agents/codex/test_live_trajectory.py": 0.1, "tst/unit/agents/codex/test_message_contract.py": 0.1, - "tst/unit/agents/codex/test_object_transfer.py": 0.8, - "tst/unit/agents/gemini/test_card_contract.py": 1.7, - "tst/unit/agents/gemini/test_extensions.py": 0.6, + "tst/unit/agents/codex/test_object_transfer.py": 0.5, + "tst/unit/agents/gemini/test_card_contract.py": 1.2, + "tst/unit/agents/gemini/test_extensions.py": 0.2, "tst/unit/agents/gemini/test_gemini_bridge_attribution.py": 0.1, "tst/unit/agents/gemini/test_gemini_bridge_cancel.py": 5.6, - "tst/unit/agents/gemini/test_gemini_bridge_failure_message.py": 0.3, - "tst/unit/agents/gemini/test_gemini_bridge_live.py": 1.3, + "tst/unit/agents/gemini/test_gemini_bridge_failure_message.py": 0.2, + "tst/unit/agents/gemini/test_gemini_bridge_live.py": 1.2, "tst/unit/agents/gemini/test_image_contract.py": 0.1, "tst/unit/agents/gemini/test_install.py": 0.1, - "tst/unit/agents/gemini/test_litellm_proxy.py": 0.5, - "tst/unit/agents/gemini/test_message_contract.py": 0.4, - "tst/unit/agents/gemini/test_object_transfer.py": 3.5, - "tst/unit/agents/hermes/test_card_contract.py": 1.6, - "tst/unit/agents/hermes/test_held_work.py": 0.8, - "tst/unit/agents/hermes/test_hermes_bridge.py": 3.6, - "tst/unit/agents/hermes/test_message_contract.py": 0.7, - "tst/unit/agents/letta_code/test_bridge.py": 0.8, - "tst/unit/agents/opencode/test_card_contract.py": 1.8, - "tst/unit/agents/opencode/test_image_contract.py": 0.2, + "tst/unit/agents/gemini/test_litellm_proxy.py": 0.3, + "tst/unit/agents/gemini/test_message_contract.py": 0.3, + "tst/unit/agents/gemini/test_object_transfer.py": 2.7, + "tst/unit/agents/hermes/test_card_contract.py": 1.1, + "tst/unit/agents/hermes/test_held_work.py": 0.7, + "tst/unit/agents/hermes/test_hermes_bridge.py": 3.4, + "tst/unit/agents/hermes/test_message_contract.py": 0.4, + "tst/unit/agents/letta_code/test_bridge.py": 0.5, + "tst/unit/agents/opencode/test_card_contract.py": 1.2, + "tst/unit/agents/opencode/test_image_contract.py": 0.1, "tst/unit/agents/opencode/test_install.py": 0.1, - "tst/unit/agents/opencode/test_message_contract.py": 1.1, - "tst/unit/agents/opencode/test_object_transfer.py": 0.7, - "tst/unit/agents/opencode/test_opencode_bridge_builtin_tools.py": 0.3, - "tst/unit/agents/opencode/test_opencode_bridge_cancel.py": 5.7, - "tst/unit/agents/opencode/test_opencode_bridge_config.py": 0.2, + "tst/unit/agents/opencode/test_message_contract.py": 1.0, + "tst/unit/agents/opencode/test_object_transfer.py": 0.4, + "tst/unit/agents/opencode/test_opencode_bridge_builtin_tools.py": 0.1, + "tst/unit/agents/opencode/test_opencode_bridge_cancel.py": 5.8, + "tst/unit/agents/opencode/test_opencode_bridge_config.py": 0.1, "tst/unit/agents/opencode/test_opencode_bridge_events.py": 0.1, - "tst/unit/agents/opencode/test_opencode_bridge_live.py": 1.3, + "tst/unit/agents/opencode/test_opencode_bridge_live.py": 1.2, "tst/unit/agents/opencode/test_opencode_bridge_stdin.py": 0.1, "tst/unit/agents/openhands/test_conversation_run.py": 0.1, - "tst/unit/agents/openhands/test_openhands_agent.py": 4.8, - "tst/unit/agents/pi/test_pi_agent.py": 2.7, - "tst/unit/agents/proxy/test_proxy_agent.py": 0.6, - "tst/unit/agents/pydantic_ai/test_pydantic_ai_agent.py": 3.5, - "tst/unit/agents/test_host_workdir.py": 0.1, - "tst/unit/agents/test_installed_workspace.py": 0.4, + "tst/unit/agents/openhands/test_openhands_agent.py": 4.3, + "tst/unit/agents/pi/test_pi_agent.py": 2.2, + "tst/unit/agents/proxy/test_proxy_agent.py": 0.5, + "tst/unit/agents/pydantic_ai/test_pydantic_ai_agent.py": 3.1, + "tst/unit/agents/test_host_workdir.py": 0.0, + "tst/unit/agents/test_installed_workspace.py": 0.3, "tst/unit/artifact/cli_artifact_test.py": 0.1, "tst/unit/artifact/environment_files_test.py": 0.4, "tst/unit/artifact/environment_universe_folder_test.py": 0.0, - "tst/unit/artifact/registry_test.py": 1.0, + "tst/unit/artifact/registry_test.py": 0.6, "tst/unit/artifact/skill_artifact_test.py": 0.2, "tst/unit/artifact/test_artifact_metadata.py": 0.1, "tst/unit/artifact/test_artifact_put.py": 0.0, - "tst/unit/artifact/test_computer_artifact.py": 1.1, - "tst/unit/artifact/test_docker_image_build_context.py": 0.5, + "tst/unit/artifact/test_computer_artifact.py": 1.0, + "tst/unit/artifact/test_docker_image_build_context.py": 0.4, "tst/unit/artifact/test_docker_image_github_clone.py": 0.1, - "tst/unit/artifact/test_docker_image_github_push.py": 0.2, + "tst/unit/artifact/test_docker_image_github_push.py": 0.1, "tst/unit/artifact/test_docker_image_pulled.py": 0.1, - "tst/unit/artifact/test_docker_image_put_ref.py": 0.5, - "tst/unit/artifact/test_object_url_keys.py": 0.4, - "tst/unit/artifact/test_removed_service_aliases.py": 1.9, + "tst/unit/artifact/test_docker_image_put_ref.py": 0.4, + "tst/unit/artifact/test_object_url_keys.py": 0.2, + "tst/unit/artifact/test_removed_service_aliases.py": 1.5, "tst/unit/artifact/test_service_artifact_alias.py": 0.1, - "tst/unit/artifact/test_service_universe_file_view.py": 0.1, - "tst/unit/artifact/test_store_put_document.py": 0.2, + "tst/unit/artifact/test_service_universe_file_view.py": 0.0, + "tst/unit/artifact/test_store_put_document.py": 0.1, "tst/unit/attribution_test.py": 0.0, - "tst/unit/bundle/agent_override_test.py": 2.7, - "tst/unit/bundle/aliases_test.py": 0.6, - "tst/unit/bundle/artifact_toml_test.py": 5.0, - "tst/unit/bundle/authoring_test.py": 0.7, - "tst/unit/bundle/cli_folder_test.py": 2.1, - "tst/unit/bundle/computer_app_env_test.py": 12.6, - "tst/unit/bundle/computer_driver_env_test.py": 18.3, - "tst/unit/bundle/computer_env_folder_test.py": 55.1, - "tst/unit/bundle/computer_folder_test.py": 1.5, - "tst/unit/bundle/env_toml_test.py": 6.5, - "tst/unit/bundle/file_artifacts_test.py": 0.8, - "tst/unit/bundle/hub_test.py": 2.6, - "tst/unit/bundle/image_folder_test.py": 3.8, - "tst/unit/bundle/importer_entities_test.py": 9.8, - "tst/unit/bundle/importer_image_refs_test.py": 4.2, - "tst/unit/bundle/importer_test.py": 20.7, - "tst/unit/bundle/installed_entities_test.py": 8.0, - "tst/unit/bundle/installed_test.py": 5.6, + "tst/unit/bundle/agent_override_test.py": 1.3, + "tst/unit/bundle/aliases_test.py": 0.3, + "tst/unit/bundle/artifact_toml_test.py": 2.5, + "tst/unit/bundle/authoring_test.py": 0.4, + "tst/unit/bundle/cli_folder_test.py": 0.8, + "tst/unit/bundle/computer_app_env_test.py": 8.7, + "tst/unit/bundle/computer_driver_env_test.py": 12.1, + "tst/unit/bundle/computer_env_folder_test.py": 30.5, + "tst/unit/bundle/computer_folder_test.py": 1.0, + "tst/unit/bundle/env_toml_test.py": 3.3, + "tst/unit/bundle/file_artifacts_test.py": 0.5, + "tst/unit/bundle/hub_test.py": 1.4, + "tst/unit/bundle/image_folder_test.py": 3.1, + "tst/unit/bundle/importer_entities_test.py": 5.6, + "tst/unit/bundle/importer_image_refs_test.py": 2.2, + "tst/unit/bundle/importer_test.py": 10.8, + "tst/unit/bundle/installed_entities_test.py": 7.4, + "tst/unit/bundle/installed_test.py": 5.7, "tst/unit/bundle/ledger_digest_test.py": 0.1, - "tst/unit/bundle/ledger_test.py": 21.3, - "tst/unit/bundle/materialize_test.py": 14.5, - "tst/unit/bundle/parse_test.py": 4.1, - "tst/unit/bundle/plan_test.py": 5.9, - "tst/unit/bundle/plugin_artifact_types_test.py": 1.2, - "tst/unit/bundle/preflight_test.py": 57.1, - "tst/unit/bundle/referenced_context_test.py": 1.9, - "tst/unit/bundle/register_test.py": 10.9, - "tst/unit/bundle/requires_test.py": 9.2, - "tst/unit/bundle/resolve_test.py": 6.0, - "tst/unit/bundle/run_teardown_test.py": 24.5, - "tst/unit/bundle/run_test.py": 11.4, + "tst/unit/bundle/ledger_test.py": 13.6, + "tst/unit/bundle/materialize_test.py": 11.5, + "tst/unit/bundle/parse_test.py": 2.8, + "tst/unit/bundle/plan_test.py": 2.0, + "tst/unit/bundle/plugin_artifact_types_test.py": 0.5, + "tst/unit/bundle/preflight_test.py": 22.5, + "tst/unit/bundle/referenced_context_test.py": 0.9, + "tst/unit/bundle/register_test.py": 6.6, + "tst/unit/bundle/requires_test.py": 5.4, + "tst/unit/bundle/resolve_test.py": 2.9, + "tst/unit/bundle/run_teardown_test.py": 17.2, + "tst/unit/bundle/run_test.py": 9.2, "tst/unit/bundle/shipped_bundles_test.py": 2.5, - "tst/unit/bundle/shipped_computers_test.py": 1.5, - "tst/unit/bundle/to_toml_round_trip_test.py": 6.4, - "tst/unit/bundle/toml_refs_test.py": 0.4, - "tst/unit/bundle/toml_writer_test.py": 0.1, - "tst/unit/bundle/variants_test.py": 6.0, + "tst/unit/bundle/shipped_computers_test.py": 0.8, + "tst/unit/bundle/to_toml_round_trip_test.py": 3.6, + "tst/unit/bundle/toml_refs_test.py": 0.1, + "tst/unit/bundle/toml_writer_test.py": 0.0, + "tst/unit/bundle/variants_test.py": 5.5, "tst/unit/bundle/website_optional_frontend_test.py": 0.0, - "tst/unit/cli/a2a_agent_list_test.py": 0.3, - "tst/unit/cli/a2a_agent_validate_test.py": 0.3, + "tst/unit/cli/a2a_agent_list_test.py": 0.1, + "tst/unit/cli/a2a_agent_validate_test.py": 0.2, "tst/unit/cli/base_metadata_version_test.py": 0.0, - "tst/unit/cli/build_platform_test.py": 0.4, - "tst/unit/cli/card_naming_relocation_test.py": 0.2, + "tst/unit/cli/build_platform_test.py": 0.3, + "tst/unit/cli/card_naming_relocation_test.py": 0.3, "tst/unit/cli/deploy_vm_sizing_test.py": 0.1, "tst/unit/cli/deployed_env_output_test.py": 0.1, - "tst/unit/cli/env_provider_type_test.py": 0.2, - "tst/unit/cli/env_put_validation_test.py": 0.5, + "tst/unit/cli/env_provider_type_test.py": 0.1, + "tst/unit/cli/env_put_validation_test.py": 0.4, "tst/unit/cli/env_state_type_parity_test.py": 0.1, - "tst/unit/cli/environment_name_alias_test.py": 0.4, - "tst/unit/cli/eval_run_teardown_test.py": 0.2, - "tst/unit/cli/image_ref_put_test.py": 0.7, - "tst/unit/cli/init_env_state_cli_test.py": 0.2, + "tst/unit/cli/environment_name_alias_test.py": 0.3, + "tst/unit/cli/eval_run_teardown_test.py": 0.3, + "tst/unit/cli/image_ref_put_test.py": 0.4, + "tst/unit/cli/init_env_state_cli_test.py": 0.1, "tst/unit/cli/load_artifact_target_test.py": 0.1, - "tst/unit/cli/plugin_command_test.py": 41.2, - "tst/unit/cli/plugin_install_test.py": 9.3, - "tst/unit/cli/plugin_report_test.py": 21.3, - "tst/unit/cli/plugins_test.py": 10.8, - "tst/unit/cli/run_role_models_test.py": 0.2, - "tst/unit/cli/sandbox_url_relocation_test.py": 3.1, + "tst/unit/cli/plugin_command_test.py": 19.3, + "tst/unit/cli/plugin_install_test.py": 6.5, + "tst/unit/cli/plugin_report_test.py": 12.0, + "tst/unit/cli/plugins_test.py": 8.3, + "tst/unit/cli/run_role_models_test.py": 0.3, + "tst/unit/cli/sandbox_url_relocation_test.py": 1.9, "tst/unit/cli/snapshot_step_output_test.py": 0.0, "tst/unit/cli/stage_free_commands_test.py": 0.0, - "tst/unit/cli/submit_runs_test.py": 5.7, - "tst/unit/cli/task_run_requires_test.py": 3.5, - "tst/unit/cli/task_run_stored_test.py": 0.7, - "tst/unit/cli/task_run_teardown_test.py": 7.9, + "tst/unit/cli/submit_runs_test.py": 5.8, + "tst/unit/cli/task_run_requires_test.py": 1.8, + "tst/unit/cli/task_run_stored_test.py": 0.4, + "tst/unit/cli/task_run_teardown_test.py": 7.6, "tst/unit/cli/teardown_env_state_cli_test.py": 0.1, "tst/unit/cli/test_release_gate_decision.py": 0.1, - "tst/unit/cli/test_removed_cli_aliases.py": 0.3, + "tst/unit/cli/test_removed_cli_aliases.py": 0.1, "tst/unit/cli/test_spec_conformance_display.py": 0.1, - "tst/unit/cli/test_task_create_preflight.py": 0.1, - "tst/unit/cli/user_facing_errors_test.py": 0.2, - "tst/unit/cli/verbose_logging_test.py": 2.7, - "tst/unit/cli/website_server_image_cli_test.py": 1.0, + "tst/unit/cli/test_task_create_preflight.py": 0.0, + "tst/unit/cli/user_facing_errors_test.py": 0.1, + "tst/unit/cli/verbose_logging_test.py": 2.2, + "tst/unit/cli/website_live_cli_test.py": 0.3, + "tst/unit/cli/website_server_image_cli_test.py": 0.5, "tst/unit/cli/write_context_filename_test.py": 0.1, - "tst/unit/config/test_config_holds_its_document.py": 0.2, - "tst/unit/config/test_config_profiles.py": 0.2, - "tst/unit/config/test_default_a2a_agent.py": 0.2, - "tst/unit/config/test_default_env_ids.py": 0.3, - "tst/unit/config/test_describe.py": 2.6, - "tst/unit/config/test_explain_and_sources.py": 11.5, - "tst/unit/config/test_fixture_prefix_keys.py": 0.2, - "tst/unit/config/test_human_a2a_url.py": 0.4, - "tst/unit/config/test_loader.py": 1.0, - "tst/unit/config/test_model.py": 0.8, - "tst/unit/config/test_no_stage_concept.py": 0.1, - "tst/unit/config/test_one_document_per_process.py": 3.5, + "tst/unit/config/test_config_holds_its_document.py": 0.1, + "tst/unit/config/test_config_profiles.py": 0.1, + "tst/unit/config/test_default_a2a_agent.py": 0.1, + "tst/unit/config/test_default_env_ids.py": 0.2, + "tst/unit/config/test_describe.py": 1.1, + "tst/unit/config/test_explain_and_sources.py": 5.7, + "tst/unit/config/test_fixture_prefix_keys.py": 0.1, + "tst/unit/config/test_human_a2a_url.py": 0.5, + "tst/unit/config/test_loader.py": 0.9, + "tst/unit/config/test_model.py": 0.7, + "tst/unit/config/test_no_stage_concept.py": 0.0, + "tst/unit/config/test_one_document_per_process.py": 3.4, "tst/unit/config/test_paths.py": 0.2, - "tst/unit/config/test_registry_builders_take_a_config.py": 0.4, - "tst/unit/config/test_reset_config.py": 1.3, + "tst/unit/config/test_registry_builders_take_a_config.py": 0.1, + "tst/unit/config/test_reset_config.py": 0.8, "tst/unit/config/test_resolve_reference.py": 0.0, "tst/unit/config/test_run_env_ids.py": 0.1, - "tst/unit/config/test_unread_keys.py": 1.5, - "tst/unit/drivers/agent_desktop_driver_test.py": 15.2, - "tst/unit/drivers/codex_computer_use_driver_test.py": 15.4, - "tst/unit/drivers/cua_driver_test.py": 1.7, + "tst/unit/config/test_unread_keys.py": 1.4, + "tst/unit/drivers/agent_desktop_driver_test.py": 13.0, + "tst/unit/drivers/aside_driver_test.py": 13.4, + "tst/unit/drivers/codex_computer_use_driver_test.py": 15.1, + "tst/unit/drivers/cua_driver_test.py": 1.0, "tst/unit/drivers/macos_harness_driver_test.py": 0.4, - "tst/unit/drivers/page_driver_test.py": 0.2, - "tst/unit/drivers/reference_driver_test.py": 4.1, + "tst/unit/drivers/page_driver_test.py": 0.1, + "tst/unit/drivers/reference_driver_test.py": 3.0, "tst/unit/entity_refs_import_test.py": 0.0, - "tst/unit/env/alias_get_test.py": 0.4, - "tst/unit/env/bootstrap_test.py": 8.2, - "tst/unit/env/envs/service_db/service_db_test.py": 0.3, - "tst/unit/env/envs/test_artifact_staging.py": 0.3, + "tst/unit/env/alias_get_test.py": 0.2, + "tst/unit/env/bootstrap_test.py": 7.2, + "tst/unit/env/envs/service_db/service_db_test.py": 0.1, + "tst/unit/env/envs/test_artifact_staging.py": 0.9, "tst/unit/env/envs/test_chromium_app.py": 0.4, - "tst/unit/env/envs/test_computer_apps.py": 10.8, - "tst/unit/env/envs/test_computer_builder.py": 8.0, - "tst/unit/env/envs/test_computer_disk.py": 22.3, - "tst/unit/env/envs/test_computer_env.py": 59.4, - "tst/unit/env/envs/test_computer_macos_grants.py": 0.2, - "tst/unit/env/envs/test_computer_site_proxy.py": 4.1, - "tst/unit/env/envs/test_computer_sites.py": 3.0, - "tst/unit/env/envs/test_computer_vm_bundle.py": 8.0, - "tst/unit/env/envs/test_computer_windows.py": 3.4, - "tst/unit/env/envs/test_disk_recipe.py": 68.0, - "tst/unit/env/envs/test_env_card_loads.py": 0.3, + "tst/unit/env/envs/test_computer_apps.py": 6.2, + "tst/unit/env/envs/test_computer_builder.py": 4.5, + "tst/unit/env/envs/test_computer_disk.py": 13.8, + "tst/unit/env/envs/test_computer_env.py": 36.0, + "tst/unit/env/envs/test_computer_macos_grants.py": 0.1, + "tst/unit/env/envs/test_computer_omarchy.py": 1.9, + "tst/unit/env/envs/test_computer_site_proxy.py": 4.6, + "tst/unit/env/envs/test_computer_sites.py": 1.6, + "tst/unit/env/envs/test_computer_stand_in_proxy.py": 4.6, + "tst/unit/env/envs/test_computer_vm_bundle.py": 5.0, + "tst/unit/env/envs/test_computer_windows.py": 1.8, + "tst/unit/env/envs/test_disk_recipe.py": 8.1, + "tst/unit/env/envs/test_env_card_loads.py": 0.4, "tst/unit/env/envs/test_env_close_teardown.py": 0.1, "tst/unit/env/envs/test_environment_name_alias.py": 0.2, "tst/unit/env/envs/test_install_platform_keys.py": 0.0, - "tst/unit/env/envs/test_mcp_server_container_mode.py": 0.6, - "tst/unit/env/envs/test_mcp_server_load.py": 0.1, - "tst/unit/env/envs/test_mcp_server_plugin_provider.py": 0.5, - "tst/unit/env/envs/test_multi_env_computers.py": 1.3, - "tst/unit/env/envs/test_multi_env_load_concurrency.py": 0.3, + "tst/unit/env/envs/test_mcp_server_container_mode.py": 0.4, + "tst/unit/env/envs/test_mcp_server_load.py": 0.0, + "tst/unit/env/envs/test_mcp_server_plugin_provider.py": 0.3, + "tst/unit/env/envs/test_multi_env_computers.py": 3.5, + "tst/unit/env/envs/test_multi_env_load_concurrency.py": 0.4, "tst/unit/env/envs/test_multi_env_load_resume.py": 0.2, - "tst/unit/env/envs/test_multi_env_name.py": 0.2, - "tst/unit/env/envs/test_multi_env_plugin_provider.py": 0.6, + "tst/unit/env/envs/test_multi_env_name.py": 0.1, + "tst/unit/env/envs/test_multi_env_plugin_provider.py": 0.4, "tst/unit/env/envs/test_multi_env_snapshot_bake.py": 0.2, "tst/unit/env/envs/test_multi_env_snapshot_guard.py": 0.1, - "tst/unit/env/envs/test_multi_env_snapshot_reload_name.py": 0.5, - "tst/unit/env/envs/test_multi_env_vm_sizing.py": 0.3, - "tst/unit/env/envs/test_playwright_mcp_recorder.py": 2.9, - "tst/unit/env/envs/test_put_from_github_token.py": 0.1, + "tst/unit/env/envs/test_multi_env_snapshot_reload_name.py": 0.3, + "tst/unit/env/envs/test_multi_env_vm_sizing.py": 2.0, + "tst/unit/env/envs/test_playwright_mcp_recorder.py": 2.8, + "tst/unit/env/envs/test_put_from_github_token.py": 0.0, "tst/unit/env/envs/test_server_reset.py": 0.1, - "tst/unit/env/envs/test_website_env_name_alias.py": 0.1, - "tst/unit/env/envs/test_website_server_image.py": 0.7, - "tst/unit/env/envs/test_website_site_names.py": 1.9, - "tst/unit/env/gateway/browser_route_test.py": 3.6, - "tst/unit/env/gateway/caller_test.py": 0.1, + "tst/unit/env/envs/test_thin_disk.py": 0.1, + "tst/unit/env/envs/test_website_env_name_alias.py": 0.0, + "tst/unit/env/envs/test_website_live.py": 0.1, + "tst/unit/env/envs/test_website_server_image.py": 1.3, + "tst/unit/env/envs/test_website_site_names.py": 1.1, + "tst/unit/env/gateway/browser_route_test.py": 3.4, + "tst/unit/env/gateway/caller_test.py": 0.0, "tst/unit/env/gateway/changes_test.py": 0.4, - "tst/unit/env/gateway/child_outage_socket_test.py": 9.3, - "tst/unit/env/gateway/child_sessions_test.py": 0.5, + "tst/unit/env/gateway/child_outage_socket_test.py": 9.0, + "tst/unit/env/gateway/child_sessions_test.py": 0.4, "tst/unit/env/gateway/child_transport_test.py": 0.1, - "tst/unit/env/gateway/clock_advance_test.py": 0.3, + "tst/unit/env/gateway/clock_advance_test.py": 0.2, + "tst/unit/env/gateway/control_token_test.py": 0.5, "tst/unit/env/gateway/data_plane_timeout_test.py": 0.1, "tst/unit/env/gateway/env_trajectory_route_test.py": 0.1, - "tst/unit/env/gateway/gateway_card_test.py": 0.6, - "tst/unit/env/gateway/get_time_test.py": 0.5, - "tst/unit/env/gateway/hidden_by_default_test.py": 15.7, - "tst/unit/env/gateway/import_graph_test.py": 3.6, + "tst/unit/env/gateway/gateway_card_test.py": 0.5, + "tst/unit/env/gateway/get_time_test.py": 0.3, + "tst/unit/env/gateway/hidden_by_default_test.py": 11.5, + "tst/unit/env/gateway/import_graph_test.py": 1.9, "tst/unit/env/gateway/next_event_test.py": 0.4, - "tst/unit/env/gateway/notifications_test.py": 1.6, + "tst/unit/env/gateway/notifications_test.py": 1.4, "tst/unit/env/gateway/process_scope_socket_test.py": 1.0, - "tst/unit/env/gateway/rest_proxy_socket_test.py": 1.8, - "tst/unit/env/gateway/rest_proxy_stream_test.py": 0.6, + "tst/unit/env/gateway/rest_proxy_socket_test.py": 1.5, + "tst/unit/env/gateway/rest_proxy_stream_test.py": 0.5, "tst/unit/env/gateway/role_forwarding_test.py": 0.1, - "tst/unit/env/gateway/role_rules_test.py": 0.3, - "tst/unit/env/gateway/tool_access_parity_test.py": 16.7, + "tst/unit/env/gateway/role_rules_test.py": 0.2, + "tst/unit/env/gateway/tool_access_parity_test.py": 9.6, "tst/unit/env/gateway/tool_name_clash_test.py": 0.1, "tst/unit/env/gateway/trajectory_virtual_time_test.py": 0.1, - "tst/unit/env/gateway/triggers_ctx_test.py": 2.5, - "tst/unit/env/gateway/triggers_test.py": 13.7, - "tst/unit/env/gateway/triggers_time_test.py": 1.8, - "tst/unit/env/gateway/triggers_website_test.py": 1.2, - "tst/unit/env/gateway/website_mcp_test.py": 1.9, - "tst/unit/env/gateway/website_reserved_paths_test.py": 0.3, - "tst/unit/env/gateway/website_websocket_test.py": 4.8, + "tst/unit/env/gateway/triggers_ctx_test.py": 2.2, + "tst/unit/env/gateway/triggers_test.py": 12.5, + "tst/unit/env/gateway/triggers_time_test.py": 1.5, + "tst/unit/env/gateway/triggers_website_test.py": 1.0, + "tst/unit/env/gateway/website_mcp_test.py": 1.8, + "tst/unit/env/gateway/website_reserved_paths_test.py": 0.2, + "tst/unit/env/gateway/website_websocket_test.py": 4.1, "tst/unit/env/published_images_test.py": 0.5, - "tst/unit/env/store_test.py": 0.2, + "tst/unit/env/store_test.py": 0.1, "tst/unit/env/task_step/deploy_agent_env_vars_test.py": 0.1, - "tst/unit/env/task_step/test_context_ops.py": 0.5, - "tst/unit/env/task_step/test_score_aggregator.py": 0.2, - "tst/unit/env/task_step/verify_env_card_test.py": 0.2, + "tst/unit/env/task_step/test_context_ops.py": 0.3, + "tst/unit/env/task_step/test_score_aggregator.py": 0.1, + "tst/unit/env/task_step/verify_env_card_test.py": 0.1, "tst/unit/env/task_step/verify_env_core_protocol_test.py": 0.2, - "tst/unit/env/test_env.py": 0.9, - "tst/unit/env/test_legacy_protocol.py": 0.3, - "tst/unit/env/test_registry.py": 0.7, + "tst/unit/env/test_env.py": 0.5, + "tst/unit/env/test_legacy_protocol.py": 0.2, + "tst/unit/env/test_registry.py": 0.3, "tst/unit/env/test_snapshot_fingerprint.py": 0.1, "tst/unit/explorer/entity_ids_test.py": 0.1, - "tst/unit/explorer/explorer_app_test.py": 20.8, - "tst/unit/openenv/app_test.py": 19.2, - "tst/unit/openenv/environment_test.py": 13.5, - "tst/unit/plugin_inventory_test.py": 1.3, - "tst/unit/plugin_requirements_test.py": 0.3, - "tst/unit/plugin_settings_test.py": 11.8, - "tst/unit/plugins_test.py": 2.3, - "tst/unit/providers/compose_host_port_publish_test.py": 1.0, - "tst/unit/providers/env_providers/env_gateway_provider_test.py": 7.3, - "tst/unit/providers/env_providers/env_provider_test.py": 0.2, - "tst/unit/providers/env_providers/env_server_provider_test.py": 0.6, - "tst/unit/providers/env_state/test_config_state_providers.py": 0.9, - "tst/unit/providers/env_state/test_env_state_provider.py": 0.5, - "tst/unit/providers/sandbox_providers/agent37_sandbox_provider_test.py": 0.6, - "tst/unit/providers/sandbox_providers/agent37_sandbox_test.py": 1.2, - "tst/unit/providers/sandbox_providers/attribution_wire_test.py": 0.4, - "tst/unit/providers/sandbox_providers/boat_sandbox_provider_test.py": 0.6, - "tst/unit/providers/sandbox_providers/boat_sandbox_test.py": 0.5, - "tst/unit/providers/sandbox_providers/boxd_sandbox_provider_test.py": 1.7, - "tst/unit/providers/sandbox_providers/boxd_sandbox_test.py": 0.5, - "tst/unit/providers/sandbox_providers/coreweave_deploy_paths_test.py": 0.2, - "tst/unit/providers/sandbox_providers/coreweave_sandbox_provider_test.py": 1.8, - "tst/unit/providers/sandbox_providers/coreweave_sandbox_test.py": 0.3, - "tst/unit/providers/sandbox_providers/daytona_network_test.py": 0.2, - "tst/unit/providers/sandbox_providers/daytona_sandbox_provider_test.py": 2.0, - "tst/unit/providers/sandbox_providers/daytona_sandbox_test.py": 1.2, + "tst/unit/explorer/explorer_app_test.py": 15.8, + "tst/unit/openenv/app_test.py": 9.8, + "tst/unit/openenv/environment_test.py": 10.4, + "tst/unit/plugin_inventory_test.py": 0.8, + "tst/unit/plugin_requirements_test.py": 0.2, + "tst/unit/plugin_settings_test.py": 6.9, + "tst/unit/plugins_test.py": 1.4, + "tst/unit/providers/compose_host_port_publish_test.py": 0.4, + "tst/unit/providers/env_providers/env_gateway_provider_test.py": 63.8, + "tst/unit/providers/env_providers/env_provider_test.py": 0.1, + "tst/unit/providers/env_providers/env_server_provider_test.py": 0.4, + "tst/unit/providers/env_state/test_config_state_providers.py": 0.5, + "tst/unit/providers/env_state/test_env_state_provider.py": 0.3, + "tst/unit/providers/sandbox_providers/agent37_sandbox_provider_test.py": 0.4, + "tst/unit/providers/sandbox_providers/agent37_sandbox_test.py": 1.1, + "tst/unit/providers/sandbox_providers/attribution_wire_test.py": 0.3, + "tst/unit/providers/sandbox_providers/boat_sandbox_provider_test.py": 0.4, + "tst/unit/providers/sandbox_providers/boat_sandbox_test.py": 0.3, + "tst/unit/providers/sandbox_providers/boxd_sandbox_provider_test.py": 1.2, + "tst/unit/providers/sandbox_providers/boxd_sandbox_test.py": 0.3, + "tst/unit/providers/sandbox_providers/coreweave_deploy_paths_test.py": 0.3, + "tst/unit/providers/sandbox_providers/coreweave_sandbox_provider_test.py": 1.6, + "tst/unit/providers/sandbox_providers/coreweave_sandbox_test.py": 0.7, + "tst/unit/providers/sandbox_providers/daytona_network_test.py": 0.5, + "tst/unit/providers/sandbox_providers/daytona_sandbox_provider_test.py": 1.3, + "tst/unit/providers/sandbox_providers/daytona_sandbox_test.py": 1.0, "tst/unit/providers/sandbox_providers/e2b_sandbox_provider_test.py": 0.2, - "tst/unit/providers/sandbox_providers/e2b_sandbox_test.py": 1.2, - "tst/unit/providers/sandbox_providers/e2b_template_test.py": 0.6, - "tst/unit/providers/sandbox_providers/egress_hosts_test.py": 0.4, - "tst/unit/providers/sandbox_providers/host_images_test.py": 0.9, + "tst/unit/providers/sandbox_providers/e2b_sandbox_test.py": 1.3, + "tst/unit/providers/sandbox_providers/e2b_template_test.py": 0.5, + "tst/unit/providers/sandbox_providers/egress_hosts_test.py": 0.2, + "tst/unit/providers/sandbox_providers/host_images_test.py": 0.8, "tst/unit/providers/sandbox_providers/local_sandbox_host_ports_test.py": 0.5, - "tst/unit/providers/sandbox_providers/local_sandbox_test.py": 12.6, - "tst/unit/providers/sandbox_providers/lume_sandbox_provider_test.py": 10.7, - "tst/unit/providers/sandbox_providers/modal_context_build_test.py": 0.8, - "tst/unit/providers/sandbox_providers/modal_create_signature_test.py": 0.2, - "tst/unit/providers/sandbox_providers/modal_gpu_sandbox_test.py": 0.0, - "tst/unit/providers/sandbox_providers/modal_network_policy_test.py": 0.2, - "tst/unit/providers/sandbox_providers/modal_network_policy_wiring_test.py": 0.1, + "tst/unit/providers/sandbox_providers/local_sandbox_test.py": 10.9, + "tst/unit/providers/sandbox_providers/lume_sandbox_provider_test.py": 10.4, + "tst/unit/providers/sandbox_providers/modal_context_build_test.py": 0.7, + "tst/unit/providers/sandbox_providers/modal_create_signature_test.py": 0.1, + "tst/unit/providers/sandbox_providers/modal_gpu_sandbox_test.py": 0.1, + "tst/unit/providers/sandbox_providers/modal_network_policy_test.py": 0.1, + "tst/unit/providers/sandbox_providers/modal_network_policy_wiring_test.py": 0.0, "tst/unit/providers/sandbox_providers/modal_sandbox_started_log_test.py": 0.1, "tst/unit/providers/sandbox_providers/modal_sandbox_tags_test.py": 0.1, - "tst/unit/providers/sandbox_providers/modal_sandbox_test.py": 0.7, - "tst/unit/providers/sandbox_providers/modal_vm_sandbox_test.py": 1.2, - "tst/unit/providers/sandbox_providers/network_policy_providers_test.py": 0.4, + "tst/unit/providers/sandbox_providers/modal_sandbox_test.py": 0.5, + "tst/unit/providers/sandbox_providers/modal_vm_sandbox_test.py": 1.3, + "tst/unit/providers/sandbox_providers/network_policy_providers_test.py": 0.1, "tst/unit/providers/sandbox_providers/network_policy_stamping_test.py": 0.1, - "tst/unit/providers/sandbox_providers/network_policy_test.py": 0.2, - "tst/unit/providers/sandbox_providers/provider_capabilities_test.py": 3.2, + "tst/unit/providers/sandbox_providers/network_policy_test.py": 0.1, + "tst/unit/providers/sandbox_providers/provider_capabilities_test.py": 1.8, "tst/unit/providers/sandbox_providers/relay_test.py": 0.1, - "tst/unit/providers/sandbox_providers/sail_vm_model_key_test.py": 2.1, - "tst/unit/providers/sandbox_providers/sail_vm_sandbox_provider_test.py": 2.0, - "tst/unit/providers/sandbox_providers/sail_vm_sandbox_test.py": 0.3, - "tst/unit/providers/sandbox_providers/sandbox_provider_test.py": 0.7, - "tst/unit/providers/sandbox_providers/tenki_sandbox_provider_test.py": 0.9, - "tst/unit/providers/sandbox_providers/tenki_sandbox_test.py": 0.3, - "tst/unit/providers/sandbox_providers/tensorlake_sandbox_provider_test.py": 0.4, - "tst/unit/providers/sandbox_providers/tensorlake_sandbox_test.py": 5.4, - "tst/unit/providers/sandbox_providers/test_config_sandbox_providers.py": 1.5, - "tst/unit/providers/sandbox_providers/test_reachability_contributions.py": 0.5, - "tst/unit/providers/sandbox_providers/test_url_rewrites.py": 0.7, - "tst/unit/providers/sandbox_providers/vercel_sandbox_provider_test.py": 0.4, - "tst/unit/providers/sandbox_providers/vercel_sandbox_test.py": 3.8, - "tst/unit/providers/sandbox_providers/vm_file_transfer_test.py": 0.2, - "tst/unit/providers/sandbox_providers/vm_object_push_test.py": 0.6, - "tst/unit/providers/sandbox_providers/vm_sandbox_test.py": 0.7, - "tst/unit/runner/local_runner_test.py": 7.6, + "tst/unit/providers/sandbox_providers/sail_vm_model_key_test.py": 0.6, + "tst/unit/providers/sandbox_providers/sail_vm_sandbox_provider_test.py": 1.3, + "tst/unit/providers/sandbox_providers/sail_vm_sandbox_test.py": 0.2, + "tst/unit/providers/sandbox_providers/sandbox_provider_test.py": 0.4, + "tst/unit/providers/sandbox_providers/tenki_sandbox_provider_test.py": 0.7, + "tst/unit/providers/sandbox_providers/tenki_sandbox_test.py": 0.1, + "tst/unit/providers/sandbox_providers/tensorlake_sandbox_provider_test.py": 0.9, + "tst/unit/providers/sandbox_providers/tensorlake_sandbox_test.py": 3.4, + "tst/unit/providers/sandbox_providers/test_config_sandbox_providers.py": 0.6, + "tst/unit/providers/sandbox_providers/test_reachability_contributions.py": 0.2, + "tst/unit/providers/sandbox_providers/test_url_rewrites.py": 0.3, + "tst/unit/providers/sandbox_providers/vercel_sandbox_provider_test.py": 0.2, + "tst/unit/providers/sandbox_providers/vercel_sandbox_test.py": 3.6, + "tst/unit/providers/sandbox_providers/vm_file_transfer_test.py": 0.1, + "tst/unit/providers/sandbox_providers/vm_object_push_test.py": 0.4, + "tst/unit/providers/sandbox_providers/vm_sandbox_test.py": 0.6, + "tst/unit/runner/local_runner_test.py": 7.0, "tst/unit/runner/run_store_test.py": 0.1, - "tst/unit/serialization/test_golden_wire_format.py": 0.4, + "tst/unit/serialization/test_golden_wire_format.py": 0.2, "tst/unit/store/awaiting_lock_test.py": 1.0, - "tst/unit/store/aws/aws_secret_store_test.py": 0.3, - "tst/unit/store/aws/dynamodb_document_store_test.py": 14.1, - "tst/unit/store/aws/dynamodb_step_journal_test.py": 13.7, - "tst/unit/store/aws/ecr_image_store_test.py": 0.1, - "tst/unit/store/aws/s3_grant_lifetime_test.py": 0.1, - "tst/unit/store/aws/s3_object_store_test.py": 6.5, + "tst/unit/store/aws/aws_secret_store_test.py": 0.1, + "tst/unit/store/aws/dynamodb_document_store_test.py": 10.6, + "tst/unit/store/aws/dynamodb_step_journal_test.py": 11.0, + "tst/unit/store/aws/ecr_image_store_test.py": 0.0, + "tst/unit/store/aws/s3_grant_lifetime_test.py": 0.0, + "tst/unit/store/aws/s3_object_store_test.py": 4.3, "tst/unit/store/aws/s3_transfer_grants_test.py": 0.2, - "tst/unit/store/aws/test_secret_logging.py": 0.1, + "tst/unit/store/aws/test_secret_logging.py": 0.0, "tst/unit/store/aws/test_shared_credentials.py": 0.2, - "tst/unit/store/derived_ids_test.py": 9.1, + "tst/unit/store/derived_ids_test.py": 8.8, "tst/unit/store/fake_object_store_test.py": 0.1, "tst/unit/store/firestore_mongo_document_store_test.py": 0.3, "tst/unit/store/gcp_secret_manager_secret_store_test.py": 0.1, - "tst/unit/store/gcs_object_store_test.py": 0.9, - "tst/unit/store/google_credentials_test.py": 0.8, - "tst/unit/store/google_transport_test.py": 0.2, + "tst/unit/store/gcs_object_store_test.py": 0.5, + "tst/unit/store/google_credentials_test.py": 0.6, + "tst/unit/store/google_transport_test.py": 0.1, "tst/unit/store/grant_lifetime_test.py": 0.1, - "tst/unit/store/ids_test.py": 1.1, - "tst/unit/store/local_backends_composition_test.py": 1.2, - "tst/unit/store/local_grant_server_test.py": 10.9, - "tst/unit/store/local_id_acceptance_test.py": 2.0, - "tst/unit/store/local_object_store_test.py": 1.7, + "tst/unit/store/ids_test.py": 0.8, + "tst/unit/store/local_backends_composition_test.py": 1.0, + "tst/unit/store/local_grant_server_test.py": 10.2, + "tst/unit/store/local_id_acceptance_test.py": 1.2, + "tst/unit/store/local_object_store_test.py": 1.6, "tst/unit/store/local_registry_image_store_test.py": 0.1, "tst/unit/store/local_secret_store_test.py": 0.1, - "tst/unit/store/local_tls_test.py": 0.5, - "tst/unit/store/local_tokens_test.py": 0.2, + "tst/unit/store/local_tls_test.py": 0.3, + "tst/unit/store/local_tokens_test.py": 0.1, "tst/unit/store/mongo_document_store_test.py": 0.8, - "tst/unit/store/oci_registry_credentials_test.py": 0.2, - "tst/unit/store/oci_registry_image_store_test.py": 0.4, - "tst/unit/store/readable_url_test.py": 0.3, - "tst/unit/store/registry_api_test.py": 0.5, - "tst/unit/store/routing_test.py": 3.4, - "tst/unit/store/sqlite_document_store_test.py": 11.3, - "tst/unit/store/test_config_document_store.py": 0.3, - "tst/unit/store/test_config_image_store.py": 0.3, - "tst/unit/store/test_config_model.py": 0.6, - "tst/unit/store/test_config_mongo_client.py": 0.1, - "tst/unit/store/test_config_object_store.py": 0.2, + "tst/unit/store/oci_registry_credentials_test.py": 0.1, + "tst/unit/store/oci_registry_image_store_test.py": 0.3, + "tst/unit/store/readable_url_test.py": 0.1, + "tst/unit/store/registry_api_test.py": 0.3, + "tst/unit/store/routing_test.py": 2.4, + "tst/unit/store/sqlite_document_store_test.py": 8.1, + "tst/unit/store/test_config_document_store.py": 0.2, + "tst/unit/store/test_config_image_store.py": 0.2, + "tst/unit/store/test_config_model.py": 0.3, + "tst/unit/store/test_config_mongo_client.py": 0.0, + "tst/unit/store/test_config_object_store.py": 0.1, "tst/unit/store/test_config_secret_bundle_keys.py": 0.0, - "tst/unit/store/test_config_secret_store.py": 0.2, - "tst/unit/store/test_document_store.py": 0.7, - "tst/unit/store/test_object_transfer_grants.py": 0.5, - "tst/unit/store/test_task_instance_indexes.py": 0.1, - "tst/unit/store/version_lookup_benchmark_test.py": 1.5, - "tst/unit/task/batch_universe_ids_test.py": 0.0, + "tst/unit/store/test_config_secret_store.py": 0.1, + "tst/unit/store/test_document_store.py": 0.5, + "tst/unit/store/test_object_transfer_grants.py": 0.2, + "tst/unit/store/test_task_instance_indexes.py": 0.0, + "tst/unit/store/version_lookup_benchmark_test.py": 1.2, + "tst/unit/task/batch_universe_ids_test.py": 0.2, "tst/unit/task/benchmark_test.py": 0.0, "tst/unit/task/control_grant_test.py": 0.1, "tst/unit/task/depends_on_test.py": 0.9, - "tst/unit/task/episode/proxy_test.py": 0.3, - "tst/unit/task/episode/run_test.py": 20.1, - "tst/unit/task/episode/spec_test.py": 2.5, - "tst/unit/task/local_run_write_fence_test.py": 2.9, + "tst/unit/task/episode/proxy_test.py": 0.2, + "tst/unit/task/episode/run_test.py": 15.9, + "tst/unit/task/episode/spec_test.py": 1.3, + "tst/unit/task/local_run_write_fence_test.py": 2.2, "tst/unit/task/retry_sandbox_teardown_test.py": 0.1, "tst/unit/task/seed_context_fence_test.py": 0.1, - "tst/unit/task/seed_substitution_test.py": 0.1, - "tst/unit/task/step_journal_rules_test.py": 0.2, - "tst/unit/task/step_journal_test.py": 1.7, - "tst/unit/task/task_document_test.py": 0.4, - "tst/unit/task/task_failure_write_retry_test.py": 0.2, - "tst/unit/task/task_instance_reads_test.py": 0.2, - "tst/unit/task/teardown_test.py": 2.7, + "tst/unit/task/seed_substitution_test.py": 0.0, + "tst/unit/task/step_journal_rules_test.py": 0.1, + "tst/unit/task/step_journal_test.py": 1.1, + "tst/unit/task/task_document_test.py": 0.3, + "tst/unit/task/task_failure_write_retry_test.py": 0.1, + "tst/unit/task/task_instance_reads_test.py": 0.1, + "tst/unit/task/teardown_test.py": 1.7, "tst/unit/task_step/add_skills_env_test.py": 0.2, "tst/unit/task_step/attribution_serialization_test.py": 0.2, - "tst/unit/task_step/computer_recording_test.py": 1.1, + "tst/unit/task_step/computer_recording_test.py": 0.8, "tst/unit/task_step/context_ops_journal_test.py": 0.1, "tst/unit/task_step/deploy_agent_cleanup_test.py": 0.0, "tst/unit/task_step/deploy_agent_linked_sandbox_test.py": 0.0, "tst/unit/task_step/deploy_agent_test.py": 0.1, - "tst/unit/task_step/deploy_env_test.py": 1.4, + "tst/unit/task_step/deploy_env_test.py": 0.8, "tst/unit/task_step/deploy_human_agent_test.py": 0.1, "tst/unit/task_step/deploy_sandbox_default_cpu_test.py": 0.1, "tst/unit/task_step/deploy_sandbox_image_test.py": 0.1, "tst/unit/task_step/deploy_sandbox_network_policy_test.py": 0.1, "tst/unit/task_step/deploy_sandbox_provider_override_test.py": 0.1, - "tst/unit/task_step/install_agent_guards_test.py": 0.4, - "tst/unit/task_step/install_agent_test.py": 0.5, - "tst/unit/task_step/local_container_urls_test.py": 1.8, - "tst/unit/task_step/local_step_containers_test.py": 0.3, - "tst/unit/task_step/prompt_agent_file_parts_test.py": 0.3, - "tst/unit/task_step/retry_test.py": 1.8, - "tst/unit/task_step/run_context_object_url_test.py": 0.3, + "tst/unit/task_step/install_agent_guards_test.py": 0.2, + "tst/unit/task_step/install_agent_test.py": 0.4, + "tst/unit/task_step/local_container_urls_test.py": 1.1, + "tst/unit/task_step/local_step_containers_test.py": 0.2, + "tst/unit/task_step/prompt_agent_file_parts_test.py": 0.2, + "tst/unit/task_step/retry_test.py": 1.2, + "tst/unit/task_step/run_context_object_url_test.py": 0.2, "tst/unit/task_step/run_docker_container_test.py": 0.2, - "tst/unit/task_step/skill_object_url_test.py": 0.2, - "tst/unit/task_step/snapshot_computer_env_test.py": 0.6, - "tst/unit/task_step/snapshot_env_upload_grant_test.py": 1.0, - "tst/unit/task_step/snapshot_env_without_gateway_test.py": 0.6, + "tst/unit/task_step/skill_object_url_test.py": 0.5, + "tst/unit/task_step/snapshot_computer_env_test.py": 0.3, + "tst/unit/task_step/snapshot_env_upload_grant_test.py": 0.8, + "tst/unit/task_step/snapshot_env_without_gateway_test.py": 0.4, "tst/unit/task_step/stored_priority_test.py": 0.1, - "tst/unit/task_step/stored_s3_form_fields_test.py": 0.1, - "tst/unit/task_step/sync_env_clock_test.py": 0.6, - "tst/unit/task_step/test_advance_to_next_event_hook.py": 1.1, + "tst/unit/task_step/stored_s3_form_fields_test.py": 0.0, + "tst/unit/task_step/sync_env_clock_test.py": 0.4, + "tst/unit/task_step/test_advance_to_next_event_hook.py": 0.9, "tst/unit/task_step/test_agent_model_precedence.py": 0.1, - "tst/unit/task_step/test_agent_state_capture.py": 1.2, - "tst/unit/task_step/test_apply_server_config.py": 1.0, + "tst/unit/task_step/test_agent_state_capture.py": 0.9, + "tst/unit/task_step/test_apply_server_config.py": 0.5, "tst/unit/task_step/test_browser_connect_cdp.py": 0.2, - "tst/unit/task_step/test_browser_steps.py": 1.0, - "tst/unit/task_step/test_collect_artifacts.py": 1.1, + "tst/unit/task_step/test_browser_sign_in.py": 0.0, + "tst/unit/task_step/test_browser_steps.py": 0.7, + "tst/unit/task_step/test_collect_artifacts.py": 0.7, "tst/unit/task_step/test_collect_artifacts_universe_suffix.py": 0.2, - "tst/unit/task_step/test_collect_artifacts_vm_host.py": 0.3, + "tst/unit/task_step/test_collect_artifacts_vm_host.py": 0.1, "tst/unit/task_step/test_collect_integrity.py": 0.1, "tst/unit/task_step/test_combine_universe_verdicts.py": 0.1, - "tst/unit/task_step/test_config_task_steps.py": 0.7, - "tst/unit/task_step/test_configure_scheduled_checks.py": 0.2, + "tst/unit/task_step/test_config_task_steps.py": 0.2, + "tst/unit/task_step/test_configure_scheduled_checks.py": 0.0, "tst/unit/task_step/test_container_sandbox_routing.py": 0.3, - "tst/unit/task_step/test_deploy_agent_changelog_objects.py": 1.0, - "tst/unit/task_step/test_deploy_agent_enable_docker.py": 0.1, + "tst/unit/task_step/test_deploy_agent_changelog_objects.py": 0.3, + "tst/unit/task_step/test_deploy_agent_enable_docker.py": 0.0, "tst/unit/task_step/test_deploy_agent_live_endpoint.py": 0.1, - "tst/unit/task_step/test_deploy_agent_mcp_alias.py": 0.2, - "tst/unit/task_step/test_deploy_agent_role_delivery.py": 1.2, - "tst/unit/task_step/test_deploy_agent_snapshot_objects.py": 0.5, - "tst/unit/task_step/test_deploy_ttl_from_budget.py": 0.0, - "tst/unit/task_step/test_entity_refs.py": 1.0, - "tst/unit/task_step/test_field_scopes.py": 0.7, - "tst/unit/task_step/test_install_agent_registers_instance.py": 0.1, + "tst/unit/task_step/test_deploy_agent_mcp_alias.py": 0.1, + "tst/unit/task_step/test_deploy_agent_role_delivery.py": 0.3, + "tst/unit/task_step/test_deploy_agent_snapshot_objects.py": 0.4, + "tst/unit/task_step/test_deploy_ttl_from_budget.py": 0.1, + "tst/unit/task_step/test_entity_refs.py": 1.9, + "tst/unit/task_step/test_field_scopes.py": 1.3, + "tst/unit/task_step/test_install_agent_registers_instance.py": 0.0, "tst/unit/task_step/test_load_artifact_agent_container_target.py": 0.1, - "tst/unit/task_step/test_load_artifact_container_sandbox.py": 0.1, - "tst/unit/task_step/test_load_artifact_env_binding.py": 0.1, - "tst/unit/task_step/test_load_artifact_file.py": 0.1, + "tst/unit/task_step/test_load_artifact_container_sandbox.py": 0.0, + "tst/unit/task_step/test_load_artifact_env_binding.py": 0.0, + "tst/unit/task_step/test_load_artifact_file.py": 0.0, "tst/unit/task_step/test_load_artifact_overrides.py": 0.1, - "tst/unit/task_step/test_load_artifact_service_payload.py": 0.5, - "tst/unit/task_step/test_load_artifact_service_universe.py": 0.1, - "tst/unit/task_step/test_load_artifact_snapshot_reporting.py": 0.1, - "tst/unit/task_step/test_load_artifact_url_filenames.py": 0.1, - "tst/unit/task_step/test_load_artifact_vm_target.py": 0.2, - "tst/unit/task_step/test_manifest_cli_builder.py": 15.0, - "tst/unit/task_step/test_mcp_cli_builder.py": 1.7, + "tst/unit/task_step/test_load_artifact_service_payload.py": 0.3, + "tst/unit/task_step/test_load_artifact_service_universe.py": 0.0, + "tst/unit/task_step/test_load_artifact_snapshot_reporting.py": 0.0, + "tst/unit/task_step/test_load_artifact_url_filenames.py": 0.0, + "tst/unit/task_step/test_load_artifact_vm_target.py": 0.0, + "tst/unit/task_step/test_manifest_cli_builder.py": 13.1, + "tst/unit/task_step/test_mcp_cli_builder.py": 1.2, "tst/unit/task_step/test_modify_env_tool_access.py": 0.0, - "tst/unit/task_step/test_next_env_event_hook.py": 1.8, + "tst/unit/task_step/test_next_env_event_hook.py": 1.4, "tst/unit/task_step/test_parallel_deploy_env_binding.py": 0.1, - "tst/unit/task_step/test_preflight_pinned_versions.py": 0.1, - "tst/unit/task_step/test_prompt_agent.py": 0.2, + "tst/unit/task_step/test_preflight_pinned_versions.py": 0.0, + "tst/unit/task_step/test_prompt_agent.py": 0.1, "tst/unit/task_step/test_prompt_agent_builtin_tools.py": 0.0, "tst/unit/task_step/test_prompt_agent_conversation_tool_calls.py": 0.0, "tst/unit/task_step/test_prompt_agent_human_default.py": 0.0, - "tst/unit/task_step/test_prompt_agent_live_trajectory.py": 0.8, + "tst/unit/task_step/test_prompt_agent_live_trajectory.py": 0.6, "tst/unit/task_step/test_prompt_agent_model_params.py": 0.0, - "tst/unit/task_step/test_prompt_agent_notifications.py": 0.6, - "tst/unit/task_step/test_prompt_agent_post_turn_hooks.py": 1.9, - "tst/unit/task_step/test_prompt_agent_snapshots.py": 2.8, - "tst/unit/task_step/test_prompt_agent_triggers.py": 1.1, - "tst/unit/task_step/test_prompt_agent_unreachable.py": 0.0, + "tst/unit/task_step/test_prompt_agent_notifications.py": 0.2, + "tst/unit/task_step/test_prompt_agent_post_turn_hooks.py": 1.1, + "tst/unit/task_step/test_prompt_agent_snapshots.py": 2.3, + "tst/unit/task_step/test_prompt_agent_triggers.py": 0.9, + "tst/unit/task_step/test_prompt_agent_unreachable.py": 0.1, "tst/unit/task_step/test_prompt_agent_user_model.py": 0.0, - "tst/unit/task_step/test_prompt_agent_user_side.py": 0.4, + "tst/unit/task_step/test_prompt_agent_user_side.py": 0.8, "tst/unit/task_step/test_recorded_models.py": 0.1, - "tst/unit/task_step/test_register_agent_triggers.py": 0.2, - "tst/unit/task_step/test_register_env_triggers.py": 7.5, - "tst/unit/task_step/test_reset_env.py": 0.1, - "tst/unit/task_step/test_review.py": 0.2, - "tst/unit/task_step/test_run_code.py": 18.3, + "tst/unit/task_step/test_register_agent_triggers.py": 0.1, + "tst/unit/task_step/test_register_env_triggers.py": 7.3, + "tst/unit/task_step/test_reset_env.py": 0.0, + "tst/unit/task_step/test_review.py": 0.1, + "tst/unit/task_step/test_run_code.py": 16.5, "tst/unit/task_step/test_sandbox_utils_agent_container.py": 0.0, "tst/unit/task_step/test_sandbox_utils_logs.py": 0.1, - "tst/unit/task_step/test_snapshot_agent_state.py": 0.2, - "tst/unit/task_step/test_snapshot_env.py": 1.1, + "tst/unit/task_step/test_snapshot_agent_state.py": 0.1, + "tst/unit/task_step/test_snapshot_env.py": 0.8, "tst/unit/task_step/test_snapshot_env_env_binding.py": 0.1, - "tst/unit/task_step/test_step_overrides_agent_and_model.py": 0.2, - "tst/unit/task_step/test_teardown_sandboxes.py": 0.4, + "tst/unit/task_step/test_step_overrides_agent_and_model.py": 0.1, + "tst/unit/task_step/test_teardown_sandboxes.py": 0.2, "tst/unit/task_step/test_universe_comparison.py": 0.1, "tst/unit/task_step/test_validation_gate_aggregator.py": 0.1, "tst/unit/task_step/test_verify_a2a_agent_mcp.py": 0.0, - "tst/unit/task_step/test_verify_a2a_builtin_tools.py": 0.1, + "tst/unit/task_step/test_verify_a2a_builtin_tools.py": 0.0, "tst/unit/task_step/test_verify_spec_conformance.py": 0.2, "tst/unit/task_step/test_verify_universe_agent_judge.py": 0.1, - "tst/unit/task_step/test_verify_universe_roundtrip.py": 0.2, + "tst/unit/task_step/test_verify_universe_roundtrip.py": 0.1, "tst/unit/task_step/thread_work_test.py": 0.6, - "tst/unit/task_step/unwritten_local_agent_test.py": 0.9, - "tst/unit/task_step/verifiers/judge_short_keys_test.py": 0.1, - "tst/unit/task_step/verifiers/judge_utils/test_frame_selection.py": 0.2, + "tst/unit/task_step/unwritten_local_agent_test.py": 0.3, + "tst/unit/task_step/verifiers/judge_short_keys_test.py": 0.0, + "tst/unit/task_step/verifiers/judge_utils/test_frame_selection.py": 0.1, "tst/unit/task_step/verifiers/judge_utils/test_frame_selection_tool_name.py": 0.0, "tst/unit/task_step/verifiers/judge_utils/test_judge_output_format.py": 0.2, "tst/unit/task_step/verifiers/judge_utils/test_trajectory_filter.py": 0.0, - "tst/unit/task_step/verifiers/run_container_unit_tests_verifier_test.py": 0.9, + "tst/unit/task_step/verifiers/run_container_unit_tests_verifier_test.py": 0.6, "tst/unit/task_step/verifiers/test_env_outcome_verifier_step.py": 0.1, - "tst/unit/task_step/verifiers/test_rubrics_verifier_criteria_override.py": 0.1, - "tst/unit/task_step/verifiers/test_rubrics_verifier_grade_up_to_turn.py": 0.2, + "tst/unit/task_step/verifiers/test_rubrics_verifier_criteria_override.py": 0.0, + "tst/unit/task_step/verifiers/test_rubrics_verifier_grade_up_to_turn.py": 0.1, "tst/unit/task_step/verifiers/test_rubrics_verifier_judge_batches.py": 0.2, - "tst/unit/task_step/verifiers/test_rubrics_verifier_judge_model.py": 0.0, - "tst/unit/task_step/verifiers/test_rubrics_verifier_judge_retry.py": 0.1, + "tst/unit/task_step/verifiers/test_rubrics_verifier_judge_model.py": 0.1, + "tst/unit/task_step/verifiers/test_rubrics_verifier_judge_retry.py": 0.0, "tst/unit/task_step/verifiers/test_rubrics_verifier_judge_teardown.py": 0.0, "tst/unit/task_step/verifiers/test_rubrics_verifier_judge_timeout.py": 0.0, - "tst/unit/task_step/verifiers/test_rubrics_verifier_judge_trajectory.py": 0.5, + "tst/unit/task_step/verifiers/test_rubrics_verifier_judge_trajectory.py": 0.4, + "tst/unit/task_step/verifiers/test_rubrics_verifier_litellm_contract.py": 0.2, "tst/unit/task_step/verifiers/test_rubrics_verifier_mistakes_entry.py": 0.2, - "tst/unit/task_step/verifiers/test_rubrics_verifier_multiturn.py": 0.7, - "tst/unit/task_step/verifiers/test_rubrics_verifier_nonfinite_scores.py": 3.1, - "tst/unit/task_step/verifiers/test_rubrics_verifier_per_criterion.py": 0.4, - "tst/unit/task_step/verifiers/test_rubrics_verifier_screenshots.py": 4.4, + "tst/unit/task_step/verifiers/test_rubrics_verifier_multiturn.py": 0.9, + "tst/unit/task_step/verifiers/test_rubrics_verifier_nonfinite_scores.py": 2.2, + "tst/unit/task_step/verifiers/test_rubrics_verifier_per_criterion.py": 0.2, + "tst/unit/task_step/verifiers/test_rubrics_verifier_screenshots.py": 0.1, "tst/unit/task_step/verifiers/test_run_context.py": 1.6, "tst/unit/task_step/verifiers/test_score_parity.py": 0.0, - "tst/unit/task_step/verifiers/test_trajectory_mistakes_format.py": 0.2, - "tst/unit/task_step/verifiers/test_verify_sandbox.py": 0.2, - "tst/unit/test_capabilities.py": 0.3, - "tst/unit/test_check_plugin_api.py": 21.1, - "tst/unit/test_check_skip_policy.py": 0.3, + "tst/unit/task_step/verifiers/test_trajectory_mistakes_format.py": 0.1, + "tst/unit/task_step/verifiers/test_verify_sandbox.py": 0.1, + "tst/unit/test_capabilities.py": 0.2, + "tst/unit/test_check_plugin_api.py": 13.2, + "tst/unit/test_check_skip_policy.py": 0.2, "tst/unit/test_clean_install_wheel.py": 0.1, "tst/unit/test_client_identity.py": 0.0, - "tst/unit/test_infra_build_script.py": 1.3, - "tst/unit/test_infra_images_script.py": 0.6, + "tst/unit/test_infra_build_script.py": 0.7, + "tst/unit/test_infra_images_script.py": 0.3, "tst/unit/test_mirror_base_images_script.py": 0.1, - "tst/unit/test_optional_extras_stay_optional.py": 592.4, - "tst/unit/test_pypi_release_script.py": 0.3, - "tst/unit/test_release_infra_images.py": 0.7, - "tst/unit/test_release_protocol_pins.py": 0.3, - "tst/unit/test_runtime_dependencies_are_imported.py": 33.9, - "tst/unit/test_shards.py": 13.2, + "tst/unit/test_optional_extras_stay_optional.py": 172.7, + "tst/unit/test_package_cache.py": 0.1, + "tst/unit/test_prune_registry_script.py": 0.0, + "tst/unit/test_published_image.py": 0.1, + "tst/unit/test_pypi_release_script.py": 0.1, + "tst/unit/test_release_infra_images.py": 0.6, + "tst/unit/test_release_protocol_pins.py": 0.2, + "tst/unit/test_runtime_dependencies_are_imported.py": 16.3, + "tst/unit/test_shards.py": 9.3, "tst/unit/test_slow_test_durations_script.py": 0.2, - "tst/unit/test_subclass_hooks_are_annotated.py": 2.2, - "tst/unit/test_tls_verification.py": 0.2, - "tst/unit/training/chat_test.py": 14.7, - "tst/unit/training/harness_test.py": 24.0, - "tst/unit/training/nemo_gym_test.py": 4.1, + "tst/unit/test_subclass_hooks_are_annotated.py": 3.7, + "tst/unit/test_tls_verification.py": 0.1, + "tst/unit/training/chat_test.py": 12.6, + "tst/unit/training/harness_test.py": 13.3, + "tst/unit/training/nemo_gym_test.py": 2.8, "tst/unit/training/sessions_test.py": 0.2, - "tst/unit/training/skyrl_test.py": 6.4, - "tst/unit/training/tools_test.py": 0.3, - "tst/unit/training/trl_test.py": 39.2, - "tst/unit/training/verl_test.py": 3.6, - "tst/unit/utils/docker/build_test.py": 0.4, - "tst/unit/utils/docker/context_test.py": 0.6, - "tst/unit/utils/docker/dockerfile_test.py": 1.0, - "tst/unit/utils/docker/installed_test.py": 0.2, - "tst/unit/utils/docker/lock_test.py": 0.2, + "tst/unit/training/skyrl_test.py": 5.0, + "tst/unit/training/tools_test.py": 0.1, + "tst/unit/training/trl_test.py": 30.6, + "tst/unit/training/verl_test.py": 2.9, + "tst/unit/utils/docker/build_test.py": 0.2, + "tst/unit/utils/docker/context_test.py": 0.3, + "tst/unit/utils/docker/dockerfile_test.py": 0.4, + "tst/unit/utils/docker/installed_test.py": 0.1, + "tst/unit/utils/docker/lock_test.py": 0.3, "tst/unit/utils/docker/metadata_test.py": 0.1, - "tst/unit/utils/docker/prune_test.py": 0.8, + "tst/unit/utils/docker/prune_test.py": 0.5, "tst/unit/utils/exec_retry_test.py": 0.1, "tst/unit/utils/test_card_naming_github_token.py": 0.0, - "tst/unit/utils/test_paths.py": 0.2 + "tst/unit/utils/test_paths.py": 0.1 } }