From a6d2cb8c2453ed093cc7c59543642294527ba7c7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 18 Apr 2026 01:00:33 +0000 Subject: [PATCH 1/3] Initial plan From 5813225896f11b906d5ff2f764799d00aea19901 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 18 Apr 2026 01:04:14 +0000 Subject: [PATCH 2/3] Add set_issue_fields to guard write coverage and DIFC rules Agent-Logs-Url: https://github.com/github/gh-aw-mcpg/sessions/70c367d1-6251-4a1a-9af4-37658ef8f89e Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com> --- guards/github-guard/rust-guard/src/labels/mod.rs | 1 + guards/github-guard/rust-guard/src/labels/tool_rules.rs | 1 + guards/github-guard/rust-guard/src/tools.rs | 2 ++ 3 files changed, 4 insertions(+) diff --git a/guards/github-guard/rust-guard/src/labels/mod.rs b/guards/github-guard/rust-guard/src/labels/mod.rs index 804dcc13..de1a80b3 100644 --- a/guards/github-guard/rust-guard/src/labels/mod.rs +++ b/guards/github-guard/rust-guard/src/labels/mod.rs @@ -4753,6 +4753,7 @@ mod tests { "update_issue_state", "update_issue_title", "update_issue_type", + "set_issue_fields", ] { let (secrecy, integrity, _desc) = apply_tool_labels( tool, diff --git a/guards/github-guard/rust-guard/src/labels/tool_rules.rs b/guards/github-guard/rust-guard/src/labels/tool_rules.rs index 6ba98578..6298a7d8 100644 --- a/guards/github-guard/rust-guard/src/labels/tool_rules.rs +++ b/guards/github-guard/rust-guard/src/labels/tool_rules.rs @@ -543,6 +543,7 @@ pub fn apply_tool_labels( | "update_issue_state" | "update_issue_title" | "update_issue_type" + | "set_issue_fields" | "add_sub_issue" | "remove_sub_issue" | "reprioritize_sub_issue" diff --git a/guards/github-guard/rust-guard/src/tools.rs b/guards/github-guard/rust-guard/src/tools.rs index 375a6673..49f5e935 100644 --- a/guards/github-guard/rust-guard/src/tools.rs +++ b/guards/github-guard/rust-guard/src/tools.rs @@ -99,6 +99,7 @@ pub const READ_WRITE_OPERATIONS: &[&str] = &[ "update_issue_state", // PATCH — opens or closes an issue "update_issue_title", // PATCH — modifies issue title "update_issue_type", // PATCH — modifies issue type + "set_issue_fields", // GraphQL — sets org-level custom field values on an issue // Sub-issue management tools (alongside sub_issue_write composite) "add_sub_issue", // POST /repos/.../issues/{number}/sub_issues @@ -348,6 +349,7 @@ mod tests { "update_issue_state", "update_issue_title", "update_issue_type", + "set_issue_fields", ] { assert!( is_read_write_operation(op), From 20642f1eacdacb5918507711cd8f3033e834f3cc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 18 Apr 2026 01:24:31 +0000 Subject: [PATCH 3/3] Clarify set_issue_fields scope and isolate DIFC handling Agent-Logs-Url: https://github.com/github/gh-aw-mcpg/sessions/1aeeeede-3244-49df-a783-de344cbe4a72 Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com> --- .../github-guard/rust-guard/src/labels/mod.rs | 35 ++++++++++++++++++- .../rust-guard/src/labels/tool_rules.rs | 10 +++++- guards/github-guard/rust-guard/src/tools.rs | 20 +++++++++-- 3 files changed, 61 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 de1a80b3..61ee4ee6 100644 --- a/guards/github-guard/rust-guard/src/labels/mod.rs +++ b/guards/github-guard/rust-guard/src/labels/mod.rs @@ -4753,7 +4753,6 @@ mod tests { "update_issue_state", "update_issue_title", "update_issue_type", - "set_issue_fields", ] { let (secrecy, integrity, _desc) = apply_tool_labels( tool, @@ -4771,6 +4770,40 @@ mod tests { } } + #[test] + fn test_apply_tool_labels_set_issue_fields_writer_integrity() { + let ctx = default_ctx(); + let repo_id = "github/copilot"; + let tool_args = json!({ + "owner": "github", + "repo": "copilot", + "issue_number": 1, + "fields": [ + { + "field_id": "PVTSSF_example", + "text_value": "In progress" + } + ] + }); + + let (secrecy, integrity, _desc) = apply_tool_labels( + "set_issue_fields", + &tool_args, + repo_id, + vec![], + vec![], + String::new(), + &ctx, + ); + + assert_eq!(secrecy, vec![] as Vec, "set_issue_fields secrecy mismatch"); + assert_eq!( + integrity, + writer_integrity(repo_id, &ctx), + "set_issue_fields should have writer integrity" + ); + } + #[test] fn test_apply_tool_labels_granular_sub_issue_tools_writer_integrity() { let ctx = default_ctx(); diff --git a/guards/github-guard/rust-guard/src/labels/tool_rules.rs b/guards/github-guard/rust-guard/src/labels/tool_rules.rs index 6298a7d8..d0948e5b 100644 --- a/guards/github-guard/rust-guard/src/labels/tool_rules.rs +++ b/guards/github-guard/rust-guard/src/labels/tool_rules.rs @@ -533,6 +533,15 @@ pub fn apply_tool_labels( integrity = writer_integrity(repo_id, ctx); } + // === Issue custom fields mutation (repo-scoped write) === + "set_issue_fields" => { + // Field definitions are organization-level, but the mutation targets a specific + // issue in owner/repo and returns issue-scoped metadata. + // S = S(repo); I = writer + secrecy = apply_repo_visibility_secrecy(&owner, &repo, repo_id, secrecy, ctx); + integrity = writer_integrity(repo_id, ctx); + } + // === Granular repo-scoped write operations === // Covers granular issue PATCH tools, sub-issue management, granular PR PATCH tools, // and PR review tools. All follow: S = S(repo), I = writer. @@ -543,7 +552,6 @@ pub fn apply_tool_labels( | "update_issue_state" | "update_issue_title" | "update_issue_type" - | "set_issue_fields" | "add_sub_issue" | "remove_sub_issue" | "reprioritize_sub_issue" diff --git a/guards/github-guard/rust-guard/src/tools.rs b/guards/github-guard/rust-guard/src/tools.rs index 49f5e935..2bd68f54 100644 --- a/guards/github-guard/rust-guard/src/tools.rs +++ b/guards/github-guard/rust-guard/src/tools.rs @@ -99,7 +99,9 @@ pub const READ_WRITE_OPERATIONS: &[&str] = &[ "update_issue_state", // PATCH — opens or closes an issue "update_issue_title", // PATCH — modifies issue title "update_issue_type", // PATCH — modifies issue type - "set_issue_fields", // GraphQL — sets org-level custom field values on an issue + + // Issue custom field mutation (field definitions are org-level; target issue is repo-scoped) + "set_issue_fields", // GraphQL — sets custom field values on a specific repository issue // Sub-issue management tools (alongside sub_issue_write composite) "add_sub_issue", // POST /repos/.../issues/{number}/sub_issues @@ -349,7 +351,6 @@ mod tests { "update_issue_state", "update_issue_title", "update_issue_type", - "set_issue_fields", ] { assert!( is_read_write_operation(op), @@ -364,6 +365,21 @@ mod tests { } } + #[test] + fn test_set_issue_fields_is_read_write_operation() { + let op = "set_issue_fields"; + assert!( + is_read_write_operation(op), + "{} must be classified as a read-write operation", + op + ); + assert!( + !is_write_operation(op), + "{} should not be in WRITE_OPERATIONS (it is in READ_WRITE_OPERATIONS)", + op + ); + } + #[test] fn test_sub_issue_management_tools_are_read_write_operations() { for op in &["add_sub_issue", "remove_sub_issue", "reprioritize_sub_issue"] {