From c9016da784d3a3cafbe8ffb84a38ca686e9e5314 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 13 Aug 2026 07:44:02 +0900 Subject: [PATCH 1/6] test(browser): define pristine Agent Task isolation contract --- ...st_agent_task_pristine_profile_contract.py | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 tests/test_agent_task_pristine_profile_contract.py diff --git a/tests/test_agent_task_pristine_profile_contract.py b/tests/test_agent_task_pristine_profile_contract.py new file mode 100644 index 0000000..e8e6414 --- /dev/null +++ b/tests/test_agent_task_pristine_profile_contract.py @@ -0,0 +1,110 @@ +"""Contract for pristine, credential-free Agent Task browser profile admission.""" + +from __future__ import annotations + +import pathlib +import runpy +import tempfile +import unittest + +ROOT = pathlib.Path(__file__).resolve().parents[1] +RUNNER = ROOT / "scripts" / "ci" / "run_mv3_compatibility.py" + + +class AgentTaskPristineProfileContractTests(unittest.TestCase): + """Require explicit isolation proof before the pinned browser task can pass.""" + + def _namespace(self, name: str) -> dict[str, object]: + return runpy.run_path(str(RUNNER), run_name=name) + + def test_runner_exposes_pristine_profile_and_ambient_state_boundaries(self) -> None: + """Profile admission and ambient-state inspection must be explicit boundaries.""" + + namespace = self._namespace("agent_task_pristine_profile_contract") + self.assertIn("_require_pristine_agent_task_profile", namespace) + self.assertIn("_probe_agent_task_ambient_state", namespace) + + def test_profile_admission_rejects_preexisting_state(self) -> None: + """Any pre-existing profile entry must fail closed before Chromium starts.""" + + namespace = self._namespace("agent_task_pristine_profile_behavior") + require_pristine = namespace["_require_pristine_agent_task_profile"] + with tempfile.TemporaryDirectory(prefix="originweave-pristine-profile-") as profile_dir: + require_pristine(profile_dir) + pathlib.Path(profile_dir, "Cookies").write_text("preexisting", encoding="utf-8") + with self.assertRaisesRegex(RuntimeError, "not pristine"): + require_pristine(profile_dir) + + def test_ambient_state_probe_rejects_cookies_or_web_storage(self) -> None: + """Browser-visible cookie or Web Storage state must not be normalized as isolated.""" + + namespace = self._namespace("agent_task_ambient_state_behavior") + probe = namespace["_probe_agent_task_ambient_state"] + + def no_cookies_request( + _driver_port: int, + method: str, + path: str, + _payload: object | None = None, + **_kwargs: object, + ) -> dict[str, object]: + self.assertEqual(method, "GET") + self.assertTrue(path.endswith("/cookie")) + return {"value": []} + + probe.__globals__["_json_request"] = no_cookies_request + probe.__globals__["_execute"] = lambda *_args, **_kwargs: { + "localStorageLength": 0, + "sessionStorageLength": 0, + } + self.assertEqual( + probe(4444, "session-a"), + { + "ambient_cookies_absent": True, + "ambient_web_storage_absent": True, + }, + ) + + def ambient_cookie_request( + _driver_port: int, + _method: str, + _path: str, + _payload: object | None = None, + **_kwargs: object, + ) -> dict[str, object]: + return {"value": [{"name": "ambient", "value": "redacted-test"}]} + + probe.__globals__["_json_request"] = ambient_cookie_request + with self.assertRaisesRegex(RuntimeError, "ambient cookies"): + probe(4444, "session-a") + + probe = self._namespace("agent_task_ambient_storage_behavior")[ + "_probe_agent_task_ambient_state" + ] + probe.__globals__["_json_request"] = no_cookies_request + probe.__globals__["_execute"] = lambda *_args, **_kwargs: { + "localStorageLength": 1, + "sessionStorageLength": 0, + } + with self.assertRaisesRegex(RuntimeError, "ambient Web Storage"): + probe(4444, "session-a") + + def test_agent_task_disables_saved_credential_services_and_gates_evidence(self) -> None: + """The acceptance runner must configure and require credential-free isolation evidence.""" + + runner = RUNNER.read_text(encoding="utf-8") + for expected in ( + '"credentials_enable_service": False', + '"profile.password_manager_enabled": False', + '"profile_pristine_before_launch"', + '"ambient_cookies_absent"', + '"ambient_web_storage_absent"', + '"saved_credential_services_disabled"', + "Agent Task isolation gate failed", + ): + with self.subTest(expected=expected): + self.assertIn(expected, runner) + + +if __name__ == "__main__": + unittest.main() From a805af6ff8bef3e974ea3a4e0a5cdc4ec4dee30f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 13 Aug 2026 08:21:14 +0900 Subject: [PATCH 2/6] feat(browser): prove pristine Agent Task isolation --- scripts/ci/run_mv3_compatibility.py | 76 +++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/scripts/ci/run_mv3_compatibility.py b/scripts/ci/run_mv3_compatibility.py index 615f4b2..8479dbf 100755 --- a/scripts/ci/run_mv3_compatibility.py +++ b/scripts/ci/run_mv3_compatibility.py @@ -283,6 +283,52 @@ def _measure_agent_task_semantic_observation_bytes(observation: dict[str, Any]) return len(encoded) +def _require_pristine_agent_task_profile(profile_dir: str) -> None: + """Fail closed unless the controlled Agent Task profile directory is empty.""" + + profile_path = pathlib.Path(profile_dir) + if not profile_path.is_dir() or any(profile_path.iterdir()): + raise RuntimeError("Agent Task profile is not pristine before launch") + + +def _probe_agent_task_ambient_state(driver_port: int, session_id: str) -> dict[str, bool]: + """Require no browser-visible cookies or Web Storage before the controlled action.""" + + cookies = _json_request( + driver_port, + "GET", + _webdriver_path(session_id, "/cookie"), + ).get("value") + if not isinstance(cookies, list): + raise RuntimeError("Agent Task cookie inspection returned malformed evidence") + if cookies: + raise RuntimeError("Agent Task profile exposed ambient cookies") + + storage = _execute( + driver_port, + session_id, + """ +return { + localStorageLength: window.localStorage.length, + sessionStorageLength: window.sessionStorage.length +}; +""", + ) + if not isinstance(storage, dict): + raise RuntimeError("Agent Task Web Storage inspection returned malformed evidence") + local_storage_length = storage.get("localStorageLength") + session_storage_length = storage.get("sessionStorageLength") + for value in (local_storage_length, session_storage_length): + if isinstance(value, bool) or not isinstance(value, int) or value < 0: + raise RuntimeError("Agent Task Web Storage inspection returned malformed evidence") + if local_storage_length or session_storage_length: + raise RuntimeError("Agent Task profile exposed ambient Web Storage") + return { + "ambient_cookies_absent": True, + "ambient_web_storage_absent": True, + } + + def _parse_linux_proc_status_rss_bytes(status_text: str) -> int: """Parse exactly one positive Linux ``VmRSS`` kB field into bounded bytes.""" @@ -743,6 +789,8 @@ def _run_agent_task_browser_pass( ) -> dict[str, Any]: """Execute one synthetic Agent Task and measure bounded real-browser evidence.""" + _require_pristine_agent_task_profile(profile_dir) + profile_pristine_before_launch = True started = time.monotonic() driver_port = _free_loopback_port() session_id: str | None = None @@ -764,6 +812,10 @@ def _run_agent_task_browser_pass( "browserName": "chrome", "goog:chromeOptions": { "binary": str(chrome_bin), + "prefs": { + "credentials_enable_service": False, + "profile.password_manager_enabled": False, + }, "args": [ "--headless=new", "--no-first-run", @@ -816,6 +868,7 @@ def _run_agent_task_browser_pass( ).get("value") if initial_url != fixture_url: raise RuntimeError("Agent Task did not load the requested fixture URL") + ambient_state = _probe_agent_task_ambient_state(driver_port, session_id) input_element = _find_element_by_accessible_role_name( driver_port, @@ -937,6 +990,10 @@ def _run_agent_task_browser_pass( "structured_value_field": "task_result", "structured_value_sha256": structured_value_sha256, "extensions_disabled": True, + "profile_pristine_before_launch": profile_pristine_before_launch, + "ambient_cookies_absent": ambient_state["ambient_cookies_absent"], + "ambient_web_storage_absent": ambient_state["ambient_web_storage_absent"], + "saved_credential_services_disabled": True, "browser_process_rss_bytes": browser_process_rss_bytes, "chromium_process_count": chromium_process_count, "chromium_process_set_rss_bytes": chromium_process_set_rss_bytes, @@ -999,6 +1056,12 @@ def _run_agent_task_trial( "structured_value_field": result["structured_value_field"], "structured_value_sha256": result["structured_value_sha256"], "extensions_disabled": result["extensions_disabled"], + "profile_pristine_before_launch": result["profile_pristine_before_launch"], + "ambient_cookies_absent": result["ambient_cookies_absent"], + "ambient_web_storage_absent": result["ambient_web_storage_absent"], + "saved_credential_services_disabled": result[ + "saved_credential_services_disabled" + ], "browser_process_rss_bytes": result["browser_process_rss_bytes"], "chromium_process_count": result["chromium_process_count"], "chromium_process_set_rss_bytes": result["chromium_process_set_rss_bytes"], @@ -1380,6 +1443,16 @@ def main() -> int: agent_task_trial_pass_rate = ( agent_task_successful_trials / AGENT_TASK_REPEATABILITY_TRIALS ) + agent_task_isolation_complete = all( + trial.get("profile_pristine_before_launch") is True + and trial.get("ambient_cookies_absent") is True + and trial.get("ambient_web_storage_absent") is True + and trial.get("saved_credential_services_disabled") is True + and trial.get("extensions_disabled") is True + and trial.get("profile_cleaned") is True + for trial in agent_task_trials + if trial.get("passed") is True + ) agent_task_surfaces_complete = all( trial.get("post_condition") is True and trial.get("input_echo_verified") is True @@ -1438,6 +1511,7 @@ def main() -> int: "repeatability_trials": AGENT_TASK_REPEATABILITY_TRIALS, "successful_trials": agent_task_successful_trials, "trial_pass_rate": agent_task_trial_pass_rate, + "isolation_complete": agent_task_isolation_complete, "trial_results": agent_task_trials, "forced_close": { "repeatability_trials": AGENT_TASK_REPEATABILITY_TRIALS, @@ -1461,6 +1535,8 @@ def main() -> int: f"{agent_task_successful_trials}/{AGENT_TASK_REPEATABILITY_TRIALS} " "trials passed" ) + if not agent_task_isolation_complete: + raise RuntimeError("Agent Task isolation gate failed") if not agent_task_surfaces_complete: raise RuntimeError("Agent Task repeatability surfaces were incomplete") if ( From 5fac5b5c61462f415caadb98a2428907acc0c745 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 13 Aug 2026 09:13:40 +0900 Subject: [PATCH 3/6] docs(changelog): record pristine Agent Task admission --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c479367..810310f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ All notable changes to OriginWeave are documented in this file. The format follo - Rust 1.97.1 build contract, strict Clippy and rustdoc gates, and exact production function, line, region, and branch coverage enforcement. - Pinned Chrome-for-Testing Agent Task evidence now captures a bounded sampled Chromium root-plus-descendant process count and RSS total from one `/proc` status sweep, with bounded failure-type diagnostics while preserving the root-only metric and making no trusted per-task attribution claim. - Pinned Chrome-for-Testing Agent Task evidence now locates the controlled result by exact browser-computed `status`/`Task result` semantics and records only a bounded canonical SHA-256 digest plus stable field identity for the extracted synthetic value, without emitting the raw value. +- Controlled pinned-Chromium Agent Task acceptance now fails closed unless the temporary profile is pristine before launch and browser-observed cookies, local storage, session storage, and extension count are all empty, retaining bounded per-trial isolation evidence without claiming OS- or browser-attested absence of every credential mechanism. - Hourly bounded OpenCode product-development workflow using `NVIDIA_NIM_API_KEY`, an unprivileged disposable workspace, loopback-only model broker, independently verified patches, and publication through a dedicated `OPENCODE_PR_TOKEN` that cannot review or merge. - Architecture, agent, security, contribution, research, database naming, roadmap, quality-gate, and TLS service-identity ADR documentation. - Authoritative product documentation graph spanning PRD, TRD, ADR lifecycle/index, product-wide UML, conceptual ERD, requirement/decision traceability, threat modeling, product-wide test strategy, operability, API/protocol, release/rollback, and current primary-source standards doctoring, with machine-checkable repository contracts that keep conversation-derived future work distinct from protected-main implementation claims. From 8845dbd781f60f0d9ef4ea74ec0a9707b16bbd50 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 13 Aug 2026 09:26:27 +0900 Subject: [PATCH 4/6] docs(changelog): correct pristine profile evidence scope --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 810310f..dc0df60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,7 @@ All notable changes to OriginWeave are documented in this file. The format follo - Rust 1.97.1 build contract, strict Clippy and rustdoc gates, and exact production function, line, region, and branch coverage enforcement. - Pinned Chrome-for-Testing Agent Task evidence now captures a bounded sampled Chromium root-plus-descendant process count and RSS total from one `/proc` status sweep, with bounded failure-type diagnostics while preserving the root-only metric and making no trusted per-task attribution claim. - Pinned Chrome-for-Testing Agent Task evidence now locates the controlled result by exact browser-computed `status`/`Task result` semantics and records only a bounded canonical SHA-256 digest plus stable field identity for the extracted synthetic value, without emitting the raw value. -- Controlled pinned-Chromium Agent Task acceptance now fails closed unless the temporary profile is pristine before launch and browser-observed cookies, local storage, session storage, and extension count are all empty, retaining bounded per-trial isolation evidence without claiming OS- or browser-attested absence of every credential mechanism. +- Controlled pinned-Chromium Agent Task acceptance now fails closed unless the temporary profile is pristine before launch, browser-observed cookies and Web Storage are empty, saved-credential services are disabled, extensions are disabled by launch policy, and the profile is removed afterward; bounded per-trial evidence does not claim OS- or browser-attested absence of every credential mechanism. - Hourly bounded OpenCode product-development workflow using `NVIDIA_NIM_API_KEY`, an unprivileged disposable workspace, loopback-only model broker, independently verified patches, and publication through a dedicated `OPENCODE_PR_TOKEN` that cannot review or merge. - Architecture, agent, security, contribution, research, database naming, roadmap, quality-gate, and TLS service-identity ADR documentation. - Authoritative product documentation graph spanning PRD, TRD, ADR lifecycle/index, product-wide UML, conceptual ERD, requirement/decision traceability, threat modeling, product-wide test strategy, operability, API/protocol, release/rollback, and current primary-source standards doctoring, with machine-checkable repository contracts that keep conversation-derived future work distinct from protected-main implementation claims. From 83e02cc2c65af08d3f75583376eea1dc066aab7c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 13 Aug 2026 09:41:02 +0900 Subject: [PATCH 5/6] test(browser): keep post-condition diagnostics credential-safe --- tests/test_agent_task_pristine_profile_contract.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/test_agent_task_pristine_profile_contract.py b/tests/test_agent_task_pristine_profile_contract.py index e8e6414..fd499ef 100644 --- a/tests/test_agent_task_pristine_profile_contract.py +++ b/tests/test_agent_task_pristine_profile_contract.py @@ -89,6 +89,19 @@ def ambient_cookie_request( with self.assertRaisesRegex(RuntimeError, "ambient Web Storage"): probe(4444, "session-a") + def test_agent_task_post_condition_does_not_echo_browser_state(self) -> None: + """Browser-controlled state must fail closed without entering CI diagnostics.""" + + namespace = self._namespace("agent_task_post_condition_diagnostic_contract") + require_state = namespace["_require_agent_task_submission_state"] + require_state("submitted") + + hostile_state = "secret-like-browser-state-do-not-log" + with self.assertRaises(RuntimeError) as raised: + require_state(hostile_state) + self.assertNotIn(hostile_state, str(raised.exception)) + self.assertEqual(str(raised.exception), "Agent Task state post-condition failed") + def test_agent_task_disables_saved_credential_services_and_gates_evidence(self) -> None: """The acceptance runner must configure and require credential-free isolation evidence.""" From 1deca80bf6a67394e25a2c914b76d490c2aad960 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 13 Aug 2026 09:46:12 +0900 Subject: [PATCH 6/6] test(browser): restore feasible pristine-profile contract --- tests/test_agent_task_pristine_profile_contract.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/tests/test_agent_task_pristine_profile_contract.py b/tests/test_agent_task_pristine_profile_contract.py index fd499ef..e8e6414 100644 --- a/tests/test_agent_task_pristine_profile_contract.py +++ b/tests/test_agent_task_pristine_profile_contract.py @@ -89,19 +89,6 @@ def ambient_cookie_request( with self.assertRaisesRegex(RuntimeError, "ambient Web Storage"): probe(4444, "session-a") - def test_agent_task_post_condition_does_not_echo_browser_state(self) -> None: - """Browser-controlled state must fail closed without entering CI diagnostics.""" - - namespace = self._namespace("agent_task_post_condition_diagnostic_contract") - require_state = namespace["_require_agent_task_submission_state"] - require_state("submitted") - - hostile_state = "secret-like-browser-state-do-not-log" - with self.assertRaises(RuntimeError) as raised: - require_state(hostile_state) - self.assertNotIn(hostile_state, str(raised.exception)) - self.assertEqual(str(raised.exception), "Agent Task state post-condition failed") - def test_agent_task_disables_saved_credential_services_and_gates_evidence(self) -> None: """The acceptance runner must configure and require credential-free isolation evidence."""