Skip to content

Commit b31de02

Browse files
davidslaterGitHub Acebot
authored
ci(detection-only): re-point detection job at standalone smoke sibling (#589)
* ci(detection-only): re-point detection job at standalone smoke sibling Mirror the smoke-copilot-standalone detection job body in detection-only.yml: install the released threat-detect binary via install_threat_detect_binary.sh, run `threat-detect --engine copilot --output detection_result.json` under AWF, and conclude from the structured detection_result.json via conclude_threat_detection.sh. This removes the dangling coupling to the deprecated *-container smoke siblings. The GH_AW_THREAT_DETECTION_VERSION override is preserved, and the activation/agent fixture-upload stubs are unchanged. Update the README detection-only note to describe the standalone mechanism. Closes #582 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: David Slater <12449447+davidslater@users.noreply.github.com> * ci(detection-only): validate detection max-ai-credits before config Retain the numeric guard for GH_AW_DEFAULT_DETECTION_MAX_AI_CREDITS so a free-form or malformed repository variable cannot produce invalid awf-config.json JSON and block the manual detection workflow. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: David Slater <12449447+davidslater@users.noreply.github.com> --------- Co-authored-by: GitHub Ace <githubnext@users.noreply.github.com> Co-authored-by: David Slater <12449447+davidslater@users.noreply.github.com> Co-authored-by: bot <bot@example.com>
1 parent d775112 commit b31de02

2 files changed

Lines changed: 76 additions & 65 deletions

File tree

.github/workflows/detection-only.yml

Lines changed: 75 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -83,22 +83,27 @@ jobs:
8383
permissions:
8484
contents: read
8585
packages: read
86+
copilot-requests: write
87+
env:
88+
GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }}
8689
outputs:
8790
detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }}
8891
detection_reason: ${{ steps.detection_conclusion.outputs.reason }}
8992
detection_success: ${{ steps.detection_conclusion.outputs.success }}
9093
steps:
9194
- name: Setup Scripts
9295
id: setup
93-
uses: github/gh-aw-actions/setup@v0.79.6
96+
uses: github/gh-aw-actions/setup@v0.82.14
9497
with:
9598
destination: ${{ runner.temp }}/gh-aw/actions
9699
job-name: ${{ github.job }}
97100
trace-id: ${{ needs.activation.outputs.setup-trace-id }}
98101
env:
99-
GH_AW_SETUP_WORKFLOW_NAME: "Smoke Copilot"
102+
GH_AW_SETUP_WORKFLOW_NAME: "Smoke Copilot Standalone"
100103
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/smoke-copilot-standalone.lock.yml@${{ github.ref }}
101-
GH_AW_INFO_VERSION: "1.0.40"
104+
GH_AW_INFO_VERSION: "1.0.71"
105+
GH_AW_INFO_AWF_VERSION: "v0.27.37"
106+
GH_AW_INFO_ENGINE_ID: "copilot"
102107
- name: Download agent output artifact
103108
id: download-agent-output
104109
continue-on-error: true
@@ -124,7 +129,7 @@ jobs:
124129
rm -rf /tmp/gh-aw/sandbox/firewall/logs
125130
rm -rf /tmp/gh-aw/sandbox/firewall/audit
126131
- name: Download container images
127-
run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4 ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591
132+
run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.37@sha256:0d35e8682845f183c1c634699a8e8a6cbe2c271b867031410df74533243c5f67 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.37@sha256:fc2970aadaeae05993e76697d29f03dc8bfb9248ff87a8f3d8b0975485a4b317 ghcr.io/github/gh-aw-firewall/squid:0.27.37@sha256:5abc51995e5901c5d1daeefc957301ee409980e2e607391ec22c06cb2513327b
128133
- name: Check if detection needed
129134
id: detection_guard
130135
if: always()
@@ -143,13 +148,17 @@ jobs:
143148
if: always() && steps.detection_guard.outputs.run_detection == 'true'
144149
run: |
145150
rm -f "${RUNNER_TEMP}/gh-aw/mcp-config/mcp-servers.json"
146-
rm -f /home/runner/.copilot/mcp-config.json
151+
rm -f "$HOME/.copilot/mcp-config.json"
147152
rm -f "$GITHUB_WORKSPACE/.gemini/settings.json"
148153
- name: Prepare threat detection files
149154
if: always() && steps.detection_guard.outputs.run_detection == 'true'
150155
run: |
151156
mkdir -p /tmp/gh-aw/threat-detection/aw-prompts
157+
rm -f /tmp/gh-aw/agent_usage.json
152158
cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true
159+
if [ ! -s /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt ]; then
160+
echo "::warning::ERR_VALIDATION: Missing or empty detection context prompt at /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt. Ensure the agent artifact includes /tmp/gh-aw/aw-prompts/prompt.txt. Detection will continue with fallback workflow context."
161+
fi
153162
cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true
154163
for f in /tmp/gh-aw/aw-*.patch; do
155164
[ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
@@ -163,8 +172,8 @@ jobs:
163172
if: always() && steps.detection_guard.outputs.run_detection == 'true'
164173
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
165174
env:
166-
WORKFLOW_NAME: "Smoke Copilot"
167-
WORKFLOW_DESCRIPTION: "Smoke test workflow that validates Copilot engine execution in this repository"
175+
WORKFLOW_NAME: "Smoke Copilot Standalone"
176+
WORKFLOW_DESCRIPTION: "Smoke test workflow that validates Copilot engine execution with the released threat-detect binary"
168177
HAS_PATCH: ${{ needs.agent.outputs.has_patch }}
169178
with:
170179
script: |
@@ -177,64 +186,79 @@ jobs:
177186
run: |
178187
mkdir -p /tmp/gh-aw/threat-detection
179188
touch /tmp/gh-aw/threat-detection/detection.log
180-
- name: Setup Node.js
181-
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
182-
with:
183-
node-version: '24'
184-
package-manager-cache: false
189+
- name: Install AWF binary
190+
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.27.37
185191
- name: Install GitHub Copilot CLI
186-
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.40
192+
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.71
187193
env:
188194
GH_HOST: github.com
189-
- name: Install AWF binary
190-
run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.27.2
191-
- name: Download threat detection binary
195+
- name: Install threat-detect binary
192196
if: always() && steps.detection_guard.outputs.run_detection == 'true'
193197
env:
194-
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }}
195198
THREAT_DETECTION_VERSION: ${{ vars.GH_AW_THREAT_DETECTION_VERSION || '' }}
196-
DETECTOR_REPO: github/gh-aw-threat-detection
197199
run: |
198-
set -euo pipefail
199-
dest_dir="${RUNNER_TEMP}/gh-aw/threat-detect-bin"
200-
mkdir -p "$dest_dir"
201-
download_dir="$(mktemp -d)"
202-
trap 'rm -rf "$download_dir"' EXIT
203-
case "$(uname -m)" in
204-
x86_64|amd64) asset="threat-detect-linux-amd64" ;;
205-
aarch64|arm64) asset="threat-detect-linux-arm64" ;;
206-
*) echo "::error::Unsupported architecture: $(uname -m)"; exit 1 ;;
207-
esac
208-
args=(--repo "$DETECTOR_REPO" --pattern "$asset" --pattern checksums.txt --dir "$download_dir")
209-
if [ -n "${THREAT_DETECTION_VERSION:-}" ]; then
210-
gh release download "$THREAT_DETECTION_VERSION" "${args[@]}"
211-
else
212-
gh release download "${args[@]}"
213-
fi
214-
( cd "$download_dir" && sha256sum --check --ignore-missing checksums.txt )
215-
install -m 0755 "$download_dir/$asset" "$dest_dir/threat-detect"
200+
bash "${RUNNER_TEMP}/gh-aw/actions/install_threat_detect_binary.sh" "${THREAT_DETECTION_VERSION:-v0.2.2}"
216201
- name: Execute threat detection with AWF
202+
id: detection_agentic_execution
217203
if: always() && steps.detection_guard.outputs.run_detection == 'true'
218204
continue-on-error: true
219-
id: detection_agentic_execution
220-
timeout-minutes: 20
221-
env:
222-
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
223-
THREAT_DETECTION_MODEL: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || '' }}
224-
WORKFLOW_DESCRIPTION: "Smoke test workflow that validates Copilot engine execution in this repository"
225-
WORKFLOW_NAME: ${{ github.workflow }}
226205
run: |
227206
set -o pipefail
228-
touch /tmp/gh-aw/agent-step-summary.md
207+
printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt
229208
(umask 177 && touch /tmp/gh-aw/threat-detection/detection.log)
230209
GH_AW_MAX_AI_CREDITS="${{ vars.GH_AW_DEFAULT_DETECTION_MAX_AI_CREDITS || '400' }}"
231210
# Validate that the credit limit is a numeric JSON literal to prevent malformed JSON
232211
[[ "${GH_AW_MAX_AI_CREDITS}" =~ ^(0|[1-9][0-9]*)(\.[0-9]+)?$ ]] || GH_AW_MAX_AI_CREDITS="400"
233-
printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"github.com\",\"host.docker.internal\",\"telemetry.enterprise.githubcopilot.com\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" && cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
234-
# shellcheck disable=SC1003
235-
sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env COPILOT_GITHUB_TOKEN --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull --mount "/tmp/gh-aw/threat-detection:/tmp/gh-aw/threat-detection:rw" \
236-
-- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 4 -type d -name bin 2>/dev/null | paste -sd: -):$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; result_path="/tmp/gh-aw/threat-detection/detection_result.json"; status_path="/tmp/gh-aw/threat-detection/detection-status.txt"; args=(--engine copilot); if [ -n "${THREAT_DETECTION_MODEL:-}" ]; then args+=(--model "$THREAT_DETECTION_MODEL"); fi; run_status=0; "${RUNNER_TEMP}/gh-aw/threat-detect-bin/threat-detect" "${args[@]}" --output "$result_path" /tmp/gh-aw/threat-detection 2>"$status_path" || run_status=$?; cat "$status_path" >&2 || true; if [ -f "$result_path" ]; then exit 0; fi; if grep -q "reason=invalid_report_exhausted" "$status_path" 2>/dev/null; then exit 0; fi; exit "$run_status"' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log
237-
- name: Upload threat detection artifacts
212+
printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.37/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"github.com\",\"go.dev\",\"golang.org\",\"goproxy.io\",\"host.docker.internal\",\"pkg.go.dev\",\"proxy.golang.org\",\"raw.githubusercontent.com\",\"registry.npmjs.org\",\"storage.googleapis.com\",\"sum.golang.org\",\"telemetry.enterprise.githubcopilot.com\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5},\"container\":{\"imageTag\":\"0.27.37,squid=sha256:5abc51995e5901c5d1daeefc957301ee409980e2e607391ec22c06cb2513327b,agent=sha256:0d35e8682845f183c1c634699a8e8a6cbe2c271b867031410df74533243c5f67,api-proxy=sha256:fc2970aadaeae05993e76697d29f03dc8bfb9248ff87a8f3d8b0975485a4b317,cli-proxy=sha256:1d5300d9b08e1c4f2ad1830860656a0656383a83280058f17e805a7c3ecda203\"},\"logging\":{\"proxyLogsDir\":\"/tmp/gh-aw/sandbox/firewall/logs\",\"auditDir\":\"/tmp/gh-aw/sandbox/firewall/audit\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json"
213+
cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json
214+
export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json"
215+
GH_AW_DOCKER_HOST=""
216+
if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
217+
GH_AW_DOCKER_HOST="${DOCKER_HOST}"
218+
fi
219+
if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then
220+
_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; }
221+
printf '%s\n' "$_GH_AW_CHROOT_JSON" > "${RUNNER_TEMP}/gh-aw/awf-config.json"
222+
printf '%s\n' "$_GH_AW_CHROOT_JSON" > "${RUNNER_TEMP}/gh-aw/awf-config.json"
223+
fi
224+
GH_AW_TOOL_CACHE_MOUNT=""
225+
GH_AW_TOOL_CACHE="${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"
226+
if [ -d "$GH_AW_TOOL_CACHE" ]; then
227+
if [[ "$GH_AW_TOOL_CACHE" != /opt/* ]]; then
228+
GH_AW_TOOL_CACHE_MOUNT="$GH_AW_TOOL_CACHE:$GH_AW_TOOL_CACHE:ro"
229+
fi
230+
fi
231+
# shellcheck disable=SC1003,SC2016,SC2086
232+
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 COPILOT_GITHUB_TOKEN --mount /tmp/gh-aw/threat-detection:/tmp/gh-aw/threat-detection:rw --log-level info --skip-pull \
233+
-- /bin/bash -c 'set +o histexpand; : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; export PATH="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -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
234+
env:
235+
AWF_REFLECT_ENABLED: 1
236+
COPILOT_AGENT_RUNNER_TYPE: STANDALONE
237+
COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode
238+
COPILOT_GITHUB_TOKEN: ${{ github.token }}
239+
COPILOT_MODEL: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'claude-sonnet-4.6' }}
240+
GH_AW_LLM_PROVIDER: github
241+
GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_DETECTION_MAX_AI_CREDITS || '400' }}
242+
GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
243+
GH_AW_PHASE: detection
244+
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
245+
GH_AW_TIMEOUT_MINUTES: 20
246+
GH_AW_VERSION: v0.82.14
247+
GITHUB_API_URL: ${{ github.api_url }}
248+
GITHUB_AW: true
249+
GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows
250+
GITHUB_HEAD_REF: ${{ github.head_ref }}
251+
GITHUB_REF_NAME: ${{ github.ref_name }}
252+
GITHUB_SERVER_URL: ${{ github.server_url }}
253+
GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md
254+
GITHUB_WORKSPACE: ${{ github.workspace }}
255+
GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
256+
GIT_AUTHOR_NAME: github-actions[bot]
257+
GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
258+
GIT_COMMITTER_NAME: github-actions[bot]
259+
RUNNER_TEMP: ${{ runner.temp }}
260+
S2STOKENS: true
261+
- name: Upload threat detection artifact
238262
if: always() && steps.detection_guard.outputs.run_detection == 'true'
239263
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
240264
with:
@@ -243,7 +267,7 @@ jobs:
243267
/tmp/gh-aw/threat-detection/detection_result.json
244268
/tmp/gh-aw/threat-detection/detection.log
245269
if-no-files-found: ignore
246-
- name: Parse and conclude threat detection
270+
- name: Conclude threat detection
247271
id: detection_conclusion
248272
if: always()
249273
continue-on-error: true
@@ -252,17 +276,4 @@ jobs:
252276
DETECTION_AGENTIC_EXECUTION_OUTCOME: ${{ steps.detection_agentic_execution.outcome }}
253277
GH_AW_DETECTION_CONTINUE_ON_ERROR: "true"
254278
run: |
255-
bin="${RUNNER_TEMP}/gh-aw/threat-detect-bin/threat-detect"
256-
if [ ! -x "$bin" ]; then
257-
{
258-
echo "conclusion=skipped"
259-
echo "success=true"
260-
echo "reason="
261-
} >> "$GITHUB_OUTPUT"
262-
{
263-
echo "GH_AW_DETECTION_CONCLUSION=skipped"
264-
echo "GH_AW_DETECTION_REASON="
265-
} >> "$GITHUB_ENV"
266-
exit 0
267-
fi
268-
"$bin" conclude --result-file /tmp/gh-aw/threat-detection/detection_result.json
279+
bash "${RUNNER_TEMP}/gh-aw/actions/conclude_threat_detection.sh" /tmp/gh-aw/threat-detection/detection_result.json

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ Each runs daily and by `workflow_dispatch`. The top-level `Smoke` workflow can b
309309

310310
### Detection-only Workflow
311311

312-
`.github/workflows/detection-only.yml` is a manual iteration workflow for the generated detection job. It keeps the copied detection job body aligned with the `smoke-copilot-standalone` smoke workflow, while replacing prior activation and agent jobs with stubs that upload local fixtures from `testdata/detection-only/` as the `agent` artifact.
312+
`.github/workflows/detection-only.yml` is a manual iteration workflow for the generated detection job. It keeps the copied detection job body aligned with the `smoke-copilot-standalone` smoke workflow — it installs the released `threat-detect` binary, runs `threat-detect --engine copilot --output detection_result.json` under AWF, and concludes from the structured `detection_result.json` via `conclude_threat_detection.sh` while replacing prior activation and agent jobs with stubs that upload local fixtures from `testdata/detection-only/` as the `agent` artifact.
313313

314314
### Testing a Release Candidate (`smoke-standalone-latest.yml`)
315315

0 commit comments

Comments
 (0)