[eric] browser: a delete task can no longer report a send it never made

This commit is contained in:
ciregenz
2026-08-03 15:23:50 -07:00
parent ab89896443
commit 116e44255e
4 changed files with 173 additions and 5 deletions
+4 -1
View File
@@ -38,7 +38,10 @@ def test_the_stall_backstop_branches_on_evidence():
final sentence without the model ever getting to speak; it must therefore read the evidence
flag, not the resend guard."""
idx = P_SRC.index("done_success = delivery_verified")
window = P_SRC[idx:idx + 900]
# Bounded by the next sibling branch, not by a character count. The count was 900, and adding an
# `if p_task_is_removal:` branch (a delete must not borrow the send wording) pushed the honest
# line past it, failing a test whose subject had not changed.
window = P_SRC[idx:P_SRC.index("if not wrapup_nudged", idx)]
assert "compose_unverified_send" in window, \
"the unverified branch must compose an honest line, not fall straight to a template"
assert "unverified_send_note" in window, \
@@ -0,0 +1,74 @@
"""A delete task must never exit through the send machinery.
Measured live 2026-08-02. Asked to delete three reddit posts, the run replied "Done, that's sent."
and removed nothing: an independent re-read found all three still on the profile. Three separate
paths let it happen, and all three share one root cause.
`task_is_send` is TRUE for a removal task. That is deliberate and documented (`is_removal_task`
exists precisely because the send classifier keys on the verb), but every consumer of `task_is_send`
then has to remember to exclude removals, and three of them did not:
1. the two-sided receipt, which cannot tell composing from SEARCHING. To find a post you want to
delete, the model types its title into the site's search box. That sets
composer_committed_payload. Navigating to the result leaves the box empty. "Fill committed AND
box now empty" is the receipt, so a delete that deleted nothing scored a verified send.
2. the autosend path, the sharper edge: it CLICKS Send on that same typed text, so a delete task
could search for a post and then post the search.
3. the post-send stall backstop, which phrased the ending as a send confirmation.
These tests are about the WIRING, not the regexes: they assert that a removal task is excluded from
each of the three, so a future consumer of `task_is_send` that forgets the exclusion fails here.
"""
import inspect
import re
from backend.apps.agents.browser import browser_agent as BA
from backend.apps.agents.browser.browser_loop import is_removal_task
P_SRC = inspect.getsource(BA)
def p_guard_near(needle: str, window: int = 6) -> str:
"""The few lines above a landmark, where its guard lives."""
i = P_SRC.find(needle)
assert i != -1, f"landmark moved: {needle!r}"
return "\n".join(P_SRC[:i].splitlines()[-window:]) + "\n" + needle
def test_a_delete_task_is_still_classified_as_a_send():
"""The premise the other tests rest on. If this ever flips, the exclusions below become dead
code and their protection quietly disappears, so it is asserted rather than assumed."""
task = 'Go to reddit.com and delete my post titled "canary9428eec8"'
assert is_removal_task(task), "a delete task must read as a removal"
assert re.search(r"\b(post|submit|publish|send)\b", task, re.I), (
"and it also carries a publish verb, which is why task_is_send is true for it")
def test_the_two_sided_receipt_excludes_removals():
"""The path that scored the false success: typing a title into search, then navigating away."""
guard = p_guard_near('if (task_is_send and not p_task_is_removal and not send_confirmed\n'
' and "error" not in result')
assert "not p_task_is_removal" in guard
def test_the_autosend_click_path_excludes_removals():
"""The dangerous one: this path clicks Send on whatever the model just typed."""
guard = p_guard_near("and browser_send_script.autosend_enabled()):")
assert "not p_task_is_removal" in guard
def test_the_post_send_backstop_refuses_to_claim_a_send_on_a_removal():
"""Defence in depth. Even if a removal reaches the post-send ending, it must not borrow the
send wording, and it must not report success."""
i = P_SRC.find("if p_task_is_removal:")
assert i != -1, "the removal branch in the post-send backstop is gone"
branch = P_SRC[i:i + 900]
assert "done_success = False" in branch, "a removal that cannot be confirmed is not a success"
assert "could not confirm anything was deleted" in branch
# The send wording must be ASSIGNED only under the non-removal branch. Checked on the assignment
# rather than the raw text, because the comment above it quotes the bad reply on purpose.
removal_code = [ln for ln in branch.split("elif")[0].splitlines()
if "done_message" in ln and not ln.strip().startswith("#")]
assert removal_code and all("sent" not in ln for ln in removal_code), removal_code