From b15be4bd2c4d41fa1f28fa4525538e3d8ab992d6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 14 Aug 2026 07:54:53 +0900 Subject: [PATCH 1/4] test(browser): require one ordinary teardown deadline --- ...est_agent_task_shared_teardown_deadline.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/test_agent_task_shared_teardown_deadline.py diff --git a/tests/test_agent_task_shared_teardown_deadline.py b/tests/test_agent_task_shared_teardown_deadline.py new file mode 100644 index 000000000..e7304e222 --- /dev/null +++ b/tests/test_agent_task_shared_teardown_deadline.py @@ -0,0 +1,35 @@ +"""Contract for one total post-shutdown teardown deadline in the ordinary Agent Task lane.""" + +from __future__ import annotations + +import pathlib +import unittest + +ROOT = pathlib.Path(__file__).resolve().parents[1] +RUNNER = ROOT / "scripts" / "ci" / "run_mv3_compatibility.py" + + +class AgentTaskSharedTeardownDeadlineContractTests(unittest.TestCase): + """Prevent ordinary Agent Task teardown polling from multiplying the budget.""" + + def test_browser_pass_uses_only_the_combined_teardown_waiter(self) -> None: + """Root and sampled-set evidence must share one timeout authority after shutdown.""" + + runner = RUNNER.read_text(encoding="utf-8") + start = runner.index("def _run_agent_task_browser_pass(") + end = runner.index("\ndef _run_agent_task_trial(", start) + browser_pass = runner[start:end] + + self.assertIn("_wait_for_linux_process_teardown(", browser_pass) + self.assertNotIn("_wait_for_linux_process_identity_exit(", browser_pass) + self.assertNotIn("_wait_for_linux_process_identity_set_exit(", browser_pass) + + shutdown = browser_pass.index("driver.wait(timeout=5)") + teardown_wait = browser_pass.index("_wait_for_linux_process_teardown(") + failure_return = browser_pass.index("if browser_failure_type is not None:") + self.assertLess(shutdown, teardown_wait) + self.assertLess(teardown_wait, failure_return) + + +if __name__ == "__main__": + unittest.main() From bca8380c4ed1060531879e2b8419b3d6869c3669 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 14 Aug 2026 13:35:36 +0900 Subject: [PATCH 2/4] fix(browser): share ordinary teardown deadline --- scripts/ci/run_mv3_compatibility.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/scripts/ci/run_mv3_compatibility.py b/scripts/ci/run_mv3_compatibility.py index 0de08d43c..ecda65b32 100755 --- a/scripts/ci/run_mv3_compatibility.py +++ b/scripts/ci/run_mv3_compatibility.py @@ -1295,15 +1295,22 @@ def _run_agent_task_browser_pass( if browser_process_id is None or browser_process_start_time_ticks is None: raise RuntimeError("Agent Task browser process identity was not captured") - browser_process_terminated = _wait_for_linux_process_identity_exit( - browser_process_id, - browser_process_start_time_ticks, + full_process_set_captured = chromium_process_identities is not None + teardown_identities = ( + chromium_process_identities + if chromium_process_identities is not None + else ((browser_process_id, browser_process_start_time_ticks),) ) - chromium_process_set_terminated: bool | None = None - if chromium_process_identities is not None: - chromium_process_set_terminated = _wait_for_linux_process_identity_set_exit( - chromium_process_identities + browser_process_terminated, observed_process_set_terminated = ( + _wait_for_linux_process_teardown( + browser_process_id, + browser_process_start_time_ticks, + teardown_identities, ) + ) + chromium_process_set_terminated: bool | None = ( + observed_process_set_terminated if full_process_set_captured else None + ) if browser_failure_type is not None: failure_evidence: dict[str, Any] = { "failure_type": browser_failure_type, From f67e8952aaf6d6d3748a31bb3f5e036a6c12b459 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 14 Aug 2026 13:38:42 +0900 Subject: [PATCH 3/4] test(browser): align failure evidence with shared teardown --- ..._agent_task_failure_process_set_termination_contract.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/test_agent_task_failure_process_set_termination_contract.py b/tests/test_agent_task_failure_process_set_termination_contract.py index 6fe48ea9d..46e055b41 100644 --- a/tests/test_agent_task_failure_process_set_termination_contract.py +++ b/tests/test_agent_task_failure_process_set_termination_contract.py @@ -24,8 +24,9 @@ def test_browser_pass_retains_sampled_process_set_teardown_after_failure(self) - end = runner.index("\ndef _run_agent_task_trial(", start) browser_pass = runner[start:end] for expected in ( - "if chromium_process_identities is not None:", - "chromium_process_set_terminated = _wait_for_linux_process_identity_set_exit(", + "full_process_set_captured = chromium_process_identities is not None", + "_wait_for_linux_process_teardown(", + "observed_process_set_terminated if full_process_set_captured else None", 'failure_evidence["chromium_process_set_terminated"]', ): with self.subTest(expected=expected): @@ -91,4 +92,4 @@ def fail_before_process_set_capture( if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main() From cb03afd86c303e7217987f850c47c73089cef9bf Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 14 Aug 2026 17:13:28 +0900 Subject: [PATCH 4/4] docs(browser): record ordinary shared teardown deadline --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 728a1aaad..22585bcfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to OriginWeave are documented in this file. The format follo - Controlled pinned-Chromium Agent Task success now binds the ChromeDriver browser root and every PID in the already sampled bounded Chromium root-plus-descendant process set to exact Linux `/proc//stat` start-time identities before shutdown and fails closed unless those exact identities terminate after session/driver shutdown; PID reuse counts only as termination of the original identity, and this does not attest cgroup/task ownership, processes appearing only after the sample, or OS-wide orphan absence. - The controlled forced-close Agent Task recovery probe now binds the ChromeDriver browser root and its already sampled bounded Chromium descendant set to exact Linux PID/start-time identities before forcing the disposable context closed, and successful recovery is accepted only after session/driver shutdown proves root and sampled-set termination under one shared bounded monotonic deadline; this remains bounded compatibility evidence and does not attest cgroup ownership, post-snapshot processes, cross-platform supervision, or OS-wide orphan absence. +- Controlled ordinary Agent Task teardown now observes the exact browser root and already sampled Chromium process set under one shared bounded monotonic deadline after session/driver shutdown, preserving separate root/process-set termination evidence and retaining `None` when no full process set was captured; this prevents sequential waiters from extending a nominal teardown budget while making no claim about cgroup ownership, post-snapshot processes, cross-platform supervision, or OS-wide orphan absence. - Failed ordinary and forced-close Agent Task browser trials now retain credential-free temporary-profile cleanup evidence after bounded browser errors, and separate aggregate compatibility gates require cleanup proof from every trial rather than filtering unsuccessful trials out; this does not attest adversarial filesystem erasure, process termination, or arbitrary browser recovery. - Failed Manifest V3 restart trials now retain credential-free temporary-profile cleanup evidence after bounded browser errors, successful trials record the same cleanup fact, and an aggregate compatibility gate requires teardown proof from every MV3 trial before repeatability acceptance without retaining exception messages; this does not attest adversarial filesystem erasure, browser-process termination, or cleanup outside the controlled temporary profile. - Rust workspace for independently reusable core, policy, destination, network, TLS, resource, and evidence modules.