From 1b9428f9fa42d99c94827006ec7bce3c5e495caa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 23 Jun 2026 19:22:53 +0000 Subject: [PATCH 1/3] Configure pi workflow detection to use copilot engine Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/agent-persona-explorer.lock.yml | 2 +- .github/workflows/agent-persona-explorer.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/agent-persona-explorer.lock.yml b/.github/workflows/agent-persona-explorer.lock.yml index 66b3545bf73..994a3d0f74a 100644 --- a/.github/workflows/agent-persona-explorer.lock.yml +++ b/.github/workflows/agent-persona-explorer.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"1a46dd3511a30e5cf43fb8c4b12a64d7cf3aec846d6f4a28200fc631cf339efe","body_hash":"e5148ec80d0184e3ee540b5542256e8cc00380d23ef410088c2bedd34dd24c15","strict":true,"agent_id":"pi","agent_model":"copilot/gpt-5.4","engine_versions":{"pi":"0.79.9"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"978030e32d9dc5d7984d417c37d5a3ef5113616f66d917a4580695a25fd1fcc2","body_hash":"e5148ec80d0184e3ee540b5542256e8cc00380d23ef410088c2bedd34dd24c15","strict":true,"agent_id":"pi","agent_model":"copilot/gpt-5.4","detection_agent_id":"copilot","engine_versions":{"copilot":"1.0.63","pi":"0.79.9"}} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0","version":"v7.0.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"docker/build-push-action","sha":"f9f3042f7e2789586610d6e8b85c8f03e5195baf","version":"v7.2.0"},{"repo":"docker/setup-buildx-action","sha":"d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5","version":"v4.1.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.7","digest":"sha256:aae231e4635c8999d039c132f1602d3df850fe9b84a00aa2b5ac981179b5661c","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.7@sha256:aae231e4635c8999d039c132f1602d3df850fe9b84a00aa2b5ac981179b5661c"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.7","digest":"sha256:009caf2e3d88fa77b64e9a03a95a228fc58db0f1701c6d324b29ba5a3c7c79b6","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.7@sha256:009caf2e3d88fa77b64e9a03a95a228fc58db0f1701c6d324b29ba5a3c7c79b6"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.7","digest":"sha256:4757f198a3fa20f88bdbe70be7ae1a05f127d9c0a9e96a5d6460ef40c08fc83d","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.7@sha256:4757f198a3fa20f88bdbe70be7ae1a05f127d9c0a9e96a5d6460ef40c08fc83d"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.7","digest":"sha256:deb1d4e19de62d51cee0508057a596a19315c3423ada4d675cad136dc8037c96","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.7@sha256:deb1d4e19de62d51cee0508057a596a19315c3423ada4d675cad136dc8037c96"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.27","digest":"sha256:fe984bddde4ec05d756d9043edb0a32912e6b7b72f6a121b1082f29221421cc7","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.27@sha256:fe984bddde4ec05d756d9043edb0a32912e6b7b72f6a121b1082f29221421cc7"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b","pinned_image":"ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b"},{"image":"ghcr.io/github/github-mcp-server:v1.4.0","digest":"sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036","pinned_image":"ghcr.io/github/github-mcp-server:v1.4.0@sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036"}]} # This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # diff --git a/.github/workflows/agent-persona-explorer.md b/.github/workflows/agent-persona-explorer.md index af3972dd1e8..683095410e0 100644 --- a/.github/workflows/agent-persona-explorer.md +++ b/.github/workflows/agent-persona-explorer.md @@ -48,6 +48,8 @@ safe-outputs: max: 1 close-older-issues: true expires: false + threat-detection: + engine: copilot timeout-minutes: 180 imports: - shared/reporting.md From 670708e0a2a8b8bad759ce5e0a2c087a9559eb94 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 23 Jun 2026 20:25:31 +0000 Subject: [PATCH 2/3] Default threat detection to copilot for pi workflows Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/threat_detection.go | 34 +++++++------ .../threat_detection_isolation_test.go | 50 +++++++++++++++++++ pkg/workflow/threat_detection_test.go | 10 ++-- 3 files changed, 74 insertions(+), 20 deletions(-) diff --git a/pkg/workflow/threat_detection.go b/pkg/workflow/threat_detection.go index cdf94aef226..09f21950d12 100644 --- a/pkg/workflow/threat_detection.go +++ b/pkg/workflow/threat_detection.go @@ -890,34 +890,38 @@ func getThreatDetectionAdditionalAllowedDomains(data *WorkflowData) []string { // getThreatDetectionEngineID returns the effective engine ID for the detection job. // It mirrors threat-detection engine resolution: threat-detection.engine overrides main engine. func (c *Compiler) getThreatDetectionEngineID(data *WorkflowData) string { + var engineID string + if data.SafeOutputs != nil && data.SafeOutputs.ThreatDetection != nil && data.SafeOutputs.ThreatDetection.EngineConfig != nil && data.SafeOutputs.ThreatDetection.EngineConfig.ID != "" { - return data.SafeOutputs.ThreatDetection.EngineConfig.ID + engineID = data.SafeOutputs.ThreatDetection.EngineConfig.ID + } else { + mainEngineID := data.AI + if mainEngineID == "" && data.EngineConfig != nil && data.EngineConfig.ID != "" { + mainEngineID = data.EngineConfig.ID + } + engineID = mainEngineID } - mainEngineID := data.AI - if mainEngineID == "" && data.EngineConfig != nil && data.EngineConfig.ID != "" { - mainEngineID = data.EngineConfig.ID + if engineID == "" { + engineID = "claude" } - if mainEngineID != "" { - return mainEngineID + // Threat detection currently does not support the Pi engine backend. + // Normalize to Copilot so workflows with engine: pi still get a working detector. + if engineID == "pi" { + return "copilot" } - return "claude" + return engineID } // getExternalThreatDetectionEngineID returns the engine used by the external -// threat-detect path. Pi workflows currently fall back to the Copilot engine -// because threat-detect only knows how to launch the built-in gh-aw agentic -// engines, and Pi is not one of those supported detector backends yet. +// threat-detect path. Threat-detection engine resolution is centralized in +// getThreatDetectionEngineID, including Pi -> Copilot normalization. func (c *Compiler) getExternalThreatDetectionEngineID(data *WorkflowData) string { - engineID := c.getThreatDetectionEngineID(data) - if engineID == "pi" { - return "copilot" - } - return engineID + return c.getThreatDetectionEngineID(data) } func canReuseThreatDetectionEngineConfigForExternalDetector(data *WorkflowData, engineID string) bool { diff --git a/pkg/workflow/threat_detection_isolation_test.go b/pkg/workflow/threat_detection_isolation_test.go index 3ab6f10b4b5..851ff17b9fb 100644 --- a/pkg/workflow/threat_detection_isolation_test.go +++ b/pkg/workflow/threat_detection_isolation_test.go @@ -283,6 +283,56 @@ Test workflow` } } +func TestInlineDetectionUsesCopilotForPiWorkflows(t *testing.T) { + compiler := NewCompiler() + + tmpDir := testutil.TempDir(t, "test-inline-detector-pi-*") + workflowPath := filepath.Join(tmpDir, "test-inline-detector-pi.md") + + workflowContent := `--- +on: push +engine: + id: pi + model: copilot/gpt-5.4 +safe-outputs: + create-issue: +tools: + github: + mode: gh-proxy + cli-proxy: true +--- +Test workflow` + + if err := os.WriteFile(workflowPath, []byte(workflowContent), 0644); err != nil { + t.Fatalf("Failed to write workflow file: %v", err) + } + + if err := compiler.CompileWorkflow(workflowPath); err != nil { + t.Fatalf("Failed to compile workflow: %v", err) + } + + lockFile := stringutil.MarkdownToLockFile(workflowPath) + result, err := os.ReadFile(lockFile) + if err != nil { + t.Fatalf("Failed to read compiled workflow: %v", err) + } + + detectionSection := extractJobSection(string(result), "detection") + if detectionSection == "" { + t.Fatal("Detection job not found in compiled workflow") + } + + if !strings.Contains(detectionSection, "install_copilot_cli.sh") { + t.Error("Pi inline detection path must install the Copilot engine") + } + if strings.Contains(detectionSection, "@earendil-works/pi-coding-agent") { + t.Error("Pi inline detection path must not install the Pi engine") + } + if !strings.Contains(detectionSection, "COPILOT_GITHUB_TOKEN:") { + t.Error("Pi inline detection path must inherit Copilot auth env") + } +} + func TestExternalDetectorPathPreparesCodexConfig(t *testing.T) { compiler := NewCompiler() diff --git a/pkg/workflow/threat_detection_test.go b/pkg/workflow/threat_detection_test.go index 65350c804af..d1af1a6229c 100644 --- a/pkg/workflow/threat_detection_test.go +++ b/pkg/workflow/threat_detection_test.go @@ -2104,7 +2104,7 @@ func TestBuildDetectionEngineExecutionStepPropagatesHarnessScriptOverride(t *tes } } -func TestBuildDetectionEngineExecutionStepOmitsPiCooldownEnv(t *testing.T) { +func TestBuildDetectionEngineExecutionStepUsesCopilotForPi(t *testing.T) { compiler := NewCompiler() data := &WorkflowData{ @@ -2123,11 +2123,11 @@ func TestBuildDetectionEngineExecutionStepOmitsPiCooldownEnv(t *testing.T) { } rendered := strings.Join(steps, "") - if !strings.Contains(rendered, "Install Pi CLI") { - t.Fatal("expected detection steps to include the Pi install step") + if !strings.Contains(rendered, "Install GitHub Copilot CLI") { + t.Fatal("expected detection steps to include the Copilot install step for pi workflows") } - if strings.Contains(rendered, "NPM_CONFIG_MIN_RELEASE_AGE:") { - t.Fatalf("expected detection steps to omit npm cooldown env for Pi installs") + if strings.Contains(rendered, "Install Pi CLI") { + t.Fatal("expected detection steps to avoid Pi install step") } } From d0203fe6bc51389802925c24116735068124b08b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 23 Jun 2026 20:29:18 +0000 Subject: [PATCH 3/3] Refine pi threat-detection engine normalization Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/threat_detection.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pkg/workflow/threat_detection.go b/pkg/workflow/threat_detection.go index 09f21950d12..4fa23980af2 100644 --- a/pkg/workflow/threat_detection.go +++ b/pkg/workflow/threat_detection.go @@ -897,11 +897,10 @@ func (c *Compiler) getThreatDetectionEngineID(data *WorkflowData) string { data.SafeOutputs.ThreatDetection.EngineConfig.ID != "" { engineID = data.SafeOutputs.ThreatDetection.EngineConfig.ID } else { - mainEngineID := data.AI - if mainEngineID == "" && data.EngineConfig != nil && data.EngineConfig.ID != "" { - mainEngineID = data.EngineConfig.ID + engineID = data.AI + if engineID == "" && data.EngineConfig != nil && data.EngineConfig.ID != "" { + engineID = data.EngineConfig.ID } - engineID = mainEngineID } if engineID == "" {