From 3abe31fb016b0091ccee0d7f9fc50d4b19ae6205 Mon Sep 17 00:00:00 2001 From: ciregenz Date: Sat, 15 Aug 2026 22:53:46 -0700 Subject: [PATCH] arena: implement v39 mutation-diff action feedback (Agent-E) -- all four Tier-1 ingestions now flag-gated and ready to pilot Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01WsbS5x2rYsMDxP2kW3qqmQ --- e2e/browser-v3/arena/llm_policy.py | 13 +++++++++++++ e2e/browser-v3/arena/run.py | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/e2e/browser-v3/arena/llm_policy.py b/e2e/browser-v3/arena/llm_policy.py index 88427ef7..4b72d311 100644 --- a/e2e/browser-v3/arena/llm_policy.py +++ b/e2e/browser-v3/arena/llm_policy.py @@ -190,6 +190,10 @@ class LlmPolicy: notes: list[str] = field(default_factory=list) # v38: table->markdown rendering of table/grid subtrees (perception.tables_markdown). table_md: bool = False + # v39: mutation-diff action feedback -- run.py appends the page-text delta after each action + # (Agent-E's MutationObserver, approximated text-side). Autocomplete popups, error banners, + # and new rows become explicit feedback instead of something the model must notice unaided. + mutation_diff: bool = False def notes_gated(self, goal: str) -> bool: return self.note_pad and bool(re.search( @@ -995,6 +999,15 @@ def build(name: str, model: str = "", endpoint: str = "", **_: Any) -> Any: scripted_drag=True, auto_complete=True, som=False, native_pickers=True, verify_terminal=True, post_mouse_vision=True, multi_cap=6, fill_verify=True, **v17) + if name == "osw-llm-v39": # v35 + mutation-diff action feedback (Agent-E observer, text-side) + v39 = dict(v7, system=OSW_SYSTEM_V8 + OSW_SYSTEM_V9_WIDGETS + OSW_SYSTEM_V16 + OSW_SYSTEM_V30, + max_tokens=800) + return OpenSwarmLlmPolicy(name=name, multi=True, vision="progressive", fastpath=True, + scripted_drag=True, auto_complete=True, som=False, + native_pickers=True, verify_terminal=True, post_mouse_vision=True, + multi_cap=6, fill_verify=True, dispatch=True, offscreen=True, + local_ctx=True, blocker_probe=True, suppress_wrappers=True, + force_unblock=True, native_js_fallback=True, mutation_diff=True, **v39) if name == "osw-llm-v38": # v35 + table->markdown page rendering (AgentOccam action_reformat_table) v38 = dict(v7, system=OSW_SYSTEM_V8 + OSW_SYSTEM_V9_WIDGETS + OSW_SYSTEM_V16 + OSW_SYSTEM_V30, max_tokens=800) diff --git a/e2e/browser-v3/arena/run.py b/e2e/browser-v3/arena/run.py index bf292eba..e1caad86 100644 --- a/e2e/browser-v3/arena/run.py +++ b/e2e/browser-v3/arena/run.py @@ -236,9 +236,28 @@ def run_episode(arm: str, task: str, seed: int, rec: Recorder, args: argparse.Na break if ep.first_action_s == 0.0: ep.first_action_s = time.time() - t0 + # v39 (gated, ingested from Agent-E's mutation observer): snapshot the page text + # before the action so the delta after it can ride into history as feedback. + pre_text = "" + if getattr(policy, "mutation_diff", False): + try: + pre_text = perception.page_text(obs, limit=2000) + except Exception: + pass t_act = time.time() obs, reward, terminated, truncated, _ = with_deadline( lambda: env.step(decision.action), args.step_timeout) + if getattr(policy, "mutation_diff", False) and hasattr(policy, "history"): + try: + post_text = perception.page_text(obs, limit=2000) + pre_lines = set(pre_text.split("\n")) + fresh = [l.strip() for l in post_text.split("\n") + if l.strip() and l not in pre_lines][:4] + if fresh: + policy.history.append( + "(page reacted: new text appeared -> " + " | ".join(fresh)[:220] + ")") + except Exception: + pass rec_step.action_ms = (time.time() - t_act) * 1000 rec_step.reward = float(reward or 0) err = str(obs.get("last_action_error") or "")