@guilz-dev/sdlc-gh 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/.github/CODEOWNERS +5 -0
  2. package/.github/ISSUE_TEMPLATE/bug_report.yml +68 -0
  3. package/.github/ISSUE_TEMPLATE/config.yml +1 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.yml +39 -0
  5. package/.github/ISSUE_TEMPLATE/support.yml +56 -0
  6. package/.github/ISSUE_TEMPLATE/task.yml +89 -0
  7. package/.github/agents/implementer.agent.md +17 -0
  8. package/.github/agents/reviewer.agent.md +18 -0
  9. package/.github/agents/triager.agent.md +13 -0
  10. package/.github/aw/actions-lock.json +9 -0
  11. package/.github/copilot-instructions.md +35 -0
  12. package/.github/hooks/hooks.json +12 -0
  13. package/.github/instructions/core.instructions.md +11 -0
  14. package/.github/instructions/profiles/go.instructions.md +10 -0
  15. package/.github/instructions/profiles/php.instructions.md +11 -0
  16. package/.github/instructions/profiles/python.instructions.md +11 -0
  17. package/.github/instructions/profiles/ruby.instructions.md +11 -0
  18. package/.github/instructions/profiles/typescript.instructions.md +11 -0
  19. package/.github/labels.yml +55 -0
  20. package/.github/pull_request_template.md +33 -0
  21. package/.github/ruleset.example.json +33 -0
  22. package/.github/ruleset.harness-eval.example.json +29 -0
  23. package/.github/skills/quality-loop/SKILL.md +23 -0
  24. package/.github/workflows/agent-retry-orchestrator.yml +161 -0
  25. package/.github/workflows/copilot-setup-steps.yml +64 -0
  26. package/.github/workflows/eval-ci.yml +169 -0
  27. package/.github/workflows/eval-drift.yml +75 -0
  28. package/.github/workflows/gh-aw-dogfood-ci.yml +73 -0
  29. package/.github/workflows/harness-ci.yml +244 -0
  30. package/.github/workflows/harness-sync.yml +28 -0
  31. package/.github/workflows/l1-readiness-check.yml +45 -0
  32. package/.github/workflows/labels-sync.yml +24 -0
  33. package/.github/workflows/nightly-harness-review.lock.yml +1643 -0
  34. package/.github/workflows/nightly-harness-review.md +87 -0
  35. package/.github/workflows/nightly-harness-review.yml +63 -0
  36. package/.github/workflows/npm-publish.yml +49 -0
  37. package/.github/workflows/pr-context-comment.yml +138 -0
  38. package/.github/workflows/product-ci-go.yml +33 -0
  39. package/.github/workflows/product-ci-php.yml +39 -0
  40. package/.github/workflows/product-ci-python.yml +34 -0
  41. package/.github/workflows/product-ci-ruby.yml +35 -0
  42. package/.github/workflows/product-ci-ts.yml +37 -0
  43. package/.github/workflows/task-issue-label-sync.yml +50 -0
  44. package/.github/workflows/weekly-redteam.lock.yml +1571 -0
  45. package/.github/workflows/weekly-redteam.md +76 -0
  46. package/.github/zizmor.yml +11 -0
  47. package/AGENTS.md +54 -0
  48. package/LICENSE +21 -0
  49. package/README.md +366 -0
  50. package/config/stacks.json +55 -0
  51. package/docs/adoption.md +126 -0
  52. package/docs/arch.md +535 -0
  53. package/docs/auth-boundaries.md +16 -0
  54. package/docs/coding-agent-l1.md +152 -0
  55. package/docs/exceptions/README.md +25 -0
  56. package/docs/exceptions/TEMPLATE.md +8 -0
  57. package/docs/failure-taxonomy.md +23 -0
  58. package/docs/gh-aw-dogfood.md +109 -0
  59. package/docs/kpi-baseline.md +9 -0
  60. package/docs/nightly-harness-review.md +94 -0
  61. package/docs/operations.md +108 -0
  62. package/docs/publishing.md +79 -0
  63. package/docs/revert-playbook.md +44 -0
  64. package/docs/shared-config.md +30 -0
  65. package/docs/telemetry-artifacts.md +78 -0
  66. package/docs/telemetry-schema.md +60 -0
  67. package/evals/.score-baseline.json +6 -0
  68. package/evals/e2e-bench/README.md +28 -0
  69. package/evals/e2e-bench/manifest.json +16 -0
  70. package/evals/e2e-bench/tasks/e2e-001.yml +10 -0
  71. package/evals/e2e-bench/tasks/e2e-002.yml +11 -0
  72. package/evals/e2e-bench/tasks/e2e-003.yml +10 -0
  73. package/evals/e2e-bench/tasks/e2e-004.yml +14 -0
  74. package/evals/e2e-bench/tasks/e2e-005.yml +11 -0
  75. package/evals/e2e-bench/tasks/e2e-006.yml +10 -0
  76. package/evals/e2e-bench/tasks/e2e-007.yml +10 -0
  77. package/evals/e2e-bench/tasks/e2e-008.yml +10 -0
  78. package/evals/e2e-bench/tasks/e2e-009.yml +10 -0
  79. package/evals/trajectories/rubric.md +12 -0
  80. package/evals/trajectories/test_harness_conventions.py +271 -0
  81. package/infra/README.md +49 -0
  82. package/infra/langfuse/docker-compose.yml +25 -0
  83. package/infra/otel/collector-config.yml +24 -0
  84. package/infra/samples/gh-aw-dogfood-report.json +44 -0
  85. package/infra/samples/harness-review-routing-plan.json +19 -0
  86. package/infra/samples/harness-review-summary.json +61 -0
  87. package/infra/samples/telemetry-artifact.json +29 -0
  88. package/infra/samples/telemetry-payload.json +19 -0
  89. package/package.json +85 -0
  90. package/prompts/triager-classify.prompt.yml +10 -0
  91. package/sample/go/add.go +5 -0
  92. package/sample/go/add_test.go +9 -0
  93. package/sample/go/go.mod +3 -0
  94. package/sample/php/composer.json +26 -0
  95. package/sample/php/composer.lock +1881 -0
  96. package/sample/php/phpunit.xml +8 -0
  97. package/sample/php/src/Add.php +13 -0
  98. package/sample/php/tests/AddTest.php +16 -0
  99. package/sample/python/requirements-dev.txt +2 -0
  100. package/sample/python/src/__init__.py +0 -0
  101. package/sample/python/src/greet.py +3 -0
  102. package/sample/python/tests/conftest.py +4 -0
  103. package/sample/python/tests/test_greet.py +5 -0
  104. package/sample/ruby/.rubocop.yml +10 -0
  105. package/sample/ruby/Gemfile +6 -0
  106. package/sample/ruby/Gemfile.lock +58 -0
  107. package/sample/ruby/lib/add.rb +9 -0
  108. package/sample/ruby/spec/add_spec.rb +11 -0
  109. package/sample/ts/biome.json +6 -0
  110. package/sample/ts/package-lock.json +1763 -0
  111. package/sample/ts/package.json +15 -0
  112. package/sample/ts/src/add.ts +3 -0
  113. package/sample/ts/tests/add.test.ts +8 -0
  114. package/sample/ts/tsconfig.json +12 -0
  115. package/scripts/aggregate-harness-review.mjs +48 -0
  116. package/scripts/bootstrap-harness.sh +411 -0
  117. package/scripts/check-diff-size.mjs +46 -0
  118. package/scripts/check-e2e-manifest.mjs +35 -0
  119. package/scripts/check-eval-score-drift.mjs +31 -0
  120. package/scripts/check-gh-aw-dogfood-scope.mjs +51 -0
  121. package/scripts/check-issue-spec.mjs +215 -0
  122. package/scripts/check-l1-readiness.mjs +82 -0
  123. package/scripts/check-open-pr-limit.mjs +34 -0
  124. package/scripts/doctor.mjs +177 -0
  125. package/scripts/emit-gh-aw-dogfood-report.mjs +112 -0
  126. package/scripts/emit-telemetry-artifact.mjs +99 -0
  127. package/scripts/fetch-telemetry-artifacts.mjs +176 -0
  128. package/scripts/harness-drift-report.mjs +99 -0
  129. package/scripts/lib/bootstrap-copy.mjs +123 -0
  130. package/scripts/lib/ccsd-contract.mjs +212 -0
  131. package/scripts/lib/diff-size.mjs +103 -0
  132. package/scripts/lib/doctor-local.mjs +179 -0
  133. package/scripts/lib/e2e-manifest.mjs +76 -0
  134. package/scripts/lib/gh-aw-dogfood.mjs +293 -0
  135. package/scripts/lib/github-config.mjs +94 -0
  136. package/scripts/lib/harness-ci-fragments.mjs +98 -0
  137. package/scripts/lib/harness-review-routing.mjs +244 -0
  138. package/scripts/lib/harness-review.mjs +388 -0
  139. package/scripts/lib/issue-form-label-sync.mjs +56 -0
  140. package/scripts/lib/l1-readiness.mjs +258 -0
  141. package/scripts/lib/merge-harness-package.mjs +36 -0
  142. package/scripts/lib/npm-package.mjs +129 -0
  143. package/scripts/lib/setup-wizard.mjs +224 -0
  144. package/scripts/lib/stacks.mjs +138 -0
  145. package/scripts/lib/telemetry-artifact.mjs +253 -0
  146. package/scripts/lib/template-root.mjs +39 -0
  147. package/scripts/merge-harness-package.mjs +14 -0
  148. package/scripts/route-harness-review.mjs +168 -0
  149. package/scripts/run-e2e-bench.mjs +216 -0
  150. package/scripts/sdlc-gh-cli.mjs +91 -0
  151. package/scripts/select-eval-jobs.mjs +41 -0
  152. package/scripts/setup-github.mjs +242 -0
  153. package/scripts/setup-github.sh +4 -0
  154. package/scripts/setup-wizard.mjs +426 -0
  155. package/scripts/test-bootstrap-guidance-scenarios.mjs +94 -0
  156. package/scripts/test-diff-size-scenarios.mjs +88 -0
  157. package/scripts/test-doctor-scenarios.mjs +70 -0
  158. package/scripts/test-e2e-manifest-scenarios.mjs +65 -0
  159. package/scripts/test-gh-aw-dogfood-scenarios.mjs +74 -0
  160. package/scripts/test-harness-review-routing-scenarios.mjs +130 -0
  161. package/scripts/test-harness-review-scenarios.mjs +92 -0
  162. package/scripts/test-hooks-scenarios.mjs +44 -0
  163. package/scripts/test-issue-form-label-sync-scenarios.mjs +48 -0
  164. package/scripts/test-issue-spec-scenarios.mjs +258 -0
  165. package/scripts/test-l1-readiness-scenarios.mjs +204 -0
  166. package/scripts/test-merge-harness-package-scenarios.mjs +53 -0
  167. package/scripts/test-npm-package-scenarios.mjs +31 -0
  168. package/scripts/test-sdlc-gh-cli-scenarios.mjs +54 -0
  169. package/scripts/test-setup-github-scenarios.mjs +103 -0
  170. package/scripts/test-setup-wizard-scenarios.mjs +114 -0
  171. package/scripts/test-telemetry-artifact-scenarios.mjs +69 -0
  172. package/scripts/trim-harness-ci.mjs +18 -0
  173. package/scripts/validate-gh-aw-compile.mjs +64 -0
  174. package/scripts/validate-harness.mjs +199 -0
  175. package/scripts/validate-telemetry.mjs +21 -0
  176. package/scripts/verify-bootstrap-stacks.sh +192 -0
@@ -0,0 +1,1643 @@
1
+ # gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"5551f0d0995ea3dc03ab7c649c406f9b70a742ac723fc74db656c39a1d961692","body_hash":"8cb38b00bfa40df475cee2690b9d3865cb6e146e5ad480c3f8a5914aedb7ef05","compiler_version":"v0.81.6","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.65"}}
2
+ # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","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-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba6380cc6e5be5d21677bebe04d52fb48e3abec7","version":"v0.81.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.11","digest":"sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.11@sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11","digest":"sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11@sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.11","digest":"sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.11@sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.30","digest":"sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.30@sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be"},{"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"}]}
3
+ # This file was automatically generated by gh-aw (v0.81.6). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md
4
+ #
5
+ # ___ _ _
6
+ # / _ \ | | (_)
7
+ # | |_| | __ _ ___ _ __ | |_ _ ___
8
+ # | _ |/ _` |/ _ \ '_ \| __| |/ __|
9
+ # | | | | (_| | __/ | | | |_| | (__
10
+ # \_| |_/\__, |\___|_| |_|\__|_|\___|
11
+ # __/ |
12
+ # _ _ |___/
13
+ # | | | | / _| |
14
+ # | | | | ___ _ __ _ __| |_| | _____ ____
15
+ # | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___|
16
+ # \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \
17
+ # \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/
18
+ #
19
+ #
20
+ # To update this file, edit the corresponding .md file and run:
21
+ # gh aw compile
22
+ # Not all edits will cause changes to this file.
23
+ #
24
+ # For more information: https://github.github.com/gh-aw/introduction/overview/
25
+ #
26
+ # Nightly harness review — classify failures and propose harness revisions.
27
+ #
28
+ # Secrets used:
29
+ # - COPILOT_GITHUB_TOKEN
30
+ # - GH_AW_CI_TRIGGER_TOKEN
31
+ # - GH_AW_GITHUB_MCP_SERVER_TOKEN
32
+ # - GH_AW_GITHUB_TOKEN
33
+ # - GITHUB_TOKEN
34
+ #
35
+ # Custom actions used:
36
+ # - actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
37
+ # - actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
38
+ # - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
39
+ # - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
40
+ # - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
41
+ # - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 (source v9)
42
+ # - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
43
+ # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
44
+ # - github/gh-aw-actions/setup@ba6380cc6e5be5d21677bebe04d52fb48e3abec7 # v0.81.6
45
+ #
46
+ # Container images used:
47
+ # - ghcr.io/github/gh-aw-firewall/agent:0.27.11@sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7
48
+ # - ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11@sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d
49
+ # - ghcr.io/github/gh-aw-firewall/squid:0.27.11@sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d
50
+ # - ghcr.io/github/gh-aw-mcpg:v0.3.30@sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be
51
+ # - ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b
52
+ # - ghcr.io/github/github-mcp-server:v1.4.0@sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036
53
+
54
+ name: "Nightly harness review"
55
+ on:
56
+ schedule:
57
+ - cron: "0 2 * * *"
58
+ workflow_dispatch:
59
+ inputs:
60
+ aw_context:
61
+ default: ""
62
+ description: "Agent caller context (used internally by Agentic Workflows)."
63
+ required: false
64
+ type: string
65
+
66
+ permissions: {}
67
+
68
+ concurrency:
69
+ group: "gh-aw-${{ github.workflow }}"
70
+
71
+ run-name: "Nightly harness review"
72
+
73
+ jobs:
74
+ activation:
75
+ runs-on: ubuntu-slim
76
+ permissions:
77
+ actions: read
78
+ contents: read
79
+ env:
80
+ GH_AW_MAX_DAILY_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS || '5000' }}
81
+ GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
82
+ outputs:
83
+ comment_id: ""
84
+ comment_repo: ""
85
+ daily_ai_credits_exceeded: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_ai_credits_exceeded == 'true' }}
86
+ daily_ai_credits_threshold: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_ai_credits_threshold || '' }}
87
+ daily_ai_credits_total_effective_tokens: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_ai_credits_total_effective_tokens || '' }}
88
+ engine_id: ${{ steps.generate_aw_info.outputs.engine_id }}
89
+ lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }}
90
+ model: ${{ steps.generate_aw_info.outputs.model }}
91
+ secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }}
92
+ setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }}
93
+ setup-span-id: ${{ steps.setup.outputs.span-id }}
94
+ setup-trace-id: ${{ steps.setup.outputs.trace-id }}
95
+ stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }}
96
+ steps:
97
+ - name: Setup Scripts
98
+ id: setup
99
+ uses: github/gh-aw-actions/setup@ba6380cc6e5be5d21677bebe04d52fb48e3abec7 # v0.81.6
100
+ with:
101
+ destination: ${{ runner.temp }}/gh-aw/actions
102
+ job-name: ${{ github.job }}
103
+ safe-output-artifact-client: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }}
104
+ env:
105
+ GH_AW_SETUP_WORKFLOW_NAME: "Nightly harness review"
106
+ GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/nightly-harness-review.lock.yml@${{ github.ref }}
107
+ GH_AW_INFO_VERSION: "1.0.65"
108
+ GH_AW_INFO_AWF_VERSION: "v0.27.11"
109
+ GH_AW_INFO_ENGINE_ID: "copilot"
110
+ - name: Generate agentic run info
111
+ id: generate_aw_info
112
+ env:
113
+ GH_AW_INFO_ENGINE_ID: "copilot"
114
+ GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI"
115
+ GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'claude-sonnet-4.6' }}
116
+ GH_AW_INFO_VERSION: "1.0.65"
117
+ GH_AW_INFO_AGENT_VERSION: "1.0.65"
118
+ GH_AW_INFO_CLI_VERSION: "v0.81.6"
119
+ GH_AW_INFO_WORKFLOW_NAME: "Nightly harness review"
120
+ GH_AW_INFO_EXPERIMENTAL: "false"
121
+ GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true"
122
+ GH_AW_INFO_STAGED: "false"
123
+ GH_AW_INFO_ALLOWED_DOMAINS: '["defaults"]'
124
+ GH_AW_INFO_FIREWALL_ENABLED: "true"
125
+ GH_AW_INFO_AWF_VERSION: "v0.27.11"
126
+ GH_AW_INFO_AWMG_VERSION: ""
127
+ GH_AW_INFO_FIREWALL_TYPE: "squid"
128
+ GH_AW_COMPILED_STRICT: "true"
129
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
130
+ with:
131
+ script: |
132
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
133
+ setupGlobals(core, github, context, exec, io, getOctokit);
134
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs');
135
+ await main(core, context);
136
+ - name: Restore daily AIC usage cache
137
+ id: restore-daily-aic-cache
138
+ if: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }}
139
+ continue-on-error: true
140
+ uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
141
+ with:
142
+ key: agentic-workflow-usage-nightlyharnessreview-${{ github.run_id }}
143
+ restore-keys: agentic-workflow-usage-nightlyharnessreview-
144
+ path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl
145
+ - name: Restore daily AIC usage cache (artifact fallback)
146
+ id: restore-daily-aic-cache-fallback
147
+ if: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }}
148
+ continue-on-error: true
149
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
150
+ env:
151
+ GH_AW_RESTORE_DAILY_AIC_CACHE_HIT: ${{ steps.restore-daily-aic-cache.outputs.cache-hit }}
152
+ GH_AW_RESTORE_DAILY_AIC_CACHE_MATCHED_KEY: ${{ steps.restore-daily-aic-cache.outputs.cache-matched-key }}
153
+ with:
154
+ github-token: ${{ secrets.GITHUB_TOKEN }}
155
+ script: |
156
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
157
+ setupGlobals(core, github, context, exec, io, getOctokit);
158
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/restore_aic_usage_cache_fallback.cjs');
159
+ await main();
160
+ - name: Check daily workflow token guardrail
161
+ id: daily-effective-workflow-guardrail
162
+ if: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }}
163
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
164
+ env:
165
+ GH_AW_WORKFLOW_NAME: "Nightly harness review"
166
+ GH_AW_WORKFLOW_ID: "nightly-harness-review"
167
+ GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
168
+ GH_AW_WORKFLOW_DISPATCH_AW_CONTEXT: ${{ github.event.inputs.aw_context || '' }}
169
+ GH_AW_HAS_SLASH_COMMAND: "false"
170
+ GH_AW_HAS_LABEL_COMMAND: "false"
171
+ GH_AW_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
172
+ GH_AW_MAX_DAILY_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS || '5000' }}
173
+ with:
174
+ github-token: ${{ secrets.GITHUB_TOKEN }}
175
+ script: |
176
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
177
+ setupGlobals(core, github, context, exec, io, getOctokit);
178
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/check_daily_aic_workflow_guardrail.cjs');
179
+ await main();
180
+ - name: Validate COPILOT_GITHUB_TOKEN secret
181
+ id: validate-secret
182
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default
183
+ env:
184
+ COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
185
+ - name: Checkout .github and .agents folders
186
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
187
+ with:
188
+ persist-credentials: false
189
+ sparse-checkout: |
190
+ .github
191
+ .agents
192
+ .antigravity
193
+ .claude
194
+ .codex
195
+ .crush
196
+ .gemini
197
+ .opencode
198
+ .pi
199
+ sparse-checkout-cone-mode: true
200
+ fetch-depth: 1
201
+ - name: Save agent config folders for base branch restoration
202
+ env:
203
+ GH_AW_AGENT_FOLDERS: ".agents .antigravity .claude .codex .crush .gemini .github .opencode .pi"
204
+ GH_AW_AGENT_FILES: ".crush.json AGENTS.md ANTIGRAVITY.md CLAUDE.md GEMINI.md PI.md opencode.jsonc"
205
+ # poutine:ignore untrusted_checkout_exec
206
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh"
207
+ - name: Check workflow lock file
208
+ id: check-lock-file
209
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
210
+ env:
211
+ GH_AW_WORKFLOW_FILE: "nightly-harness-review.lock.yml"
212
+ GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}"
213
+ with:
214
+ script: |
215
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
216
+ setupGlobals(core, github, context, exec, io, getOctokit);
217
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs');
218
+ await main();
219
+ - name: Check compile-agentic version
220
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
221
+ env:
222
+ GH_AW_COMPILED_VERSION: "v0.81.6"
223
+ with:
224
+ script: |
225
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
226
+ setupGlobals(core, github, context, exec, io, getOctokit);
227
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/check_version_updates.cjs');
228
+ await main();
229
+ - name: Log runtime features
230
+ if: ${{ contains(toJSON(vars), '"GH_AW_RUNTIME_FEATURES":') }}
231
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/log_runtime_features_summary.sh"
232
+ - name: Create prompt with built-in context
233
+ env:
234
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
235
+ GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl
236
+ GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
237
+ GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
238
+ GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
239
+ GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }}
240
+ GH_AW_GITHUB_ACTOR: ${{ github.actor }}
241
+ GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
242
+ GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
243
+ GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
244
+ # poutine:ignore untrusted_checkout_exec
245
+ run: |
246
+ bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
247
+ {
248
+ cat << 'GH_AW_PROMPT_9f6e8f0c3d1ca4fe_EOF'
249
+ <system>
250
+ GH_AW_PROMPT_9f6e8f0c3d1ca4fe_EOF
251
+ cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md"
252
+ cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md"
253
+ cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md"
254
+ cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
255
+ cat << 'GH_AW_PROMPT_9f6e8f0c3d1ca4fe_EOF'
256
+ <safe-output-tools>
257
+ Tools: create_issue(max:3), create_pull_request, missing_tool, missing_data, noop
258
+ GH_AW_PROMPT_9f6e8f0c3d1ca4fe_EOF
259
+ cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md"
260
+ cat << 'GH_AW_PROMPT_9f6e8f0c3d1ca4fe_EOF'
261
+ </safe-output-tools>
262
+ GH_AW_PROMPT_9f6e8f0c3d1ca4fe_EOF
263
+ cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"
264
+ cat << 'GH_AW_PROMPT_9f6e8f0c3d1ca4fe_EOF'
265
+ <github-context>
266
+ The following GitHub context information is available for this workflow:
267
+ {{#if github.actor}}
268
+ - **actor**: __GH_AW_GITHUB_ACTOR__
269
+ {{/if}}
270
+ {{#if github.repository}}
271
+ - **repository**: __GH_AW_GITHUB_REPOSITORY__
272
+ {{/if}}
273
+ {{#if github.workspace}}
274
+ - **workspace**: __GH_AW_GITHUB_WORKSPACE__
275
+ {{/if}}
276
+ {{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}
277
+ - **issue-number**: #__GH_AW_EXPR_802A9F6A__
278
+ {{/if}}
279
+ {{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}
280
+ - **discussion-number**: #__GH_AW_EXPR_1A3A194A__
281
+ {{/if}}
282
+ {{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}
283
+ - **pull-request-number**: #__GH_AW_EXPR_463A214A__
284
+ {{/if}}
285
+ {{#if github.event.comment.id || github.aw.context.comment_id}}
286
+ - **comment-id**: __GH_AW_EXPR_FF1D34CE__
287
+ {{/if}}
288
+ {{#if github.run_id}}
289
+ - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__
290
+ {{/if}}
291
+ </github-context>
292
+
293
+ GH_AW_PROMPT_9f6e8f0c3d1ca4fe_EOF
294
+ cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
295
+ cat << 'GH_AW_PROMPT_9f6e8f0c3d1ca4fe_EOF'
296
+ </system>
297
+ {{#runtime-import .github/workflows/nightly-harness-review.md}}
298
+ GH_AW_PROMPT_9f6e8f0c3d1ca4fe_EOF
299
+ } > "$GH_AW_PROMPT"
300
+ - name: Interpolate variables and render templates
301
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
302
+ env:
303
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
304
+ GH_AW_ENGINE_ID: "copilot"
305
+ with:
306
+ script: |
307
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
308
+ setupGlobals(core, github, context, exec, io, getOctokit);
309
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs');
310
+ await main();
311
+ - name: Substitute placeholders
312
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
313
+ env:
314
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
315
+ GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
316
+ GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
317
+ GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
318
+ GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }}
319
+ GH_AW_GITHUB_ACTOR: ${{ github.actor }}
320
+ GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
321
+ GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
322
+ GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
323
+ GH_AW_MCP_CLI_SERVERS_LIST: '- `safeoutputs` — run `safeoutputs --help` to see available tools'
324
+ with:
325
+ script: |
326
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
327
+ setupGlobals(core, github, context, exec, io, getOctokit);
328
+
329
+ const substitutePlaceholders = require('${{ runner.temp }}/gh-aw/actions/substitute_placeholders.cjs');
330
+
331
+ // Call the substitution function
332
+ return await substitutePlaceholders({
333
+ file: process.env.GH_AW_PROMPT,
334
+ substitutions: {
335
+ GH_AW_EXPR_1A3A194A: process.env.GH_AW_EXPR_1A3A194A,
336
+ GH_AW_EXPR_463A214A: process.env.GH_AW_EXPR_463A214A,
337
+ GH_AW_EXPR_802A9F6A: process.env.GH_AW_EXPR_802A9F6A,
338
+ GH_AW_EXPR_FF1D34CE: process.env.GH_AW_EXPR_FF1D34CE,
339
+ GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR,
340
+ GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY,
341
+ GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID,
342
+ GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE,
343
+ GH_AW_MCP_CLI_SERVERS_LIST: process.env.GH_AW_MCP_CLI_SERVERS_LIST
344
+ }
345
+ });
346
+ - name: Validate prompt placeholders
347
+ env:
348
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
349
+ # poutine:ignore untrusted_checkout_exec
350
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh"
351
+ - name: Print prompt
352
+ env:
353
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
354
+ # poutine:ignore untrusted_checkout_exec
355
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh"
356
+ - name: Upload activation artifact
357
+ if: success()
358
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
359
+ with:
360
+ name: activation
361
+ include-hidden-files: true
362
+ path: |
363
+ /tmp/gh-aw/aw_info.json
364
+ /tmp/gh-aw/models.json
365
+ /tmp/gh-aw/aw-prompts/prompt.txt
366
+ /tmp/gh-aw/aw-prompts/prompt-template.txt
367
+ /tmp/gh-aw/aw-prompts/prompt-import-tree.json
368
+ /tmp/gh-aw/github_rate_limits.jsonl
369
+ /tmp/gh-aw/base
370
+ /tmp/gh-aw/.github/agents
371
+ /tmp/gh-aw/.github/skills
372
+ if-no-files-found: ignore
373
+ retention-days: 1
374
+
375
+ agent:
376
+ needs: activation
377
+ if: needs.activation.outputs.daily_ai_credits_exceeded != 'true'
378
+ runs-on: ubuntu-latest
379
+ permissions:
380
+ contents: read
381
+ issues: read
382
+ concurrency:
383
+ group: "gh-aw-copilot-${{ github.workflow }}"
384
+ queue: max
385
+ env:
386
+ DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
387
+ GH_AW_ASSETS_ALLOWED_EXTS: ""
388
+ GH_AW_ASSETS_BRANCH: ""
389
+ GH_AW_ASSETS_MAX_SIZE_KB: 0
390
+ GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs
391
+ GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
392
+ GH_AW_WORKFLOW_ID_SANITIZED: nightlyharnessreview
393
+ outputs:
394
+ agentic_engine_timeout: ${{ steps.detect-agent-errors.outputs.agentic_engine_timeout || 'false' }}
395
+ ai_credits_rate_limit_error: ${{ steps.parse-mcp-gateway.outputs.ai_credits_rate_limit_error || 'false' }}
396
+ aic: ${{ steps.parse-mcp-gateway.outputs.aic }}
397
+ ambient_context: ${{ steps.parse-mcp-gateway.outputs.ambient_context }}
398
+ checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }}
399
+ effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }}
400
+ has_patch: ${{ steps.collect_output.outputs.has_patch }}
401
+ inference_access_error: ${{ steps.detect-agent-errors.outputs.inference_access_error || 'false' }}
402
+ mcp_policy_error: ${{ steps.detect-agent-errors.outputs.mcp_policy_error || 'false' }}
403
+ model: ${{ needs.activation.outputs.model }}
404
+ model_not_supported_error: ${{ steps.detect-agent-errors.outputs.model_not_supported_error || 'false' }}
405
+ output: ${{ steps.collect_output.outputs.output }}
406
+ output_types: ${{ steps.collect_output.outputs.output_types }}
407
+ setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }}
408
+ setup-span-id: ${{ steps.setup.outputs.span-id }}
409
+ setup-trace-id: ${{ steps.setup.outputs.trace-id }}
410
+ unknown_model_ai_credits: ${{ steps.parse-mcp-gateway.outputs.unknown_model_ai_credits || 'false' }}
411
+ steps:
412
+ - name: Setup Scripts
413
+ id: setup
414
+ uses: github/gh-aw-actions/setup@ba6380cc6e5be5d21677bebe04d52fb48e3abec7 # v0.81.6
415
+ with:
416
+ destination: ${{ runner.temp }}/gh-aw/actions
417
+ job-name: ${{ github.job }}
418
+ trace-id: ${{ needs.activation.outputs.setup-trace-id }}
419
+ parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
420
+ env:
421
+ GH_AW_SETUP_WORKFLOW_NAME: "Nightly harness review"
422
+ GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/nightly-harness-review.lock.yml@${{ github.ref }}
423
+ GH_AW_INFO_VERSION: "1.0.65"
424
+ GH_AW_INFO_AWF_VERSION: "v0.27.11"
425
+ GH_AW_INFO_ENGINE_ID: "copilot"
426
+ - name: Set runtime paths
427
+ id: set-runtime-paths
428
+ run: |
429
+ {
430
+ echo "GH_AW_SAFE_OUTPUTS=${RUNNER_TEMP}/gh-aw/safeoutputs/outputs.jsonl"
431
+ echo "GH_AW_SAFE_OUTPUTS_CONFIG_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/config.json"
432
+ echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json"
433
+ } >> "$GITHUB_OUTPUT"
434
+ - name: Checkout repository
435
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
436
+ with:
437
+ persist-credentials: false
438
+ - name: Create gh-aw temp directory
439
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/create_gh_aw_tmp_dir.sh"
440
+ - name: Configure gh CLI for GitHub Enterprise
441
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh"
442
+ env:
443
+ GH_TOKEN: ${{ github.token }}
444
+ - name: Configure Git credentials
445
+ env:
446
+ GITHUB_REPOSITORY: ${{ github.repository }}
447
+ GITHUB_SERVER_URL: ${{ github.server_url }}
448
+ GITHUB_TOKEN: ${{ github.token }}
449
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_git_credentials.sh"
450
+ - name: Checkout PR branch
451
+ id: checkout-pr
452
+ if: |
453
+ github.event.pull_request || github.event.issue.pull_request || github.event_name == 'workflow_dispatch' && fromJSON(github.event.inputs.aw_context || '{}').item_type == 'pull_request'
454
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
455
+ env:
456
+ GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
457
+ with:
458
+ github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
459
+ script: |
460
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
461
+ setupGlobals(core, github, context, exec, io, getOctokit);
462
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs');
463
+ await main();
464
+ - name: Install GitHub Copilot CLI
465
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.65
466
+ env:
467
+ GH_HOST: github.com
468
+ - name: Install AWF binary
469
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.27.11
470
+ - name: Determine automatic lockdown mode for GitHub MCP Server
471
+ id: determine-automatic-lockdown
472
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 (source v9)
473
+ env:
474
+ GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }}
475
+ GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }}
476
+ with:
477
+ script: |
478
+ const determineAutomaticLockdown = require('${{ runner.temp }}/gh-aw/actions/determine_automatic_lockdown.cjs');
479
+ await determineAutomaticLockdown(github, context, core);
480
+ - name: Download activation artifact
481
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
482
+ with:
483
+ name: activation
484
+ path: /tmp/gh-aw
485
+ - name: Restore agent config folders from base branch
486
+ if: steps.checkout-pr.outcome == 'success'
487
+ env:
488
+ GH_AW_AGENT_FOLDERS: ".agents .antigravity .claude .codex .crush .gemini .github .opencode .pi"
489
+ GH_AW_AGENT_FILES: ".crush.json AGENTS.md ANTIGRAVITY.md CLAUDE.md GEMINI.md PI.md opencode.jsonc"
490
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_base_github_folders.sh"
491
+ - name: Restore inline sub-agents from activation artifact
492
+ env:
493
+ GH_AW_SUB_AGENT_DIR: ".github/agents"
494
+ GH_AW_SUB_AGENT_EXT: ".agent.md"
495
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_sub_agents.sh"
496
+ - name: Restore inline skills from activation artifact
497
+ env:
498
+ GH_AW_SKILL_DIR: ".github/skills"
499
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh"
500
+ - name: Download container images
501
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.11@sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11@sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d ghcr.io/github/gh-aw-firewall/squid:0.27.11@sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d ghcr.io/github/gh-aw-mcpg:v0.3.30@sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b ghcr.io/github/github-mcp-server:v1.4.0@sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036
502
+ - name: Generate Safe Outputs Config
503
+ run: |
504
+ mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs"
505
+ mkdir -p /tmp/gh-aw/safeoutputs
506
+ mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs
507
+ cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_4cd4e076200c1d8d_EOF'
508
+ {"create_issue":{"max":3},"create_pull_request":{"max":1,"max_patch_files":100,"max_patch_size":4096,"protect_top_level_dot_folders":true,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS","DESIGN.md","README.md","CONTRIBUTING.md","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","AGENTS.md","CLAUDE.md","GEMINI.md"],"protected_files_policy":"request_review"},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}}
509
+ GH_AW_SAFE_OUTPUTS_CONFIG_4cd4e076200c1d8d_EOF
510
+ - name: Generate Safe Outputs Tools
511
+ env:
512
+ GH_AW_TOOLS_META_JSON: |
513
+ {
514
+ "description_suffixes": {
515
+ "create_issue": " CONSTRAINTS: Maximum 3 issue(s) can be created.",
516
+ "create_pull_request": " CONSTRAINTS: Maximum 1 pull request(s) can be created."
517
+ },
518
+ "repo_params": {},
519
+ "dynamic_tools": []
520
+ }
521
+ GH_AW_VALIDATION_JSON: |
522
+ {
523
+ "create_issue": {
524
+ "defaultMax": 1,
525
+ "fields": {
526
+ "body": {
527
+ "required": true,
528
+ "type": "string",
529
+ "sanitize": true,
530
+ "maxLength": 65000,
531
+ "minLength": 20
532
+ },
533
+ "fields": {
534
+ "type": "array"
535
+ },
536
+ "labels": {
537
+ "type": "array",
538
+ "itemType": "string",
539
+ "itemSanitize": true,
540
+ "itemMaxLength": 128
541
+ },
542
+ "parent": {
543
+ "issueOrPRNumber": true
544
+ },
545
+ "repo": {
546
+ "type": "string",
547
+ "maxLength": 256
548
+ },
549
+ "temporary_id": {
550
+ "type": "string"
551
+ },
552
+ "title": {
553
+ "required": true,
554
+ "type": "string",
555
+ "sanitize": true,
556
+ "maxLength": 128
557
+ }
558
+ }
559
+ },
560
+ "create_pull_request": {
561
+ "defaultMax": 1,
562
+ "fields": {
563
+ "base": {
564
+ "type": "string",
565
+ "sanitize": true,
566
+ "maxLength": 128
567
+ },
568
+ "body": {
569
+ "required": true,
570
+ "type": "string",
571
+ "sanitize": true,
572
+ "maxLength": 65000
573
+ },
574
+ "branch": {
575
+ "required": true,
576
+ "type": "string",
577
+ "sanitize": true,
578
+ "maxLength": 256
579
+ },
580
+ "draft": {
581
+ "type": "boolean"
582
+ },
583
+ "labels": {
584
+ "type": "array",
585
+ "itemType": "string",
586
+ "itemSanitize": true,
587
+ "itemMaxLength": 128
588
+ },
589
+ "repo": {
590
+ "type": "string",
591
+ "maxLength": 256
592
+ },
593
+ "title": {
594
+ "required": true,
595
+ "type": "string",
596
+ "sanitize": true,
597
+ "maxLength": 128
598
+ }
599
+ }
600
+ },
601
+ "missing_data": {
602
+ "defaultMax": 20,
603
+ "fields": {
604
+ "alternatives": {
605
+ "type": "string",
606
+ "sanitize": true,
607
+ "maxLength": 256
608
+ },
609
+ "context": {
610
+ "type": "string",
611
+ "sanitize": true,
612
+ "maxLength": 256
613
+ },
614
+ "data_type": {
615
+ "type": "string",
616
+ "sanitize": true,
617
+ "maxLength": 128
618
+ },
619
+ "reason": {
620
+ "type": "string",
621
+ "sanitize": true,
622
+ "maxLength": 256
623
+ }
624
+ }
625
+ },
626
+ "missing_tool": {
627
+ "defaultMax": 20,
628
+ "fields": {
629
+ "alternatives": {
630
+ "type": "string",
631
+ "sanitize": true,
632
+ "maxLength": 512
633
+ },
634
+ "reason": {
635
+ "required": true,
636
+ "type": "string",
637
+ "sanitize": true,
638
+ "maxLength": 256
639
+ },
640
+ "tool": {
641
+ "type": "string",
642
+ "sanitize": true,
643
+ "maxLength": 128
644
+ }
645
+ }
646
+ },
647
+ "noop": {
648
+ "defaultMax": 1,
649
+ "fields": {
650
+ "message": {
651
+ "required": true,
652
+ "type": "string",
653
+ "sanitize": true,
654
+ "maxLength": 65000
655
+ }
656
+ }
657
+ },
658
+ "report_incomplete": {
659
+ "defaultMax": 5,
660
+ "fields": {
661
+ "details": {
662
+ "type": "string",
663
+ "sanitize": true,
664
+ "maxLength": 65000
665
+ },
666
+ "reason": {
667
+ "required": true,
668
+ "type": "string",
669
+ "sanitize": true,
670
+ "maxLength": 1024
671
+ }
672
+ }
673
+ }
674
+ }
675
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
676
+ with:
677
+ script: |
678
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
679
+ setupGlobals(core, github, context, exec, io, getOctokit);
680
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_safe_outputs_tools.cjs');
681
+ await main();
682
+ - name: Start MCP Gateway
683
+ id: start-mcp-gateway
684
+ env:
685
+ GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST: ${{ vars.GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST || 'true' }}
686
+ GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
687
+ GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS_CONFIG_PATH }}
688
+ GH_AW_SAFE_OUTPUTS_TOOLS_PATH: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS_TOOLS_PATH }}
689
+ GITHUB_MCP_GUARD_MIN_INTEGRITY: ${{ steps.determine-automatic-lockdown.outputs.min_integrity }}
690
+ GITHUB_MCP_GUARD_REPOS: ${{ steps.determine-automatic-lockdown.outputs.repos }}
691
+ GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
692
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
693
+ run: |
694
+ set -eo pipefail
695
+ mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-config"
696
+
697
+ # Export gateway environment variables for MCP config and gateway script
698
+ export MCP_GATEWAY_PORT="8080"
699
+ export MCP_GATEWAY_DOMAIN="host.docker.internal"
700
+ export MCP_GATEWAY_HOST_DOMAIN="localhost"
701
+ MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=')
702
+ echo "::add-mask::${MCP_GATEWAY_API_KEY}"
703
+ export MCP_GATEWAY_API_KEY
704
+ export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads"
705
+ mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}"
706
+ export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288"
707
+ export DEBUG="*"
708
+
709
+ export GH_AW_ENGINE="copilot"
710
+ MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0')
711
+ MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0')
712
+ case "${DOCKER_HOST:-}" in
713
+ unix://* ) DOCKER_SOCK_PATH="${DOCKER_HOST#unix://}" ;;
714
+ /* ) DOCKER_SOCK_PATH="$DOCKER_HOST" ;;
715
+ * ) DOCKER_SOCK_PATH=/var/run/docker.sock ;;
716
+ esac
717
+ DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0')
718
+ export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --name awmg-mcpg --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e RUNNER_TEMP -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw -v '"${RUNNER_TEMP}"'/gh-aw/safeoutputs:'"${RUNNER_TEMP}"'/gh-aw/safeoutputs:rw ghcr.io/github/gh-aw-mcpg:v0.3.30'
719
+
720
+ mkdir -p "$HOME/.copilot"
721
+ GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node)
722
+ cat << GH_AW_MCP_CONFIG_f014db59cae17bc3_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
723
+ {
724
+ "mcpServers": {
725
+ "github": {
726
+ "type": "stdio",
727
+ "container": "ghcr.io/github/github-mcp-server:v1.4.0",
728
+ "env": {
729
+ "GITHUB_HOST": "${GITHUB_SERVER_URL}",
730
+ "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_MCP_SERVER_TOKEN}",
731
+ "GITHUB_READ_ONLY": "1",
732
+ "GITHUB_TOOLSETS": "context,repos,issues,pull_requests"
733
+ },
734
+ "guard-policies": {
735
+ "allow-only": {
736
+ "min-integrity": "$GITHUB_MCP_GUARD_MIN_INTEGRITY",
737
+ "repos": "$GITHUB_MCP_GUARD_REPOS"
738
+ }
739
+ }
740
+ },
741
+ "safeoutputs": {
742
+ "type": "stdio",
743
+ "container": "ghcr.io/github/gh-aw-node",
744
+ "mounts": ["\${GITHUB_WORKSPACE}:\${GITHUB_WORKSPACE}:rw", "${RUNNER_TEMP}/gh-aw/safeoutputs:${RUNNER_TEMP}/gh-aw/safeoutputs:rw", "/tmp/gh-aw:/tmp/gh-aw:rw"],
745
+ "args": ["-w", "\${GITHUB_WORKSPACE}"],
746
+ "entrypoint": "sh",
747
+ "entrypointArgs": ["-c", "sh ${RUNNER_TEMP}/gh-aw/safeoutputs/start_safe_outputs_mcp.sh"],
748
+ "env": {
749
+ "DEBUG": "*",
750
+ "DEFAULT_BRANCH": "\${DEFAULT_BRANCH}",
751
+ "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}",
752
+ "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}",
753
+ "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}",
754
+ "GH_AW_MCP_LOG_DIR": "\${GH_AW_MCP_LOG_DIR}",
755
+ "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}",
756
+ "GH_AW_SAFE_OUTPUTS_CONFIG_PATH": "\${GH_AW_SAFE_OUTPUTS_CONFIG_PATH}",
757
+ "GH_AW_SAFE_OUTPUTS_TOOLS_PATH": "\${GH_AW_SAFE_OUTPUTS_TOOLS_PATH}",
758
+ "GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST": "\${GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST}",
759
+ "GITHUB_REPOSITORY": "\${GITHUB_REPOSITORY}",
760
+ "GITHUB_TOKEN": "\${GITHUB_TOKEN}",
761
+ "GITHUB_WORKSPACE": "\${GITHUB_WORKSPACE}",
762
+ "RUNNER_TEMP": "\${RUNNER_TEMP}"
763
+ },
764
+ "guard-policies": {
765
+ "write-sink": {
766
+ "accept": [
767
+ "*"
768
+ ]
769
+ }
770
+ }
771
+ }
772
+ },
773
+ "gateway": {
774
+ "port": $MCP_GATEWAY_PORT,
775
+ "domain": "${MCP_GATEWAY_DOMAIN}",
776
+ "apiKey": "${MCP_GATEWAY_API_KEY}",
777
+ "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}"
778
+ }
779
+ }
780
+ GH_AW_MCP_CONFIG_f014db59cae17bc3_EOF
781
+ - name: Mount MCP servers as CLIs
782
+ id: mount-mcp-clis
783
+ continue-on-error: true
784
+ env:
785
+ MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }}
786
+ MCP_GATEWAY_DOMAIN: ${{ steps.start-mcp-gateway.outputs.gateway-domain }}
787
+ MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }}
788
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
789
+ with:
790
+ script: |
791
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
792
+ setupGlobals(core, github, context, exec, io);
793
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/mount_mcp_as_cli.cjs');
794
+ await main();
795
+ - name: Clean credentials
796
+ continue-on-error: true
797
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh"
798
+ - name: Audit pre-agent workspace
799
+ id: pre_agent_audit
800
+ continue-on-error: true
801
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh"
802
+ - name: Execute GitHub Copilot CLI
803
+ id: agentic_execution
804
+ # Copilot CLI tool arguments (sorted):
805
+ timeout-minutes: 20
806
+ run: |
807
+ set -o pipefail
808
+ printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt
809
+ trap 'rm -f "$HOME/.copilot/settings.json"' EXIT
810
+ mkdir -p "$HOME/.copilot"
811
+ printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > "$HOME/.copilot/settings.json"
812
+ export XDG_CONFIG_HOME="$HOME"
813
+ export GH_AW_MCP_CONFIG="$HOME/.copilot/mcp-config.json"
814
+ touch /tmp/gh-aw/agent-step-summary.md
815
+ GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true)
816
+ export GH_AW_NODE_BIN
817
+ export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK"
818
+ (umask 177 && touch /tmp/gh-aw/agent-stdio.log)
819
+ GH_AW_MAX_AI_CREDITS="${GH_AW_MAX_AI_CREDITS:-1000}"
820
+ printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.11/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"azure.archive.ubuntu.com\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"github.com\",\"host.docker.internal\",\"json-schema.org\",\"json.schemastore.org\",\"keyserver.ubuntu.com\",\"ocsp.digicert.com\",\"ocsp.geotrust.com\",\"ocsp.globalsign.com\",\"ocsp.identrust.com\",\"ocsp.sectigo.com\",\"ocsp.ssl.com\",\"ocsp.thawte.com\",\"ocsp.usertrust.com\",\"ocsp.verisign.com\",\"packagecloud.io\",\"packages.cloud.google.com\",\"packages.microsoft.com\",\"ppa.launchpad.net\",\"raw.githubusercontent.com\",\"registry.npmjs.org\",\"s.symcb.com\",\"s.symcd.com\",\"security.ubuntu.com\",\"telemetry.enterprise.githubcopilot.com\",\"ts-crl.ws.symantec.com\",\"ts-ocsp.ws.symantec.com\",\"www.googleapis.com\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5,\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.5\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"gpt-5\":[\"copilot/gpt-5*\",\"openai/gpt-5*\"],\"gpt-5-codex\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\"],\"gpt-5-mini\":[\"copilot/gpt-5*mini*\",\"openai/gpt-5*mini*\"],\"gpt-5-nano\":[\"copilot/gpt-5*nano*\",\"openai/gpt-5*nano*\"],\"gpt-5-pro\":[\"copilot/gpt-5*pro*\",\"openai/gpt-5*pro*\"],\"gpt-5.1\":[\"copilot/gpt-5.1*\",\"openai/gpt-5.1*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"image-generation\":[\"copilot/gpt-image*\",\"openai/gpt-image*\",\"openai/chatgpt-image*\",\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"google/imagen*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.11,squid=sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d,agent=sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7,api-proxy=sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json"
821
+ cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
822
+ export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json"
823
+ GH_AW_DOCKER_HOST=""
824
+ if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
825
+ GH_AW_DOCKER_HOST="${DOCKER_HOST}"
826
+ fi
827
+ GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS=""
828
+ if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
829
+ GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="--docker-host-path-prefix /tmp/gh-aw"
830
+ GH_AW_CHROOT_BINARIES_SOURCE_PATH=/tmp/gh-aw GH_AW_CHROOT_IDENTITY_HOME=/tmp/gh-aw/home node "${RUNNER_TEMP}/gh-aw/actions/patch_awf_chroot_config.cjs"
831
+ fi
832
+ GH_AW_TOOL_CACHE_MOUNT=""
833
+ GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"
834
+ if [ -d "$GH_AW_TOOL_CACHE" ]; then
835
+ if [[ "$GH_AW_TOOL_CACHE" != /opt/* ]]; then
836
+ GH_AW_TOOL_CACHE_MOUNT="$GH_AW_TOOL_CACHE:$GH_AW_TOOL_CACHE:ro"
837
+ fi
838
+ fi
839
+ # shellcheck disable=SC1003,SC2086
840
+ sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} ${GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS} --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \
841
+ -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; export PATH="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log
842
+ env:
843
+ AWF_REFLECT_ENABLED: 1
844
+ COPILOT_AGENT_RUNNER_TYPE: STANDALONE
845
+ COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode
846
+ COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
847
+ COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'claude-sonnet-4.6' }}
848
+ GH_AW_LLM_PROVIDER: github
849
+ GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}
850
+ GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
851
+ GH_AW_PHASE: agent
852
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
853
+ GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
854
+ GH_AW_TIMEOUT_MINUTES: 20
855
+ GH_AW_VERSION: v0.81.6
856
+ GITHUB_API_URL: ${{ github.api_url }}
857
+ GITHUB_AW: true
858
+ GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows
859
+ GITHUB_HEAD_REF: ${{ github.head_ref }}
860
+ GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
861
+ GITHUB_REF_NAME: ${{ github.ref_name }}
862
+ GITHUB_SERVER_URL: ${{ github.server_url }}
863
+ GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md
864
+ GITHUB_WORKSPACE: ${{ github.workspace }}
865
+ GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
866
+ GIT_AUTHOR_NAME: github-actions[bot]
867
+ GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
868
+ GIT_COMMITTER_NAME: github-actions[bot]
869
+ RUNNER_TEMP: ${{ runner.temp }}
870
+ TRACEPARENT: ${{ env.GITHUB_AW_OTEL_TRACE_ID != '' && env.GITHUB_AW_OTEL_PARENT_SPAN_ID != '' && format('00-{0}-{1}-01', env.GITHUB_AW_OTEL_TRACE_ID, env.GITHUB_AW_OTEL_PARENT_SPAN_ID) || '' }}
871
+ - name: Detect agent errors
872
+ if: always()
873
+ id: detect-agent-errors
874
+ continue-on-error: true
875
+ run: node "${RUNNER_TEMP}/gh-aw/actions/detect_agent_errors.cjs"
876
+ - name: Configure Git credentials
877
+ env:
878
+ GITHUB_REPOSITORY: ${{ github.repository }}
879
+ GITHUB_SERVER_URL: ${{ github.server_url }}
880
+ GITHUB_TOKEN: ${{ github.token }}
881
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_git_credentials.sh"
882
+ - name: Copy Copilot session state files to logs
883
+ if: always()
884
+ continue-on-error: true
885
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh"
886
+ - name: Stop MCP Gateway
887
+ if: always()
888
+ continue-on-error: true
889
+ env:
890
+ MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }}
891
+ MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }}
892
+ GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }}
893
+ run: |
894
+ bash "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID"
895
+ - name: Redact secrets in logs
896
+ if: always()
897
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
898
+ with:
899
+ script: |
900
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
901
+ setupGlobals(core, github, context, exec, io, getOctokit);
902
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs');
903
+ await main();
904
+ env:
905
+ GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN'
906
+ SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
907
+ SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }}
908
+ SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }}
909
+ SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
910
+ - name: Append agent step summary
911
+ if: always()
912
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/append_agent_step_summary.sh"
913
+ - name: Copy Safe Outputs
914
+ if: always()
915
+ env:
916
+ GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
917
+ run: |
918
+ mkdir -p /tmp/gh-aw
919
+ cp "$GH_AW_SAFE_OUTPUTS" /tmp/gh-aw/safeoutputs.jsonl 2>/dev/null || true
920
+ - name: Ingest agent output
921
+ id: collect_output
922
+ if: always()
923
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
924
+ env:
925
+ GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
926
+ GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com"
927
+ GITHUB_SERVER_URL: ${{ github.server_url }}
928
+ GITHUB_API_URL: ${{ github.api_url }}
929
+ with:
930
+ script: |
931
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
932
+ setupGlobals(core, github, context, exec, io, getOctokit);
933
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/collect_ndjson_output.cjs');
934
+ await main();
935
+ - name: Parse agent logs for step summary
936
+ if: always()
937
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
938
+ env:
939
+ GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/
940
+ with:
941
+ script: |
942
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
943
+ setupGlobals(core, github, context, exec, io, getOctokit);
944
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs');
945
+ await main();
946
+ - name: Parse MCP Gateway logs for step summary
947
+ if: always()
948
+ id: parse-mcp-gateway
949
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
950
+ with:
951
+ script: |
952
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
953
+ setupGlobals(core, github, context, exec, io, getOctokit);
954
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs');
955
+ await main();
956
+ - name: Print firewall logs
957
+ if: always()
958
+ continue-on-error: true
959
+ env:
960
+ AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs
961
+ run: |
962
+ # Fix permissions on firewall logs/audit dirs so they can be uploaded as artifacts
963
+ # AWF runs with sudo, creating files owned by root
964
+ sudo chmod -R a+rX /tmp/gh-aw/sandbox/firewall 2>/dev/null || true
965
+ # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step)
966
+ if command -v awf &> /dev/null; then
967
+ awf logs summary | tee -a "$GITHUB_STEP_SUMMARY"
968
+ else
969
+ echo 'AWF binary not installed, skipping firewall log summary'
970
+ fi
971
+ - name: Parse token usage for step summary
972
+ if: always()
973
+ continue-on-error: true
974
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
975
+ with:
976
+ script: |
977
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
978
+ setupGlobals(core, github, context, exec, io, getOctokit);
979
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_token_usage.cjs');
980
+ await main();
981
+ - name: Print AWF reflect summary
982
+ if: always()
983
+ continue-on-error: true
984
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
985
+ with:
986
+ script: |
987
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
988
+ setupGlobals(core, github, context, exec, io, getOctokit);
989
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/awf_reflect_summary.cjs');
990
+ await main();
991
+ - name: Write agent output placeholder if missing
992
+ if: always()
993
+ run: |
994
+ if [ ! -f /tmp/gh-aw/agent_output.json ]; then
995
+ echo '{"items":[]}' > /tmp/gh-aw/agent_output.json
996
+ fi
997
+ - name: Upload agent artifacts
998
+ if: always()
999
+ continue-on-error: true
1000
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
1001
+ with:
1002
+ name: agent
1003
+ path: |
1004
+ /tmp/gh-aw/aw-prompts/prompt.txt
1005
+ /tmp/gh-aw/sandbox/agent/logs/
1006
+ /tmp/gh-aw/redacted-urls.log
1007
+ /tmp/gh-aw/mcp-logs/
1008
+ /tmp/gh-aw/agent_usage.json
1009
+ /tmp/gh-aw/agent-stdio.log
1010
+ /tmp/gh-aw/pre-agent-audit.txt
1011
+ /tmp/gh-aw/agent/
1012
+ /tmp/gh-aw/github_rate_limits.jsonl
1013
+ /tmp/gh-aw/safeoutputs.jsonl
1014
+ /tmp/gh-aw/agent_output.json
1015
+ /tmp/gh-aw/aw-*.patch
1016
+ /tmp/gh-aw/aw-*.bundle
1017
+ /tmp/gh-aw/awf-config.json
1018
+ /tmp/gh-aw/sandbox/firewall/logs/
1019
+ /tmp/gh-aw/sandbox/firewall/audit/
1020
+ /tmp/gh-aw/sandbox/firewall/awf-reflect.json
1021
+ if-no-files-found: ignore
1022
+
1023
+ conclusion:
1024
+ needs:
1025
+ - activation
1026
+ - agent
1027
+ - detection
1028
+ - safe_outputs
1029
+ if: >
1030
+ always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' ||
1031
+ needs.activation.outputs.stale_lock_file_failed == 'true' || needs.activation.outputs.daily_ai_credits_exceeded == 'true')
1032
+ runs-on: ubuntu-slim
1033
+ permissions:
1034
+ contents: write
1035
+ issues: write
1036
+ pull-requests: write
1037
+ concurrency:
1038
+ group: "gh-aw-conclusion-nightly-harness-review"
1039
+ cancel-in-progress: false
1040
+ queue: max
1041
+ env:
1042
+ GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
1043
+ outputs:
1044
+ incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }}
1045
+ noop_message: ${{ steps.noop.outputs.noop_message }}
1046
+ tools_reported: ${{ steps.missing_tool.outputs.tools_reported }}
1047
+ total_count: ${{ steps.missing_tool.outputs.total_count }}
1048
+ steps:
1049
+ - name: Setup Scripts
1050
+ id: setup
1051
+ uses: github/gh-aw-actions/setup@ba6380cc6e5be5d21677bebe04d52fb48e3abec7 # v0.81.6
1052
+ with:
1053
+ destination: ${{ runner.temp }}/gh-aw/actions
1054
+ job-name: ${{ github.job }}
1055
+ trace-id: ${{ needs.activation.outputs.setup-trace-id }}
1056
+ parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
1057
+ env:
1058
+ GH_AW_SETUP_WORKFLOW_NAME: "Nightly harness review"
1059
+ GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/nightly-harness-review.lock.yml@${{ github.ref }}
1060
+ GH_AW_INFO_VERSION: "1.0.65"
1061
+ GH_AW_INFO_AWF_VERSION: "v0.27.11"
1062
+ GH_AW_INFO_ENGINE_ID: "copilot"
1063
+ - name: Download agent output artifact
1064
+ id: download-agent-output
1065
+ continue-on-error: true
1066
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
1067
+ with:
1068
+ name: agent
1069
+ path: /tmp/gh-aw/
1070
+ - name: Setup agent output environment variable
1071
+ id: setup-agent-output-env
1072
+ if: steps.download-agent-output.outcome == 'success'
1073
+ run: |
1074
+ mkdir -p /tmp/gh-aw/
1075
+ find "/tmp/gh-aw/" -type f -print
1076
+ echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
1077
+ - name: Collect usage artifact files
1078
+ if: always()
1079
+ continue-on-error: true
1080
+ run: |
1081
+ mkdir -p /tmp/gh-aw/usage/agent /tmp/gh-aw/usage/detection
1082
+ echo "Usage artifact source file status:"
1083
+ for file in /tmp/gh-aw/aw_info.json /tmp/gh-aw/aw-info.jsonl /tmp/gh-aw/agent_usage.json /tmp/gh-aw/agent_usage.jsonl /tmp/gh-aw/detection_usage.jsonl /tmp/gh-aw/github_rate_limits.jsonl /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl; do
1084
+ [ -f "$file" ] && echo "FOUND: $file" || echo "MISSING: $file"
1085
+ done
1086
+ [ -f /tmp/gh-aw/aw_info.json ] && cp /tmp/gh-aw/aw_info.json /tmp/gh-aw/usage/aw_info.json || true
1087
+ [ -f /tmp/gh-aw/aw-info.jsonl ] && cp /tmp/gh-aw/aw-info.jsonl /tmp/gh-aw/usage/aw-info.jsonl || true
1088
+ [ -f /tmp/gh-aw/agent_usage.json ] && cp /tmp/gh-aw/agent_usage.json /tmp/gh-aw/usage/agent_usage.json || true
1089
+ [ -f /tmp/gh-aw/agent_usage.jsonl ] && cp /tmp/gh-aw/agent_usage.jsonl /tmp/gh-aw/usage/agent_usage.jsonl || true
1090
+ [ -f /tmp/gh-aw/detection_usage.jsonl ] && cp /tmp/gh-aw/detection_usage.jsonl /tmp/gh-aw/usage/detection_usage.jsonl || true
1091
+ [ -f /tmp/gh-aw/github_rate_limits.jsonl ] && cp /tmp/gh-aw/github_rate_limits.jsonl /tmp/gh-aw/usage/github_rate_limits.jsonl || true
1092
+ [ -s /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true
1093
+ [ -s /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true
1094
+ [ -s /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true
1095
+ [ -s /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true
1096
+ [ -s /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true
1097
+ [ -s /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true
1098
+ [ -f /tmp/gh-aw/usage/agent/token_usage.jsonl ] || : > /tmp/gh-aw/usage/agent/token_usage.jsonl
1099
+ [ -f /tmp/gh-aw/usage/detection/token_usage.jsonl ] || : > /tmp/gh-aw/usage/detection/token_usage.jsonl
1100
+ mkdir -p /tmp/gh-aw/usage/activity
1101
+ node ${{ runner.temp }}/gh-aw/actions/generate_usage_activity_summary.cjs
1102
+ find /tmp/gh-aw/usage -type f -print | sort
1103
+ - name: Upload usage artifact
1104
+ if: always()
1105
+ continue-on-error: true
1106
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
1107
+ with:
1108
+ name: usage
1109
+ path: |
1110
+ /tmp/gh-aw/usage/aw_info.json
1111
+ /tmp/gh-aw/usage/aw-info.jsonl
1112
+ /tmp/gh-aw/usage/agent_usage.json
1113
+ /tmp/gh-aw/usage/agent_usage.jsonl
1114
+ /tmp/gh-aw/usage/detection_usage.jsonl
1115
+ /tmp/gh-aw/usage/github_rate_limits.jsonl
1116
+ /tmp/gh-aw/usage/agent/token_usage.jsonl
1117
+ /tmp/gh-aw/usage/detection/token_usage.jsonl
1118
+ /tmp/gh-aw/usage/activity/summary.json
1119
+ if-no-files-found: ignore
1120
+ - name: Restore daily AIC usage cache
1121
+ id: restore-daily-aic-cache-conclusion
1122
+ if: always()
1123
+ continue-on-error: true
1124
+ uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
1125
+ with:
1126
+ key: agentic-workflow-usage-nightlyharnessreview-${{ github.run_id }}
1127
+ restore-keys: agentic-workflow-usage-nightlyharnessreview-
1128
+ path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl
1129
+ - name: Write daily AIC usage cache entry
1130
+ id: write-daily-aic-cache
1131
+ if: always()
1132
+ continue-on-error: true
1133
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1134
+ with:
1135
+ github-token: ${{ github.token }}
1136
+ script: |
1137
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
1138
+ setupGlobals(core, github, context);
1139
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/write_daily_aic_usage_cache.cjs');
1140
+ await main();
1141
+ - name: Save daily AIC usage cache
1142
+ id: save-daily-aic-cache
1143
+ if: always()
1144
+ continue-on-error: true
1145
+ uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
1146
+ with:
1147
+ key: agentic-workflow-usage-nightlyharnessreview-${{ github.run_id }}
1148
+ path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl
1149
+ - name: Upload daily AIC usage cache artifact
1150
+ id: upload-daily-aic-cache
1151
+ if: always()
1152
+ continue-on-error: true
1153
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
1154
+ with:
1155
+ name: aic-usage-cache
1156
+ path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl
1157
+ if-no-files-found: ignore
1158
+ retention-days: 7
1159
+ - name: Process no-op messages
1160
+ id: noop
1161
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1162
+ env:
1163
+ GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
1164
+ GH_AW_NOOP_MAX: "1"
1165
+ GH_AW_WORKFLOW_NAME: "Nightly harness review"
1166
+ GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/nightly-harness-review.md"
1167
+ GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
1168
+ GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
1169
+ GH_AW_NOOP_REPORT_AS_ISSUE: "true"
1170
+ GH_AW_AIC: ${{ needs.agent.outputs.aic }}
1171
+ GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }}
1172
+ GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }}
1173
+ GH_AW_WORKFLOW_ID: "nightly-harness-review"
1174
+ with:
1175
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1176
+ script: |
1177
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
1178
+ setupGlobals(core, github, context, exec, io, getOctokit);
1179
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_noop_message.cjs');
1180
+ await main();
1181
+ - name: Log detection run
1182
+ id: detection_runs
1183
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1184
+ env:
1185
+ GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
1186
+ GH_AW_WORKFLOW_NAME: "Nightly harness review"
1187
+ GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/nightly-harness-review.md"
1188
+ GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
1189
+ GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }}
1190
+ GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }}
1191
+ with:
1192
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1193
+ script: |
1194
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
1195
+ setupGlobals(core, github, context, exec, io, getOctokit);
1196
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_detection_runs.cjs');
1197
+ await main();
1198
+ - name: Record missing tool
1199
+ id: missing_tool
1200
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1201
+ env:
1202
+ GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
1203
+ GH_AW_MISSING_TOOL_CREATE_ISSUE: "true"
1204
+ GH_AW_WORKFLOW_NAME: "Nightly harness review"
1205
+ GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/nightly-harness-review.md"
1206
+ with:
1207
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1208
+ script: |
1209
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
1210
+ setupGlobals(core, github, context, exec, io, getOctokit);
1211
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/missing_tool.cjs');
1212
+ await main();
1213
+ - name: Record incomplete
1214
+ id: report_incomplete
1215
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1216
+ env:
1217
+ GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
1218
+ GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true"
1219
+ GH_AW_WORKFLOW_NAME: "Nightly harness review"
1220
+ GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/nightly-harness-review.md"
1221
+ with:
1222
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1223
+ script: |
1224
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
1225
+ setupGlobals(core, github, context, exec, io, getOctokit);
1226
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/report_incomplete_handler.cjs');
1227
+ await main();
1228
+ - name: Handle agent failure
1229
+ id: handle_agent_failure
1230
+ if: always()
1231
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1232
+ env:
1233
+ GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
1234
+ GH_AW_WORKFLOW_NAME: "Nightly harness review"
1235
+ GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/nightly-harness-review.md"
1236
+ GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
1237
+ GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
1238
+ GH_AW_WORKFLOW_ID: "nightly-harness-review"
1239
+ GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168"
1240
+ GH_AW_ENGINE_ID: "copilot"
1241
+ GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }}
1242
+ GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }}
1243
+ GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens || '' }}
1244
+ GH_AW_AI_CREDITS_RATE_LIMIT_ERROR: ${{ needs.agent.outputs.ai_credits_rate_limit_error || 'false' }}
1245
+ GH_AW_UNKNOWN_MODEL_AI_CREDITS: ${{ needs.agent.outputs.unknown_model_ai_credits || 'false' }}
1246
+ GH_AW_AIC: ${{ needs.agent.outputs.aic }}
1247
+ GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }}
1248
+ GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}
1249
+ GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }}
1250
+ GH_AW_MCP_POLICY_ERROR: ${{ needs.agent.outputs.mcp_policy_error }}
1251
+ GH_AW_AGENTIC_ENGINE_TIMEOUT: ${{ needs.agent.outputs.agentic_engine_timeout }}
1252
+ GH_AW_MODEL_NOT_SUPPORTED_ERROR: ${{ needs.agent.outputs.model_not_supported_error }}
1253
+ GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com"
1254
+ GH_AW_CODE_PUSH_FAILURE_ERRORS: ${{ needs.safe_outputs.outputs.code_push_failure_errors }}
1255
+ GH_AW_CODE_PUSH_FAILURE_COUNT: ${{ needs.safe_outputs.outputs.code_push_failure_count }}
1256
+ GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }}
1257
+ GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }}
1258
+ GH_AW_DAILY_AI_CREDITS_EXCEEDED: ${{ needs.activation.outputs.daily_ai_credits_exceeded }}
1259
+ GH_AW_DAILY_AI_CREDITS_TOTAL_EFFECTIVE_TOKENS: ${{ needs.activation.outputs.daily_ai_credits_total_effective_tokens }}
1260
+ GH_AW_DAILY_AI_CREDITS_THRESHOLD: ${{ needs.activation.outputs.daily_ai_credits_threshold }}
1261
+ GH_AW_GROUP_REPORTS: "false"
1262
+ GH_AW_FAILURE_REPORT_AS_ISSUE: "true"
1263
+ GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true"
1264
+ GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true"
1265
+ GH_AW_TIMEOUT_MINUTES: "20"
1266
+ with:
1267
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1268
+ script: |
1269
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
1270
+ setupGlobals(core, github, context, exec, io, getOctokit);
1271
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_agent_failure.cjs');
1272
+ await main();
1273
+
1274
+ detection:
1275
+ needs:
1276
+ - activation
1277
+ - agent
1278
+ if: always() && needs.agent.result != 'skipped'
1279
+ runs-on: ubuntu-latest
1280
+ permissions:
1281
+ contents: read
1282
+ env:
1283
+ GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
1284
+ outputs:
1285
+ aic: ${{ steps.parse_detection_token_usage.outputs.aic }}
1286
+ detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }}
1287
+ detection_reason: ${{ steps.detection_conclusion.outputs.reason }}
1288
+ detection_success: ${{ steps.detection_conclusion.outputs.success }}
1289
+ steps:
1290
+ - name: Setup Scripts
1291
+ id: setup
1292
+ uses: github/gh-aw-actions/setup@ba6380cc6e5be5d21677bebe04d52fb48e3abec7 # v0.81.6
1293
+ with:
1294
+ destination: ${{ runner.temp }}/gh-aw/actions
1295
+ job-name: ${{ github.job }}
1296
+ trace-id: ${{ needs.activation.outputs.setup-trace-id }}
1297
+ parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
1298
+ env:
1299
+ GH_AW_SETUP_WORKFLOW_NAME: "Nightly harness review"
1300
+ GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/nightly-harness-review.lock.yml@${{ github.ref }}
1301
+ GH_AW_INFO_VERSION: "1.0.65"
1302
+ GH_AW_INFO_AWF_VERSION: "v0.27.11"
1303
+ GH_AW_INFO_ENGINE_ID: "copilot"
1304
+ - name: Download agent output artifact
1305
+ id: download-agent-output
1306
+ continue-on-error: true
1307
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
1308
+ with:
1309
+ name: agent
1310
+ path: /tmp/gh-aw/
1311
+ - name: Setup agent output environment variable
1312
+ id: setup-agent-output-env
1313
+ if: steps.download-agent-output.outcome == 'success'
1314
+ run: |
1315
+ mkdir -p /tmp/gh-aw/
1316
+ find "/tmp/gh-aw/" -type f -print
1317
+ echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
1318
+ - name: Checkout repository for patch context
1319
+ if: needs.agent.outputs.has_patch == 'true'
1320
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
1321
+ with:
1322
+ persist-credentials: false
1323
+ # --- Threat Detection ---
1324
+ - name: Clean stale firewall files from agent artifact
1325
+ run: |
1326
+ rm -rf /tmp/gh-aw/sandbox/firewall/logs
1327
+ rm -rf /tmp/gh-aw/sandbox/firewall/audit
1328
+ - name: Download container images
1329
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.11@sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11@sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d ghcr.io/github/gh-aw-firewall/squid:0.27.11@sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d
1330
+ - name: Check if detection needed
1331
+ id: detection_guard
1332
+ if: always()
1333
+ env:
1334
+ OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }}
1335
+ HAS_PATCH: ${{ needs.agent.outputs.has_patch }}
1336
+ run: |
1337
+ if [[ -n "$OUTPUT_TYPES" || "$HAS_PATCH" == "true" ]]; then
1338
+ echo "run_detection=true" >> "$GITHUB_OUTPUT"
1339
+ echo "Detection will run: output_types=$OUTPUT_TYPES, has_patch=$HAS_PATCH"
1340
+ else
1341
+ echo "run_detection=false" >> "$GITHUB_OUTPUT"
1342
+ echo "Detection skipped: no agent outputs or patches to analyze"
1343
+ fi
1344
+ - name: Clear MCP Config for detection
1345
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
1346
+ run: |
1347
+ rm -f "${RUNNER_TEMP}/gh-aw/mcp-config/mcp-servers.json"
1348
+ rm -f "$HOME/.copilot/mcp-config.json"
1349
+ rm -f "$GITHUB_WORKSPACE/.gemini/settings.json"
1350
+ - name: Prepare threat detection files
1351
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
1352
+ run: |
1353
+ mkdir -p /tmp/gh-aw/threat-detection/aw-prompts
1354
+ rm -f /tmp/gh-aw/agent_usage.json
1355
+ cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true
1356
+ if [ ! -s /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt ]; then
1357
+ echo "::warning::ERR_VALIDATION: Missing or empty detection context prompt at /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt. Ensure the agent artifact includes /tmp/gh-aw/aw-prompts/prompt.txt. Detection will continue with fallback workflow context."
1358
+ fi
1359
+ cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true
1360
+ for f in /tmp/gh-aw/aw-*.patch; do
1361
+ [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
1362
+ done
1363
+ for f in /tmp/gh-aw/aw-*.bundle; do
1364
+ [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
1365
+ done
1366
+ echo "Prepared threat detection files:"
1367
+ ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true
1368
+ - name: Setup threat detection
1369
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
1370
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1371
+ env:
1372
+ WORKFLOW_NAME: "Nightly harness review"
1373
+ WORKFLOW_DESCRIPTION: "Nightly harness review — classify failures and propose harness revisions."
1374
+ HAS_PATCH: ${{ needs.agent.outputs.has_patch }}
1375
+ with:
1376
+ script: |
1377
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
1378
+ setupGlobals(core, github, context, exec, io, getOctokit);
1379
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/setup_threat_detection.cjs');
1380
+ await main();
1381
+ - name: Ensure threat-detection directory and log
1382
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
1383
+ run: |
1384
+ mkdir -p /tmp/gh-aw/threat-detection
1385
+ touch /tmp/gh-aw/threat-detection/detection.log
1386
+ - name: Setup Node.js
1387
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
1388
+ with:
1389
+ node-version: '24'
1390
+ package-manager-cache: false
1391
+ - name: Install GitHub Copilot CLI
1392
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.65
1393
+ env:
1394
+ GH_HOST: github.com
1395
+ - name: Install AWF binary
1396
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.27.11
1397
+ - name: Execute GitHub Copilot CLI
1398
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
1399
+ continue-on-error: true
1400
+ id: detection_agentic_execution
1401
+ # Copilot CLI tool arguments (sorted):
1402
+ timeout-minutes: 20
1403
+ run: |
1404
+ set -o pipefail
1405
+ printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt
1406
+ trap 'rm -f "$HOME/.copilot/settings.json"' EXIT
1407
+ mkdir -p "$HOME/.copilot"
1408
+ printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > "$HOME/.copilot/settings.json"
1409
+ export XDG_CONFIG_HOME="$HOME"
1410
+ touch /tmp/gh-aw/agent-step-summary.md
1411
+ GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true)
1412
+ export GH_AW_NODE_BIN
1413
+ export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK"
1414
+ (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log)
1415
+ GH_AW_MAX_AI_CREDITS="${GH_AW_MAX_AI_CREDITS:-400}"
1416
+ printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.11/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"github.com\",\"host.docker.internal\",\"registry.npmjs.org\",\"telemetry.enterprise.githubcopilot.com\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5},\"container\":{\"imageTag\":\"0.27.11,squid=sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d,agent=sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7,api-proxy=sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json"
1417
+ cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
1418
+ export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json"
1419
+ GH_AW_DOCKER_HOST=""
1420
+ if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
1421
+ GH_AW_DOCKER_HOST="${DOCKER_HOST}"
1422
+ fi
1423
+ GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS=""
1424
+ if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
1425
+ GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="--docker-host-path-prefix /tmp/gh-aw"
1426
+ _GH_AW_CHROOT_JSON=$(jq -c --arg src /tmp/gh-aw --arg user "$(id -un)" --argjson uid "$(id -u)" --argjson gid "$(id -g)" --arg home /tmp/gh-aw/home '.chroot={"binariesSourcePath":$src,"identity":{"user":$user,"uid":$uid,"gid":$gid,"home":$home}}' "${RUNNER_TEMP}/gh-aw/awf-config.json") || { echo "chroot config patch failed" >&2; exit 1; }
1427
+ printf '%s\n' "$_GH_AW_CHROOT_JSON" > "${RUNNER_TEMP}/gh-aw/awf-config.json"
1428
+ printf '%s\n' "$_GH_AW_CHROOT_JSON" > "/tmp/gh-aw/awf-config.json"
1429
+ fi
1430
+ GH_AW_TOOL_CACHE_MOUNT=""
1431
+ GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"
1432
+ if [ -d "$GH_AW_TOOL_CACHE" ]; then
1433
+ if [[ "$GH_AW_TOOL_CACHE" != /opt/* ]]; then
1434
+ GH_AW_TOOL_CACHE_MOUNT="$GH_AW_TOOL_CACHE:$GH_AW_TOOL_CACHE:ro"
1435
+ fi
1436
+ fi
1437
+ # shellcheck disable=SC1003,SC2086
1438
+ sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} ${GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS} --env-all --exclude-env COPILOT_GITHUB_TOKEN --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \
1439
+ -- /bin/bash -c 'set +o histexpand; : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; export PATH="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log
1440
+ env:
1441
+ AWF_REFLECT_ENABLED: 1
1442
+ COPILOT_AGENT_RUNNER_TYPE: STANDALONE
1443
+ COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode
1444
+ COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
1445
+ COPILOT_MODEL: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'claude-sonnet-4.6' }}
1446
+ GH_AW_LLM_PROVIDER: github
1447
+ GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_DETECTION_MAX_AI_CREDITS || '400' }}
1448
+ GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
1449
+ GH_AW_PHASE: detection
1450
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
1451
+ GH_AW_TIMEOUT_MINUTES: 20
1452
+ GH_AW_VERSION: v0.81.6
1453
+ GITHUB_API_URL: ${{ github.api_url }}
1454
+ GITHUB_AW: true
1455
+ GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows
1456
+ GITHUB_HEAD_REF: ${{ github.head_ref }}
1457
+ GITHUB_REF_NAME: ${{ github.ref_name }}
1458
+ GITHUB_SERVER_URL: ${{ github.server_url }}
1459
+ GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md
1460
+ GITHUB_WORKSPACE: ${{ github.workspace }}
1461
+ GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
1462
+ GIT_AUTHOR_NAME: github-actions[bot]
1463
+ GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
1464
+ GIT_COMMITTER_NAME: github-actions[bot]
1465
+ RUNNER_TEMP: ${{ runner.temp }}
1466
+ TRACEPARENT: ${{ env.GITHUB_AW_OTEL_TRACE_ID != '' && env.GITHUB_AW_OTEL_PARENT_SPAN_ID != '' && format('00-{0}-{1}-01', env.GITHUB_AW_OTEL_TRACE_ID, env.GITHUB_AW_OTEL_PARENT_SPAN_ID) || '' }}
1467
+ - name: Parse threat detection token usage for step summary
1468
+ id: parse_detection_token_usage
1469
+ if: always()
1470
+ continue-on-error: true
1471
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1472
+ env:
1473
+ GH_AW_TOKEN_USAGE_SUMMARY_TITLE: Threat Detection Token Usage
1474
+ with:
1475
+ script: |
1476
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
1477
+ setupGlobals(core, github, context, exec, io, getOctokit);
1478
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_token_usage.cjs');
1479
+ await main();
1480
+ - name: Upload threat detection log
1481
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
1482
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
1483
+ with:
1484
+ name: detection
1485
+ path: /tmp/gh-aw/threat-detection/detection.log
1486
+ if-no-files-found: ignore
1487
+ - name: Parse and conclude threat detection
1488
+ id: detection_conclusion
1489
+ if: always()
1490
+ continue-on-error: true
1491
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1492
+ env:
1493
+ RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }}
1494
+ DETECTION_AGENTIC_EXECUTION_OUTCOME: ${{ steps.detection_agentic_execution.outcome }}
1495
+ GH_AW_DETECTION_CONTINUE_ON_ERROR: "true"
1496
+ with:
1497
+ script: |
1498
+ try {
1499
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
1500
+ setupGlobals(core, github, context, exec, io, getOctokit);
1501
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs');
1502
+ await main();
1503
+ } catch (loadErr) {
1504
+ const continueOnError = process.env.GH_AW_DETECTION_CONTINUE_ON_ERROR !== 'false';
1505
+ const detectionExecutionFailed = process.env.DETECTION_AGENTIC_EXECUTION_OUTCOME === 'failure';
1506
+ const msg = 'ERR_SYSTEM: \u274C Unexpected error loading threat detection module: ' + (loadErr && loadErr.message ? loadErr.message : String(loadErr));
1507
+ core.error(msg);
1508
+ core.setOutput('reason', 'parse_error');
1509
+ if (continueOnError && !detectionExecutionFailed) {
1510
+ core.warning('\u26A0\uFE0F ' + msg);
1511
+ core.setOutput('conclusion', 'warning');
1512
+ core.setOutput('success', 'false');
1513
+ } else {
1514
+ core.setOutput('conclusion', 'failure');
1515
+ core.setOutput('success', 'false');
1516
+ core.setFailed(msg);
1517
+ }
1518
+ }
1519
+
1520
+ safe_outputs:
1521
+ needs:
1522
+ - activation
1523
+ - agent
1524
+ - detection
1525
+ if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success'
1526
+ runs-on: ubuntu-slim
1527
+ permissions:
1528
+ contents: write
1529
+ issues: write
1530
+ pull-requests: write
1531
+ timeout-minutes: 45
1532
+ env:
1533
+ GH_AW_AGENT_AIC: ${{ needs.agent.outputs.aic }}
1534
+ GH_AW_AIC: ${{ needs.agent.outputs.aic }}
1535
+ GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }}
1536
+ GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/nightly-harness-review"
1537
+ GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }}
1538
+ GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }}
1539
+ GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }}
1540
+ GH_AW_ENGINE_ID: "copilot"
1541
+ GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }}
1542
+ GH_AW_ENGINE_VERSION: "1.0.65"
1543
+ GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
1544
+ GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }}
1545
+ GH_AW_WORKFLOW_ID: "nightly-harness-review"
1546
+ GH_AW_WORKFLOW_NAME: "Nightly harness review"
1547
+ GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/nightly-harness-review.md"
1548
+ outputs:
1549
+ code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }}
1550
+ code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }}
1551
+ create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }}
1552
+ create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }}
1553
+ created_issue_number: ${{ steps.process_safe_outputs.outputs.created_issue_number }}
1554
+ created_issue_url: ${{ steps.process_safe_outputs.outputs.created_issue_url }}
1555
+ created_pr_number: ${{ steps.process_safe_outputs.outputs.created_pr_number }}
1556
+ created_pr_url: ${{ steps.process_safe_outputs.outputs.created_pr_url }}
1557
+ process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }}
1558
+ process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }}
1559
+ steps:
1560
+ - name: Setup Scripts
1561
+ id: setup
1562
+ uses: github/gh-aw-actions/setup@ba6380cc6e5be5d21677bebe04d52fb48e3abec7 # v0.81.6
1563
+ with:
1564
+ destination: ${{ runner.temp }}/gh-aw/actions
1565
+ job-name: ${{ github.job }}
1566
+ trace-id: ${{ needs.activation.outputs.setup-trace-id }}
1567
+ parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
1568
+ env:
1569
+ GH_AW_SETUP_WORKFLOW_NAME: "Nightly harness review"
1570
+ GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/nightly-harness-review.lock.yml@${{ github.ref }}
1571
+ GH_AW_INFO_VERSION: "1.0.65"
1572
+ GH_AW_INFO_AWF_VERSION: "v0.27.11"
1573
+ GH_AW_INFO_ENGINE_ID: "copilot"
1574
+ - name: Download agent output artifact
1575
+ id: download-agent-output
1576
+ continue-on-error: true
1577
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
1578
+ with:
1579
+ name: agent
1580
+ path: /tmp/gh-aw/
1581
+ - name: Setup agent output environment variable
1582
+ id: setup-agent-output-env
1583
+ if: steps.download-agent-output.outcome == 'success'
1584
+ run: |
1585
+ mkdir -p /tmp/gh-aw/
1586
+ find "/tmp/gh-aw/" -type f -print
1587
+ echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
1588
+ - name: Download patch artifact
1589
+ continue-on-error: true
1590
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
1591
+ with:
1592
+ name: agent
1593
+ path: /tmp/gh-aw/
1594
+ - name: Checkout repository
1595
+ if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request')
1596
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
1597
+ with:
1598
+ persist-credentials: true
1599
+ token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1600
+ - name: Configure Git credentials
1601
+ if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request')
1602
+ env:
1603
+ GITHUB_REPOSITORY: ${{ github.repository }}
1604
+ GITHUB_SERVER_URL: ${{ github.server_url }}
1605
+ GIT_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1606
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_git_credentials.sh"
1607
+ - name: Configure GH_HOST for enterprise compatibility
1608
+ id: ghes-host-config
1609
+ shell: bash
1610
+ run: | # zizmor: ignore[github-env] - GITHUB_SERVER_URL is set by GitHub Actions, not user input.
1611
+ # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct
1612
+ # GitHub instance (GHES/GHEC). On github.com this is a harmless no-op.
1613
+ GH_HOST="${GITHUB_SERVER_URL#https://}"
1614
+ GH_HOST="${GH_HOST#http://}"
1615
+ echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV"
1616
+ - name: Process Safe Outputs
1617
+ id: process_safe_outputs
1618
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1619
+ env:
1620
+ GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
1621
+ GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }}
1622
+ GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com"
1623
+ GITHUB_SERVER_URL: ${{ github.server_url }}
1624
+ GITHUB_API_URL: ${{ github.api_url }}
1625
+ GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"max\":3},\"create_pull_request\":{\"max\":1,\"max_patch_files\":100,\"max_patch_size\":4096,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"CHANGELOG.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\",\"CLAUDE.md\",\"GEMINI.md\"],\"protected_files_policy\":\"request_review\"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}"
1626
+ GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }}
1627
+ with:
1628
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1629
+ script: |
1630
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
1631
+ setupGlobals(core, github, context, exec, io, getOctokit);
1632
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/safe_output_handler_manager.cjs');
1633
+ await main();
1634
+ - name: Upload Safe Outputs Items
1635
+ if: always()
1636
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
1637
+ with:
1638
+ name: safe-outputs-items
1639
+ path: |
1640
+ /tmp/gh-aw/safe-output-items.jsonl
1641
+ /tmp/gh-aw/temporary-id-map.json
1642
+ if-no-files-found: ignore
1643
+