@juangcarmona/lighthouse-sdlc 0.7.0 → 0.8.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.
@@ -0,0 +1,2212 @@
1
+ # gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"f456a5fb316ce09d00925b022d29d92ae8ab7391a45df1c31a849a38aac234e9","body_hash":"245a033a9e58c7058cfbdca9fc38fb8ad2b02df0303bc8a4249b20e56030f7c2","compiler_version":"v0.93.2","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.101"},"agent_image_runner":"[\"self-hosted\",\"linux\",\"lighthouse-sdlc\"]"}
2
+ # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_DEFAULT_OTLP_ENDPOINT","GH_AW_DEFAULT_OTLP_HEADERS","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"9000827ccba6bdab643e8b6fd33ac0654aef8333","version":"v8.0.2"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"949feb2413d6458794dcd2491c4babbbce0c15c1","version":"v7.1.0"},{"repo":"actions/upload-artifact","sha":"cf430e030ddbb5b0abf93d22962f4752f3646cd9","version":"v7.0.2"},{"repo":"github/gh-aw-actions/setup","sha":"d9128eb3ea40c18b77c76184eda03c0ff2608d79","version":"v0.93.2"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.28.70","digest":"sha256:b15ab48cbbab02904eb9bbd359a398db59690eebbea1e6934d47ed2bb407dd34","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.28.70@sha256:b15ab48cbbab02904eb9bbd359a398db59690eebbea1e6934d47ed2bb407dd34"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.28.70","digest":"sha256:9ac8f9c7294e892c916de3da9d2588dfd8cd4931e5c39b00143266d7ed9fd52a","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.28.70@sha256:9ac8f9c7294e892c916de3da9d2588dfd8cd4931e5c39b00143266d7ed9fd52a"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.28.70","digest":"sha256:b5bc53f4becfd96e926e63c83831f1b3c9512f713c83161d2b8c9b7204b3e917","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.28.70@sha256:b5bc53f4becfd96e926e63c83831f1b3c9512f713c83161d2b8c9b7204b3e917"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.37","digest":"sha256:9c7f242f6dec2d7d7b55d4c9e07872d59b85377c6cb3de46c915a5d1ffb91442","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.37@sha256:9c7f242f6dec2d7d7b55d4c9e07872d59b85377c6cb3de46c915a5d1ffb91442"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:41835613992df88f51e923bad486f96dfb2e6cda29f13e217df41833284ae382","pinned_image":"ghcr.io/github/gh-aw-node@sha256:41835613992df88f51e923bad486f96dfb2e6cda29f13e217df41833284ae382"},{"image":"ghcr.io/github/github-mcp-server:v2.0.2","digest":"sha256:ffced0d76e77428532a2ced185516992d77fd146d69eec2f244e6237d1a97796","pinned_image":"ghcr.io/github/github-mcp-server:v2.0.2@sha256:ffced0d76e77428532a2ced185516992d77fd146d69eec2f244e6237d1a97796"}],"mcp_servers":[{"name":"github","tools":["get_commit","get_file_contents","get_latest_release","get_pull_request","get_pull_request_comments","get_pull_request_diff","get_pull_request_files","get_pull_request_review_comments","get_pull_request_reviews","get_pull_request_status","get_release_by_tag","get_tag","issue_read","list_branches","list_commits","list_issue_types","list_issues","list_pull_requests","list_releases","list_starred_repositories","list_tags","pull_request_read","search_code","search_issues","search_pull_requests","search_repositories"]},{"name":"safeoutputs","tools":["noop","report_incomplete","report_missing_data","report_missing_tool"]}],"threat_detection":{"mode":"enabled"},"admission":false}
3
+ # This file was automatically generated by gh-aw (v0.93.2). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md
4
+ #
5
+ # To update this file, edit the corresponding .md file and run:
6
+ # gh aw compile
7
+ # Not all edits will cause changes to this file.
8
+ #
9
+ # For more information: https://github.github.com/gh-aw/introduction/overview/
10
+ #
11
+ # Execute only the Lighthouse integration stage and return its declared stage result.
12
+ #
13
+ # Resolved workflow manifest:
14
+ # Imports:
15
+ # - shared/lighthouse-sdlc-stage.md
16
+ #
17
+ # Frontmatter env variables:
18
+ # - LIGHTHOUSE_SKILL: (main workflow)
19
+ # - LIGHTHOUSE_STAGE: (main workflow)
20
+ #
21
+ # Secrets used:
22
+ # - COPILOT_GITHUB_TOKEN
23
+ # - GH_AW_DEFAULT_OTLP_ENDPOINT
24
+ # - GH_AW_DEFAULT_OTLP_HEADERS
25
+ # - GH_AW_GITHUB_MCP_SERVER_TOKEN
26
+ # - GH_AW_GITHUB_TOKEN
27
+ # - GITHUB_TOKEN
28
+ #
29
+ # Custom actions used:
30
+ # - actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
31
+ # - actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
32
+ # - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
33
+ # - actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
34
+ # - actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
35
+ # - github/gh-aw-actions/setup@d9128eb3ea40c18b77c76184eda03c0ff2608d79 # v0.93.2
36
+ #
37
+ # Container images used:
38
+ # - ghcr.io/github/gh-aw-firewall/agent:0.28.70@sha256:b15ab48cbbab02904eb9bbd359a398db59690eebbea1e6934d47ed2bb407dd34
39
+ # - ghcr.io/github/gh-aw-firewall/api-proxy:0.28.70@sha256:9ac8f9c7294e892c916de3da9d2588dfd8cd4931e5c39b00143266d7ed9fd52a
40
+ # - ghcr.io/github/gh-aw-firewall/squid:0.28.70@sha256:b5bc53f4becfd96e926e63c83831f1b3c9512f713c83161d2b8c9b7204b3e917
41
+ # - ghcr.io/github/gh-aw-mcpg:v0.4.37@sha256:9c7f242f6dec2d7d7b55d4c9e07872d59b85377c6cb3de46c915a5d1ffb91442
42
+ # - ghcr.io/github/gh-aw-node@sha256:41835613992df88f51e923bad486f96dfb2e6cda29f13e217df41833284ae382
43
+ # - ghcr.io/github/github-mcp-server:v2.0.2@sha256:ffced0d76e77428532a2ced185516992d77fd146d69eec2f244e6237d1a97796
44
+
45
+ name: "Lighthouse SDLC integrate"
46
+ on:
47
+ workflow_call:
48
+ inputs:
49
+ aw_context:
50
+ default: ""
51
+ description: "Agent caller context (Reserved for Agentic Workflows)."
52
+ required: false
53
+ type: string
54
+ input:
55
+ default: "{}"
56
+ description: Compact JSON input for this stage.
57
+ required: false
58
+ type: string
59
+ previous-stage:
60
+ default: implement
61
+ description: Previous stage artifact name.
62
+ required: false
63
+ type: string
64
+ route:
65
+ description: Lighthouse route selected by the host.
66
+ required: true
67
+ type: string
68
+ run-id:
69
+ description: Stable Lighthouse run identifier.
70
+ required: true
71
+ type: string
72
+ secrets:
73
+ COPILOT_GITHUB_TOKEN:
74
+ required: false
75
+ GH_AW_DEFAULT_OTLP_ENDPOINT:
76
+ required: false
77
+ GH_AW_DEFAULT_OTLP_HEADERS:
78
+ required: false
79
+ GH_AW_GITHUB_MCP_SERVER_TOKEN:
80
+ required: false
81
+ GH_AW_GITHUB_TOKEN:
82
+ required: false
83
+
84
+ # Jobs receive only their explicitly declared permissions.
85
+ permissions: {}
86
+
87
+ concurrency:
88
+ group: "gh-aw-lighthouse-sdlc-integrate-${{ github.run_id }}"
89
+ queue: max
90
+
91
+ run-name: "Lighthouse SDLC integrate"
92
+
93
+ env:
94
+ LIGHTHOUSE_SKILL: src/packages/sdlc/skills/integrate/SKILL.md
95
+ LIGHTHOUSE_STAGE: integrate
96
+ OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.GH_AW_DEFAULT_OTLP_ENDPOINT || vars.GH_AW_DEFAULT_OTLP_ENDPOINT }}
97
+ OTEL_SERVICE_NAME: gh-aw.lighthouse-sdlc-integrate
98
+ OTEL_RESOURCE_ATTRIBUTES: 'gh-aw.workflow.name=Lighthouse%20SDLC%20integrate,gh-aw.repository=${{ github.repository }},gh-aw.run.id=${{ github.run_id }},github.run_id=${{ github.run_id }},gh-aw.engine.id=copilot'
99
+ OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.GH_AW_DEFAULT_OTLP_HEADERS }}
100
+ GH_AW_OTLP_ENDPOINTS: '[{"url":"${{ secrets.GH_AW_DEFAULT_OTLP_ENDPOINT || vars.GH_AW_DEFAULT_OTLP_ENDPOINT }}","headers":"${{ secrets.GH_AW_DEFAULT_OTLP_HEADERS }}"}]'
101
+ GH_AW_OTLP_IF_MISSING: ignore
102
+
103
+ jobs:
104
+ activation:
105
+ name: activation
106
+ needs: pre_activation
107
+ if: needs.pre_activation.outputs.activated == 'true'
108
+ runs-on: ubuntu-24.04
109
+ # Permissions for the activation job (workflow permissions default to none).
110
+ permissions:
111
+ actions: read
112
+ contents: read
113
+ env:
114
+ GH_AW_MAX_DAILY_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS || '5000' }}
115
+ GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
116
+ outputs:
117
+ artifact_prefix: ${{ steps.artifact-prefix.outputs.prefix }}
118
+ aw_context: ${{ steps.generate_aw_info.outputs.aw_context }}
119
+ comment_id: ""
120
+ comment_repo: ""
121
+ daily_ai_credits_estimated: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_estimated || '' }}
122
+ daily_ai_credits_exceeded: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_exceeded == 'true' }}
123
+ daily_ai_credits_guardrail_error: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_guardrail_error || '' }}
124
+ daily_ai_credits_guardrail_status: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_guardrail_status || '' }}
125
+ daily_ai_credits_threshold: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_threshold || '' }}
126
+ daily_ai_credits_total: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_total || '' }}
127
+ engine_id: ${{ steps.generate_aw_info.outputs.engine_id }}
128
+ lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }}
129
+ model: ${{ steps.generate_aw_info.outputs.model }}
130
+ oauth_token_check_failed: ${{ steps.check-oauth-tokens.outputs.oauth_token_check_failed == 'true' }}
131
+ secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }}
132
+ setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }}
133
+ setup-span-id: ${{ steps.setup.outputs.span-id }}
134
+ setup-trace-id: ${{ steps.setup.outputs.trace-id }}
135
+ stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }}
136
+ target_checkout_ref: ${{ steps.resolve-host-repo.outputs.target_checkout_ref }}
137
+ target_ref: ${{ steps.resolve-host-repo.outputs.target_ref }}
138
+ target_repo: ${{ steps.resolve-host-repo.outputs.target_repo }}
139
+ target_repo_name: ${{ steps.resolve-host-repo.outputs.target_repo_name }}
140
+ steps:
141
+ - name: Setup Scripts
142
+ id: setup
143
+ uses: github/gh-aw-actions/setup@d9128eb3ea40c18b77c76184eda03c0ff2608d79 # v0.93.2
144
+ with:
145
+ destination: ${{ runner.temp }}/gh-aw/actions
146
+ job-name: ${{ github.job }}
147
+ trace-id: ${{ needs.pre_activation.outputs.setup-trace-id }}
148
+ parent-span-id: ${{ needs.pre_activation.outputs.setup-parent-span-id || needs.pre_activation.outputs.setup-span-id }}
149
+ safe-output-artifact-client: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }}
150
+ env:
151
+ GH_AW_SETUP_WORKFLOW_NAME: "Lighthouse SDLC integrate"
152
+ GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/lighthouse-sdlc-integrate.lock.yml@${{ github.ref }}
153
+ GH_AW_INFO_VERSION: "1.0.101"
154
+ GH_AW_INFO_AWF_VERSION: "v0.28.70"
155
+ GH_AW_INFO_ENGINE_ID: "copilot"
156
+ GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }}
157
+ - name: Mask OTLP telemetry headers
158
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh"
159
+ - name: Resolve host repo for activation checkout
160
+ id: resolve-host-repo
161
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
162
+ env:
163
+ JOB_WORKFLOW_REPOSITORY: ${{ job.workflow_repository }}
164
+ JOB_WORKFLOW_SHA: ${{ job.workflow_sha }}
165
+ JOB_WORKFLOW_REF: ${{ job.workflow_ref }}
166
+ JOB_WORKFLOW_FILE_PATH: ${{ job.workflow_file_path }}
167
+ with:
168
+ script: |
169
+ const path = require('path');
170
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
171
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
172
+ setupGlobals(core, github, context, exec, io, getOctokit);
173
+ const { main } = require(path.join(actionsDir, 'resolve_host_repo.cjs'));
174
+ await main();
175
+ - name: Compute artifact prefix
176
+ id: artifact-prefix
177
+ env:
178
+ INPUTS_JSON: ${{ toJSON(inputs) }}
179
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/compute_artifact_prefix.sh"
180
+ - name: Generate agentic run info
181
+ id: generate_aw_info
182
+ env:
183
+ GH_AW_INFO_ENGINE_ID: "copilot"
184
+ GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI"
185
+ GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }}
186
+ GH_AW_INFO_VERSION: "1.0.101"
187
+ GH_AW_INFO_AGENT_VERSION: "1.0.101"
188
+ GH_AW_INFO_CLI_VERSION: "v0.93.2"
189
+ GH_AW_INFO_WORKFLOW_NAME: "Lighthouse SDLC integrate"
190
+ GH_AW_INFO_WORKFLOW_ID: ${{ job.workflow_ref }}
191
+ GH_AW_INFO_EXPERIMENTAL: "false"
192
+ GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true"
193
+ GH_AW_INFO_STAGED: "false"
194
+ GH_AW_INFO_ALLOWED_DOMAINS: '["defaults"]'
195
+ GH_AW_INFO_FIREWALL_ENABLED: "true"
196
+ GH_AW_INFO_AWF_VERSION: "v0.28.70"
197
+ GH_AW_INFO_AWMG_VERSION: ""
198
+ GH_AW_INFO_FIREWALL_TYPE: "squid"
199
+ GH_AW_INFO_AGENT_RUNTIME: ""
200
+ GH_AW_INFO_ENGINE_HARNESS: "copilot-cli"
201
+ GH_AW_INFO_MODEL_CONFIG: '{"routing":{"enabled":false},"models":{"allowed":[],"blocked":[]},"max_ai_credits_source":"default"}'
202
+ GH_AW_INFO_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}
203
+ GH_AW_COMPILED_STRICT: "true"
204
+ GH_AW_INFO_TARGET_REPO: ${{ steps.resolve-host-repo.outputs.target_repo }}
205
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
206
+ with:
207
+ script: |
208
+ const path = require('path');
209
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
210
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
211
+ setupGlobals(core, github, context, exec, io, getOctokit);
212
+ const { main } = require(path.join(actionsDir, 'generate_aw_info.cjs'));
213
+ await main(core, context);
214
+ - name: Restore daily AIC scan observations
215
+ id: restore-daily-aic-cache-fallback
216
+ if: ${{ env.GH_AW_ADMISSION_RESULT != 'admitted' && env.GH_AW_MAX_DAILY_AI_CREDITS != '' }}
217
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
218
+ env:
219
+ GH_AW_HAS_SLASH_COMMAND: "false"
220
+ GH_AW_HAS_LABEL_COMMAND: "false"
221
+ with:
222
+ github-token: ${{ secrets.GITHUB_TOKEN }}
223
+ script: |
224
+ const path = require('path');
225
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
226
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
227
+ setupGlobals(core, github, context, exec, io, getOctokit);
228
+ const { main } = require(path.join(actionsDir, 'restore_aic_scan_cache.cjs'));
229
+ await main();
230
+ - name: Check daily workflow token guardrail
231
+ id: daily-ai-credits-workflow-guardrail
232
+ if: ${{ env.GH_AW_ADMISSION_RESULT != 'admitted' && env.GH_AW_MAX_DAILY_AI_CREDITS != '' }}
233
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
234
+ env:
235
+ GH_AW_WORKFLOW_NAME: "Lighthouse SDLC integrate"
236
+ GH_AW_WORKFLOW_ID: "lighthouse-sdlc-integrate"
237
+ GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
238
+ GH_AW_WORKFLOW_DISPATCH_AW_CONTEXT: ${{ github.event.inputs.aw_context || '' }}
239
+ GH_AW_HAS_SLASH_COMMAND: "false"
240
+ GH_AW_HAS_LABEL_COMMAND: "false"
241
+ GH_AW_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
242
+ GH_AW_MAX_DAILY_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS || '5000' }}
243
+ GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}
244
+ with:
245
+ github-token: ${{ secrets.GITHUB_TOKEN }}
246
+ script: |
247
+ const path = require('path');
248
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
249
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
250
+ setupGlobals(core, github, context, exec, io, getOctokit);
251
+ const { main } = require(path.join(actionsDir, 'check_daily_aic_workflow_guardrail.cjs'));
252
+ await main();
253
+ - name: Publish daily AIC scan observations
254
+ if: always() && env.GH_AW_ADMISSION_RESULT != 'admitted' && env.GH_AW_MAX_DAILY_AI_CREDITS != ''
255
+ continue-on-error: true
256
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
257
+ with:
258
+ name: aic-usage-scan-v2
259
+ path: /tmp/gh-aw/agentic-workflow-usage-scan-v2.jsonl
260
+ overwrite: true
261
+ if-no-files-found: ignore
262
+ retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '3' }}
263
+ - name: Validate COPILOT_GITHUB_TOKEN secret
264
+ id: validate-secret
265
+ 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
266
+ env:
267
+ COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
268
+ - name: Check for OAuth tokens
269
+ id: check-oauth-tokens
270
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/check_oauth_tokens.sh"
271
+ env:
272
+ COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
273
+ GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }}
274
+ GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }}
275
+ - name: Print cross-repo setup guidance
276
+ if: failure() && steps.resolve-host-repo.outputs.target_repo != github.repository
277
+ run: |
278
+ echo "::error::COPILOT_GITHUB_TOKEN must be configured in the CALLER repository's secrets."
279
+ echo "::error::For cross-repo workflow_call, secrets must be set in the repository that triggers the workflow."
280
+ echo "::error::See: https://github.github.com/gh-aw/patterns/central-repo-ops/#cross-repo-setup"
281
+ - name: Checkout .github and .agents folders
282
+ if: steps.resolve-host-repo.outputs.target_repo == github.repository
283
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
284
+ with:
285
+ persist-credentials: false
286
+ repository: ${{ steps.resolve-host-repo.outputs.target_repo }}
287
+ ref: ${{ steps.resolve-host-repo.outputs.target_checkout_ref }}
288
+ sparse-checkout: |
289
+ .github
290
+ .agents
291
+ .claude
292
+ .codex
293
+ .gemini
294
+ .pi
295
+ sparse-checkout-cone-mode: true
296
+ fetch-depth: 1
297
+ - name: Save agent config folders for base branch restoration
298
+ env:
299
+ GH_AW_AGENT_FOLDERS: ".agents .github"
300
+ GH_AW_AGENT_FILES: "AGENTS.md"
301
+ run: |
302
+ bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh"
303
+ - name: Check workflow lock file
304
+ id: check-lock-file
305
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
306
+ env:
307
+ GH_AW_WORKFLOW_FILE: "lighthouse-sdlc-integrate.lock.yml"
308
+ GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}"
309
+ with:
310
+ script: |
311
+ const path = require('path');
312
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
313
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
314
+ setupGlobals(core, github, context, exec, io, getOctokit);
315
+ const { main } = require(path.join(actionsDir, 'check_workflow_timestamp_api.cjs'));
316
+ await main();
317
+ - name: Check compile-agentic version
318
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
319
+ env:
320
+ GH_AW_COMPILED_VERSION: "v0.93.2"
321
+ GH_AW_HAS_SAFE_OUTPUTS: "true"
322
+ GH_AW_BLOCKED_VERSION_REPORT_AS_ISSUE: "false"
323
+ GH_AW_WORKFLOW_NAME: "Lighthouse SDLC integrate"
324
+ with:
325
+ script: |
326
+ const path = require('path');
327
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
328
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
329
+ setupGlobals(core, github, context, exec, io, getOctokit);
330
+ const { main } = require(path.join(actionsDir, 'check_version_updates.cjs'));
331
+ await main();
332
+ - name: Log runtime features
333
+ if: ${{ contains(toJSON(vars), '"GH_AW_RUNTIME_FEATURES":') }}
334
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/log_runtime_features_summary.sh"
335
+ - name: Create prompt with built-in context
336
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
337
+ env:
338
+ GH_AW_ACTIONS_DIR: ${{ runner.temp }}/gh-aw/actions
339
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
340
+ GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl
341
+ GH_AW_PROMPT_CONFIG: "{\"items\":[{\"content_env\":\"GH_AW_PROMPT_CONTENT_0000\"},{\"file\":\"xpia.md\"},{\"file\":\"temp_folder_prompt.md\"},{\"file\":\"markdown.md\"},{\"file\":\"safe_outputs_mcp_transport_prompt.md\"},{\"file\":\"safe_outputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0001\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0002\"},{\"file\":\"mcp_cli_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0003\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0006\"}],\"system_item_count\":12}"
342
+ GH_AW_ENV_LIGHTHOUSE_SKILL: ${{ env.LIGHTHOUSE_SKILL }}
343
+ GH_AW_EXPR_76DF9333: ${{ github.event.pull_request.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'pull_request' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }}
344
+ GH_AW_EXPR_77C1A4D2: ${{ github.event.comment.id || fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').comment_id }}
345
+ GH_AW_EXPR_7C248226: ${{ github.event.issue.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'issue' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }}
346
+ GH_AW_EXPR_C19C384F: ${{ github.event.discussion.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'discussion' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }}
347
+ GH_AW_GITHUB_ACTOR: ${{ github.actor }}
348
+ GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
349
+ GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
350
+ GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
351
+ GH_AW_PROMPT_CONTENT_0000: "<system>\n"
352
+ GH_AW_PROMPT_CONTENT_0001: "<safe-output-tools>\nTools: report_missing_tool, report_missing_data, noop\n"
353
+ GH_AW_PROMPT_CONTENT_0002: "</safe-output-tools>\n"
354
+ GH_AW_PROMPT_CONTENT_0003: "<github-context>\nThe following GitHub context information is available for this workflow:\n{{#if github.actor}}\n- **actor**: __GH_AW_GITHUB_ACTOR__\n{{/if}}\n{{#if github.repository}}\n- **repository**: __GH_AW_GITHUB_REPOSITORY__\n{{/if}}\n{{#if github.workspace}}\n- **workspace**: __GH_AW_GITHUB_WORKSPACE__\n{{/if}}\n{{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}\n- **issue-number**: #__GH_AW_EXPR_7C248226__\n{{/if}}\n{{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}\n- **discussion-number**: #__GH_AW_EXPR_C19C384F__\n{{/if}}\n{{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}\n- **pull-request-number**: #__GH_AW_EXPR_76DF9333__\n{{/if}}\n{{#if github.event.comment.id || github.aw.context.comment_id}}\n- **comment-id**: __GH_AW_EXPR_77C1A4D2__\n{{/if}}\n{{#if github.run_id}}\n- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__\n{{/if}}\n- **checkouts**: The following repositories have been checked out and are available in the workspace:\n - repo `__GH_AW_GITHUB_REPOSITORY__` → `__GH_AW_GITHUB_WORKSPACE__` (cwd) [full history, all branches available as remote-tracking refs]\n - **Note**: The workspace path reported above may contain a separate shallow, credential-free checkout of the host repository. Use the exact checkout path shown for the repository you need. Before concluding that a branch is unavailable, confirm your working directory matches that path and inspect refs there. If the branch is not present in that checkout and is not listed as an additional fetched ref, it has NOT been checked out. For private repositories you cannot fetch it. If the branch is required and not available, exit with an error and ask the user to add it to the `fetch:` option of the `checkout:` configuration (e.g., `fetch: [\"refs/pulls/open/*\"]` for all open PR refs, or `fetch: [\"main\", \"feature/my-branch\"]` for specific branches).\n - **Warning: No git credentials are available to the agent.** Credentials are\n intentionally removed after the checkout step for security. This means any git\n operation that needs to authenticate to the remote will fail. In private repositories, that includes:\n - `git fetch`, `git pull`, `git clone`, and `git push` (direct push, not via safe-output tools)\n - Checking out or switching to a remote branch that is not already fetched\n - Deepening a shallow clone (`git fetch --unshallow`)\n - On-demand blob fetches in partial/blobless clones (operations on files not in the initial checkout)\n Do NOT attempt to configure credentials, run `git credential fill`, or modify `.gitconfig` —\n authentication will not succeed. If you encounter credential prompts or authentication errors,\n stop immediately and report the limitation rather than spending turns trying to work around it.\n</github-context>\n\n"
355
+ GH_AW_PROMPT_CONTENT_0004: "</system>\n"
356
+ GH_AW_PROMPT_CONTENT_0005: "{{#runtime-import .github/workflows/shared/lighthouse-sdlc-stage.md}}\n"
357
+ GH_AW_PROMPT_CONTENT_0006: "{{#runtime-import .github/workflows/lighthouse-sdlc-integrate.md}}\n"
358
+ with:
359
+ script: |
360
+ const { setupGlobals } = require(process.env.GH_AW_ACTIONS_DIR + '/setup_globals.cjs');
361
+ setupGlobals(core, github, context, exec, io, getOctokit);
362
+ const { main } = require(process.env.GH_AW_ACTIONS_DIR + '/create_prompt.cjs');
363
+ await main(core);
364
+ - name: Interpolate variables and render templates
365
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
366
+ env:
367
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
368
+ GH_AW_ENGINE_ID: "copilot"
369
+ GH_AW_SUB_AGENT_DIR: ".github/agents"
370
+ GH_AW_SUB_AGENT_EXT: ".agent.md"
371
+ GH_AW_SKILL_DIR: ".github/skills"
372
+ GH_AW_SKILL_EXT: "/SKILL.md"
373
+ GH_AW_ENV_LIGHTHOUSE_SKILL: ${{ env.LIGHTHOUSE_SKILL }}
374
+ with:
375
+ script: |
376
+ const path = require('path');
377
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
378
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
379
+ setupGlobals(core, github, context, exec, io, getOctokit);
380
+ const { main } = require(path.join(actionsDir, 'interpolate_prompt.cjs'));
381
+ await main();
382
+ - name: Substitute placeholders
383
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
384
+ env:
385
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
386
+ GH_AW_ENV_LIGHTHOUSE_SKILL: ${{ env.LIGHTHOUSE_SKILL }}
387
+ GH_AW_EXPR_76DF9333: ${{ github.event.pull_request.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'pull_request' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }}
388
+ GH_AW_EXPR_77C1A4D2: ${{ github.event.comment.id || fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').comment_id }}
389
+ GH_AW_EXPR_7C248226: ${{ github.event.issue.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'issue' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }}
390
+ GH_AW_EXPR_C19C384F: ${{ github.event.discussion.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'discussion' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }}
391
+ GH_AW_GITHUB_ACTOR: ${{ github.actor }}
392
+ GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
393
+ GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
394
+ GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
395
+ GH_AW_MCP_CLI_SERVERS_LIST: "- `github` — run `github --help` to see available tools\n- `safeoutputs` — run `safeoutputs --help` to see available tools"
396
+ GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }}
397
+ with:
398
+ script: |
399
+ const path = require('path');
400
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
401
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
402
+ setupGlobals(core, github, context, exec, io, getOctokit);
403
+
404
+ const substitutePlaceholders = require(path.join(actionsDir, 'substitute_placeholders.cjs'));
405
+
406
+ // Call the substitution function
407
+ return await substitutePlaceholders({
408
+ file: process.env.GH_AW_PROMPT,
409
+ substitutions: {
410
+ GH_AW_ENV_LIGHTHOUSE_SKILL: process.env.GH_AW_ENV_LIGHTHOUSE_SKILL,
411
+ GH_AW_EXPR_76DF9333: process.env.GH_AW_EXPR_76DF9333,
412
+ GH_AW_EXPR_77C1A4D2: process.env.GH_AW_EXPR_77C1A4D2,
413
+ GH_AW_EXPR_7C248226: process.env.GH_AW_EXPR_7C248226,
414
+ GH_AW_EXPR_C19C384F: process.env.GH_AW_EXPR_C19C384F,
415
+ GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR,
416
+ GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY,
417
+ GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID,
418
+ GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE,
419
+ GH_AW_MCP_CLI_SERVERS_LIST: process.env.GH_AW_MCP_CLI_SERVERS_LIST,
420
+ GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED
421
+ }
422
+ });
423
+ - name: Validate prompt placeholders
424
+ env:
425
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
426
+ run: |
427
+ bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh"
428
+ - name: Print prompt
429
+ env:
430
+ GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt
431
+ run: |
432
+ bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh"
433
+ - name: Inventory installed skills
434
+ if: success() || failure()
435
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
436
+ env:
437
+ GH_AW_SKILL_DIR: ".github/skills"
438
+ with:
439
+ script: |
440
+ const path = require('path');
441
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
442
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
443
+ setupGlobals(core, github, context, exec, io, getOctokit);
444
+ const { main } = require(path.join(actionsDir, 'skill_inventory.cjs'));
445
+ await main();
446
+ - name: Upload info artifact
447
+ if: success() || failure()
448
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
449
+ with:
450
+ name: ${{ steps.artifact-prefix.outputs.prefix }}info
451
+ path: /tmp/gh-aw/aw_info.json
452
+ if-no-files-found: ignore
453
+ retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}
454
+ - name: Stage prompt files for artifact upload
455
+ run: |
456
+ mkdir -p /tmp/gh-aw/aw-prompts
457
+ cp -a "${RUNNER_TEMP}/gh-aw/aw-prompts/." /tmp/gh-aw/aw-prompts/
458
+ - name: Upload activation artifact
459
+ if: success() || failure()
460
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
461
+ with:
462
+ name: ${{ steps.artifact-prefix.outputs.prefix }}activation
463
+ include-hidden-files: true
464
+ path: |
465
+ /tmp/gh-aw/aw_info.json
466
+ /tmp/gh-aw/models.json
467
+ /tmp/gh-aw/aw-prompts/prompt.txt
468
+ /tmp/gh-aw/aw-prompts/system.txt
469
+ /tmp/gh-aw/aw-prompts/user.txt
470
+ /tmp/gh-aw/aw-prompts/prompt-template.txt
471
+ /tmp/gh-aw/aw-prompts/prompt-import-tree.json
472
+ /tmp/gh-aw/github_rate_limits.jsonl
473
+ /tmp/gh-aw/base
474
+ /tmp/gh-aw/.github/agents
475
+ /tmp/gh-aw/.github/skills
476
+ /tmp/gh-aw/skill_inventory.json
477
+ if-no-files-found: ignore
478
+ retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '1' }}
479
+
480
+ agent:
481
+ name: agent
482
+ needs: activation
483
+ if: needs.activation.outputs.daily_ai_credits_exceeded != 'true'
484
+ runs-on:
485
+ - self-hosted
486
+ - linux
487
+ - lighthouse-sdlc
488
+ # Permissions for the agent job (workflow permissions default to none).
489
+ permissions:
490
+ contents: read
491
+ concurrency:
492
+ group: "gh-aw-copilot-lighthouse-sdlc-integrate"
493
+ queue: max
494
+ timeout-minutes: 60
495
+ env:
496
+ DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
497
+ GH_AW_ASSETS_ALLOWED_EXTS: ""
498
+ GH_AW_ASSETS_BRANCH: ""
499
+ GH_AW_ASSETS_MAX_SIZE_KB: 0
500
+ GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs
501
+ GH_AW_PR_HEAD_BASE_BRANCH: ""
502
+ GH_AW_PR_HEAD_BASE_PR_NUMBER: ""
503
+ GH_AW_PR_HEAD_BASE_REF: ""
504
+ GH_AW_PR_HEAD_BASE_REPO: ""
505
+ GH_AW_PR_HEAD_BASE_SHA: ""
506
+ GH_AW_PR_HEAD_REPO: ""
507
+ GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
508
+ GH_AW_TARGET_REPO_SLUG: ""
509
+ GH_AW_WORKFLOW_ID_SANITIZED: lighthousesdlcintegrate
510
+ outputs:
511
+ agentic_engine_timeout: ${{ steps.detect-agent-errors.outputs.agentic_engine_timeout || 'false' }}
512
+ ai_credits_rate_limit_error: ${{ steps.parse-mcp-gateway.outputs.ai_credits_rate_limit_error || 'false' }}
513
+ aic: ${{ steps.parse-token-usage.outputs.aic }}
514
+ ambient_context: ${{ steps.parse-token-usage.outputs.ambient_context }}
515
+ artifact_prefix: ${{ needs.activation.outputs.artifact_prefix }}
516
+ checkout_pr_invalidated: ${{ steps.checkout-pr.outputs.checkout_pr_invalidated || 'false' }}
517
+ checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }}
518
+ has_patch: ${{ steps.collect_output.outputs.has_patch }}
519
+ http_400_response_error: ${{ steps.detect-agent-errors.outputs.http_400_response_error || 'false' }}
520
+ inference_access_error: ${{ steps.detect-agent-errors.outputs.inference_access_error || 'false' }}
521
+ invocation_cap_exceeded: ${{ steps.detect-agent-errors.outputs.invocation_cap_exceeded || 'false' }}
522
+ max_cache_misses_exceeded: ${{ steps.detect-agent-errors.outputs.max_cache_misses_exceeded || 'false' }}
523
+ mcp_policy_error: ${{ steps.detect-agent-errors.outputs.mcp_policy_error || 'false' }}
524
+ missing_model_pricing_error: ${{ steps.detect-agent-errors.outputs.missing_model_pricing_error || 'false' }}
525
+ missing_model_pricing_model_name: ${{ steps.detect-agent-errors.outputs.missing_model_pricing_model_name || '' }}
526
+ model: ${{ needs.activation.outputs.model }}
527
+ model_endpoint_mismatch_error: ${{ steps.detect-agent-errors.outputs.model_endpoint_mismatch_error || 'false' }}
528
+ model_not_supported_error: ${{ steps.detect-agent-errors.outputs.model_not_supported_error || 'false' }}
529
+ output: ${{ steps.collect_output.outputs.output }}
530
+ output_types: ${{ steps.collect_output.outputs.output_types }}
531
+ setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }}
532
+ setup-span-id: ${{ steps.setup.outputs.span-id }}
533
+ setup-trace-id: ${{ steps.setup.outputs.trace-id }}
534
+ shell_expansion_guard_rejected: ${{ steps.detect-agent-errors.outputs.shell_expansion_guard_rejected || 'false' }}
535
+ unknown_model_ai_credits: ${{ steps.parse-mcp-gateway.outputs.unknown_model_ai_credits || 'false' }}
536
+ steps:
537
+ - name: Setup Scripts
538
+ id: setup
539
+ uses: github/gh-aw-actions/setup@d9128eb3ea40c18b77c76184eda03c0ff2608d79 # v0.93.2
540
+ with:
541
+ destination: ${{ runner.temp }}/gh-aw/actions
542
+ job-name: ${{ github.job }}
543
+ trace-id: ${{ needs.activation.outputs.setup-trace-id }}
544
+ parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
545
+ env:
546
+ GH_AW_SETUP_WORKFLOW_NAME: "Lighthouse SDLC integrate"
547
+ GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/lighthouse-sdlc-integrate.lock.yml@${{ github.ref }}
548
+ GH_AW_INFO_VERSION: "1.0.101"
549
+ GH_AW_INFO_AWF_VERSION: "v0.28.70"
550
+ GH_AW_INFO_ENGINE_ID: "copilot"
551
+ GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }}
552
+ - name: Set runtime paths
553
+ id: set-runtime-paths
554
+ env:
555
+ GH_AW_RUNNER_TOOL_CACHE: ${{ runner.tool_cache }}
556
+ run: | # zizmor: ignore[github-env] - runner.tool_cache is set by GitHub Actions, not user input.
557
+ if [ -z "${RUNNER_TOOL_CACHE:-}" ]; then
558
+ echo "RUNNER_TOOL_CACHE=${GH_AW_RUNNER_TOOL_CACHE}" >> "$GITHUB_ENV"
559
+ fi
560
+ {
561
+ echo "GH_AW_SAFE_OUTPUTS=${RUNNER_TEMP}/gh-aw/safeoutputs/outputs.jsonl"
562
+ echo "GH_AW_SAFE_OUTPUTS_CONFIG_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/config.json"
563
+ echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json"
564
+ } >> "$GITHUB_OUTPUT"
565
+ - name: Mask OTLP telemetry headers
566
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh"
567
+ - name: Check OTLP telemetry configuration
568
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/check_otlp_default_credentials.sh"
569
+ - name: Checkout repository (gh-aw default)
570
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
571
+ with:
572
+ persist-credentials: false
573
+ fetch-depth: 0
574
+ - name: Initialize agent execution evidence
575
+ run: |
576
+ mkdir -p "/tmp/gh-aw"
577
+ evidence_tmp="/tmp/gh-aw/agent_execution.json.tmp"
578
+ printf '{"version":1,"component":"agent","run_id":%s,"run_attempt":%s,"state":"not_started"}\n' "$GITHUB_RUN_ID" "$GITHUB_RUN_ATTEMPT" > "$evidence_tmp"
579
+ mv "$evidence_tmp" "/tmp/gh-aw/agent_execution.json"
580
+ - name: Setup Node.js
581
+ uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
582
+ with:
583
+ node-version: '24'
584
+ package-manager-cache: false
585
+ - name: Create gh-aw temp directory
586
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/create_gh_aw_tmp_dir.sh"
587
+ - name: Configure gh CLI for GitHub Enterprise
588
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh"
589
+ env:
590
+ GH_TOKEN: ${{ github.token }}
591
+ - name: Download activation artifact
592
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
593
+ with:
594
+ name: ${{ needs.activation.outputs.artifact_prefix }}activation
595
+ path: /tmp/gh-aw
596
+ - env:
597
+ STAGE_INPUT: ${{ inputs.input }}
598
+ name: Materialize the host input
599
+ run: "set -euo pipefail\nmkdir -p /tmp/gh-aw/agent\nprintf '%s\\n' \"${STAGE_INPUT:-{}}\" > /tmp/gh-aw/agent/input.json\n"
600
+ shell: bash
601
+ - if: inputs.previous-stage != ''
602
+ name: Load the previous stage result
603
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
604
+ with:
605
+ name: lighthouse-sdlc-${{ inputs.run-id }}-${{ inputs.previous-stage }}
606
+ path: /tmp/gh-aw/agent/previous
607
+
608
+ - name: Configure Git credentials
609
+ env:
610
+ GITHUB_REPOSITORY: ${{ github.repository }}
611
+ GITHUB_SERVER_URL: ${{ github.server_url }}
612
+ GITHUB_TOKEN: ${{ github.token }}
613
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_git_credentials.sh"
614
+ - name: Checkout PR branch
615
+ id: checkout-pr
616
+ if: |
617
+ github.event.pull_request || github.event.issue.pull_request || github.event_name == 'workflow_dispatch'
618
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
619
+ env:
620
+ GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
621
+ with:
622
+ github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
623
+ script: |
624
+ const path = require('path');
625
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
626
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
627
+ setupGlobals(core, github, context, exec, io, getOctokit);
628
+ const { main } = require(path.join(actionsDir, 'checkout_pr_branch.cjs'));
629
+ await main();
630
+ - name: Install GitHub Copilot CLI
631
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.101 --checksums-sha256 018625eac68670d66ede904b9b82cdcd6ab8f87ba20e6e1fbdf0b62c8295d5be --prefer-toolcache
632
+ env:
633
+ GH_HOST: github.com
634
+ GH_AW_COPILOT_MIN_VERSION: 1.0.35
635
+ - name: Install AWF binary
636
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.28.70 --rootless
637
+ - name: Determine automatic lockdown mode for GitHub MCP Server
638
+ id: determine-automatic-lockdown
639
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
640
+ env:
641
+ GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }}
642
+ GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }}
643
+ with:
644
+ script: |
645
+ const path = require('path');
646
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
647
+ const determineAutomaticLockdown = require(path.join(actionsDir, 'determine_automatic_lockdown.cjs'));
648
+ await determineAutomaticLockdown(github, context, core);
649
+ - name: Restore agent config folders from base branch
650
+ if: steps.checkout-pr.outcome == 'success'
651
+ env:
652
+ GH_AW_AGENT_FOLDERS: ".agents .github"
653
+ GH_AW_AGENT_FILES: "AGENTS.md"
654
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_base_github_folders.sh"
655
+ - name: Restore inline sub-agents from activation artifact
656
+ env:
657
+ GH_AW_SUB_AGENT_DIR: ".github/agents"
658
+ GH_AW_SUB_AGENT_EXT: ".agent.md"
659
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_sub_agents.sh"
660
+ - name: Restore inline skills from activation artifact
661
+ env:
662
+ GH_AW_SKILL_DIR: ".github/skills"
663
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh"
664
+ - name: Download container images
665
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.28.70@sha256:b15ab48cbbab02904eb9bbd359a398db59690eebbea1e6934d47ed2bb407dd34 ghcr.io/github/gh-aw-firewall/api-proxy:0.28.70@sha256:9ac8f9c7294e892c916de3da9d2588dfd8cd4931e5c39b00143266d7ed9fd52a ghcr.io/github/gh-aw-firewall/squid:0.28.70@sha256:b5bc53f4becfd96e926e63c83831f1b3c9512f713c83161d2b8c9b7204b3e917 ghcr.io/github/gh-aw-mcpg:v0.4.37@sha256:9c7f242f6dec2d7d7b55d4c9e07872d59b85377c6cb3de46c915a5d1ffb91442 ghcr.io/github/gh-aw-node@sha256:41835613992df88f51e923bad486f96dfb2e6cda29f13e217df41833284ae382 ghcr.io/github/github-mcp-server:v2.0.2@sha256:ffced0d76e77428532a2ced185516992d77fd146d69eec2f244e6237d1a97796
666
+ - name: Prepare Safe Outputs Directories
667
+ run: |
668
+ mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs"
669
+ mkdir -p /tmp/gh-aw/safeoutputs
670
+ mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs
671
+ - name: Generate Safe Outputs Config
672
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
673
+ env:
674
+ GH_AW_FILE_ROOT: "${{ runner.temp }}/gh-aw"
675
+ GH_AW_FILE_CONFIG: "{\"files\":[{\"path\":\"safeoutputs/config.json\",\"content_env\":\"GH_AW_SAFE_OUTPUTS_CONFIG\"}]}"
676
+ GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_report_incomplete_issue\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"false\"},\"report_incomplete\":{},\"report_missing_data\":{},\"report_missing_tool\":{}}"
677
+ with:
678
+ script: |
679
+ const path = require('path');
680
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
681
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
682
+ setupGlobals(core, github, context, exec, io, getOctokit);
683
+ const { main } = require(path.join(actionsDir, 'create_files.cjs'));
684
+ await main();
685
+ - name: Generate Safe Outputs Tools
686
+ env:
687
+ GH_AW_TOOLS_META_JSON: |
688
+ {
689
+ "description_suffixes": {},
690
+ "repo_params": {},
691
+ "dynamic_tools": []
692
+ }
693
+ GH_AW_VALIDATION_JSON: |
694
+ {
695
+ "noop": {
696
+ "defaultMax": 2,
697
+ "fields": {
698
+ "message": {
699
+ "required": true,
700
+ "type": "string",
701
+ "sanitize": true,
702
+ "maxLength": 65000
703
+ }
704
+ }
705
+ },
706
+ "report_incomplete": {
707
+ "defaultMax": 5,
708
+ "fields": {
709
+ "details": {
710
+ "type": "string",
711
+ "sanitize": true,
712
+ "maxLength": 65000
713
+ },
714
+ "reason": {
715
+ "required": true,
716
+ "type": "string",
717
+ "sanitize": true,
718
+ "maxLength": 1024
719
+ }
720
+ }
721
+ },
722
+ "report_missing_data": {
723
+ "defaultMax": 20,
724
+ "fields": {
725
+ "alternatives": {
726
+ "type": "string",
727
+ "sanitize": true,
728
+ "maxLength": 256
729
+ },
730
+ "context": {
731
+ "type": "string",
732
+ "sanitize": true,
733
+ "maxLength": 256
734
+ },
735
+ "data_type": {
736
+ "type": "string",
737
+ "sanitize": true,
738
+ "maxLength": 128
739
+ },
740
+ "reason": {
741
+ "type": "string",
742
+ "sanitize": true,
743
+ "maxLength": 256
744
+ }
745
+ }
746
+ },
747
+ "report_missing_tool": {
748
+ "defaultMax": 20,
749
+ "fields": {
750
+ "alternatives": {
751
+ "type": "string",
752
+ "sanitize": true,
753
+ "maxLength": 512
754
+ },
755
+ "reason": {
756
+ "required": true,
757
+ "type": "string",
758
+ "sanitize": true,
759
+ "maxLength": 256
760
+ },
761
+ "tool": {
762
+ "type": "string",
763
+ "sanitize": true,
764
+ "maxLength": 128
765
+ }
766
+ }
767
+ }
768
+ }
769
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
770
+ with:
771
+ script: |
772
+ const path = require('path');
773
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
774
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
775
+ setupGlobals(core, github, context, exec, io, getOctokit);
776
+ const { main } = require(path.join(actionsDir, 'generate_safe_outputs_tools.cjs'));
777
+ await main();
778
+ - name: Start MCP Gateway
779
+ id: start-mcp-gateway
780
+ env:
781
+ DEBUG: ${{ env.DEBUG || runner.debug == '1' && '*' || '' }}
782
+ GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST: ${{ vars.GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST || 'true' }}
783
+ GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
784
+ GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS_CONFIG_PATH }}
785
+ GH_AW_SAFE_OUTPUTS_TOOLS_PATH: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS_TOOLS_PATH }}
786
+ GH_AW_SINK_VISIBILITY: ${{ steps.determine-automatic-lockdown.outputs.visibility }}
787
+ GITHUB_MCP_GUARD_MIN_INTEGRITY: ${{ steps.determine-automatic-lockdown.outputs.min_integrity }}
788
+ GITHUB_MCP_GUARD_REPOS: ${{ steps.determine-automatic-lockdown.outputs.repos }}
789
+ GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
790
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
791
+ run: |
792
+ set -eo pipefail
793
+ mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-config"
794
+ if [ -n "${GITHUB_EVENT_PATH:-}" ] && [ -r "${GITHUB_EVENT_PATH}" ]; then
795
+ GH_AW_SAFEOUTPUTS_EVENT_PATH="${RUNNER_TEMP}/gh-aw/safeoutputs/github_event.json"
796
+ cp "${GITHUB_EVENT_PATH}" "${GH_AW_SAFEOUTPUTS_EVENT_PATH}"
797
+ export GITHUB_EVENT_PATH="${GH_AW_SAFEOUTPUTS_EVENT_PATH}"
798
+ fi
799
+
800
+ # Export gateway environment variables for MCP config and gateway script
801
+ export MCP_GATEWAY_PORT="8080"
802
+ export MCP_GATEWAY_DOMAIN="awmg-mcpg"
803
+ export MCP_GATEWAY_HOST_DOMAIN="localhost"
804
+ MCP_GATEWAY_AGENT_ID=$(openssl rand -base64 45 | tr -d '/+=')
805
+ echo "::add-mask::${MCP_GATEWAY_AGENT_ID}"
806
+ export MCP_GATEWAY_AGENT_ID
807
+ export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads"
808
+ mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}"
809
+ export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288"
810
+ export MCP_GATEWAY_ALLOWED_MOUNT_ROOTS="${GITHUB_WORKSPACE}:rw,${RUNNER_TEMP}/gh-aw:ro,${RUNNER_TEMP}/gh-aw/safeoutputs:rw,/opt:ro,/tmp:rw,/usr/bin/gh:ro"
811
+ export GH_AW_PR_HEAD_BASE_BRANCH="${GH_AW_PR_HEAD_BASE_BRANCH:-}"
812
+ export GH_AW_PR_HEAD_BASE_SHA="${GH_AW_PR_HEAD_BASE_SHA:-}"
813
+ export GH_AW_PR_HEAD_BASE_REPO="${GH_AW_PR_HEAD_BASE_REPO:-}"
814
+ export GH_AW_PR_HEAD_BASE_PR_NUMBER="${GH_AW_PR_HEAD_BASE_PR_NUMBER:-}"
815
+ export GH_AW_PR_HEAD_BASE_REF="${GH_AW_PR_HEAD_BASE_REF:-}"
816
+ export GH_AW_PR_HEAD_REPO="${GH_AW_PR_HEAD_REPO:-}"
817
+ export GH_AW_TARGET_REPO_SLUG="${GH_AW_TARGET_REPO_SLUG:-}"
818
+ export GH_AW_ENGINE="copilot"
819
+ MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0')
820
+ MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0')
821
+ source "${RUNNER_TEMP}/gh-aw/actions/resolve_docker_socket_gid.sh"
822
+ export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network bridge -p 127.0.0.1:'"${MCP_GATEWAY_PORT}"':'"${MCP_GATEWAY_PORT}"' --name awmg-mcpg --add-host host.docker.internal:host-gateway --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_AGENT_ID -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_TARGET_REPO_SLUG -e GH_AW_PR_HEAD_BASE_BRANCH -e GH_AW_PR_HEAD_BASE_SHA -e GH_AW_PR_HEAD_BASE_REPO -e GH_AW_PR_HEAD_BASE_PR_NUMBER -e GH_AW_PR_HEAD_BASE_REF -e GH_AW_PR_HEAD_REPO -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 GH_AW_SINK_VISIBILITY -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 -e RUNNER_TOOL_CACHE -e MCP_GATEWAY_ALLOWED_MOUNT_ROOTS -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -e OTEL_EXPORTER_OTLP_HEADERS -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.4.37@sha256:9c7f242f6dec2d7d7b55d4c9e07872d59b85377c6cb3de46c915a5d1ffb91442'
823
+
824
+ mkdir -p "$HOME/.copilot"
825
+ GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node)
826
+ cat << GH_AW_MCP_CONFIG_3db6aaf67c51d953_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
827
+ {
828
+ "mcpServers": {
829
+ "github": {
830
+ "type": "stdio",
831
+ "container": "ghcr.io/github/github-mcp-server:v2.0.2",
832
+ "env": {
833
+ "GITHUB_FEATURES": "fields_param",
834
+ "GITHUB_HOST": "${GITHUB_SERVER_URL}",
835
+ "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_MCP_SERVER_TOKEN}",
836
+ "GITHUB_READ_ONLY": "1",
837
+ "GITHUB_TOOLSETS": "repos,issues,pull_requests"
838
+ },
839
+ "guard-policies": {
840
+ "allow-only": {
841
+ "min-integrity": "$GITHUB_MCP_GUARD_MIN_INTEGRITY",
842
+ "repos": "$GITHUB_MCP_GUARD_REPOS"
843
+ }
844
+ }
845
+ },
846
+ "safeoutputs": {
847
+ "type": "stdio",
848
+ "container": "ghcr.io/github/gh-aw-node@sha256:41835613992df88f51e923bad486f96dfb2e6cda29f13e217df41833284ae382",
849
+ "mounts": ["\${GITHUB_WORKSPACE}:\${GITHUB_WORKSPACE}:rw", "${RUNNER_TEMP}/gh-aw/safeoutputs:${RUNNER_TEMP}/gh-aw/safeoutputs:rw", "/tmp/gh-aw:/tmp/gh-aw:rw"],
850
+ "args": ["-w", "\${GITHUB_WORKSPACE}"],
851
+ "entrypoint": "sh",
852
+ "entrypointArgs": ["-c", "sh ${RUNNER_TEMP}/gh-aw/safeoutputs/start_safe_outputs_mcp.sh"],
853
+ "env": {
854
+ "DEBUG": "\${DEBUG}",
855
+ "DEFAULT_BRANCH": "\${DEFAULT_BRANCH}",
856
+ "GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}",
857
+ "GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}",
858
+ "GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}",
859
+ "GH_AW_MCP_LOG_DIR": "\${GH_AW_MCP_LOG_DIR}",
860
+ "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}",
861
+ "GH_AW_SAFE_OUTPUTS_CONFIG_PATH": "\${GH_AW_SAFE_OUTPUTS_CONFIG_PATH}",
862
+ "GH_AW_SAFE_OUTPUTS_TOOLS_PATH": "\${GH_AW_SAFE_OUTPUTS_TOOLS_PATH}",
863
+ "GH_AW_TARGET_REPO_SLUG": "\${GH_AW_TARGET_REPO_SLUG}",
864
+ "GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST": "\${GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST}",
865
+ "GH_AW_PR_HEAD_BASE_BRANCH": "\${GH_AW_PR_HEAD_BASE_BRANCH}",
866
+ "GH_AW_PR_HEAD_BASE_SHA": "\${GH_AW_PR_HEAD_BASE_SHA}",
867
+ "GH_AW_PR_HEAD_BASE_REPO": "\${GH_AW_PR_HEAD_BASE_REPO}",
868
+ "GH_AW_PR_HEAD_BASE_PR_NUMBER": "\${GH_AW_PR_HEAD_BASE_PR_NUMBER}",
869
+ "GH_AW_PR_HEAD_BASE_REF": "\${GH_AW_PR_HEAD_BASE_REF}",
870
+ "GH_AW_PR_HEAD_REPO": "\${GH_AW_PR_HEAD_REPO}",
871
+ "GITHUB_EVENT_NAME": "\${GITHUB_EVENT_NAME}",
872
+ "GITHUB_EVENT_PATH": "\${GITHUB_EVENT_PATH}",
873
+ "GITHUB_REPOSITORY": "\${GITHUB_REPOSITORY}",
874
+ "GITHUB_SHA": "\${GITHUB_SHA}",
875
+ "GITHUB_TOKEN": "\${GITHUB_TOKEN}",
876
+ "GITHUB_WORKSPACE": "\${GITHUB_WORKSPACE}",
877
+ "RUNNER_TEMP": "\${RUNNER_TEMP}"
878
+ },
879
+ "guard-policies": {
880
+ "write-sink": {
881
+ "accept": [
882
+ "*"
883
+ ],
884
+ "sink-visibility": "${GH_AW_SINK_VISIBILITY}"
885
+ }
886
+ }
887
+ }
888
+ },
889
+ "gateway": {
890
+ "port": $MCP_GATEWAY_PORT,
891
+ "domain": "${MCP_GATEWAY_DOMAIN}",
892
+ "agentId": "${MCP_GATEWAY_AGENT_ID}",
893
+ "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}",
894
+ "startupTimeout": 120,
895
+ "opentelemetry": {
896
+ "endpoint": "${OTEL_EXPORTER_OTLP_ENDPOINT}",
897
+ "traceId": "${GITHUB_AW_OTEL_TRACE_ID}",
898
+ "spanId": "${GITHUB_AW_OTEL_PARENT_SPAN_ID}"
899
+ }
900
+ }
901
+ }
902
+ GH_AW_MCP_CONFIG_3db6aaf67c51d953_EOF
903
+ - name: Mount MCP servers as CLIs
904
+ id: mount-mcp-clis
905
+ continue-on-error: true
906
+ env:
907
+ MCP_GATEWAY_AGENT_ID: ${{ steps.start-mcp-gateway.outputs.gateway-agent-id }}
908
+ MCP_GATEWAY_DOMAIN: ${{ steps.start-mcp-gateway.outputs.gateway-domain }}
909
+ MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }}
910
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
911
+ with:
912
+ script: |
913
+ const path = require('path');
914
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
915
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
916
+ setupGlobals(core, github, context, exec, io);
917
+ const { main } = require(path.join(actionsDir, 'mount_mcp_as_cli.cjs'));
918
+ await main();
919
+ - name: Clean credentials
920
+ run: |
921
+ bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh"
922
+ bash "${RUNNER_TEMP}/gh-aw/actions/verify_git_credentials.sh"
923
+ - name: Audit pre-agent workspace
924
+ id: pre_agent_audit
925
+ continue-on-error: true
926
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh"
927
+ - name: Log GitHub rate limits at agent start
928
+ continue-on-error: true
929
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
930
+ with:
931
+ github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
932
+ script: |
933
+ const path = require('path');
934
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
935
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
936
+ setupGlobals(core, github, context, exec, io, getOctokit);
937
+ const { fetchAndLogRateLimit } = require(path.join(actionsDir, 'github_rate_limit_logger.cjs'));
938
+ await fetchAndLogRateLimit(github, 'agent_start', true);
939
+ - name: Execute GitHub Copilot CLI
940
+ id: agentic_execution
941
+ # Copilot CLI tool arguments (sorted):
942
+ # --allow-tool github
943
+ # --allow-tool safeoutputs
944
+ # --allow-tool shell(cat)
945
+ # --allow-tool shell(date)
946
+ # --allow-tool shell(echo)
947
+ # --allow-tool shell(find)
948
+ # --allow-tool shell(git:*)
949
+ # --allow-tool shell(github:*)
950
+ # --allow-tool shell(grep)
951
+ # --allow-tool shell(head)
952
+ # --allow-tool shell(ls)
953
+ # --allow-tool shell(node)
954
+ # --allow-tool shell(npm:*)
955
+ # --allow-tool shell(npx:*)
956
+ # --allow-tool shell(printf)
957
+ # --allow-tool shell(pwd)
958
+ # --allow-tool shell(rg)
959
+ # --allow-tool shell(safeoutputs:*)
960
+ # --allow-tool shell(sort)
961
+ # --allow-tool shell(tail)
962
+ # --allow-tool shell(uniq)
963
+ # --allow-tool shell(wc)
964
+ # --allow-tool shell(yq)
965
+ # --allow-tool write
966
+ timeout-minutes: ${{ fromJSON(vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || '20') }}
967
+ run: |
968
+ set -o pipefail
969
+ printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt
970
+ gh_aw_exit_code=0
971
+ trap 'gh_aw_exit_code=$?; mkdir -p /tmp/gh-aw >/dev/null 2>&1 || true; printf "%s" "$gh_aw_exit_code" > /tmp/gh-aw/agent_execution_exit_code.txt || true; rm -f "$HOME/.copilot/settings.json"; if [ "$gh_aw_exit_code" -ne 0 ]; then echo "::error::Agent execution exited with code $gh_aw_exit_code"; fi' EXIT
972
+ mkdir -p "$HOME/.copilot"
973
+ printf '%s' '{"builtInAgents":{"rubberDuck":false},"enabledFeatureFlags":{"EXTENSIONS":false}}' > "$HOME/.copilot/settings.json"
974
+ export XDG_CONFIG_HOME="$HOME"
975
+ export GH_AW_MCP_CONFIG="$HOME/.copilot/mcp-config.json"
976
+ GH_AW_COPILOT_SRC="$(command -v copilot 2>/dev/null || true)"
977
+ if [ -z "$GH_AW_COPILOT_SRC" ] || [ ! -x "$GH_AW_COPILOT_SRC" ]; then
978
+ echo "GitHub Copilot CLI executable not found on PATH after installation" >&2
979
+ exit 127
980
+ fi
981
+ GH_AW_COPILOT_BIN="${RUNNER_TEMP}/gh-aw/bin/copilot"
982
+ mkdir -p "${RUNNER_TEMP}/gh-aw/bin"
983
+ if [ "$GH_AW_COPILOT_SRC" != "$GH_AW_COPILOT_BIN" ]; then
984
+ cp "$GH_AW_COPILOT_SRC" "$GH_AW_COPILOT_BIN"
985
+ fi
986
+ chmod 755 "$GH_AW_COPILOT_BIN"
987
+
988
+ touch /tmp/gh-aw/agent-step-summary.md
989
+ GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true)
990
+ export GH_AW_NODE_BIN
991
+ export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK"
992
+ (umask 177 && touch /tmp/gh-aw/agent-stdio.log)
993
+ GH_AW_MAX_AI_CREDITS="${GH_AW_MAX_AI_CREDITS:-1000}"
994
+ if [[ ! "$GH_AW_MAX_AI_CREDITS" =~ ^[0-9]+$ ]]; then
995
+ GH_AW_MAX_AI_CREDITS="1000"
996
+ fi
997
+ if [[ "${GH_AW_ADMISSION_RESULT:-}" == "admitted" && -z "${GH_AW_ADMISSION_MAX_AI_CREDITS:-}" ]]; then
998
+ echo "ERR_ADMISSION: Missing required runtime admission allowance." >&2
999
+ exit 1
1000
+ fi
1001
+
1002
+ if [[ "${GH_AW_ADMISSION_RESULT:-}" == "admitted" && -n "${GH_AW_ADMISSION_MAX_AI_CREDITS:-}" ]]; then
1003
+ if [[ ! "$GH_AW_ADMISSION_MAX_AI_CREDITS" =~ ^[1-9][0-9]{0,9}$ ]] || (( GH_AW_ADMISSION_MAX_AI_CREDITS > 2147483647 )); then
1004
+ echo "ERR_ADMISSION: Invalid runtime admission allowance." >&2
1005
+ exit 1
1006
+ fi
1007
+ GH_AW_MAX_AI_CREDITS="$GH_AW_ADMISSION_MAX_AI_CREDITS"
1008
+ echo "Admission allowance applied (value withheld)."
1009
+ else
1010
+ echo "No component admission allowance; retaining existing budget policy (value withheld)."
1011
+ fi
1012
+ unset GH_AW_ADMISSION_RESULT GH_AW_ADMISSION_MAX_AI_CREDITS
1013
+ printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.28.70/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"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\",\"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\",\"s.symcb.com\",\"s.symcd.com\",\"security.ubuntu.com\",\"ts-crl.ws.symantec.com\",\"ts-ocsp.ws.symantec.com\",\"www.googleapis.com\"],\"isolation\":true,\"topologyAttach\":[\"awmg-mcpg\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5,\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-6\",\"gpt-5.4\",\"gpt-5.5\",\"gpt-5.6\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"auto\":[\"copilot/auto\",\"large\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\",\"kimi\"],\"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*\"],\"detection\":[\"small\"],\"evals\":[\"small\"],\"fable\":[\"copilot/*fable*\",\"anthropic/*fable*\"],\"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-3.6-flash\":[\"copilot/gemini-3.6*flash*\",\"google/gemini-3.6*flash*\",\"gemini/gemini-3.6*flash*\"],\"gemini-3.7-flash\":[\"copilot/gemini-3.7*flash*\",\"google/gemini-3.7*flash*\",\"gemini/gemini-3.7*flash*\"],\"gemini-3.8-flash\":[\"copilot/gemini-3.8*flash*\",\"google/gemini-3.8*flash*\",\"gemini/gemini-3.8*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-omni\":[\"copilot/gemini-omni*\",\"google/gemini-omni*\",\"gemini/gemini-omni*\"],\"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*\"],\"gpt-5.6\":[\"copilot/gpt-5.6*\",\"openai/gpt-5.6*\"],\"gpt-6\":[\"copilot/gpt-6*\",\"openai/gpt-6*\"],\"grok\":[\"copilot/*grok*\",\"openai/*grok*\"],\"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*\"],\"kimi\":[\"copilot/kimi*\",\"openai/kimi*\"],\"kiwi\":[\"copilot/kiwi*\",\"openai/kiwi*\"],\"large\":[\"sonnet\",\"gpt-6\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"lyria\":[\"google/lyria*\",\"gemini/lyria*\",\"copilot/lyria*\"],\"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\"],\"raptor-mini\":[\"copilot/raptor*\",\"openai/raptor*\"],\"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-5*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\",\"anthropic/*sonnet-5*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"veo\":[\"google/veo*\",\"gemini/veo*\"],\"vision\":[\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.28.70,squid=sha256:b5bc53f4becfd96e926e63c83831f1b3c9512f713c83161d2b8c9b7204b3e917,agent=sha256:b15ab48cbbab02904eb9bbd359a398db59690eebbea1e6934d47ed2bb407dd34,api-proxy=sha256:9ac8f9c7294e892c916de3da9d2588dfd8cd4931e5c39b00143266d7ed9fd52a,cli-proxy=sha256:372ac51a5cccffdfe484f3f7be427d2d1c566e8ae550d55bd45d9fd166a154b4\"},\"logging\":{\"proxyLogsDir\":\"/tmp/gh-aw/sandbox/firewall/logs\",\"auditDir\":\"/tmp/gh-aw/sandbox/firewall/audit\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json"
1014
+ cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
1015
+ export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json"
1016
+ GH_AW_DOCKER_HOST=""
1017
+ if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
1018
+ GH_AW_DOCKER_HOST="${DOCKER_HOST}"
1019
+ fi
1020
+ if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
1021
+ GH_AW_CHROOT_BINARIES_SOURCE_PATH="${RUNNER_TEMP}/gh-aw" GH_AW_CHROOT_IDENTITY_HOME="${RUNNER_TEMP}/gh-aw/home" node "${RUNNER_TEMP}/gh-aw/actions/patch_awf_chroot_config.cjs"
1022
+ fi
1023
+ GH_AW_TOOL_CACHE_MOUNT=""
1024
+ GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"
1025
+ if [ -d "$GH_AW_TOOL_CACHE" ]; then
1026
+ if [[ "$GH_AW_TOOL_CACHE" != /opt/* ]]; then
1027
+ GH_AW_TOOL_CACHE_MOUNT="$GH_AW_TOOL_CACHE:$GH_AW_TOOL_CACHE:ro"
1028
+ fi
1029
+ fi
1030
+ # shellcheck disable=SC1003,SC2016,SC2086
1031
+ mkdir -p "/tmp/gh-aw"
1032
+ evidence_tmp="/tmp/gh-aw/agent_execution.json.tmp"
1033
+ printf '{"version":1,"component":"agent","run_id":%s,"run_attempt":%s,"state":"started"}\n' "$GITHUB_RUN_ID" "$GITHUB_RUN_ATTEMPT" > "$evidence_tmp"
1034
+ mv "$evidence_tmp" "/tmp/gh-aw/agent_execution.json"
1035
+ export GH_AW_AWF_EXECUTION_COMPONENT="agent"
1036
+ export GH_AW_AWF_EXECUTION_EVIDENCE_FILE="/tmp/gh-aw/agent_execution.json"
1037
+ GH_AW_AWF_ENGINE_NAME=copilot \
1038
+ GH_AW_AWF_HARNESS_MARKER='[copilot-harness]' \
1039
+ GH_AW_AWF_LOG_FILE=/tmp/gh-aw/agent-stdio.log \
1040
+ GH_AW_AWF_ATTEMPT_LOG_NAME=copilot \
1041
+ bash "${RUNNER_TEMP}/gh-aw/actions/run_awf_with_startup_retries.sh" -- \
1042
+ 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_ENGINE_STEP_TIMEOUT_MINUTES:+--agent-timeout "$GH_AW_ENGINE_STEP_TIMEOUT_MINUTES"} ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_AW_OTLP_ALL_HEADERS --exclude-env GH_AW_OTLP_ENDPOINTS --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_AGENT_ID --exclude-env OTEL_EXPORTER_OTLP_ENDPOINT --exclude-env OTEL_EXPORTER_OTLP_HEADERS --mount /tmp/gh-aw:/tmp/gh-aw:rw --log-level info --session-state-dir /tmp/gh-aw/sandbox/agent/session-state --skip-pull \
1043
+ -- /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"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr "\n" ":")"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/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" "${RUNNER_TEMP}/gh-aw/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-tool github --allow-tool safeoutputs --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(find)'\'' --allow-tool '\''shell(git:*)'\'' --allow-tool '\''shell(github:*)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(node)'\'' --allow-tool '\''shell(npm:*)'\'' --allow-tool '\''shell(npx:*)'\'' --allow-tool '\''shell(printf)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(rg)'\'' --allow-tool '\''shell(safeoutputs:*)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --deny-tool workflow --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt'
1044
+ env:
1045
+ AWF_REFLECT_ENABLED: 1
1046
+ COPILOT_AGENT_RUNNER_TYPE: STANDALONE
1047
+ COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode
1048
+ COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
1049
+ COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }}
1050
+ GH_AW_ADMISSION_MAX_AI_CREDITS: ${{ needs.activation.outputs.admission-max-ai-credits }}
1051
+ GH_AW_ADMISSION_RESULT: ${{ needs.activation.outputs.admission-result }}
1052
+ GH_AW_ENGINE_STEP_TIMEOUT_MINUTES: ${{ fromJSON(vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || '20') }}
1053
+ GH_AW_LLM_PROVIDER: github
1054
+ GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}
1055
+ GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
1056
+ GH_AW_PHASE: agent
1057
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
1058
+ GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
1059
+ GH_AW_TIMEOUT_MINUTES: ${{ fromJSON(vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || '20') }}
1060
+ GH_AW_VERSION: v0.93.2
1061
+ GITHUB_API_URL: ${{ github.api_url }}
1062
+ GITHUB_AW: true
1063
+ GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows
1064
+ GITHUB_COPILOT_PROMPT_MODE_EXTENSIONS: false
1065
+ GITHUB_HEAD_REF: ${{ github.head_ref }}
1066
+ GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1067
+ GITHUB_REF_NAME: ${{ github.ref_name }}
1068
+ GITHUB_SERVER_URL: ${{ github.server_url }}
1069
+ GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md
1070
+ GITHUB_WORKSPACE: ${{ github.workspace }}
1071
+ GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
1072
+ GIT_AUTHOR_NAME: github-actions[bot]
1073
+ GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
1074
+ GIT_COMMITTER_NAME: github-actions[bot]
1075
+ RUNNER_TEMP: ${{ runner.temp }}
1076
+ 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) || '' }}
1077
+ - name: Log GitHub rate limits at agent end
1078
+ if: always()
1079
+ continue-on-error: true
1080
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1081
+ with:
1082
+ github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1083
+ script: |
1084
+ const path = require('path');
1085
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1086
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1087
+ setupGlobals(core, github, context, exec, io, getOctokit);
1088
+ const { fetchAndLogRateLimit } = require(path.join(actionsDir, 'github_rate_limit_logger.cjs'));
1089
+ await fetchAndLogRateLimit(github, 'agent_end', true);
1090
+ - name: Detect agent errors
1091
+ if: always()
1092
+ id: detect-agent-errors
1093
+ continue-on-error: true
1094
+ env:
1095
+ GH_AW_AGENTIC_EXECUTION_OUTCOME: ${{ steps.agentic_execution.outcome }}
1096
+ GH_AW_ENGINE_STEP_TIMEOUT_MINUTES: ${{ fromJSON(vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || '20') }}
1097
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1098
+ with:
1099
+ script: |
1100
+ const path = require('path');
1101
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1102
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1103
+ setupGlobals(core, github, context, exec, io, getOctokit);
1104
+ const { main } = require(path.join(actionsDir, 'detect_agent_errors.cjs'));
1105
+ await main();
1106
+ - name: Configure Git credentials
1107
+ env:
1108
+ GITHUB_REPOSITORY: ${{ github.repository }}
1109
+ GITHUB_SERVER_URL: ${{ github.server_url }}
1110
+ GITHUB_TOKEN: ${{ github.token }}
1111
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_git_credentials.sh"
1112
+ - name: Copy Copilot session state files to logs
1113
+ if: always()
1114
+ continue-on-error: true
1115
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh"
1116
+ - name: Stop MCP Gateway
1117
+ if: always()
1118
+ continue-on-error: true
1119
+ env:
1120
+ MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }}
1121
+ MCP_GATEWAY_AGENT_ID: ${{ steps.start-mcp-gateway.outputs.gateway-agent-id }}
1122
+ GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }}
1123
+ run: |
1124
+ bash "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID"
1125
+ - name: Redact secrets in logs
1126
+ id: redact_secrets
1127
+ if: always()
1128
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1129
+ with:
1130
+ script: |
1131
+ const path = require('path');
1132
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1133
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1134
+ setupGlobals(core, github, context, exec, io, getOctokit);
1135
+ const { main } = require(path.join(actionsDir, 'redact_secrets.cjs'));
1136
+ await main();
1137
+ env:
1138
+ GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN'
1139
+ SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
1140
+ SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }}
1141
+ SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }}
1142
+ SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1143
+ - name: Append agent step summary
1144
+ if: always()
1145
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/append_agent_step_summary.sh"
1146
+ - name: Copy Safe Outputs
1147
+ if: always()
1148
+ env:
1149
+ GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
1150
+ run: |
1151
+ mkdir -p /tmp/gh-aw
1152
+ cp "$GH_AW_SAFE_OUTPUTS" /tmp/gh-aw/safeoutputs.jsonl 2>/dev/null || true
1153
+ - name: Ingest agent output
1154
+ id: collect_output
1155
+ if: always()
1156
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1157
+ env:
1158
+ GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
1159
+ GH_AW_ALLOWED_DOMAINS: "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,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,s.symcb.com,s.symcd.com,security.ubuntu.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com"
1160
+ GITHUB_SERVER_URL: ${{ github.server_url }}
1161
+ GITHUB_API_URL: ${{ github.api_url }}
1162
+ with:
1163
+ script: |
1164
+ const path = require('path');
1165
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1166
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1167
+ setupGlobals(core, github, context, exec, io, getOctokit);
1168
+ const { main } = require(path.join(actionsDir, 'collect_ndjson_output.cjs'));
1169
+ await main();
1170
+ - name: Parse agent logs for step summary
1171
+ if: always()
1172
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1173
+ env:
1174
+ GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/
1175
+ GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
1176
+ with:
1177
+ script: |
1178
+ const path = require('path');
1179
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1180
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1181
+ setupGlobals(core, github, context, exec, io, getOctokit);
1182
+ const { main } = require(path.join(actionsDir, 'parse_copilot_log.cjs'));
1183
+ await main();
1184
+ - name: Parse MCP Gateway logs for step summary
1185
+ if: always()
1186
+ id: parse-mcp-gateway
1187
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1188
+ with:
1189
+ script: |
1190
+ const path = require('path');
1191
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1192
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1193
+ setupGlobals(core, github, context, exec, io, getOctokit);
1194
+ const { main } = require(path.join(actionsDir, 'parse_mcp_gateway_log.cjs'));
1195
+ await main();
1196
+ - name: Print firewall logs
1197
+ if: always()
1198
+ continue-on-error: true
1199
+ env:
1200
+ AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs
1201
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/print_firewall_logs.sh" --rootless
1202
+ - name: Parse token usage for step summary
1203
+ if: always()
1204
+ id: parse-token-usage
1205
+ continue-on-error: true
1206
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1207
+ with:
1208
+ script: |
1209
+ const path = require('path');
1210
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1211
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1212
+ setupGlobals(core, github, context, exec, io, getOctokit);
1213
+ const { main } = require(path.join(actionsDir, 'parse_token_usage.cjs'));
1214
+ await main();
1215
+ - name: Print AWF reflect summary
1216
+ if: always()
1217
+ continue-on-error: true
1218
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1219
+ with:
1220
+ script: |
1221
+ const path = require('path');
1222
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1223
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1224
+ setupGlobals(core, github, context, exec, io, getOctokit);
1225
+ const { main } = require(path.join(actionsDir, 'awf_reflect_summary.cjs'));
1226
+ await main();
1227
+ - name: Generate observability summary
1228
+ if: always()
1229
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1230
+ with:
1231
+ script: |
1232
+ const path = require('path');
1233
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1234
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1235
+ setupGlobals(core, github, context, exec, io, getOctokit);
1236
+ const { main } = require(path.join(actionsDir, 'generate_observability_summary.cjs'));
1237
+ await main(core);
1238
+ - name: Write agent output placeholder if missing
1239
+ if: always()
1240
+ run: |
1241
+ if [ ! -f /tmp/gh-aw/agent_output.json ]; then
1242
+ echo '{"items":[]}' > /tmp/gh-aw/agent_output.json
1243
+ fi
1244
+ - if: always()
1245
+ name: Preserve the stage result
1246
+ run: |
1247
+ set -euo pipefail
1248
+ mkdir -p "$GITHUB_WORKSPACE/.lighthouse/gh-aw"
1249
+ result=/tmp/gh-aw/agent/stage-result.json
1250
+ if [ -f "$result" ]; then
1251
+ cp "$result" "$GITHUB_WORKSPACE/.lighthouse/gh-aw/stage-result.json"
1252
+ else
1253
+ echo "::error::The worker did not produce /tmp/gh-aw/agent/stage-result.json"
1254
+ exit 1
1255
+ fi
1256
+ shell: bash
1257
+ - env:
1258
+ EXPECTED_STAGE: ${{ env.LIGHTHOUSE_STAGE }}
1259
+ RESULT_FILE: /tmp/gh-aw/agent/stage-result.json
1260
+ if: always()
1261
+ name: Validate the stage result and declared gate
1262
+ run: |
1263
+ set -euo pipefail
1264
+ node src/packages/sdlc/src/sdlc.mjs stage-result --input "$RESULT_FILE" --format json
1265
+ EXPECTED_STAGE="$EXPECTED_STAGE" RESULT_FILE="$RESULT_FILE" node --input-type=module <<'NODE'
1266
+ import { readFileSync } from 'node:fs';
1267
+
1268
+ const stage = process.env.EXPECTED_STAGE;
1269
+ const result = JSON.parse(readFileSync(process.env.RESULT_FILE, 'utf8'));
1270
+ const contract = JSON.parse(readFileSync('src/packages/sdlc/stages.json', 'utf8'));
1271
+ const expected = contract.stages.find((item) => item.id === stage);
1272
+ if (!expected || result.stage !== stage || result.gate !== expected.gate) {
1273
+ console.error(`stage-result does not match stages.json for ${stage}`);
1274
+ process.exit(1);
1275
+ }
1276
+ NODE
1277
+ shell: bash
1278
+ - if: always()
1279
+ name: Upload stage evidence
1280
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
1281
+ with:
1282
+ if-no-files-found: warn
1283
+ name: lighthouse-sdlc-${{ inputs.run-id }}-${{ env.LIGHTHOUSE_STAGE }}
1284
+ path: ${{ github.workspace }}/.lighthouse/gh-aw/stage-result.json
1285
+ retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '14' }}
1286
+
1287
+ # Small dedicated copy of the agent output so safe-output processing
1288
+ # survives a failed or timed-out upload of the larger agent artifact
1289
+ - name: Upload agent output fallback artifact
1290
+ if: always() && steps.redact_secrets.outcome == 'success'
1291
+ continue-on-error: true
1292
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
1293
+ with:
1294
+ name: ${{ needs.activation.outputs.artifact_prefix }}agent-output-fallback
1295
+ path: |
1296
+ /tmp/gh-aw/agent_output.json
1297
+ /tmp/gh-aw/safeoutputs.jsonl
1298
+ /tmp/gh-aw/agent_execution.json
1299
+ /tmp/gh-aw/agent_execution_exit_code.txt
1300
+ /tmp/gh-aw/agent_usage.jsonl
1301
+ /tmp/gh-aw/agent_usage.json
1302
+ /tmp/gh-aw/agent/model-endpoint-mismatch.json
1303
+ /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl
1304
+ /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/model-routing.jsonl
1305
+ /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl
1306
+ /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/model-routing.jsonl
1307
+ /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl
1308
+ /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/model-routing.jsonl
1309
+ /tmp/gh-aw/awf-resolved-config.json
1310
+ if-no-files-found: ignore
1311
+ retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}
1312
+ - name: Upload agent artifacts
1313
+ if: always() && steps.redact_secrets.outcome == 'success'
1314
+ continue-on-error: true
1315
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
1316
+ with:
1317
+ name: ${{ needs.activation.outputs.artifact_prefix }}agent
1318
+ path: |
1319
+ /tmp/gh-aw/aw-prompts/prompt.txt
1320
+ /tmp/gh-aw/agent_execution.json
1321
+ /tmp/gh-aw/agent_execution_exit_code.txt
1322
+ /tmp/gh-aw/agent-session.jsonl
1323
+ /tmp/gh-aw/agent-errors.jsonl
1324
+ /tmp/gh-aw/aw-prompts/user.txt
1325
+ /tmp/gh-aw/aw-prompts/system.txt
1326
+ /tmp/gh-aw/skill_inventory.json
1327
+ /tmp/gh-aw/sandbox/agent/logs/
1328
+ /tmp/gh-aw/redacted-urls.log
1329
+ /tmp/gh-aw/mcp-logs/
1330
+ /tmp/gh-aw/agent_usage.json
1331
+ /tmp/gh-aw/runtime/aw_info.json
1332
+ /tmp/gh-aw/agent_usage.jsonl
1333
+ /tmp/gh-aw/agent/model-endpoint-mismatch.json
1334
+ /tmp/gh-aw/agent/model-resolution.json
1335
+ /tmp/gh-aw/agent-stdio.log
1336
+ /tmp/gh-aw/pre-agent-audit.txt
1337
+ /tmp/gh-aw/github_rate_limits.jsonl
1338
+ /tmp/gh-aw/otel.jsonl
1339
+ /tmp/gh-aw/otlp-export-errors.jsonl
1340
+ /tmp/gh-aw/safeoutputs.jsonl
1341
+ /tmp/gh-aw/agent_output.json
1342
+ /tmp/gh-aw/aw-*.patch
1343
+ /tmp/gh-aw/aw-*.bundle
1344
+ /tmp/gh-aw/awf-config.json
1345
+ /tmp/gh-aw/awf-resolved-config.json
1346
+ /tmp/gh-aw/sandbox/firewall/logs/
1347
+ /tmp/gh-aw/sandbox/firewall/audit/
1348
+ /tmp/gh-aw/sandbox/firewall/awf-reflect.json
1349
+ if-no-files-found: ignore
1350
+ retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}
1351
+
1352
+ conclusion:
1353
+ name: conclusion
1354
+ needs:
1355
+ - activation
1356
+ - agent
1357
+ - detection
1358
+ - safe_outputs
1359
+ if: >
1360
+ always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' ||
1361
+ needs.activation.outputs.oauth_token_check_failed == 'true' || needs.activation.outputs.stale_lock_file_failed == 'true' ||
1362
+ needs.activation.outputs.secret_verification_result == 'failed' || needs.activation.outputs.daily_ai_credits_exceeded == 'true' ||
1363
+ needs.activation.outputs.daily_ai_credits_guardrail_status == 'structural_error' || needs.activation.outputs.daily_ai_credits_guardrail_status == 'transient_error')
1364
+ runs-on: ubuntu-24.04
1365
+ # Permissions for the conclusion job (workflow permissions default to none).
1366
+ permissions:
1367
+ actions: read
1368
+ issues: write
1369
+ concurrency:
1370
+ group: "gh-aw-conclusion-lighthouse-sdlc-integrate"
1371
+ cancel-in-progress: false
1372
+ queue: max
1373
+ env:
1374
+ GH_AW_JOB_DISPLAY_NAMES: "{\"activation\":\"activation\",\"agent\":\"agent\",\"conclusion\":\"conclusion\",\"detection\":\"detection\",\"pre_activation\":\"pre_activation\",\"safe_outputs\":\"safe_outputs\"}"
1375
+ GH_AW_JOB_RESULTS: "{\"activation\":{\"result\":\"${{ needs.activation.result }}\"},\"agent\":{\"result\":\"${{ needs.agent.result }}\"},\"detection\":{\"result\":\"${{ needs.detection.result }}\"},\"safe_outputs\":{\"result\":\"${{ needs.safe_outputs.result }}\"}}"
1376
+ GH_AW_JOB_TIMING_ELIGIBLE: "{\"activation\":true,\"agent\":true,\"conclusion\":true,\"detection\":true,\"pre_activation\":true,\"safe_outputs\":true}"
1377
+ GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
1378
+ outputs:
1379
+ incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }}
1380
+ noop_comment_body: ${{ steps.noop.outputs.noop_comment_body }}
1381
+ noop_message: ${{ steps.noop.outputs.noop_message }}
1382
+ tools_reported: ${{ steps.missing_tool.outputs.tools_reported }}
1383
+ total_count: ${{ steps.missing_tool.outputs.total_count }}
1384
+ steps:
1385
+ - name: Setup Scripts
1386
+ id: setup
1387
+ uses: github/gh-aw-actions/setup@d9128eb3ea40c18b77c76184eda03c0ff2608d79 # v0.93.2
1388
+ with:
1389
+ destination: ${{ runner.temp }}/gh-aw/actions
1390
+ job-name: ${{ github.job }}
1391
+ trace-id: ${{ needs.activation.outputs.setup-trace-id }}
1392
+ parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
1393
+ env:
1394
+ GH_AW_SETUP_WORKFLOW_NAME: "Lighthouse SDLC integrate"
1395
+ GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/lighthouse-sdlc-integrate.lock.yml@${{ github.ref }}
1396
+ GH_AW_INFO_VERSION: "1.0.101"
1397
+ GH_AW_INFO_AWF_VERSION: "v0.28.70"
1398
+ GH_AW_INFO_ENGINE_ID: "copilot"
1399
+ GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }}
1400
+ - name: Download agent output artifact
1401
+ id: download-agent-output
1402
+ continue-on-error: true
1403
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
1404
+ with:
1405
+ pattern: "{${{ needs.activation.outputs.artifact_prefix }}agent,${{ needs.activation.outputs.artifact_prefix }}agent-output-fallback}"
1406
+ merge-multiple: true
1407
+ path: /tmp/gh-aw/
1408
+ - name: Setup agent output environment variable
1409
+ id: setup-agent-output-env
1410
+ if: steps.download-agent-output.outcome == 'success'
1411
+ run: |
1412
+ mkdir -p /tmp/gh-aw/
1413
+ find "/tmp/gh-aw/" -type f -print
1414
+ if [ -f "/tmp/gh-aw/agent_output.json" ]; then
1415
+ echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
1416
+ fi
1417
+ - name: Restore runtime model metadata
1418
+ if: always()
1419
+ run: |
1420
+ if [ -f /tmp/gh-aw/runtime/aw_info.json ]; then cp /tmp/gh-aw/runtime/aw_info.json /tmp/gh-aw/aw_info.json; fi
1421
+ - name: Warn if threat detection produced no verdict
1422
+ if: always() && needs.detection.result != 'skipped' && (needs.detection.outputs.detection_reason == 'agent_failure' || needs.detection.outputs.detection_reason == 'parse_error' || needs.detection.outputs.detection_conclusion == '')
1423
+ run: echo "::warning::Threat detection produced no security verdict. Review the detection job logs before trusting the agent outputs."
1424
+ - name: Download detection artifact
1425
+ id: download-detection-artifact
1426
+ continue-on-error: true
1427
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
1428
+ with:
1429
+ name: ${{ needs.activation.outputs.artifact_prefix }}detection
1430
+ path: /tmp/gh-aw/threat-detection/
1431
+ - name: Download Safe Outputs Items Manifest
1432
+ id: download-safe-outputs-manifest
1433
+ if: always()
1434
+ continue-on-error: true
1435
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
1436
+ with:
1437
+ pattern: ${{ needs.activation.outputs.artifact_prefix }}safe-outputs-items
1438
+ merge-multiple: true
1439
+ path: /tmp/gh-aw/
1440
+ - name: Process no-op messages
1441
+ id: noop
1442
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1443
+ env:
1444
+ GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
1445
+ GH_AW_NOOP_MAX: "1"
1446
+ GH_AW_WORKFLOW_NAME: "Lighthouse SDLC integrate"
1447
+ GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/lighthouse-sdlc-integrate.md"
1448
+ GH_AW_ENGINE_ID: "copilot"
1449
+ GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }}
1450
+ GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
1451
+ GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
1452
+ GH_AW_NOOP_REPORT_AS_ISSUE: "false"
1453
+ GH_AW_AIC: ${{ needs.agent.outputs.aic }}
1454
+ GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }}
1455
+ GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }}
1456
+ GH_AW_WORKFLOW_ID: "lighthouse-sdlc-integrate"
1457
+ with:
1458
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1459
+ script: |
1460
+ const path = require('path');
1461
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1462
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1463
+ setupGlobals(core, github, context, exec, io, getOctokit);
1464
+ const { main } = require(path.join(actionsDir, 'handle_noop_message.cjs'));
1465
+ await main();
1466
+ - name: Log detection run
1467
+ id: detection_runs
1468
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1469
+ env:
1470
+ GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
1471
+ GH_AW_WORKFLOW_NAME: "Lighthouse SDLC integrate"
1472
+ GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/lighthouse-sdlc-integrate.md"
1473
+ GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
1474
+ GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }}
1475
+ GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }}
1476
+ with:
1477
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1478
+ script: |
1479
+ const path = require('path');
1480
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1481
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1482
+ setupGlobals(core, github, context, exec, io, getOctokit);
1483
+ const { main } = require(path.join(actionsDir, 'handle_detection_runs.cjs'));
1484
+ await main();
1485
+ - name: Record missing tool
1486
+ id: missing_tool
1487
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1488
+ env:
1489
+ GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
1490
+ GH_AW_MISSING_TOOL_CREATE_ISSUE: "true"
1491
+ GH_AW_WORKFLOW_NAME: "Lighthouse SDLC integrate"
1492
+ GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/lighthouse-sdlc-integrate.md"
1493
+ GH_AW_ENGINE_ID: "copilot"
1494
+ GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }}
1495
+ with:
1496
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1497
+ script: |
1498
+ const path = require('path');
1499
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1500
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1501
+ setupGlobals(core, github, context, exec, io, getOctokit);
1502
+ const { main } = require(path.join(actionsDir, 'missing_tool.cjs'));
1503
+ await main();
1504
+ - name: Record incomplete
1505
+ id: report_incomplete
1506
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1507
+ env:
1508
+ GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
1509
+ GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true"
1510
+ GH_AW_WORKFLOW_NAME: "Lighthouse SDLC integrate"
1511
+ GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/lighthouse-sdlc-integrate.md"
1512
+ GH_AW_ENGINE_ID: "copilot"
1513
+ GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }}
1514
+ with:
1515
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1516
+ script: |
1517
+ const path = require('path');
1518
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1519
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1520
+ setupGlobals(core, github, context, exec, io, getOctokit);
1521
+ const { main } = require(path.join(actionsDir, 'report_incomplete_handler.cjs'));
1522
+ await main();
1523
+ - name: Handle agent failure
1524
+ id: handle_agent_failure
1525
+ if: always()
1526
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1527
+ env:
1528
+ GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
1529
+ GH_AW_WORKFLOW_NAME: "Lighthouse SDLC integrate"
1530
+ GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/lighthouse-sdlc-integrate.md"
1531
+ GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
1532
+ GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
1533
+ GH_AW_WORKFLOW_ID: "lighthouse-sdlc-integrate"
1534
+ GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "0"
1535
+ GH_AW_ENGINE_ID: "copilot"
1536
+ GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }}
1537
+ GH_AW_ENGINE_SECRET_FAILURE_MESSAGE: "**Alternative**: If your organization has a Copilot subscription, you can avoid the need for a personal access token by adding a top-level `permissions` block to your workflow file. This enables Copilot inference through the org using the built-in GitHub Actions token.\n\n```yaml\npermissions:\n copilot-requests: write\n```\n\nSee: https://github.github.com/gh-aw/reference/engines/#github-copilot-default"
1538
+ GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }}
1539
+ GH_AW_CHECKOUT_PR_INVALIDATED: ${{ needs.agent.outputs.checkout_pr_invalidated }}
1540
+ GH_AW_AI_CREDITS_RATE_LIMIT_ERROR: ${{ needs.agent.outputs.ai_credits_rate_limit_error || 'false' }}
1541
+ GH_AW_UNKNOWN_MODEL_AI_CREDITS: ${{ needs.agent.outputs.unknown_model_ai_credits || 'false' }}
1542
+ GH_AW_AIC: ${{ needs.agent.outputs.aic }}
1543
+ GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }}
1544
+ GH_AW_DETECTION_JOB_RESULT: ${{ needs.detection.result }}
1545
+ GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}
1546
+ GH_AW_DEFAULT_CHECKOUT_USES_TRIGGER_REF: "true"
1547
+ GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }}
1548
+ GH_AW_MCP_POLICY_ERROR: ${{ needs.agent.outputs.mcp_policy_error }}
1549
+ GH_AW_AGENTIC_ENGINE_TIMEOUT: ${{ needs.agent.outputs.agentic_engine_timeout }}
1550
+ GH_AW_MODEL_NOT_SUPPORTED_ERROR: ${{ needs.agent.outputs.model_not_supported_error }}
1551
+ GH_AW_MODEL_ENDPOINT_MISMATCH_ERROR: ${{ needs.agent.outputs.model_endpoint_mismatch_error }}
1552
+ GH_AW_HTTP_400_RESPONSE_ERROR: ${{ needs.agent.outputs.http_400_response_error }}
1553
+ GH_AW_MAX_CACHE_MISSES_EXCEEDED: ${{ needs.agent.outputs.max_cache_misses_exceeded }}
1554
+ GH_AW_MISSING_MODEL_PRICING_ERROR: ${{ needs.agent.outputs.missing_model_pricing_error }}
1555
+ GH_AW_MISSING_MODEL_PRICING_MODEL_NAME: ${{ needs.agent.outputs.missing_model_pricing_model_name }}
1556
+ GH_AW_SHELL_EXPANSION_GUARD_REJECTED: ${{ needs.agent.outputs.shell_expansion_guard_rejected }}
1557
+ GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com"
1558
+ GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }}
1559
+ GH_AW_OAUTH_TOKEN_CHECK_FAILED: ${{ needs.activation.outputs.oauth_token_check_failed }}
1560
+ GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }}
1561
+ GH_AW_DAILY_AI_CREDITS_EXCEEDED: ${{ needs.activation.outputs.daily_ai_credits_exceeded }}
1562
+ GH_AW_DAILY_AI_CREDITS_GUARDRAIL_STATUS: ${{ needs.activation.outputs.daily_ai_credits_guardrail_status }}
1563
+ GH_AW_DAILY_AI_CREDITS_GUARDRAIL_ERROR: ${{ needs.activation.outputs.daily_ai_credits_guardrail_error }}
1564
+ GH_AW_DAILY_AI_CREDITS_TOTAL: ${{ needs.activation.outputs.daily_ai_credits_total }}
1565
+ GH_AW_DAILY_AI_CREDITS_ESTIMATED: ${{ needs.activation.outputs.daily_ai_credits_estimated }}
1566
+ GH_AW_DAILY_AI_CREDITS_THRESHOLD: ${{ needs.activation.outputs.daily_ai_credits_threshold }}
1567
+ GH_AW_DAILY_AI_CREDITS_CONTINUE_ON_ERROR: "false"
1568
+ GH_AW_GROUP_REPORTS: "false"
1569
+ GH_AW_FAILURE_REPORT_AS_ISSUE: "false"
1570
+ GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true"
1571
+ GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true"
1572
+ GH_AW_TIMEOUT_MINUTES: "${{ fromJSON(vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || '20') }}"
1573
+ with:
1574
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1575
+ script: |
1576
+ const path = require('path');
1577
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1578
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1579
+ setupGlobals(core, github, context, exec, io, getOctokit);
1580
+ const { main } = require(path.join(actionsDir, 'handle_agent_failure.cjs'));
1581
+ await main();
1582
+ - name: Report failed jobs
1583
+ id: report_failed_jobs
1584
+ if: always()
1585
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1586
+ env:
1587
+ GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
1588
+ GH_AW_WORKFLOW_NAME: "Lighthouse SDLC integrate"
1589
+ GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/lighthouse-sdlc-integrate.md"
1590
+ GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
1591
+ GH_AW_REPORT_FAILED_JOBS: "true"
1592
+ with:
1593
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
1594
+ script: |
1595
+ const path = require('path');
1596
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1597
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1598
+ setupGlobals(core, github, context, exec, io, getOctokit);
1599
+ const { main } = require(path.join(actionsDir, 'report_failed_jobs.cjs'));
1600
+ await main();
1601
+ - name: Collect usage artifact files
1602
+ if: always()
1603
+ continue-on-error: true
1604
+ env:
1605
+ GH_AW_DETECTION_JOB_RESULT: ${{ needs.detection.result }}
1606
+ GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }}
1607
+ GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }}
1608
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/collect_usage_artifact_files.sh"
1609
+ - name: Generate usage activity summary and unified session
1610
+ if: always()
1611
+ continue-on-error: true
1612
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1613
+ env:
1614
+ GH_AW_ADMISSION_RESULT: ${{ needs.activation.outputs.admission-result }}
1615
+ GH_AW_ADMISSION_MAX_AI_CREDITS: ${{ needs.activation.outputs.admission-max-ai-credits }}
1616
+ GH_AW_ADMISSION_MAX_AI_CREDITS_THREAT_DETECTION: ${{ needs.activation.outputs.admission-max-ai-credits-threat-detection }}
1617
+ GH_AW_ADMISSION_MAX_AI_CREDITS_EVALS: ${{ needs.activation.outputs.admission-max-ai-credits-evals }}
1618
+ GH_AW_GRADER_MANIFEST_0: '{"version":2,"graders":[]}'
1619
+ GH_AW_GRADER_MANIFEST_CHUNKS: '1'
1620
+ GH_AW_JOB_DURATIONS: ${{ steps.report_failed_jobs.outputs.job_durations }}
1621
+ GH_AW_DAILY_AI_CREDITS_GUARDRAIL_STATUS: ${{ needs.activation.outputs.daily_ai_credits_guardrail_status }}
1622
+ GH_AW_DAILY_AI_CREDITS_EXCEEDED: ${{ needs.activation.outputs.daily_ai_credits_exceeded }}
1623
+ GH_AW_DAILY_AI_CREDITS_TOTAL: ${{ needs.activation.outputs.daily_ai_credits_total }}
1624
+ GH_AW_DAILY_AI_CREDITS_ESTIMATED: ${{ needs.activation.outputs.daily_ai_credits_estimated }}
1625
+ GH_AW_DAILY_AI_CREDITS_THRESHOLD: ${{ needs.activation.outputs.daily_ai_credits_threshold }}
1626
+ with:
1627
+ script: |
1628
+ const path = require('path');
1629
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1630
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1631
+ setupGlobals(core, github, context, exec, io, getOctokit);
1632
+ const { main } = require(path.join(actionsDir, 'generate_usage_artifacts.cjs'));
1633
+ await main();
1634
+ - name: Upload usage artifact
1635
+ id: upload-usage-artifact
1636
+ if: always()
1637
+ continue-on-error: true
1638
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
1639
+ with:
1640
+ name: ${{ needs.activation.outputs.artifact_prefix }}usage
1641
+ path: |
1642
+ /tmp/gh-aw/usage/aw_session.jsonl
1643
+ /tmp/gh-aw/usage/aw_info.json
1644
+ /tmp/gh-aw/usage/aw-info.jsonl
1645
+ /tmp/gh-aw/usage/agent_usage.json
1646
+ /tmp/gh-aw/usage/agent_usage.jsonl
1647
+ /tmp/gh-aw/usage/detection_usage.jsonl
1648
+ /tmp/gh-aw/usage/evals.jsonl
1649
+ /tmp/gh-aw/usage/graders/grader_manifest.json
1650
+ /tmp/gh-aw/usage/graders/grader_results.json
1651
+ /tmp/gh-aw/usage/github_rate_limits.jsonl
1652
+ /tmp/gh-aw/usage/agent/token_usage.jsonl
1653
+ /tmp/gh-aw/usage/agent/model-routing.jsonl
1654
+ /tmp/gh-aw/usage/agent/execution.json
1655
+ /tmp/gh-aw/usage/detection/token_usage.jsonl
1656
+ /tmp/gh-aw/usage/detection/execution.json
1657
+ /tmp/gh-aw/usage/detection/detection_result.json
1658
+ /tmp/gh-aw/usage/evals/token_usage.jsonl
1659
+ /tmp/gh-aw/usage/evals/execution.json
1660
+ /tmp/gh-aw/usage/experiment/state.jsonl
1661
+ /tmp/gh-aw/usage/experiment/state.json
1662
+ /tmp/gh-aw/usage/experiment/assignments.json
1663
+ /tmp/gh-aw/usage/activity/summary.json
1664
+ if-no-files-found: ignore
1665
+ retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}
1666
+ - name: Wait before retrying usage artifact upload
1667
+ if: always() && steps.upload-usage-artifact.outcome == 'failure'
1668
+ run: sleep 10
1669
+ - name: Retry upload usage artifact
1670
+ id: upload-usage-artifact-retry
1671
+ if: always() && steps.upload-usage-artifact.outcome == 'failure'
1672
+ continue-on-error: true
1673
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
1674
+ with:
1675
+ name: ${{ needs.activation.outputs.artifact_prefix }}usage
1676
+ path: |
1677
+ /tmp/gh-aw/usage/aw_session.jsonl
1678
+ /tmp/gh-aw/usage/aw_info.json
1679
+ /tmp/gh-aw/usage/aw-info.jsonl
1680
+ /tmp/gh-aw/usage/agent_usage.json
1681
+ /tmp/gh-aw/usage/agent_usage.jsonl
1682
+ /tmp/gh-aw/usage/detection_usage.jsonl
1683
+ /tmp/gh-aw/usage/evals.jsonl
1684
+ /tmp/gh-aw/usage/graders/grader_manifest.json
1685
+ /tmp/gh-aw/usage/graders/grader_results.json
1686
+ /tmp/gh-aw/usage/github_rate_limits.jsonl
1687
+ /tmp/gh-aw/usage/agent/token_usage.jsonl
1688
+ /tmp/gh-aw/usage/agent/model-routing.jsonl
1689
+ /tmp/gh-aw/usage/agent/execution.json
1690
+ /tmp/gh-aw/usage/detection/token_usage.jsonl
1691
+ /tmp/gh-aw/usage/detection/execution.json
1692
+ /tmp/gh-aw/usage/detection/detection_result.json
1693
+ /tmp/gh-aw/usage/evals/token_usage.jsonl
1694
+ /tmp/gh-aw/usage/evals/execution.json
1695
+ /tmp/gh-aw/usage/experiment/state.jsonl
1696
+ /tmp/gh-aw/usage/experiment/state.json
1697
+ /tmp/gh-aw/usage/experiment/assignments.json
1698
+ /tmp/gh-aw/usage/activity/summary.json
1699
+ if-no-files-found: ignore
1700
+ overwrite: true
1701
+ retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}
1702
+
1703
+ detection:
1704
+ name: detection
1705
+ needs:
1706
+ - activation
1707
+ - agent
1708
+ if: always() && needs.agent.result != 'skipped'
1709
+ runs-on: ubuntu-latest
1710
+ # Permissions for the detection job (workflow permissions default to none).
1711
+ permissions:
1712
+ contents: read
1713
+ timeout-minutes: 10
1714
+ env:
1715
+ GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
1716
+ outputs:
1717
+ aic: ${{ steps.parse_detection_token_usage.outputs.aic }}
1718
+ detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }}
1719
+ detection_reason: ${{ steps.detection_conclusion.outputs.reason }}
1720
+ detection_success: ${{ steps.detection_conclusion.outputs.success }}
1721
+ run_detection: ${{ steps.detection_guard.outputs.run_detection }}
1722
+ steps:
1723
+ - name: Setup Scripts
1724
+ id: setup
1725
+ uses: github/gh-aw-actions/setup@d9128eb3ea40c18b77c76184eda03c0ff2608d79 # v0.93.2
1726
+ with:
1727
+ destination: ${{ runner.temp }}/gh-aw/actions
1728
+ job-name: ${{ github.job }}
1729
+ trace-id: ${{ needs.activation.outputs.setup-trace-id }}
1730
+ parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
1731
+ env:
1732
+ GH_AW_SETUP_WORKFLOW_NAME: "Lighthouse SDLC integrate"
1733
+ GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/lighthouse-sdlc-integrate.lock.yml@${{ github.ref }}
1734
+ GH_AW_INFO_VERSION: "1.0.101"
1735
+ GH_AW_INFO_AWF_VERSION: "v0.28.70"
1736
+ GH_AW_INFO_ENGINE_ID: "copilot"
1737
+ GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }}
1738
+ - name: Download activation artifact
1739
+ continue-on-error: true
1740
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
1741
+ with:
1742
+ name: ${{ needs.activation.outputs.artifact_prefix }}activation
1743
+ path: /tmp/gh-aw
1744
+ - name: Download agent output artifact
1745
+ id: download-agent-output
1746
+ continue-on-error: true
1747
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
1748
+ with:
1749
+ pattern: "{${{ needs.agent.outputs.artifact_prefix }}agent,${{ needs.agent.outputs.artifact_prefix }}agent-output-fallback}"
1750
+ merge-multiple: true
1751
+ path: /tmp/gh-aw/
1752
+ - name: Setup agent output environment variable
1753
+ id: setup-agent-output-env
1754
+ if: steps.download-agent-output.outcome == 'success'
1755
+ run: |
1756
+ mkdir -p /tmp/gh-aw/
1757
+ find "/tmp/gh-aw/" -type f -print
1758
+ if [ -f "/tmp/gh-aw/agent_output.json" ]; then
1759
+ echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
1760
+ fi
1761
+ - name: Checkout repository for patch context
1762
+ if: needs.agent.outputs.has_patch == 'true'
1763
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
1764
+ with:
1765
+ persist-credentials: false
1766
+ # --- Threat Detection ---
1767
+ - name: Initialize detection execution evidence
1768
+ run: |
1769
+ mkdir -p "/tmp/gh-aw/threat-detection"
1770
+ evidence_tmp="/tmp/gh-aw/threat-detection/execution.json.tmp"
1771
+ printf '{"version":1,"component":"detection","run_id":%s,"run_attempt":%s,"state":"not_started"}\n' "$GITHUB_RUN_ID" "$GITHUB_RUN_ATTEMPT" > "$evidence_tmp"
1772
+ mv "$evidence_tmp" "/tmp/gh-aw/threat-detection/execution.json"
1773
+ - name: Clear inherited Copilot session state
1774
+ run: rm -rf /tmp/gh-aw/sandbox/agent/logs/copilot-session-state
1775
+ - name: Clean stale firewall files from agent artifact
1776
+ run: |
1777
+ rm -rf /tmp/gh-aw/sandbox/firewall/logs
1778
+ rm -rf /tmp/gh-aw/sandbox/firewall/audit
1779
+ - name: Download container images
1780
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.28.70@sha256:b15ab48cbbab02904eb9bbd359a398db59690eebbea1e6934d47ed2bb407dd34 ghcr.io/github/gh-aw-firewall/api-proxy:0.28.70@sha256:9ac8f9c7294e892c916de3da9d2588dfd8cd4931e5c39b00143266d7ed9fd52a ghcr.io/github/gh-aw-firewall/squid:0.28.70@sha256:b5bc53f4becfd96e926e63c83831f1b3c9512f713c83161d2b8c9b7204b3e917
1781
+ - name: Check if detection needed
1782
+ id: detection_guard
1783
+ if: always()
1784
+ env:
1785
+ OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }}
1786
+ HAS_PATCH: ${{ needs.agent.outputs.has_patch }}
1787
+ run: |
1788
+ if [[ -n "$OUTPUT_TYPES" || "$HAS_PATCH" == "true" ]]; then
1789
+ echo "run_detection=true" >> "$GITHUB_OUTPUT"
1790
+ echo "Detection will run: output_types=$OUTPUT_TYPES, has_patch=$HAS_PATCH"
1791
+ else
1792
+ echo "run_detection=false" >> "$GITHUB_OUTPUT"
1793
+ echo "Detection skipped: no agent outputs or patches to analyze"
1794
+ fi
1795
+ - name: Clear MCP Config for detection
1796
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
1797
+ run: |
1798
+ rm -f "${RUNNER_TEMP}/gh-aw/mcp-config/mcp-servers.json"
1799
+ rm -f "$HOME/.copilot/mcp-config.json"
1800
+ rm -f "$GITHUB_WORKSPACE/.gemini/settings.json"
1801
+ - name: Prepare threat detection files
1802
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
1803
+ run: |
1804
+ bash "${RUNNER_TEMP}/gh-aw/actions/prepare_threat_detection_files.sh"
1805
+ - name: Setup threat detection
1806
+ id: detection_setup
1807
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
1808
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1809
+ env:
1810
+ WORKFLOW_NAME: "Lighthouse SDLC integrate"
1811
+ WORKFLOW_DESCRIPTION: "Execute only the Lighthouse integration stage and return its declared stage result."
1812
+ HAS_PATCH: ${{ needs.agent.outputs.has_patch }}
1813
+ GH_AW_DETECTION_CONTINUE_ON_ERROR: "true"
1814
+ GH_AW_DETECTION_SKIP_PROMPT_SUMMARY: "true"
1815
+ with:
1816
+ script: |
1817
+ const path = require('path');
1818
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1819
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1820
+ setupGlobals(core, github, context, exec, io, getOctokit);
1821
+ const { main } = require(path.join(actionsDir, 'setup_threat_detection.cjs'));
1822
+ await main();
1823
+ - name: Ensure threat-detection directory and log
1824
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
1825
+ run: |
1826
+ mkdir -p /tmp/gh-aw/threat-detection
1827
+ touch /tmp/gh-aw/threat-detection/detection.log
1828
+ - name: Install AWF binary
1829
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.28.70 --rootless
1830
+ - name: Setup Node.js
1831
+ uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
1832
+ with:
1833
+ node-version: '24'
1834
+ package-manager-cache: false
1835
+ - name: Install GitHub Copilot CLI
1836
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.101 --checksums-sha256 018625eac68670d66ede904b9b82cdcd6ab8f87ba20e6e1fbdf0b62c8295d5be --prefer-toolcache
1837
+ env:
1838
+ GH_HOST: github.com
1839
+ GH_AW_COPILOT_MIN_VERSION: 1.0.35
1840
+ - name: Install threat-detect binary
1841
+ id: threat_detect_install
1842
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
1843
+ continue-on-error: true
1844
+ run: |
1845
+ bash "${RUNNER_TEMP}/gh-aw/actions/install_threat_detect_binary.sh" v0.5.2 --artifact-base-url https://github.com/github/gh-aw-threat-detection/releases/download --sha256-amd64 b4ecda6a8f1ee09913c40b58e5e9d3337d2173618d41b1bfdef9207e4e7959b9 --sha256-arm64 f6260a0f9ad72bcb67c7af19c4ce262ca34e2c3d5ccbf912832a8bd277200904
1846
+ - name: Execute threat detection with AWF
1847
+ id: detection_agentic_execution
1848
+ if: always() && steps.detection_guard.outputs.run_detection == 'true' && steps.detection_setup.outcome == 'success' && steps.detection_setup.outputs.ready == 'true' && steps.threat_detect_install.outcome == 'success'
1849
+ continue-on-error: true
1850
+ timeout-minutes: 10
1851
+ env:
1852
+ AWF_REFLECT_ENABLED: 1
1853
+ COPILOT_AGENT_RUNNER_TYPE: STANDALONE
1854
+ COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode
1855
+ COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
1856
+ COPILOT_MODEL: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'detection' }}
1857
+ GH_AW_ADMISSION_MAX_AI_CREDITS: ${{ needs.activation.outputs.admission-max-ai-credits-threat-detection }}
1858
+ GH_AW_ADMISSION_RESULT: ${{ needs.activation.outputs.admission-result }}
1859
+ GH_AW_HARNESS_MAX_RETRIES: 0
1860
+ GH_AW_LLM_PROVIDER: github
1861
+ GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_DETECTION_MAX_AI_CREDITS || '400' }}
1862
+ GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
1863
+ GH_AW_MODEL_FALLBACK: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }}
1864
+ GH_AW_PHASE: detection
1865
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
1866
+ GH_AW_TIMEOUT_MINUTES: 10
1867
+ GH_AW_VERSION: v0.93.2
1868
+ GITHUB_API_URL: ${{ github.api_url }}
1869
+ GITHUB_AW: true
1870
+ GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows
1871
+ GITHUB_COPILOT_PROMPT_MODE_EXTENSIONS: false
1872
+ GITHUB_HEAD_REF: ${{ github.head_ref }}
1873
+ GITHUB_REF_NAME: ${{ github.ref_name }}
1874
+ GITHUB_SERVER_URL: ${{ github.server_url }}
1875
+ GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md
1876
+ GITHUB_WORKSPACE: ${{ github.workspace }}
1877
+ GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
1878
+ GIT_AUTHOR_NAME: github-actions[bot]
1879
+ GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
1880
+ GIT_COMMITTER_NAME: github-actions[bot]
1881
+ RUNNER_TEMP: ${{ runner.temp }}
1882
+ 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) || '' }}
1883
+ WORKFLOW_NAME: "Lighthouse SDLC integrate"
1884
+ WORKFLOW_DESCRIPTION: "Execute only the Lighthouse integration stage and return its declared stage result."
1885
+ HAS_PATCH: ${{ needs.agent.outputs.has_patch }}
1886
+ GH_AW_DETECTION_CONTINUE_ON_ERROR: "true"
1887
+ run: |
1888
+ mkdir -p "/tmp/gh-aw/threat-detection"
1889
+ evidence_tmp="/tmp/gh-aw/threat-detection/execution.json.tmp"
1890
+ printf '{"version":1,"component":"detection","run_id":%s,"run_attempt":%s,"state":"started"}\n' "$GITHUB_RUN_ID" "$GITHUB_RUN_ATTEMPT" > "$evidence_tmp"
1891
+ mv "$evidence_tmp" "/tmp/gh-aw/threat-detection/execution.json"
1892
+ export GH_AW_AWF_EXECUTION_COMPONENT="detection"
1893
+ export GH_AW_AWF_EXECUTION_EVIDENCE_FILE="/tmp/gh-aw/threat-detection/execution.json"
1894
+ set -o pipefail
1895
+ printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt
1896
+ GH_AW_COPILOT_SRC="$(command -v copilot 2>/dev/null || true)"
1897
+ if [ -z "$GH_AW_COPILOT_SRC" ] || [ ! -x "$GH_AW_COPILOT_SRC" ]; then
1898
+ echo "GitHub Copilot CLI executable not found on PATH after installation" >&2
1899
+ exit 127
1900
+ fi
1901
+ GH_AW_COPILOT_BIN="${RUNNER_TEMP}/gh-aw/bin/copilot"
1902
+ mkdir -p "${RUNNER_TEMP}/gh-aw/bin"
1903
+ if [ "$GH_AW_COPILOT_SRC" != "$GH_AW_COPILOT_BIN" ]; then
1904
+ cp "$GH_AW_COPILOT_SRC" "$GH_AW_COPILOT_BIN"
1905
+ fi
1906
+ chmod 755 "$GH_AW_COPILOT_BIN"
1907
+
1908
+ (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log)
1909
+ GH_AW_MAX_AI_CREDITS="${GH_AW_MAX_AI_CREDITS:-400}"
1910
+ if [[ ! "$GH_AW_MAX_AI_CREDITS" =~ ^[0-9]+$ ]]; then
1911
+ GH_AW_MAX_AI_CREDITS="400"
1912
+ fi
1913
+
1914
+ if [[ "${GH_AW_ADMISSION_RESULT:-}" == "admitted" && -n "${GH_AW_ADMISSION_MAX_AI_CREDITS:-}" ]]; then
1915
+ if [[ ! "$GH_AW_ADMISSION_MAX_AI_CREDITS" =~ ^[1-9][0-9]{0,9}$ ]] || (( GH_AW_ADMISSION_MAX_AI_CREDITS > 2147483647 )); then
1916
+ echo "ERR_ADMISSION: Invalid runtime admission allowance." >&2
1917
+ exit 1
1918
+ fi
1919
+ GH_AW_MAX_AI_CREDITS="$GH_AW_ADMISSION_MAX_AI_CREDITS"
1920
+ echo "Admission allowance applied (value withheld)."
1921
+ else
1922
+ echo "No component admission allowance; retaining existing budget policy (value withheld)."
1923
+ fi
1924
+ unset GH_AW_ADMISSION_RESULT GH_AW_ADMISSION_MAX_AI_CREDITS
1925
+ printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.28.70/awf-config.schema.json\",\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5,\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-6\",\"gpt-5.4\",\"gpt-5.5\",\"gpt-5.6\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"auto\":[\"copilot/auto\",\"large\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\",\"kimi\"],\"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*\"],\"detection\":[\"small\"],\"evals\":[\"small\"],\"fable\":[\"copilot/*fable*\",\"anthropic/*fable*\"],\"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-3.6-flash\":[\"copilot/gemini-3.6*flash*\",\"google/gemini-3.6*flash*\",\"gemini/gemini-3.6*flash*\"],\"gemini-3.7-flash\":[\"copilot/gemini-3.7*flash*\",\"google/gemini-3.7*flash*\",\"gemini/gemini-3.7*flash*\"],\"gemini-3.8-flash\":[\"copilot/gemini-3.8*flash*\",\"google/gemini-3.8*flash*\",\"gemini/gemini-3.8*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-omni\":[\"copilot/gemini-omni*\",\"google/gemini-omni*\",\"gemini/gemini-omni*\"],\"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*\"],\"gpt-5.6\":[\"copilot/gpt-5.6*\",\"openai/gpt-5.6*\"],\"gpt-6\":[\"copilot/gpt-6*\",\"openai/gpt-6*\"],\"grok\":[\"copilot/*grok*\",\"openai/*grok*\"],\"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*\"],\"kimi\":[\"copilot/kimi*\",\"openai/kimi*\"],\"kiwi\":[\"copilot/kiwi*\",\"openai/kiwi*\"],\"large\":[\"sonnet\",\"gpt-6\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"lyria\":[\"google/lyria*\",\"gemini/lyria*\",\"copilot/lyria*\"],\"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\"],\"raptor-mini\":[\"copilot/raptor*\",\"openai/raptor*\"],\"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-5*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\",\"anthropic/*sonnet-5*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"veo\":[\"google/veo*\",\"gemini/veo*\"],\"vision\":[\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.28.70,squid=sha256:b5bc53f4becfd96e926e63c83831f1b3c9512f713c83161d2b8c9b7204b3e917,agent=sha256:b15ab48cbbab02904eb9bbd359a398db59690eebbea1e6934d47ed2bb407dd34,api-proxy=sha256:9ac8f9c7294e892c916de3da9d2588dfd8cd4931e5c39b00143266d7ed9fd52a,cli-proxy=sha256:372ac51a5cccffdfe484f3f7be427d2d1c566e8ae550d55bd45d9fd166a154b4\",\"agentTimeout\":10},\"logging\":{\"proxyLogsDir\":\"/tmp/gh-aw/sandbox/firewall/logs\",\"auditDir\":\"/tmp/gh-aw/sandbox/firewall/audit\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json"
1926
+ cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
1927
+ export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json"
1928
+ GH_AW_DOCKER_HOST=""
1929
+ if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
1930
+ GH_AW_DOCKER_HOST="${DOCKER_HOST}"
1931
+ fi
1932
+ if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
1933
+ _GH_AW_CHROOT_JSON=$(jq -c --arg src "${RUNNER_TEMP}/gh-aw" --arg user "$(id -un)" --argjson uid "$(id -u)" --argjson gid "$(id -g)" --arg home "${RUNNER_TEMP}/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; }
1934
+ printf '%s\n' "$_GH_AW_CHROOT_JSON" > "${RUNNER_TEMP}/gh-aw/awf-config.json"
1935
+ fi
1936
+ GH_AW_TOOL_CACHE_MOUNT=""
1937
+ GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"
1938
+ if [ -d "$GH_AW_TOOL_CACHE" ]; then
1939
+ if [[ "$GH_AW_TOOL_CACHE" != /opt/* ]]; then
1940
+ GH_AW_TOOL_CACHE_MOUNT="$GH_AW_TOOL_CACHE:$GH_AW_TOOL_CACHE:ro"
1941
+ fi
1942
+ fi
1943
+ # shellcheck disable=SC1003,SC2016,SC2086
1944
+ 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"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_AW_OTLP_ALL_HEADERS --exclude-env GH_AW_OTLP_ENDPOINTS --exclude-env OTEL_EXPORTER_OTLP_ENDPOINT --exclude-env OTEL_EXPORTER_OTLP_HEADERS --mount /tmp/gh-aw:/tmp/gh-aw:rw --mount /tmp/gh-aw/threat-detection:/tmp/gh-aw/threat-detection:rw --log-level info --session-state-dir /tmp/gh-aw/sandbox/agent/session-state --skip-pull \
1945
+ -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr "\n" ":")"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && threat-detect --engine copilot --output /tmp/gh-aw/threat-detection/detection_result.json /tmp/gh-aw/threat-detection' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log
1946
+ - name: Copy detection firewall logs
1947
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
1948
+ continue-on-error: true
1949
+ run: |
1950
+ mkdir -p /tmp/gh-aw/threat-detection/sandbox/firewall
1951
+ if [ -d /tmp/gh-aw/sandbox/firewall/logs ]; then mkdir -p /tmp/gh-aw/threat-detection/sandbox/firewall/logs && cp -r /tmp/gh-aw/sandbox/firewall/logs/. /tmp/gh-aw/threat-detection/sandbox/firewall/logs/; fi
1952
+ if [ -d /tmp/gh-aw/sandbox/firewall/audit ]; then mkdir -p /tmp/gh-aw/threat-detection/sandbox/firewall/audit && cp -r /tmp/gh-aw/sandbox/firewall/audit/. /tmp/gh-aw/threat-detection/sandbox/firewall/audit/; fi
1953
+ - name: Redact secrets in detection logs
1954
+ id: redact_detection_logs
1955
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
1956
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1957
+ env:
1958
+ GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_DEFAULT_OTLP_ENDPOINT,GH_AW_DEFAULT_OTLP_HEADERS'
1959
+ SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
1960
+ SECRET_GH_AW_DEFAULT_OTLP_ENDPOINT: ${{ secrets.GH_AW_DEFAULT_OTLP_ENDPOINT }}
1961
+ SECRET_GH_AW_DEFAULT_OTLP_HEADERS: ${{ secrets.GH_AW_DEFAULT_OTLP_HEADERS }}
1962
+ with:
1963
+ script: |
1964
+ const path = require('path');
1965
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1966
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1967
+ setupGlobals(core, github, context, exec, io, getOctokit);
1968
+ const { main } = require(path.join(actionsDir, 'redact_secrets.cjs'));
1969
+ const { persistDetectionMasks } = require(path.join(actionsDir, 'detection_mask_state.cjs'));
1970
+ await main({ additionalDirectories: ["/tmp/gh-aw/threat-detection/sandbox/firewall"], persistDetectionMasks });
1971
+ - name: Parse threat detection token usage for step summary
1972
+ id: parse_detection_token_usage
1973
+ if: always() && steps.detection_guard.outputs.run_detection == 'true' && steps.redact_detection_logs.outcome == 'success'
1974
+ continue-on-error: true
1975
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1976
+ env:
1977
+ GH_AW_TOKEN_USAGE_SUMMARY_TITLE: Threat Detection Token Usage
1978
+ GH_AW_PHASE: detection
1979
+ GH_AW_AGENT_USAGE_PATH: /tmp/gh-aw/threat-detection/detection_usage.json
1980
+ GH_AW_AGENT_USAGE_JSONL_PATH: /tmp/gh-aw/threat-detection/detection_usage.jsonl
1981
+ GH_AW_WRITE_EMPTY_USAGE: "true"
1982
+ with:
1983
+ script: |
1984
+ const path = require('path');
1985
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
1986
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
1987
+ setupGlobals(core, github, context, exec, io, getOctokit);
1988
+ const { main } = require(path.join(actionsDir, 'parse_token_usage.cjs'));
1989
+ await main();
1990
+ - name: Redact secrets in detection artifacts
1991
+ id: redact_detection_artifacts
1992
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
1993
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1994
+ env:
1995
+ GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_DEFAULT_OTLP_ENDPOINT,GH_AW_DEFAULT_OTLP_HEADERS'
1996
+ SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
1997
+ SECRET_GH_AW_DEFAULT_OTLP_ENDPOINT: ${{ secrets.GH_AW_DEFAULT_OTLP_ENDPOINT }}
1998
+ SECRET_GH_AW_DEFAULT_OTLP_HEADERS: ${{ secrets.GH_AW_DEFAULT_OTLP_HEADERS }}
1999
+ with:
2000
+ script: |
2001
+ const path = require('path');
2002
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
2003
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
2004
+ setupGlobals(core, github, context, exec, io, getOctokit);
2005
+ const { main } = require(path.join(actionsDir, 'redact_secrets.cjs'));
2006
+ const { persistDetectionMasks } = require(path.join(actionsDir, 'detection_mask_state.cjs'));
2007
+ await main({ additionalDirectories: ["/tmp/gh-aw/threat-detection/sandbox/firewall"], persistDetectionMasks });
2008
+ - name: Render detection log
2009
+ if: always() && steps.detection_guard.outputs.run_detection == 'true' && steps.redact_detection_logs.outcome == 'success' && steps.redact_detection_artifacts.outcome == 'success'
2010
+ continue-on-error: true
2011
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
2012
+ with:
2013
+ script: |
2014
+ const path = require('path');
2015
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
2016
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
2017
+ setupGlobals(core, github, context, exec, io, getOctokit);
2018
+ const { main } = require(path.join(actionsDir, 'render_detection_log.cjs'));
2019
+ await main();
2020
+ - name: Upload threat detection artifact
2021
+ if: always() && steps.detection_guard.outputs.run_detection == 'true' && steps.redact_detection_logs.outcome == 'success' && steps.redact_detection_artifacts.outcome == 'success'
2022
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
2023
+ with:
2024
+ name: ${{ needs.agent.outputs.artifact_prefix }}detection
2025
+ path: |
2026
+ /tmp/gh-aw/threat-detection/detection_result.json
2027
+ /tmp/gh-aw/threat-detection/execution.json
2028
+ /tmp/gh-aw/threat-detection/detection_usage.json
2029
+ /tmp/gh-aw/threat-detection/detection_usage.jsonl
2030
+ /tmp/gh-aw/threat-detection/sandbox/firewall/logs/
2031
+ /tmp/gh-aw/threat-detection/sandbox/firewall/audit/
2032
+ if-no-files-found: ignore
2033
+ retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}
2034
+ - name: Conclude threat detection
2035
+ id: detection_conclusion
2036
+ if: always() && steps.detection_guard.outputs.run_detection == 'false' || (always() && steps.detection_guard.outputs.run_detection == 'true' && steps.redact_detection_logs.outcome == 'success' && steps.redact_detection_artifacts.outcome == 'success')
2037
+ continue-on-error: true
2038
+ env:
2039
+ RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }}
2040
+ DETECTION_AGENTIC_EXECUTION_OUTCOME: ${{ steps.detection_agentic_execution.outcome }}
2041
+ THREAT_DETECT_INSTALL_OUTCOME: ${{ steps.threat_detect_install.outcome }}
2042
+ GH_AW_DETECTION_CONTINUE_ON_ERROR: "true"
2043
+ run: |
2044
+ bash "${RUNNER_TEMP}/gh-aw/actions/conclude_threat_detection.sh" /tmp/gh-aw/threat-detection/detection_result.json
2045
+ - name: Upload skipped detection execution evidence
2046
+ if: always() && steps.detection_guard.outputs.run_detection == 'false'
2047
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
2048
+ with:
2049
+ name: ${{ needs.agent.outputs.artifact_prefix }}detection
2050
+ path: /tmp/gh-aw/threat-detection/execution.json
2051
+ if-no-files-found: ignore
2052
+ retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}
2053
+
2054
+ pre_activation:
2055
+ name: pre_activation
2056
+ runs-on: ubuntu-24.04
2057
+ env:
2058
+ GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
2059
+ outputs:
2060
+ activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }}
2061
+ matched_command: ''
2062
+ setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }}
2063
+ setup-span-id: ${{ steps.setup.outputs.span-id }}
2064
+ setup-trace-id: ${{ steps.setup.outputs.trace-id }}
2065
+ steps:
2066
+ - name: Setup Scripts
2067
+ id: setup
2068
+ uses: github/gh-aw-actions/setup@d9128eb3ea40c18b77c76184eda03c0ff2608d79 # v0.93.2
2069
+ with:
2070
+ destination: ${{ runner.temp }}/gh-aw/actions
2071
+ job-name: ${{ github.job }}
2072
+ env:
2073
+ GH_AW_SETUP_WORKFLOW_NAME: "Lighthouse SDLC integrate"
2074
+ GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/lighthouse-sdlc-integrate.lock.yml@${{ github.ref }}
2075
+ GH_AW_INFO_VERSION: "1.0.101"
2076
+ GH_AW_INFO_AWF_VERSION: "v0.28.70"
2077
+ GH_AW_INFO_ENGINE_ID: "copilot"
2078
+ GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }}
2079
+ - name: Check team membership for workflow
2080
+ id: check_membership
2081
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
2082
+ env:
2083
+ GH_AW_REQUIRED_ROLES: "admin,maintainer,write"
2084
+ with:
2085
+ github-token: ${{ secrets.GITHUB_TOKEN }}
2086
+ script: |
2087
+ const path = require('path');
2088
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
2089
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
2090
+ setupGlobals(core, github, context, exec, io, getOctokit);
2091
+ const { main } = require(path.join(actionsDir, 'check_membership.cjs'));
2092
+ await main();
2093
+
2094
+ safe_outputs:
2095
+ name: safe_outputs
2096
+ needs:
2097
+ - activation
2098
+ - agent
2099
+ - detection
2100
+ if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success'
2101
+ runs-on: ubuntu-24.04
2102
+ # Permissions for the safe_outputs job (workflow permissions default to none).
2103
+ permissions:
2104
+ issues: write
2105
+ pull-requests: read
2106
+ timeout-minutes: 45
2107
+ env:
2108
+ GH_AW_AGENT_AIC: ${{ needs.agent.outputs.aic }}
2109
+ GH_AW_AIC: ${{ needs.agent.outputs.aic }}
2110
+ GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }}
2111
+ GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/lighthouse-sdlc-integrate"
2112
+ GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }}
2113
+ GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }}
2114
+ GH_AW_ENGINE_ID: "copilot"
2115
+ GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }}
2116
+ GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
2117
+ GH_AW_RUN_DETECTION: ${{ needs.detection.outputs.run_detection }}
2118
+ GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }}
2119
+ GH_AW_WORKFLOW_ID: "lighthouse-sdlc-integrate"
2120
+ GH_AW_WORKFLOW_NAME: "Lighthouse SDLC integrate"
2121
+ GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/lighthouse-sdlc-integrate.md"
2122
+ outputs:
2123
+ code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }}
2124
+ code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }}
2125
+ create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }}
2126
+ create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }}
2127
+ process_safe_outputs_items_applied: ${{ steps.process_safe_outputs.outputs.items_applied }}
2128
+ process_safe_outputs_items_cancelled: ${{ steps.process_safe_outputs.outputs.items_cancelled }}
2129
+ process_safe_outputs_items_deferred: ${{ steps.process_safe_outputs.outputs.items_deferred }}
2130
+ process_safe_outputs_items_failed: ${{ steps.process_safe_outputs.outputs.items_failed }}
2131
+ process_safe_outputs_items_skipped: ${{ steps.process_safe_outputs.outputs.items_skipped }}
2132
+ process_safe_outputs_items_succeeded: ${{ steps.process_safe_outputs.outputs.items_succeeded }}
2133
+ process_safe_outputs_items_warnings: ${{ steps.process_safe_outputs.outputs.items_warnings }}
2134
+ process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }}
2135
+ process_safe_outputs_status: ${{ steps.process_safe_outputs.outputs.status }}
2136
+ steps:
2137
+ - name: Setup Scripts
2138
+ id: setup
2139
+ uses: github/gh-aw-actions/setup@d9128eb3ea40c18b77c76184eda03c0ff2608d79 # v0.93.2
2140
+ with:
2141
+ destination: ${{ runner.temp }}/gh-aw/actions
2142
+ job-name: ${{ github.job }}
2143
+ trace-id: ${{ needs.activation.outputs.setup-trace-id }}
2144
+ parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
2145
+ env:
2146
+ GH_AW_SETUP_WORKFLOW_NAME: "Lighthouse SDLC integrate"
2147
+ GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/lighthouse-sdlc-integrate.lock.yml@${{ github.ref }}
2148
+ GH_AW_INFO_VERSION: "1.0.101"
2149
+ GH_AW_INFO_AWF_VERSION: "v0.28.70"
2150
+ GH_AW_INFO_ENGINE_ID: "copilot"
2151
+ GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }}
2152
+ - name: Mask OTLP telemetry headers
2153
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh"
2154
+ - name: Download agent output artifact
2155
+ id: download-agent-output
2156
+ continue-on-error: true
2157
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
2158
+ with:
2159
+ pattern: "{${{ needs.activation.outputs.artifact_prefix }}agent,${{ needs.activation.outputs.artifact_prefix }}agent-output-fallback}"
2160
+ merge-multiple: true
2161
+ path: /tmp/gh-aw/
2162
+ - name: Setup agent output environment variable
2163
+ id: setup-agent-output-env
2164
+ if: steps.download-agent-output.outcome == 'success'
2165
+ run: |
2166
+ mkdir -p /tmp/gh-aw/
2167
+ find "/tmp/gh-aw/" -type f -print
2168
+ if [ -f "/tmp/gh-aw/agent_output.json" ]; then
2169
+ echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
2170
+ fi
2171
+ - name: Configure GH_HOST for enterprise compatibility
2172
+ id: ghes-host-config
2173
+ shell: bash
2174
+ run: | # zizmor: ignore[github-env] - GITHUB_SERVER_URL is set by GitHub Actions, not user input.
2175
+ # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct
2176
+ # GitHub instance (GHES/GHEC). On github.com this is a harmless no-op.
2177
+ GH_HOST="${GITHUB_SERVER_URL#https://}"
2178
+ GH_HOST="${GH_HOST#http://}"
2179
+ echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV"
2180
+ - name: Process Safe Outputs
2181
+ id: process_safe_outputs
2182
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
2183
+ env:
2184
+ GH_AW_JOB_CHECK_RUN_ID: ${{ job.check_run_id }}
2185
+ GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
2186
+ GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }}
2187
+ GH_AW_MENTIONS_GITHUB_TOKEN: ${{ github.token }}
2188
+ GH_AW_ALLOWED_DOMAINS: "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,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,s.symcb.com,s.symcd.com,security.ubuntu.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com"
2189
+ GITHUB_SERVER_URL: ${{ github.server_url }}
2190
+ GITHUB_API_URL: ${{ github.api_url }}
2191
+ GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_report_incomplete_issue\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"false\"},\"report_incomplete\":{},\"report_missing_data\":{},\"report_missing_tool\":{}}"
2192
+ GH_AW_GITHUB_TOKEN_SOURCE: ${{ secrets.GH_AW_GITHUB_TOKEN != '' && 'pat' || 'github_actions' }}
2193
+ with:
2194
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
2195
+ script: |
2196
+ const path = require('path');
2197
+ const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions');
2198
+ const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs'));
2199
+ setupGlobals(core, github, context, exec, io, getOctokit, process.env.GH_AW_GITHUB_TOKEN_SOURCE);
2200
+ const { main } = require(path.join(actionsDir, 'process_safe_outputs.cjs'));
2201
+ await main();
2202
+ - name: Upload Safe Outputs Items
2203
+ if: always()
2204
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
2205
+ with:
2206
+ name: ${{ needs.activation.outputs.artifact_prefix }}safe-outputs-items
2207
+ path: |
2208
+ /tmp/gh-aw/safe-output-items.jsonl
2209
+ /tmp/gh-aw/temporary-id-map.json
2210
+ /tmp/gh-aw/safe-output-errors.json
2211
+ if-no-files-found: ignore
2212
+ retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }}