[eric] agents: the quarantine card spells out the clicks, because 22 of 25 never recovered from naming the fix

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U6zrBsUCNzpMBnov3rTVYV
This commit is contained in:
ciregenz
2026-08-30 10:10:59 -07:00
co-authored by Claude Opus 5
parent b133ef7a1a
commit 59a95b268a
2 changed files with 66 additions and 5 deletions
@@ -194,12 +194,23 @@ async def handle_run_error(e: Exception, session: AgentSession, session_id: str,
p_report_model_error("cert_failure", session_id, session, turn, e, p_stderr_tail)
elif is_cli_binary_missing(e, extra_text=p_stderr_tail):
# The bundled CLI vanished from an installed app (Windows AV quarantine class; 22 of 25 field installs never recovered). The raw "not found at: C:\..." card is unactionable; name the likely cause and the two real fixes.
# "Restore it from your antivirus quarantine" is technically right and empirically useless:
# 22 of 25 affected field installs never recovered, and a real user replied "don't know how
# to take a file out of quarantine" (2026-08-29). A card that names a fix the reader cannot
# perform is a dead end, so spell the clicks out and put the fix that always works first.
friendly_msg = (
"A core OpenSwarm component (the bundled agent runtime) is missing from "
"this install, which usually means antivirus software quarantined it. "
"Restore it from your antivirus quarantine and add an exclusion for "
"OpenSwarm, or reinstall from openswarm.com. Your chats and settings "
"are kept either way."
"A core OpenSwarm component (the bundled agent runtime) is missing from this "
"install. Antivirus software almost always caused this by quarantining it. "
"Your chats and settings are safe either way.\n\n"
"Easiest fix: reinstall from openswarm.com over the top of this install. "
"Nothing is lost.\n\n"
"Or restore it in Windows Security:\n"
"1. Open Windows Security, then Virus & threat protection.\n"
"2. Under Current threats choose Protection history.\n"
"3. Find the quarantined OpenSwarm or claude item and choose Actions, then Restore.\n"
"4. Back in Virus & threat protection, open Manage settings, scroll to Exclusions, "
"choose Add or remove exclusions, then Add an exclusion, then Folder, and pick your "
"OpenSwarm folder. Without this step it will be quarantined again."
)
error_msg = Message(role="system", content=friendly_msg, branch_id=session.active_branch_id)
absorb_repeat_card(session, error_msg)
@@ -0,0 +1,50 @@
"""The AV-quarantine card has to be performable by the person who receives it.
Field evidence, 2026-08-29: a first-time user hit this card and replied "don't know how to take a
file out of quarantine". She is not an outlier -- 22 of 25 affected installs never produced another
agent reply. The old card named the right fix ("restore it from your antivirus quarantine and add an
exclusion") and gave no way to do it, which is a dead end dressed as guidance.
Row 4 on the ladder: the app is unusable, and the stated recovery empirically does not happen."""
import re
SRC = open("backend/apps/agents/manager/run/handle_run_error.py", encoding="utf-8").read()
# Anchor on THIS card's own words: the file holds several `friendly_msg = (` blocks and slicing the
# first one silently tested the long-context card instead.
_start = SRC.index("bundled agent runtime")
CARD = SRC[_start:SRC.index("error_msg = Message(", _start)]
def test_it_leads_with_the_fix_that_always_works():
"""Reinstall works for everyone; the quarantine dance works for the few who can do it. A card
that opens with the harder path loses the readers who needed it most."""
lower = CARD.lower()
assert "reinstall" in lower
assert lower.index("reinstall") < lower.index("windows security"), \
"the always-works fix must come before the fiddly one"
def test_the_restore_path_is_actual_clicks():
"""Naming a destination is not instructions. These are the four screens a user has to touch."""
lower = CARD.lower()
for step in ("windows security", "protection history", "restore", "exclusion"):
assert step in lower, f"the card never mentions {step!r}"
def test_it_says_why_the_exclusion_matters():
"""Restoring without an exclusion just gets it quarantined again, which is how someone 'fixes'
it twice and gives up."""
assert "quarantined again" in CARD.lower()
def test_it_still_reassures_about_data():
"""The single most common panic on this card is 'have I lost my chats'."""
lower = CARD.lower()
assert "chats and settings are safe" in lower or "your chats" in lower
def test_it_does_not_dump_the_dead_path():
"""The raw CLINotFoundError path was the original unactionable card; it must not come back."""
assert "not found at" not in CARD.lower()
assert not re.search(r"[A-Za-z]:\\\\", CARD), "no raw Windows path in the user-facing text"