From 51cfbacd18e4f9102ccd21cb737173e8bb05ef05 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Mar 2026 03:07:51 +0000 Subject: [PATCH 1/2] Initial plan From bfb3ca7db0f44838af201927d135fb5e025d4819 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Mar 2026 03:20:37 +0000 Subject: [PATCH 2/2] fix(rust-guard): use correct JSON pointer key for search_repositories response Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/gh-aw-mcpg/sessions/5dec785d-967e-45f7-ab2c-878e153c5247 --- .../github-guard/rust-guard/src/labels/mod.rs | 69 +++++++++++++++++++ .../rust-guard/src/labels/response_paths.rs | 14 ++-- 2 files changed, 79 insertions(+), 4 deletions(-) diff --git a/guards/github-guard/rust-guard/src/labels/mod.rs b/guards/github-guard/rust-guard/src/labels/mod.rs index 9c782c657..8b9adc260 100644 --- a/guards/github-guard/rust-guard/src/labels/mod.rs +++ b/guards/github-guard/rust-guard/src/labels/mod.rs @@ -3710,4 +3710,73 @@ mod tests { integrity ); } + + /// search_repositories with `repositories` key (GraphQL-style) must use + /// `/repositories/{i}` paths, not `/items/{i}`. + #[test] + fn test_search_repositories_repositories_key_uses_correct_paths() { + let ctx = default_ctx(); + let tool_args = json!({}); + let response = json!({ + "totalCount": 2, + "repositories": [ + { + "full_name": "owner/public-repo", + "private": false + }, + { + "full_name": "owner/private-repo", + "private": true + } + ] + }); + + let result = label_response_paths("search_repositories", &tool_args, &response, &ctx) + .expect("search_repositories with repositories key should produce path labels"); + + assert_eq!(result.labeled_paths.len(), 2, "both items must be labeled"); + assert_eq!( + result.items_path, + Some("/repositories".to_string()), + "items_path must reflect the actual key used" + ); + assert_eq!( + result.labeled_paths[0].path, "/repositories/0", + "first item path must use /repositories/ prefix" + ); + assert_eq!( + result.labeled_paths[1].path, "/repositories/1", + "second item path must use /repositories/ prefix" + ); + } + + /// search_repositories with `items` key (REST format) must use `/items/{i}` paths. + #[test] + fn test_search_repositories_items_key_uses_correct_paths() { + let ctx = default_ctx(); + let tool_args = json!({}); + let response = json!({ + "total_count": 1, + "items": [ + { + "full_name": "owner/public-repo", + "private": false + } + ] + }); + + let result = label_response_paths("search_repositories", &tool_args, &response, &ctx) + .expect("search_repositories with items key should produce path labels"); + + assert_eq!(result.labeled_paths.len(), 1); + assert_eq!( + result.items_path, + Some("/items".to_string()), + "items_path must be /items for REST format" + ); + assert_eq!( + result.labeled_paths[0].path, "/items/0", + "item path must use /items/ prefix for REST format" + ); + } } diff --git a/guards/github-guard/rust-guard/src/labels/response_paths.rs b/guards/github-guard/rust-guard/src/labels/response_paths.rs index 7b5cc523b..0771cd44b 100644 --- a/guards/github-guard/rust-guard/src/labels/response_paths.rs +++ b/guards/github-guard/rust-guard/src/labels/response_paths.rs @@ -48,8 +48,14 @@ pub fn label_response_paths( match tool_name { // === Repository Search - label by private/public === "search_repositories" => { - let items_opt = actual_response.get("items").and_then(|v| v.as_array()) - .or_else(|| actual_response.get("repositories").and_then(|v| v.as_array())); + let (items_opt, items_key) = + if let Some(arr) = actual_response.get("items").and_then(|v| v.as_array()) { + (Some(arr), "items") + } else if let Some(arr) = actual_response.get("repositories").and_then(|v| v.as_array()) { + (Some(arr), "repositories") + } else { + (None, "items") + }; if let Some(items) = items_opt { // Empty search results are server metadata — let lib.rs fallback handle if items.is_empty() && is_search_result_wrapper(&actual_response) { @@ -79,7 +85,7 @@ pub fn label_response_paths( }; labeled_paths.push(PathLabelEntry { - path: format!("/items/{}", i), + path: format!("/{}/{}", items_key, i), labels: crate::ResourceLabels { description: format!("repo:{}", full_name), secrecy, @@ -95,7 +101,7 @@ pub fn label_response_paths( secrecy: vec![], integrity: none_integrity("", ctx), }), - items_path: Some("/items".to_string()), + items_path: Some(format!("/{}", items_key)), }); } }