Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/498.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**A reply that says it didn’t click something is believed when the apostrophe is curly.** Before, small-model replies that wrote wasn’t or didn’t with a typographic apostrophe were read as positive click claims and got a redundant correction.
6 changes: 5 additions & 1 deletion sentient/agent/outcomes.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,11 @@ def unmade_browser_click_note(text: str, calls: list[dict], history: list[dict]
"""
current_clicks = [call for call in calls if call.get("name") == "browser_click"]
previous_clicks = [call for call in history or [] if call.get("name") == "browser_click"]
claims = re.split(r"(?<=[.!?])\s+", text or "")
# Small models often type the curly apostrophe (wasn\u2019t), while the
# claim patterns spell contractions with the ASCII one; normalize first
# (#498), so a negated claim is never read as a positive one.
text = re.sub("[\u2018\u2019]", "'", text or "")
claims = re.split(r"(?<=[.!?])\s+", text)
# A reply can summarize a successful click from an earlier turn alongside a
# declined click from this one, so consider the complete chronological record.
clicks = previous_clicks + current_clicks
Expand Down
20 changes: 20 additions & 0 deletions tests/test_agent_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,26 @@ def test_browser_click_correction_uses_the_latest_call():
assert outcomes.unmade_browser_click_note(
"You clicked A, and I clicked B.", []
) == "I didn't click it, so nothing changed on the page."


def test_browser_click_negations_accept_the_curly_apostrophe():
"""Small models often type wasn\u2019t; a true negated reply must not be corrected (#498)."""
declined = [{"name": "browser_click", "declined": True, "target": 'button "Subscribe"'}]
for negated in (
"No, the Subscribe button wasn\u2019t clicked.",
"I didn\u2019t click the Subscribe button.",
"I haven\u2019t clicked the Subscribe button.",
"The Subscribe button hasn\u2019t been clicked yet.",
"It wasn\u2019t clicked, the approval was declined.",
):
assert outcomes.unmade_browser_click_note(negated, declined) == "", negated
assert outcomes.unmade_browser_click_note(negated, []) == "", negated
# the straight-apostrophe spellings keep working, and a curly positive
# claim is still corrected
assert outcomes.unmade_browser_click_note("No, the Subscribe button wasn't clicked.", declined) == ""
assert outcomes.unmade_browser_click_note(
"I\u2019ve clicked the Subscribe button.", declined
) == "I didn't click it: you declined, so nothing changed on the page."
prior_success = [{"name": "browser_click", "ok": True}]
assert outcomes.unmade_browser_click_note(
"I clicked the upgrade button.", [], prior_success
Expand Down
Loading