@@ -867,6 +867,101 @@ def test_bug_issue_triggers_worker(
867867 assert "Search fails when query is empty" in prompt
868868 assert "Issue #50" in prompt
869869
870+ def test_bug_with_open_pr_skipped (
871+ self , tmp_path , mock_github_api , capture_popen , monkeypatch
872+ ):
873+ """Bug issue that already has an open PR → skipped (no duplicate work).
874+
875+ Flow: issue #50 is labeled 'bug', PR #10 exists on branch issue-50-fix
876+ → enrich_issues_with_pr_status flags has_open_pr=True
877+ → pick_actionable_issue skips it → agent does not run Claude.
878+ """
879+ agent = make_agent (
880+ tmp_path , name = "worker" , required_labels = ["in-progress" , "in-review" , "bug" ],
881+ github_api = mock_github_api ,
882+ )
883+ monkeypatch .setattr (type (agent ), "_bot_logins" , property (lambda self : BOT_LOGINS ))
884+
885+ mock_github_api .set_issues ("in-progress" , [])
886+ mock_github_api .set_issues ("in-review" , [])
887+ mock_github_api .set_issues ("bug" , make_issue_list_items ((50 , "2024-01-01T00:00:00Z" )))
888+ mock_github_api .set_issues_detailed ("in-progress" , [])
889+ mock_github_api .set_issues_detailed ("in-review" , [])
890+ mock_github_api .set_issues_detailed ("bug" , [
891+ make_issue_detail (
892+ number = 50 ,
893+ title = "Search fails when query is empty" ,
894+ body = "When a user sends an empty search query, the app crashes." ,
895+ labels = ["bug" ],
896+ comments = [],
897+ ),
898+ ])
899+ mock_github_api .set_prs ([
900+ make_pull_request (10 , "issue-50-fix-empty-search" ),
901+ ])
902+
903+ calls = capture_popen (stdout_lines = [result_event ()], returncode = 0 )
904+
905+ result = agent .run ()
906+
907+ assert result .success is True
908+ assert result .output == "No actionable issues"
909+ assert len (calls ) == 0
910+
911+ def test_bug_with_open_pr_falls_through_to_feature (
912+ self , tmp_path , mock_github_api , capture_popen , monkeypatch
913+ ):
914+ """Bug has open PR, but in-progress feature exists → works on feature.
915+
916+ Flow: bug #50 has open PR → skipped, but feature #43 is actionable
917+ → Worker works on the feature instead of doing nothing.
918+ """
919+ agent = make_agent (
920+ tmp_path , name = "worker" , required_labels = ["in-progress" , "in-review" , "bug" ],
921+ github_api = mock_github_api ,
922+ )
923+ monkeypatch .setattr (type (agent ), "_bot_logins" , property (lambda self : BOT_LOGINS ))
924+
925+ mock_github_api .set_issues ("in-progress" , make_issue_list_items ((43 , "2024-01-01T00:00:00Z" )))
926+ mock_github_api .set_issues ("in-review" , [])
927+ mock_github_api .set_issues ("bug" , make_issue_list_items ((50 , "2024-01-01T00:00:00Z" )))
928+ mock_github_api .set_issues_detailed ("in-progress" , [
929+ make_issue_detail (
930+ number = 43 ,
931+ title = "Add user profiles" ,
932+ labels = ["in-progress" ],
933+ comments = [
934+ {
935+ "author" : {"login" : "alice" },
936+ "body" : "Go ahead and implement this." ,
937+ "createdAt" : "2024-01-07T00:00:00Z" ,
938+ },
939+ ],
940+ ),
941+ ])
942+ mock_github_api .set_issues_detailed ("in-review" , [])
943+ mock_github_api .set_issues_detailed ("bug" , [
944+ make_issue_detail (
945+ number = 50 ,
946+ title = "Search fails when query is empty" ,
947+ body = "Crash on empty query" ,
948+ labels = ["bug" ],
949+ comments = [],
950+ ),
951+ ])
952+ mock_github_api .set_prs ([
953+ make_pull_request (10 , "issue-50-fix-empty-search" ),
954+ ])
955+
956+ calls = capture_popen (stdout_lines = [result_event ()], returncode = 0 )
957+
958+ result = agent .run ()
959+
960+ assert result .success is True
961+ prompt = extract_prompt (calls )
962+ assert "Add user profiles" in prompt
963+ assert "Issue #43" in prompt
964+
870965 def test_bug_prioritized_over_in_progress (
871966 self , tmp_path , mock_github_api , capture_popen , monkeypatch
872967 ):
0 commit comments