@@ -962,7 +962,7 @@ def _run_pi_agent(
962962 env = _local_pi_env (app , agent_cfg , computer_use_bin = computer_use_bin ),
963963 transcript_path = str (transcript ),
964964 progress_prefix = f"[verify { finding .id } ]" ,
965- tools = [ "read" , "bash" ] ,
965+ tools = _live_agent_tools ( computer_use_mode ) ,
966966 system_prompt = _localize_live_agent_paths (
967967 _live_agent_system_prompt (computer_use_mode ),
968968 repo_path = app .repo_copy ,
@@ -1010,7 +1010,7 @@ def _run_pi_agent(
10101010 model = model ,
10111011 transcript_path = str (transcript ),
10121012 progress_prefix = f"[verify:{ finding .id } ]" ,
1013- tools = [ "read" , "bash" ] ,
1013+ tools = _live_agent_tools ( computer_use_mode ) ,
10141014 system_prompt = _live_agent_system_prompt (computer_use_mode ),
10151015 event_sink = getattr (self , "event_sink" , NULL_EVENT_SINK ),
10161016 )
@@ -1049,25 +1049,27 @@ def _verdict_from_agent_result(
10491049 )
10501050 verdict = _verdict_from_payload (finding , plan , verdict_data , plugin = self .name )
10511051 verdict .artifacts ["transcript" ] = str (finding_dir / "live-agent-transcript.jsonl" )
1052- if _profile_computer_use_mode (self .profile ) == COMPUTER_USE_DAYTONA and not (
1053- _agent_result_has_daytona_command (result )
1054- ):
1055- return RuntimeVerdict (
1056- finding_id = finding .id ,
1057- title = finding .title ,
1058- plugin = self .name ,
1059- status = RUNTIME_BLOCKED ,
1060- confidence = "low" ,
1061- evidence = [
1062- "Daytona computer use was requested, but the live-agent transcript did not "
1063- "include a bash tool call invoking any cu-* command." ,
1064- "The verifier requires computer-use evidence before accepting a Daytona "
1065- "live-agent verdict." ,
1066- ],
1067- error = "missing Daytona computer-use evidence" ,
1068- artifacts = {"transcript" : str (finding_dir / "live-agent-transcript.jsonl" )},
1069- plan = plan .to_dict (),
1070- )
1052+ if _profile_computer_use_mode (self .profile ) == COMPUTER_USE_DAYTONA :
1053+ daytona_policy = _daytona_computer_only_policy (result )
1054+ if daytona_policy :
1055+ details = daytona_policy [:5 ]
1056+ if len (daytona_policy ) > len (details ):
1057+ details .append (f"... { len (daytona_policy ) - len (details )} more violation(s)" )
1058+ return RuntimeVerdict (
1059+ finding_id = finding .id ,
1060+ title = finding .title ,
1061+ plugin = self .name ,
1062+ status = RUNTIME_BLOCKED ,
1063+ confidence = "low" ,
1064+ evidence = [
1065+ "Daytona computer use was requested, but verification did not happen "
1066+ "exclusively through cu-* computer-use commands." ,
1067+ * details ,
1068+ ],
1069+ error = "missing or invalid Daytona computer-use evidence" ,
1070+ artifacts = {"transcript" : str (finding_dir / "live-agent-transcript.jsonl" )},
1071+ plan = plan .to_dict (),
1072+ )
10711073 return verdict
10721074
10731075 def _blocked (
@@ -1294,13 +1296,21 @@ def _profile_computer_use_mode(profile: AppRuntimeProfile) -> str:
12941296 return COMPUTER_USE_NONE
12951297
12961298
1299+ def _live_agent_tools (computer_use : str ) -> list [str ]:
1300+ if normalize_computer_use_mode (computer_use ) == COMPUTER_USE_DAYTONA :
1301+ return ["bash" ]
1302+ return ["read" , "bash" ]
1303+
1304+
12971305def _localize_live_agent_paths (text : str , * , repo_path : Path , artifacts_path : Path ) -> str :
12981306 return text .replace ("/work/repo" , str (repo_path )).replace (
12991307 "/work/artifacts" , str (artifacts_path )
13001308 )
13011309
13021310
1303- def _agent_result_has_daytona_command (result ) -> bool :
1311+ def _daytona_computer_only_policy (result ) -> list [str ]:
1312+ violations : list [str ] = []
1313+ saw_computer_use = False
13041314 for msg in getattr (result , "messages" , []) or []:
13051315 if msg .get ("role" ) != "assistant" :
13061316 continue
@@ -1310,13 +1320,33 @@ def _agent_result_has_daytona_command(result) -> bool:
13101320 for block in content :
13111321 if not isinstance (block , dict ) or block .get ("type" ) != "toolCall" :
13121322 continue
1313- if block .get ("name" ) != "bash" :
1323+ name = str (block .get ("name" ) or "" )
1324+ if name != "bash" :
1325+ violations .append (f"non-computer tool used: { name } " )
13141326 continue
13151327 args = block .get ("arguments" )
13161328 command = args .get ("command" ) if isinstance (args , dict ) else ""
1317- if any (cmd in str (command ) for cmd in DAYTONA_COMMANDS ):
1318- return True
1319- return False
1329+ if _bash_command_is_computer_use_only (str (command )):
1330+ saw_computer_use = True
1331+ else :
1332+ violations .append (f"non-computer bash command used: { command } " )
1333+ if not saw_computer_use :
1334+ violations .insert (0 , "no cu-* computer-use command was run" )
1335+ return violations
1336+
1337+
1338+ def _bash_command_is_computer_use_only (command : str ) -> bool :
1339+ if not command .strip ():
1340+ return False
1341+ if any (token in command for token in ("|" , "`" , "$(" )):
1342+ return False
1343+ for segment in re .split (r"\s*(?:&&|\|\||;|\n)\s*" , command ):
1344+ segment = segment .strip ()
1345+ if not segment :
1346+ continue
1347+ if segment .split ()[0 ] not in DAYTONA_COMMANDS :
1348+ return False
1349+ return True
13201350
13211351
13221352def _extract_verdict_payload (text : str ) -> dict [str , object ] | None :
@@ -1398,8 +1428,10 @@ def _live_agent_system_prompt(computer_use: str = COMPUTER_USE_NONE) -> str:
13981428- Do not start Xvfb, XFCE, x11vnc, noVNC, or a nested Daytona sandbox yourself.
13991429- Use bash-accessible local commands to control the existing desktop:
14001430 `cu-info`, `cu-screenshot`, `cu-click`, `cu-type`, `cu-key`, `cu-scroll`, and `cu-drag`.
1401- - Your first bash actions must run `cu-info` and `cu-screenshot` before reading source, installing
1402- dependencies, running tests, or writing reproduction scripts.
1431+ - Verification must happen only through these `cu-*` computer-use commands. Do not use the read tool,
1432+ do not inspect source files through shell commands, do not install dependencies, do not run tests,
1433+ and do not write reproduction scripts.
1434+ - Your first bash actions must run `cu-info` and `cu-screenshot`.
14031435- Take another screenshot after desktop/UI actions, and use the image evidence to decide whether the
14041436 action affected the expected screen.
14051437- Include the `cu-*` commands you ran and their artifact paths in the final runtime verdict evidence.
0 commit comments