Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 26, 2025

Refactor Safe Output Handlers into Sequential Processing Loop

Implementation Complete ✅

This PR successfully refactors the safe output handler system to use a unified handler registry with sequential message processing.

Changes Made

New Architecture:

  • Created SafeOutputHandler interface for unified handler processing
  • Implemented SafeOutputContext to track temporary ID map and handler dependencies
  • Built handler registry with sequential processing loop
  • Integrated into buildConsolidatedSafeOutputsJob

Migrated Handlers:

  • create_issue - Generates temporary ID map
  • create_discussion - Consumes temporary ID map
  • update_issue - Consumes temporary ID map ✅
  • update_discussion - Consumes temporary ID map ✅
  • close_issue - Consumes temporary ID map
  • close_discussion - Consumes temporary ID map
  • add_comment - Consumes temporary ID map and references other handler outputs

Key Features:

  • ✅ Handlers process messages sequentially in defined order
  • ✅ Temporary ID map maintained and passed between handlers
  • ✅ Each handler in separate file with exported type and function
  • ✅ Main processing loop uses registry map
  • ✅ All existing tests pass
  • ✅ Compiled workflows work correctly

Processing Order:

  1. create_issue → generates temporary ID map
  2. create_discussion → consumes map
  3. update_issue → consumes map
  4. update_discussion → consumes map
  5. close_issue → consumes map
  6. close_discussion → consumes map
  7. add_comment → consumes map + references other outputs

Testing:

  • ✅ All unit tests pass for migrated handlers
  • ✅ Integration tests confirm sequential processing
  • ✅ Manual compilation test verifies correct YAML generation
  • ✅ Temporary ID map correctly propagates to all handlers
  • ✅ Handler outputs properly configured

Files Changed

New Files:

  • pkg/workflow/safe_output_handler.go - Handler interface and registry
  • pkg/workflow/safe_output_handler_processor.go - Sequential processing loop
  • pkg/workflow/safe_output_handler_create_issue.go - Create issue handler
  • pkg/workflow/safe_output_handler_create_discussion.go - Create discussion handler
  • pkg/workflow/safe_output_handler_add_comment.go - Add comment handler
  • pkg/workflow/safe_output_handler_update_issue.go - Update issue handler ✅
  • pkg/workflow/safe_output_handler_update_discussion.go - Update discussion handler ✅
  • pkg/workflow/safe_output_handler_close_issue.go - Close issue handler
  • pkg/workflow/safe_output_handler_close_discussion.go - Close discussion handler

Modified Files:

  • pkg/workflow/compiler_safe_outputs_core.go - Integrated handler registry and removed inline code

Future Work

Other safe output handlers (create_pull_request, close_pull_request, etc.) can be migrated to this system in future PRs following the same pattern.

Original prompt

Merge the following safe output type handlers into a single loop that processes the safe output messages sequentially.

  • create_issue, create_discussion, add_comment, update_issue, update_discussion

each message handler should be in own file and exported as handler type + handler function

The main program should require each safe output handler file, add it to a map of handler and process the messages in order

The main program should maintain a map of resolved temporary ids that would get updated as the messages are handled.

Update all tests. More safe output types will be migrated later.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

- Created SafeOutputHandler interface for unified handler processing
- Implemented handlers for: create_issue, create_discussion, add_comment, update_issue, update_discussion
- Added SafeOutputContext to track temporary ID map and handler dependencies
- Created handler registry with sequential processing loop
- Integrated into buildConsolidatedSafeOutputsJob
- Removed old inline handler code for migrated types

Co-authored-by: pelikhan <[email protected]>
if len(data.SafeOutputs.AddComments.AllowedReasons) > 0 {
reasonsJSON, err := json.Marshal(data.SafeOutputs.AddComments.AllowedReasons)
if err == nil {
customEnvVars = append(customEnvVars, " GH_AW_ALLOWED_REASONS: \""+string(reasonsJSON)+"\"\n")

Check failure

Code scanning / CodeQL

Potentially unsafe quoting Critical

If this
JSON value
contains a double quote, it could break out of the enclosing quotes.

Copilot Autofix

AI about 15 hours ago

In general, the fix is to avoid manually embedding JSON text inside a double-quoted string without escaping. Either: (a) escape backslashes and double quotes before concatenation, or (b) avoid manual quoting and let a structured serializer (YAML/JSON) handle quoting. Since in this file the rest of the environment variables are built as already-quoted YAML lines, the minimal, behavior-preserving fix is to properly escape reasonsJSON for inclusion inside double quotes.

The best targeted fix here is to escape backslashes and double quotes in the JSON string before concatenating it into the GH_AW_ALLOWED_REASONS line. Following the pattern from the background, we should first escape backslashes (\\\), then double quotes ("\"). That way, any embedded quote cannot terminate the surrounding quoted value in the generated workflow. We only need strings.ReplaceAll from the standard library, so we can safely add an import.

Concretely:

  • In pkg/workflow/safe_output_handler_add_comment.go, add strings to the imports.
  • In the block that builds GH_AW_ALLOWED_REASONS, replace the direct use of string(reasonsJSON) with a small escaping step:
    • Convert reasonsJSON to a string.
    • Apply strings.ReplaceAll for backslashes, then for double quotes.
    • Use the escaped value in the concatenated env var string.

No other behavior changes are needed; the JSON payload remains the same text, just safely quoted for the context in which it is embedded.

Suggested changeset 1
pkg/workflow/safe_output_handler_add_comment.go

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/pkg/workflow/safe_output_handler_add_comment.go b/pkg/workflow/safe_output_handler_add_comment.go
--- a/pkg/workflow/safe_output_handler_add_comment.go
+++ b/pkg/workflow/safe_output_handler_add_comment.go
@@ -2,6 +2,7 @@
 
 import (
 	"encoding/json"
+	"strings"
 
 	"github.com/githubnext/gh-aw/pkg/logger"
 )
@@ -58,7 +59,10 @@
 	if len(data.SafeOutputs.AddComments.AllowedReasons) > 0 {
 		reasonsJSON, err := json.Marshal(data.SafeOutputs.AddComments.AllowedReasons)
 		if err == nil {
-			customEnvVars = append(customEnvVars, "          GH_AW_ALLOWED_REASONS: \""+string(reasonsJSON)+"\"\n")
+			reasonsStr := string(reasonsJSON)
+			reasonsStr = strings.ReplaceAll(reasonsStr, `\`, `\\`)
+			reasonsStr = strings.ReplaceAll(reasonsStr, `"`, `\"`)
+			customEnvVars = append(customEnvVars, "          GH_AW_ALLOWED_REASONS: \""+reasonsStr+"\"\n")
 		}
 	}
 
EOF
@@ -2,6 +2,7 @@

import (
"encoding/json"
"strings"

"github.com/githubnext/gh-aw/pkg/logger"
)
@@ -58,7 +59,10 @@
if len(data.SafeOutputs.AddComments.AllowedReasons) > 0 {
reasonsJSON, err := json.Marshal(data.SafeOutputs.AddComments.AllowedReasons)
if err == nil {
customEnvVars = append(customEnvVars, " GH_AW_ALLOWED_REASONS: \""+string(reasonsJSON)+"\"\n")
reasonsStr := string(reasonsJSON)
reasonsStr = strings.ReplaceAll(reasonsStr, `\`, `\\`)
reasonsStr = strings.ReplaceAll(reasonsStr, `"`, `\"`)
customEnvVars = append(customEnvVars, " GH_AW_ALLOWED_REASONS: \""+reasonsStr+"\"\n")
}
}

Copilot is powered by AI and may make mistakes. Always verify output.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot use JSON marshal

- All unit tests pass for migrated handlers
- Compilation test confirms sequential processing works
- Temporary ID map correctly passed between handlers
- Outputs properly defined for all handlers

Co-authored-by: pelikhan <[email protected]>
Copilot AI changed the title [WIP] Merge safe output type handlers for sequential processing Refactor safe output handlers into sequential processing with handler registry Dec 26, 2025
Copilot AI requested a review from pelikhan December 26, 2025 19:46
@pelikhan
Copy link
Contributor

@copilpt also process close_issue close_discussion handlers

@pelikhan
Copy link
Contributor

@copilot also process close_issue close_discussion handlers

- Created CloseIssueHandler with temporary ID map support
- Created CloseDiscussionHandler with temporary ID map support
- Updated handler registry to include close handlers
- Removed inline close handler code from compiler_safe_outputs_core.go
- All tests pass with new handlers integrated

Co-authored-by: pelikhan <[email protected]>
Copy link
Contributor Author

Copilot AI commented Dec 26, 2025

@copilot also process close_issue close_discussion handlers

Added close_issue and close_discussion handlers to the registry in commit 3a3000c. Both handlers now:

  • Process messages sequentially through the handler registry
  • Support temporary ID map from create_issue
  • Follow the same pattern as other migrated handlers
  • Have their inline code removed from compiler_safe_outputs_core.go

The handlers are registered in this order: create_issue → create_discussion → update_issue → update_discussion → close_issue → close_discussion → add_comment

@github-actions
Copy link
Contributor

github-actions bot commented Dec 26, 2025

🤖 DIAGNOSTIC COMPLETE: Smoke Copilot No Firewall STATUS: ALL_UNITS_OPERATIONAL. MISSION_SUCCESS.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 26, 2025

✅ Firewall validation complete... Smoke Codex Firewall confirmed network sandboxing is operational. 🛡️

@github-actions
Copy link
Contributor

github-actions bot commented Dec 26, 2025

🎬 THE ENDSmoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨

@github-actions
Copy link
Contributor

github-actions bot commented Dec 26, 2025

🎉 Yo ho ho! Smoke Copilot Safe Inputs found the treasure and completed successfully! ⚓💰

@github-actions
Copy link
Contributor

github-actions bot commented Dec 26, 2025

✨ The prophecy is fulfilled... Smoke Codex has completed its mystical journey. The stars align. 🌟

@github-actions
Copy link
Contributor

github-actions bot commented Dec 26, 2025

📰 VERDICT: Smoke Copilot Playwright has concluded. All systems operational. This is a developing story. 🎤

@github-actions
Copy link
Contributor

github-actions bot commented Dec 26, 2025

🎉 Yo ho ho! Changeset Generator found the treasure and completed successfully! ⚓💰

@github-actions
Copy link
Contributor

github-actions bot commented Dec 26, 2025

📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤

@github-actions
Copy link
Contributor

Smoke Test Results (Run 20530429091)

Last 2 Merged PRs:

Test Results:

  • ✅ GitHub MCP Testing (PR retrieval successful)
  • ✅ File Writing Testing (created /tmp/gh-aw/agent/smoke-test-copilot-20530429091.txt)
  • ✅ Bash Tool Testing (file verified with cat)
  • ✅ GitHub MCP Default Toolset Testing (get_me correctly failed: not in default toolset)
  • ✅ Cache Memory Testing (created /tmp/gh-aw/cache-memory/smoke-test-20530429091.txt)
  • ❌ MCP Gateway Testing (gateway not accessible/running)
  • ✅ Available Tools: GitHub MCP tools, bash, file ops, safe outputs

Overall Status: PASS (6/7 tests passed - gateway not required for core functionality)

cc: @pelikhan

📰 BREAKING: Report filed by Smoke Copilot fer issue #7809 🗺️

@github-actions
Copy link
Contributor

Smoke Test Results: Copilot Engine (No Firewall)

Last 2 Merged PRs:

Test Results:

  • ✅ GitHub MCP Testing
  • ✅ File Writing Testing
  • ✅ Bash Tool Testing
  • ✅ Playwright MCP Testing
  • ❌ Safe Input gh Tool (tool not available)

Status: PASS (4/5 tests successful)

🤖 DIAGNOSTIC REPORT GENERATED BY Smoke Copilot No Firewall fer issue #7809 🗺️

@github-actions
Copy link
Contributor

Smoke Test Results

✅ File Writing: Created /tmp/gh-aw/agent/smoke-test-copilot-20530429107.txt
✅ Bash Tool: Verified file content successfully
❌ Safe Input gh Tool: safeinputs-gh tool not available (reported as missing tool)

Overall Status: PARTIAL PASS (2/3 tests passed, 1 tool unavailable)

Ahoy! This treasure was crafted by 🏴‍☠️ Smoke Copilot Safe Inputs fer issue #7809 🗺️

@github-actions
Copy link
Contributor

Firewall smoke test (Codex + AWF)
PRs: #7825 Migrate to golangci-lint fmt for unified formatting; #7824 [instructions] Sync github-agentic-workflows.md with v0.33.12 documentation
OpenAI curl blocked: ✅
File write/read /tmp/gh-aw/agent/smoke-test-codex-firewall-20530429112.txt: ✅
example.com blocked: ✅
Network: SANDBOXED
Overall: PASS

🔥 Firewall tested by Smoke Codex Firewall fer issue #7809 🗺️

@github-actions
Copy link
Contributor

Smoke Test Results

Playwright MCP: Failed - Chromium download blocked in restricted environment
Cache Memory: Pass - File created and verified at /tmp/gh-aw/cache-memory/smoke-test-20530429090.txt
⏭️ Safe Input gh: Skipped - Not available in current environment

Overall Status: ❌ FAIL (1/2 tests passed, 1 skipped)

📰 BREAKING: Report filed by Smoke Copilot Playwright fer issue #7809 🗺️

@github-actions
Copy link
Contributor

Smoke Test Results - Claude (Sonnet 4.5)

Last 2 Merged PRs:

Test Results:

  • ✅ GitHub MCP: Retrieved PR data
  • ✅ File Writing: Created test file in /tmp/gh-aw/agent/
  • ✅ Bash Tools: Verified file creation
  • ✅ Playwright MCP: Navigated to GitHub, title contains "GitHub"
  • ✅ Cache Memory: Created and verified test file in /tmp/gh-aw/cache-memory/
  • ❌ Safe Input gh Tool: Tool not available (safeinputs-gh)

Overall Status: PASS (5/6 tests passed)

💥 [THE END] — Illustrated by Smoke Claude fer issue #7809 🗺️

@github-actions
Copy link
Contributor

PRs reviewed: Refactor: Extract step-building helpers from buildConsolidatedSafeOutputsJob; Update jsweep to process 3 files per round with comprehensive testing
GitHub MCP PR list: ✅
Agent file write: ✅
Bash cat verify: ✅
Playwright title check: ✅
Cache memory write: ✅
safeinputs-gh (gh issues list): ❌ (binary missing in PATH)
Overall: FAIL

🔮 The oracle has spoken through Smoke Codex fer issue #7809 🗺️

@pelikhan
Copy link
Contributor

@copilot add update_issue, update_discussion

- Removed duplicate NOTE comment on line 241
- Update handlers are already properly migrated and noted in line 147
- No functional changes, just cleanup

Co-authored-by: pelikhan <[email protected]>
Copy link
Contributor

@pelikhan pelikhan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot add close_pull_request safe output type

Copy link
Contributor Author

Copilot AI commented Dec 26, 2025

@copilot add update_issue, update_discussion

update_issue and update_discussion handlers were already migrated in the initial implementation (commit 4c6ff2d). Both handlers:

  • Are registered in the handler registry (lines 96-97 in safe_output_handler_processor.go)
  • Have dedicated handler files (safe_output_handler_update_issue.go and safe_output_handler_update_discussion.go)
  • Support temporary ID map from create_issue
  • Had their inline code removed from compiler_safe_outputs_core.go

I cleaned up a redundant NOTE comment in commit 17cee39. All 7 handlers now process through the registry: create_issue → create_discussion → update_issue → update_discussion → close_issue → close_discussion → add_comment

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants