diff --git a/.github/agentics/qf-s-benchmark.md b/.github/agentics/qf-s-benchmark.md new file mode 100644 index 000000000..9a5b46fbc --- /dev/null +++ b/.github/agentics/qf-s-benchmark.md @@ -0,0 +1,219 @@ + + + +# ZIPT String Solver Benchmark + +You are an AI agent that benchmarks the Z3 string solvers (`seq` and `nseq`) on QF_S SMT-LIB2 benchmarks from the `c3` branch, and publishes a summary report as a GitHub discussion. + +## Context + +- **Repository**: ${{ github.repository }} +- **Workspace**: ${{ github.workspace }} +- **Branch**: c3 (already checked out by the workflow setup step) + +## Phase 1: Build Z3 + +Build Z3 from the checked-out `c3` branch using CMake + Ninja. + +```bash +cd ${{ github.workspace }} + +# Install build dependencies if missing +sudo apt-get install -y ninja-build cmake python3 zstd 2>/dev/null || true + +# Configure the build +mkdir -p build +cd build +cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release 2>&1 | tail -20 + +# Build z3 binary (this takes ~15-17 minutes) +ninja -j$(nproc) z3 2>&1 | tail -30 + +# Verify the build succeeded +./z3 --version +``` + +If the build fails, report the error clearly and exit without proceeding. + +## Phase 2: Extract and Select Benchmark Files + +Extract the QF_S benchmark archive and randomly select 50 files. + +```bash +cd ${{ github.workspace }} + +# Extract the archive +mkdir -p /tmp/qfs_benchmarks +tar --zstd -xf tests/QF_S.tar.zst -C /tmp/qfs_benchmarks + +# List all .smt2 files +find /tmp/qfs_benchmarks -name "*.smt2" -type f > /tmp/all_qfs_files.txt +TOTAL_FILES=$(wc -l < /tmp/all_qfs_files.txt) +echo "Total QF_S files: $TOTAL_FILES" + +# Randomly select 50 files +shuf -n 50 /tmp/all_qfs_files.txt > /tmp/selected_files.txt +echo "Selected 50 files for benchmarking" +cat /tmp/selected_files.txt +``` + +## Phase 3: Run Benchmarks + +Run each of the 50 selected files with both string solvers. Use a 10-second timeout (`-T:10`). Also wrap each run with `time` to capture wall-clock duration. + +For each file, run: +1. `z3 smt.string_solver=seq -T:10 ` +2. `z3 smt.string_solver=nseq -T:10 ` + +Capture: +- **Verdict**: `sat`, `unsat`, `unknown`, `timeout` (if exit code indicates timeout), or `bug` (if z3 crashes / produces a non-standard result, or if seq and nseq disagree on sat vs unsat) +- **Time** (seconds): wall-clock time for the run + +Use a bash script to automate this: + +```bash +#!/usr/bin/env bash +set -euo pipefail + +Z3=${{ github.workspace }}/build/z3 +RESULTS=/tmp/benchmark_results.tsv +echo -e "file\tseq_verdict\tseq_time\tnseq_verdict\tnseq_time\tnotes" > "$RESULTS" + +run_z3() { + local solver="$1" + local file="$2" + local start end elapsed verdict output exit_code + + start=$(date +%s%3N) + output=$(timeout 12 "$Z3" "smt.string_solver=$solver" -T:10 "$file" 2>&1) + exit_code=$? + end=$(date +%s%3N) + elapsed=$(echo "scale=3; ($end - $start) / 1000" | bc) + + # Parse verdict + if echo "$output" | grep -q "^unsat"; then + verdict="unsat" + elif echo "$output" | grep -q "^sat"; then + verdict="sat" + elif echo "$output" | grep -q "^unknown"; then + verdict="unknown" + elif [ "$exit_code" -eq 124 ]; then + verdict="timeout" + elif echo "$output" | grep -qi "error\|assertion\|segfault\|SIGABRT\|exception"; then + verdict="bug" + else + verdict="unknown" + fi + + echo "$verdict $elapsed" +} + +while IFS= read -r file; do + fname=$(basename "$file") + seq_result=$(run_z3 seq "$file") + nseq_result=$(run_z3 nseq "$file") + + seq_verdict=$(echo "$seq_result" | cut -d' ' -f1) + seq_time=$(echo "$seq_result" | cut -d' ' -f2) + nseq_verdict=$(echo "$nseq_result" | cut -d' ' -f1) + nseq_time=$(echo "$nseq_result" | cut -d' ' -f2) + + # Flag as bug if the two solvers disagree on sat vs unsat + notes="" + if { [ "$seq_verdict" = "sat" ] && [ "$nseq_verdict" = "unsat" ]; } || \ + { [ "$seq_verdict" = "unsat" ] && [ "$nseq_verdict" = "sat" ]; }; then + notes="SOUNDNESS_DISAGREEMENT" + fi + + echo -e "$fname\t$seq_verdict\t$seq_time\t$nseq_verdict\t$nseq_time\t$notes" >> "$RESULTS" + echo "[$fname] seq=$seq_verdict(${seq_time}s) nseq=$nseq_verdict(${nseq_time}s) $notes" +done < /tmp/selected_files.txt + +echo "Benchmark run complete. Results saved to $RESULTS" +``` + +Save this script to `/tmp/run_benchmarks.sh`, make it executable, and run it. + +## Phase 4: Generate Summary Report + +Read `/tmp/benchmark_results.tsv` and compute statistics. Then generate a Markdown report. + +Compute: +- **Total benchmarks**: 50 +- **Per solver (seq and nseq)**: count of sat / unsat / unknown / timeout / bug verdicts +- **Total time used**: sum of all times for each solver +- **Average time per benchmark**: total_time / 50 +- **Soundness disagreements**: files where seq says sat but nseq says unsat or vice versa (these are the most critical bugs) +- **Bugs / crashes**: files with error/crash verdicts + +Format the report as a GitHub Discussion post (GitHub-flavored Markdown): + +```markdown +### ZIPT Benchmark Report — Z3 c3 branch + +**Date**: +**Branch**: c3 +**Benchmark set**: QF_S (50 randomly selected files from tests/QF_S.tar.zst) +**Timeout**: 10 seconds per benchmark (`-T:10`) + +--- + +### Summary + +| Metric | seq solver | nseq solver | +|--------|-----------|-------------| +| sat | X | X | +| unsat | X | X | +| unknown | X | X | +| timeout | X | X | +| bug/crash | X | X | +| **Total time (s)** | X.XXX | X.XXX | +| **Avg time/benchmark (s)** | X.XXX | X.XXX | + +**Soundness disagreements** (seq says sat, nseq says unsat or vice versa): N + +--- + +### Per-File Results + +| # | File | seq verdict | seq time (s) | nseq verdict | nseq time (s) | Notes | +|---|------|-------------|-------------|--------------|--------------|-------| +| 1 | benchmark_0001.smt2 | sat | 0.123 | sat | 0.456 | | +| ... | ... | ... | ... | ... | ... | ... | + +--- + +### Notable Issues + +#### Soundness Disagreements (Critical) + + +#### Crashes / Bugs + + +#### Slow Benchmarks (> 8s) + + +--- + +*Generated automatically by the ZIPT Benchmark workflow on the c3 branch.* +``` + +## Phase 5: Post to GitHub Discussion + +Post the Markdown report as a new GitHub Discussion using the `create-discussion` safe output. + +- **Category**: "Agentic Workflows" +- **Title**: `[ZIPT Benchmark] Z3 c3 branch — ` +- Close older discussions with the same title prefix to avoid clutter. + +## Guidelines + +- **Always build from c3 branch**: The workspace is already checked out on c3; don't change branches. +- **Handle build failures gracefully**: If Z3 fails to build, report the error and create a brief discussion noting the build failure. +- **Handle missing zstd**: If `tar --zstd` fails, try `zstd -d tests/QF_S.tar.zst --stdout | tar -x -C /tmp/qfs_benchmarks`. +- **Be precise with timing**: Use millisecond-precision timestamps and report times in seconds with 3 decimal places. +- **Distinguish timeout from unknown**: A timeout (process killed after 12s) is different from `(unknown)` returned by z3. +- **Report soundness bugs prominently**: If any benchmark shows seq=sat but nseq=unsat (or vice versa), highlight it as a critical finding. +- **Don't skip any file**: Run all 50 files even if some fail. +- **Large report**: If the per-file table is very long, put it in a `
` collapsible section. diff --git a/.github/agents/agentic-workflows.agent.md b/.github/agents/agentic-workflows.agent.md index 0b8c915e9..d796e3821 100644 --- a/.github/agents/agentic-workflows.agent.md +++ b/.github/agents/agentic-workflows.agent.md @@ -27,7 +27,7 @@ Workflows may optionally include: - Workflow files: `.github/workflows/*.md` and `.github/workflows/**/*.md` - Workflow lock files: `.github/workflows/*.lock.yml` - Shared components: `.github/workflows/shared/*.md` -- Configuration: https://github.com/github/gh-aw/blob/v0.45.3/.github/aw/github-agentic-workflows.md +- Configuration: https://github.com/github/gh-aw/blob/v0.45.6/.github/aw/github-agentic-workflows.md ## Problems This Solves @@ -49,7 +49,7 @@ When you interact with this agent, it will: ### Create New Workflow **Load when**: User wants to create a new workflow from scratch, add automation, or design a workflow that doesn't exist yet -**Prompt file**: https://github.com/github/gh-aw/blob/v0.45.3/.github/aw/create-agentic-workflow.md +**Prompt file**: https://github.com/github/gh-aw/blob/v0.45.6/.github/aw/create-agentic-workflow.md **Use cases**: - "Create a workflow that triages issues" @@ -59,7 +59,7 @@ When you interact with this agent, it will: ### Update Existing Workflow **Load when**: User wants to modify, improve, or refactor an existing workflow -**Prompt file**: https://github.com/github/gh-aw/blob/v0.45.3/.github/aw/update-agentic-workflow.md +**Prompt file**: https://github.com/github/gh-aw/blob/v0.45.6/.github/aw/update-agentic-workflow.md **Use cases**: - "Add web-fetch tool to the issue-classifier workflow" @@ -69,7 +69,7 @@ When you interact with this agent, it will: ### Debug Workflow **Load when**: User needs to investigate, audit, debug, or understand a workflow, troubleshoot issues, analyze logs, or fix errors -**Prompt file**: https://github.com/github/gh-aw/blob/v0.45.3/.github/aw/debug-agentic-workflow.md +**Prompt file**: https://github.com/github/gh-aw/blob/v0.45.6/.github/aw/debug-agentic-workflow.md **Use cases**: - "Why is this workflow failing?" @@ -79,7 +79,7 @@ When you interact with this agent, it will: ### Upgrade Agentic Workflows **Load when**: User wants to upgrade workflows to a new gh-aw version or fix deprecations -**Prompt file**: https://github.com/github/gh-aw/blob/v0.45.3/.github/aw/upgrade-agentic-workflows.md +**Prompt file**: https://github.com/github/gh-aw/blob/v0.45.6/.github/aw/upgrade-agentic-workflows.md **Use cases**: - "Upgrade all workflows to the latest version" @@ -89,37 +89,13 @@ When you interact with this agent, it will: ### Create Shared Agentic Workflow **Load when**: User wants to create a reusable workflow component or wrap an MCP server -**Prompt file**: https://github.com/github/gh-aw/blob/v0.45.3/.github/aw/create-shared-agentic-workflow.md +**Prompt file**: https://github.com/github/gh-aw/blob/v0.45.6/.github/aw/create-shared-agentic-workflow.md **Use cases**: - "Create a shared component for Notion integration" - "Wrap the Slack MCP server as a reusable component" - "Design a shared workflow for database queries" -### Orchestration and Delegation - -**Load when**: Creating or updating workflows that coordinate multiple agents or dispatch work to other workflows - -**Prompt file**: https://github.com/github/gh-aw/blob/v0.45.3/.github/aw/orchestration.md - -**Use cases**: -- Assigning work to AI coding agents -- Dispatching specialized worker workflows -- Using correlation IDs for tracking -- Orchestration design patterns - -### GitHub Projects Integration - -**Load when**: Creating or updating workflows that manage GitHub Projects v2 - -**Prompt file**: https://github.com/github/gh-aw/blob/v0.45.3/.github/aw/projects.md - -**Use cases**: -- Tracking items and fields with update-project -- Posting periodic run summaries -- Creating new projects -- Projects v2 authentication and configuration - ## Instructions When a user interacts with you: @@ -160,7 +136,7 @@ gh aw compile --validate ## Important Notes -- Always reference the instructions file at https://github.com/github/gh-aw/blob/v0.45.3/.github/aw/github-agentic-workflows.md for complete documentation +- Always reference the instructions file at https://github.com/github/gh-aw/blob/v0.45.6/.github/aw/github-agentic-workflows.md for complete documentation - Use the MCP tool `agentic-workflows` when running in GitHub Copilot Cloud - Workflows must be compiled to `.lock.yml` files before running in GitHub Actions - **Bash tools are enabled by default** - Don't restrict bash commands unnecessarily since workflows are sandboxed by the AWF diff --git a/.github/workflows/Windows.yml b/.github/workflows/Windows.yml index 9441f9930..24008bc72 100644 --- a/.github/workflows/Windows.yml +++ b/.github/workflows/Windows.yml @@ -28,7 +28,7 @@ jobs: runs-on: windows-latest steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Add msbuild to PATH uses: microsoft/setup-msbuild@v2 - run: | diff --git a/.github/workflows/a3-python.lock.yml b/.github/workflows/a3-python.lock.yml index 19418c3d3..9fe69e707 100644 --- a/.github/workflows/a3-python.lock.yml +++ b/.github/workflows/a3-python.lock.yml @@ -49,7 +49,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Checkout .github and .agents folders @@ -247,7 +247,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -819,7 +819,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -912,7 +912,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1023,7 +1023,7 @@ jobs: process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/agentics-maintenance.yml b/.github/workflows/agentics-maintenance.yml index 018d4c9b9..96572197e 100644 --- a/.github/workflows/agentics-maintenance.yml +++ b/.github/workflows/agentics-maintenance.yml @@ -49,7 +49,7 @@ jobs: pull-requests: write steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@v0.51.6 + uses: github/gh-aw/actions/setup@v0.57.0 with: destination: /opt/gh-aw/actions diff --git a/.github/workflows/android-build.yml b/.github/workflows/android-build.yml index 649cde2ce..451b99640 100644 --- a/.github/workflows/android-build.yml +++ b/.github/workflows/android-build.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Configure CMake and build run: | @@ -33,7 +33,7 @@ jobs: tar -cvf z3-build-${{ matrix.android-abi }}.tar *.jar *.so - name: Archive production artifacts - uses: actions/upload-artifact@v7.0.0 + uses: actions/upload-artifact@v7 with: name: android-build-${{ matrix.android-abi }} path: build/z3-build-${{ matrix.android-abi }}.tar diff --git a/.github/workflows/api-coherence-checker.lock.yml b/.github/workflows/api-coherence-checker.lock.yml index 0c2a50c1b..31e4bed7c 100644 --- a/.github/workflows/api-coherence-checker.lock.yml +++ b/.github/workflows/api-coherence-checker.lock.yml @@ -49,7 +49,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Checkout .github and .agents folders @@ -254,7 +254,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Create gh-aw temp directory @@ -831,7 +831,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -922,7 +922,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1033,7 +1033,7 @@ jobs: process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1070,7 +1070,7 @@ jobs: permissions: {} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download cache-memory artifact (default) diff --git a/.github/workflows/build-warning-fixer.lock.yml b/.github/workflows/build-warning-fixer.lock.yml index 15c1af900..5802752cc 100644 --- a/.github/workflows/build-warning-fixer.lock.yml +++ b/.github/workflows/build-warning-fixer.lock.yml @@ -49,7 +49,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Checkout .github and .agents folders @@ -242,7 +242,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -804,7 +804,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -909,7 +909,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1021,7 +1021,7 @@ jobs: process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/build-z3-cache.yml b/.github/workflows/build-z3-cache.yml index 4f3ce7089..5d6e22432 100644 --- a/.github/workflows/build-z3-cache.yml +++ b/.github/workflows/build-z3-cache.yml @@ -29,7 +29,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 459c74708..ae2136e4d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,7 @@ jobs: runRegressions: false steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -81,7 +81,7 @@ jobs: container: "quay.io/pypa/manylinux_2_34_x86_64:latest" steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python virtual environment run: "/opt/python/cp38-cp38/bin/python -m venv $PWD/env" @@ -113,7 +113,7 @@ jobs: container: quay.io/pypa/manylinux_2_28_x86_64:latest steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Download ARM toolchain run: curl -L -o /tmp/arm-toolchain.tar.xz 'https://developer.arm.com/-/media/Files/downloads/gnu/13.3.rel1/binrel/arm-gnu-toolchain-13.3.rel1-x86_64-aarch64-none-linux-gnu.tar.xz' @@ -149,7 +149,7 @@ jobs: timeout-minutes: 90 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup OCaml uses: ocaml/setup-ocaml@v3 @@ -204,7 +204,7 @@ jobs: timeout-minutes: 90 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup OCaml uses: ocaml/setup-ocaml@v3 @@ -298,7 +298,7 @@ jobs: runTests: false steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -388,7 +388,7 @@ jobs: timeout-minutes: 90 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -415,6 +415,78 @@ jobs: - name: Run regressions run: python z3test/scripts/test_benchmarks.py build/z3 z3test/regressions/smt2 + - name: Validate JNI library architecture matches host + run: | + echo "Checking libz3java.dylib architecture..." + ARCH=$(lipo -archs build/libz3java.dylib) + HOST_ARCH=$(uname -m) + echo "libz3java.dylib arch: $ARCH | host arch: $HOST_ARCH" + if [ "$ARCH" != "$HOST_ARCH" ]; then + echo "ERROR: libz3java.dylib has arch '$ARCH' but host is '$HOST_ARCH'" + exit 1 + fi + echo "OK: libz3java.dylib correctly built for $HOST_ARCH" + + # ============================================================================ + # macOS JNI cross-compilation validation (ARM64 host -> x86_64 target) + # ============================================================================ + macos-jni-cross-compile: + name: "MacOS JNI cross-compile (ARM64 -> x64) architecture validation" + runs-on: macos-15 + timeout-minutes: 90 + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: '3.x' + + - name: Configure (cross-compile ARM64 host -> x86_64 target) + run: | + CXXFLAGS="-arch x86_64" CFLAGS="-arch x86_64" LDFLAGS="-arch x86_64" \ + python scripts/mk_make.py --java --arm64=false + + - name: Build + run: | + set -e + cd build + make -j3 libz3java.dylib + cd .. + + - name: Validate libz3java.dylib is x86_64 + run: | + echo "Checking libz3java.dylib architecture..." + ARCH=$(lipo -archs build/libz3java.dylib) + echo "libz3java.dylib architecture: $ARCH" + if [ "$ARCH" != "x86_64" ]; then + echo "ERROR: Expected x86_64 (cross-compiled target), got: $ARCH" + echo "This is the regression fixed in: JNI bindings use wrong architecture in macOS cross-compilation" + exit 1 + fi + echo "OK: libz3java.dylib correctly built for x86_64 target on ARM64 host" + + # ============================================================================ + # Python script unit tests (build-script logic validation) + # ============================================================================ + python-script-tests: + name: "Python build-script unit tests" + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: '3.x' + + - name: Run Python script unit tests + working-directory: ${{ github.workspace }} + run: python -m unittest discover -s scripts/tests -p "test_*.py" -v + # ============================================================================ # macOS CMake Builds # ============================================================================ @@ -424,7 +496,7 @@ jobs: timeout-minutes: 90 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 diff --git a/.github/workflows/code-conventions-analyzer.lock.yml b/.github/workflows/code-conventions-analyzer.lock.yml index 4867d4d7b..5c27079c0 100644 --- a/.github/workflows/code-conventions-analyzer.lock.yml +++ b/.github/workflows/code-conventions-analyzer.lock.yml @@ -49,7 +49,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Checkout .github and .agents folders @@ -249,7 +249,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -910,7 +910,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1003,7 +1003,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1114,7 +1114,7 @@ jobs: process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1151,7 +1151,7 @@ jobs: permissions: {} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download cache-memory artifact (default) diff --git a/.github/workflows/code-simplifier.lock.yml b/.github/workflows/code-simplifier.lock.yml index 797cea8be..56e2a1614 100644 --- a/.github/workflows/code-simplifier.lock.yml +++ b/.github/workflows/code-simplifier.lock.yml @@ -54,7 +54,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Checkout .github and .agents folders @@ -252,7 +252,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -824,7 +824,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -925,7 +925,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1020,7 +1020,7 @@ jobs: activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_skip_if_match.outputs.skip_check_ok == 'true') }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Check team membership for workflow @@ -1073,7 +1073,7 @@ jobs: process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index e07e3e011..94d86b8cd 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -19,7 +19,7 @@ jobs: COV_DETAILS_PATH: ${{github.workspace}}/cov-details steps: - - uses: actions/checkout@v6.0.2 + - uses: actions/checkout@v6 - name: Setup run: | @@ -89,13 +89,13 @@ jobs: id: date run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT - - uses: actions/upload-artifact@v7.0.0 + - uses: actions/upload-artifact@v7 with: name: coverage-${{steps.date.outputs.date}} path: ${{github.workspace}}/coverage.html retention-days: 4 - - uses: actions/upload-artifact@v7.0.0 + - uses: actions/upload-artifact@v7 with: name: coverage-details-${{steps.date.outputs.date}} path: ${{env.COV_DETAILS_PATH}} diff --git a/.github/workflows/cross-build.yml b/.github/workflows/cross-build.yml index f8213abce..9c5dedaa0 100644 --- a/.github/workflows/cross-build.yml +++ b/.github/workflows/cross-build.yml @@ -20,7 +20,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Install cross build tools run: apt update && apt install -y ninja-build cmake python3 g++-13-${{ matrix.arch }}-linux-gnu diff --git a/.github/workflows/csa-analysis.lock.yml b/.github/workflows/csa-analysis.lock.yml index 23631e9b3..01d96f156 100644 --- a/.github/workflows/csa-analysis.lock.yml +++ b/.github/workflows/csa-analysis.lock.yml @@ -49,7 +49,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@v0.51.6 + uses: github/gh-aw/actions/setup@v0.57.0 with: destination: /opt/gh-aw/actions - name: Validate context variables @@ -238,7 +238,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@v0.51.6 + uses: github/gh-aw/actions/setup@v0.57.0 with: destination: /opt/gh-aw/actions - name: Create gh-aw temp directory @@ -949,7 +949,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@v0.51.6 + uses: github/gh-aw/actions/setup@v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1053,7 +1053,7 @@ jobs: process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@v0.51.6 + uses: github/gh-aw/actions/setup@v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1097,7 +1097,7 @@ jobs: GH_AW_WORKFLOW_ID_SANITIZED: csaanalysis steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@v0.51.6 + uses: github/gh-aw/actions/setup@v0.57.0 with: destination: /opt/gh-aw/actions - name: Download cache-memory artifact (default) diff --git a/.github/workflows/deeptest.lock.yml b/.github/workflows/deeptest.lock.yml index e0399378b..23c1c43f6 100644 --- a/.github/workflows/deeptest.lock.yml +++ b/.github/workflows/deeptest.lock.yml @@ -55,7 +55,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Checkout .github and .agents folders @@ -263,7 +263,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Create gh-aw temp directory @@ -885,7 +885,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -990,7 +990,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1103,7 +1103,7 @@ jobs: process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1166,7 +1166,7 @@ jobs: permissions: {} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download cache-memory artifact (default) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index cfea8b53f..4a9936007 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Go uses: actions/setup-go@v6 @@ -34,7 +34,7 @@ jobs: python3 mk_go_doc.py --output-dir=api/html/go --go-api-path=../src/api/go - name: Upload Go Documentation - uses: actions/upload-artifact@v7.0.0 + uses: actions/upload-artifact@v7 with: name: go-docs path: doc/api/html/go/ @@ -46,7 +46,7 @@ jobs: needs: build-go-docs steps: - name: Checkout - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup node uses: actions/setup-node@v6 @@ -125,7 +125,7 @@ jobs: python3 mk_api_doc.py --js --go --output-dir=api --mld --z3py-package-path=../build-x64/python/z3 --build=../build-x64 - name: Download Go Documentation - uses: actions/download-artifact@v8.0.0 + uses: actions/download-artifact@v8 with: name: go-docs path: doc/api/html/go/ diff --git a/.github/workflows/issue-backlog-processor.lock.yml b/.github/workflows/issue-backlog-processor.lock.yml index a4b0f2bf4..95c19bbbd 100644 --- a/.github/workflows/issue-backlog-processor.lock.yml +++ b/.github/workflows/issue-backlog-processor.lock.yml @@ -49,7 +49,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Checkout .github and .agents folders @@ -254,7 +254,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Checkout repository @@ -858,7 +858,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -949,7 +949,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1061,7 +1061,7 @@ jobs: process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -1098,7 +1098,7 @@ jobs: permissions: {} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download cache-memory artifact (default) diff --git a/.github/workflows/memory-safety-report.lock.yml b/.github/workflows/memory-safety-report.lock.yml new file mode 100644 index 000000000..dd330a450 --- /dev/null +++ b/.github/workflows/memory-safety-report.lock.yml @@ -0,0 +1,1118 @@ +# +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw (v0.45.6). DO NOT EDIT. +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# Generates a detailed Memory Safety report for Z3 by analyzing ASan/UBSan sanitizer logs from the memory-safety workflow, posting findings as a GitHub Discussion. +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"b0987209ae9803a2044e33e0218a06e8964d0d749f873a7caf17a278b594b54f"} + +name: "Memory Safety Analysis Report Generator" +"on": + workflow_dispatch: + workflow_run: + # zizmor: ignore[dangerous-triggers] - workflow_run trigger is secured with role and fork validation + types: + - completed + workflows: + - Memory Safety Analysis + +permissions: {} + +concurrency: + group: "gh-aw-${{ github.workflow }}" + +run-name: "Memory Safety Analysis Report Generator" + +jobs: + activation: + needs: pre_activation + # zizmor: ignore[dangerous-triggers] - workflow_run trigger is secured with role and fork validation + if: > + (needs.pre_activation.outputs.activated == 'true') && ((github.event_name != 'workflow_run') || ((github.event.workflow_run.repository.id == github.repository_id) && + (!(github.event.workflow_run.repository.fork)))) + runs-on: ubuntu-slim + permissions: + contents: read + outputs: + comment_id: "" + comment_repo: "" + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 + with: + destination: /opt/gh-aw/actions + - name: Checkout .github and .agents folders + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: | + .github + .agents + fetch-depth: 1 + persist-credentials: false + - name: Check workflow file timestamps + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_WORKFLOW_FILE: "memory-safety-report.lock.yml" + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/check_workflow_timestamp_api.cjs'); + await main(); + - name: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_EVENT_WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKFLOW: ${{ github.workflow }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + run: | + bash /opt/gh-aw/actions/create_prompt_first.sh + cat << 'GH_AW_PROMPT_EOF' > "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat "/opt/gh-aw/prompts/xpia.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/cache_memory_prompt.md" >> "$GH_AW_PROMPT" + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GitHub API Access Instructions + + The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. + + + To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. + + Temporary IDs: Some safe output tools support a temporary ID field (usually named temporary_id) so you can reference newly-created items elsewhere in the SAME agent output (for example, using #aw_abc1 in a later body). + + **IMPORTANT - temporary_id format rules:** + - If you DON'T need to reference the item later, OMIT the temporary_id field entirely (it will be auto-generated if needed) + - If you DO need cross-references/chaining, you MUST match this EXACT validation regex: /^aw_[A-Za-z0-9]{3,8}$/i + - Format: aw_ prefix followed by 3 to 8 alphanumeric characters (A-Z, a-z, 0-9, case-insensitive) + - Valid alphanumeric characters: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 + - INVALID examples: aw_ab (too short), aw_123456789 (too long), aw_test-id (contains hyphen), aw_id_123 (contains underscore) + - VALID examples: aw_abc, aw_abc1, aw_Test123, aw_A1B2C3D4, aw_12345678 + - To generate valid IDs: use 3-8 random alphanumeric characters or omit the field to let the system auto-generate + + Do NOT invent other aw_* formats — downstream steps will reject them with validation errors matching against /^aw_[A-Za-z0-9]{3,8}$/i. + + Discover available tools from the safeoutputs MCP server. + + **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. + + **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + + + The following GitHub context information is available for this workflow: + {{#if __GH_AW_GITHUB_ACTOR__ }} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if __GH_AW_GITHUB_REPOSITORY__ }} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if __GH_AW_GITHUB_WORKSPACE__ }} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} + - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} + - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} + - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} + - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{/if}} + {{#if __GH_AW_GITHUB_RUN_ID__ }} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + {{#runtime-import .github/workflows/memory-safety-report.md}} + GH_AW_PROMPT_EOF + - name: Interpolate variables and render templates + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_EVENT_WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_WORKFLOW: ${{ github.workflow }} + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_ALLOWED_EXTENSIONS: '' + GH_AW_CACHE_DESCRIPTION: '' + GH_AW_CACHE_DIR: '/tmp/gh-aw/cache-memory/' + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_EVENT_WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKFLOW: ${{ github.workflow }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND: ${{ needs.pre_activation.outputs.matched_command }} + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + + const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_ALLOWED_EXTENSIONS: process.env.GH_AW_ALLOWED_EXTENSIONS, + GH_AW_CACHE_DESCRIPTION: process.env.GH_AW_CACHE_DESCRIPTION, + GH_AW_CACHE_DIR: process.env.GH_AW_CACHE_DIR, + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, + GH_AW_GITHUB_EVENT_WORKFLOW_RUN_ID: process.env.GH_AW_GITHUB_EVENT_WORKFLOW_RUN_ID, + GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, + GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, + GH_AW_GITHUB_WORKFLOW: process.env.GH_AW_GITHUB_WORKFLOW, + GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED, + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND + } + }); + - name: Validate prompt placeholders + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/print_prompt_summary.sh + - name: Upload prompt artifact + if: success() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts/prompt.txt + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + discussions: read + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + GH_AW_SAFE_OUTPUTS: /opt/gh-aw/safeoutputs/outputs.jsonl + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json + GH_AW_WORKFLOW_ID_SANITIZED: memorysafetyreport + outputs: + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + model: ${{ steps.generate_aw_info.outputs.model }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 + with: + destination: /opt/gh-aw/actions + - name: Create gh-aw temp directory + run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + # Cache memory file share configuration from frontmatter processed below + - name: Create cache-memory directory + run: bash /opt/gh-aw/actions/create_cache_memory_dir.sh + - name: Restore cache-memory file share data + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + key: memory-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }} + path: /tmp/gh-aw/cache-memory + restore-keys: | + memory-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}- + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Generate agentic run info + id: generate_aw_info + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const fs = require('fs'); + + const awInfo = { + engine_id: "copilot", + engine_name: "GitHub Copilot CLI", + model: process.env.GH_AW_MODEL_AGENT_COPILOT || "", + version: "", + agent_version: "0.0.410", + cli_version: "v0.45.6", + workflow_name: "Memory Safety Analysis Report Generator", + experimental: false, + supports_tools_allowlist: true, + run_id: context.runId, + run_number: context.runNumber, + run_attempt: process.env.GITHUB_RUN_ATTEMPT, + repository: context.repo.owner + '/' + context.repo.repo, + ref: context.ref, + sha: context.sha, + actor: context.actor, + event_name: context.eventName, + staged: false, + allowed_domains: ["defaults"], + firewall_enabled: true, + awf_version: "v0.19.1", + awmg_version: "v0.1.4", + steps: { + firewall: "squid" + }, + created_at: new Date().toISOString() + }; + + // Write to /tmp/gh-aw directory to avoid inclusion in PR + const tmpPath = '/tmp/gh-aw/aw_info.json'; + fs.writeFileSync(tmpPath, JSON.stringify(awInfo, null, 2)); + console.log('Generated aw_info.json at:', tmpPath); + console.log(JSON.stringify(awInfo, null, 2)); + + // Set model as output for reuse in other steps/jobs + core.setOutput('model', awInfo.model); + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.410 + - name: Install awf binary + run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.19.1 + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + with: + script: | + const determineAutomaticLockdown = require('/opt/gh-aw/actions/determine_automatic_lockdown.cjs'); + await determineAutomaticLockdown(github, context, core); + - name: Download container images + run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/gh-aw-firewall/agent:0.19.1 ghcr.io/github/gh-aw-firewall/squid:0.19.1 ghcr.io/github/gh-aw-mcpg:v0.1.4 ghcr.io/github/github-mcp-server:v0.30.3 node:lts-alpine + - name: Write Safe Outputs Config + run: | + mkdir -p /opt/gh-aw/safeoutputs + mkdir -p /tmp/gh-aw/safeoutputs + mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs + cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' + {"create_discussion":{"expires":168,"max":1},"create_missing_tool_issue":{"max":1,"title_prefix":"[missing tool]"},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + GH_AW_SAFE_OUTPUTS_CONFIG_EOF + cat > /opt/gh-aw/safeoutputs/tools.json << 'GH_AW_SAFE_OUTPUTS_TOOLS_EOF' + [ + { + "description": "Create a GitHub discussion for announcements, Q\u0026A, reports, status updates, or community conversations. Use this for content that benefits from threaded replies, doesn't require task tracking, or serves as documentation. For actionable work items that need assignment and status tracking, use create_issue instead. CONSTRAINTS: Maximum 1 discussion(s) can be created. Title will be prefixed with \"[Memory Safety] \". Discussions will be created in category \"agentic workflows\".", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Discussion content in Markdown. Do NOT repeat the title as a heading since it already appears as the discussion's h1. Include all relevant context, findings, or questions.", + "type": "string" + }, + "category": { + "description": "Discussion category by name (e.g., 'General'), slug (e.g., 'general'), or ID. If omitted, uses the first available category. Category must exist in the repository.", + "type": "string" + }, + "title": { + "description": "Concise discussion title summarizing the topic. The title appears as the main heading, so keep it brief and descriptive.", + "type": "string" + } + }, + "required": [ + "title", + "body" + ], + "type": "object" + }, + "name": "create_discussion" + }, + { + "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "reason": { + "description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).", + "type": "string" + }, + "tool": { + "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", + "type": "string" + } + }, + "required": [ + "reason" + ], + "type": "object" + }, + "name": "missing_tool" + }, + { + "description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "message": { + "description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').", + "type": "string" + } + }, + "required": [ + "message" + ], + "type": "object" + }, + "name": "noop" + }, + { + "description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "context": { + "description": "Additional context about the missing data or where it should come from (max 256 characters).", + "type": "string" + }, + "data_type": { + "description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.", + "type": "string" + }, + "reason": { + "description": "Explanation of why this data is needed to complete the task (max 256 characters).", + "type": "string" + } + }, + "required": [], + "type": "object" + }, + "name": "missing_data" + } + ] + GH_AW_SAFE_OUTPUTS_TOOLS_EOF + cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' + { + "create_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "category": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "repo": { + "type": "string", + "maxLength": 256 + }, + "title": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + } + } + GH_AW_SAFE_OUTPUTS_VALIDATION_EOF + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash /opt/gh-aw/actions/start_safe_outputs_server.sh + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export DEBUG="*" + + export GH_AW_ENGINE="copilot" + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -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_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_LOCKDOWN -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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -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 ghcr.io/github/gh-aw-mcpg:v0.1.4' + + mkdir -p /home/runner/.copilot + cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh + { + "mcpServers": { + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.30.3", + "env": { + "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" + } + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_EOF + - name: Generate workflow overview + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); + await generateWorkflowOverview(core); + - name: Download prompt artifact + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts + - name: Clean git credentials + run: bash /opt/gh-aw/actions/clean_git_credentials.sh + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 30 + run: | + set -o pipefail + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.19.1 --skip-pull \ + -- /bin/bash -c '/usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --add-dir "${GITHUB_WORKSPACE}" --disable-builtin-mcps --allow-all-tools --add-dir /tmp/gh-aw/cache-memory/ --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"${GH_AW_MODEL_AGENT_COPILOT:+ --model "$GH_AW_MODEL_AGENT_COPILOT"}' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_MODEL_AGENT_COPILOT: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '' }} + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: | + # Copy Copilot session state files to logs folder for artifact collection + # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them + SESSION_STATE_DIR="$HOME/.copilot/session-state" + LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" + + if [ -d "$SESSION_STATE_DIR" ]; then + echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" + mkdir -p "$LOGS_DIR" + cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true + echo "Session state files copied successfully" + else + echo "No session-state directory found at $SESSION_STATE_DIR" + fi + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Upload Safe Outputs + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: safe-output + path: ${{ env.GH_AW_SAFE_OUTPUTS }} + if-no-files-found: warn + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/collect_ndjson_output.cjs'); + await main(); + - name: Upload sanitized agent output + if: always() && env.GH_AW_AGENT_OUTPUT + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: agent-output + path: ${{ env.GH_AW_AGENT_OUTPUT }} + if-no-files-found: warn + - name: Upload engine output files + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: agent_outputs + path: | + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + if-no-files-found: ignore + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/parse_copilot_log.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Upload cache-memory data as artifact + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + if: always() + with: + name: cache-memory + path: /tmp/gh-aw/cache-memory + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: agent-artifacts + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/sandbox/firewall/logs/ + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/ + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - detection + - safe_outputs + - update_cache_memory + if: (always()) && (needs.agent.result != 'skipped') + runs-on: ubuntu-slim + permissions: + contents: read + discussions: write + issues: write + outputs: + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process No-Op Messages + id: noop + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: 1 + GH_AW_WORKFLOW_NAME: "Memory Safety Analysis Report Generator" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/noop.cjs'); + await main(); + - name: Record Missing Tool + id: missing_tool + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_MISSING_TOOL_CREATE_ISSUE: "true" + GH_AW_MISSING_TOOL_TITLE_PREFIX: "[missing tool]" + GH_AW_WORKFLOW_NAME: "Memory Safety Analysis Report Generator" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Handle Agent Failure + id: handle_agent_failure + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Memory Safety Analysis Report Generator" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_WORKFLOW_ID: "memory-safety-report" + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_CREATE_DISCUSSION_ERRORS: ${{ needs.safe_outputs.outputs.create_discussion_errors }} + GH_AW_CREATE_DISCUSSION_ERROR_COUNT: ${{ needs.safe_outputs.outputs.create_discussion_error_count }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + - name: Handle No-Op Message + id: handle_noop_message + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Memory Safety Analysis Report Generator" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_NOOP_MESSAGE: ${{ steps.noop.outputs.noop_message }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); + await main(); + + detection: + needs: agent + if: needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true' + runs-on: ubuntu-latest + permissions: {} + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + timeout-minutes: 10 + outputs: + success: ${{ steps.parse_results.outputs.success }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 + with: + destination: /opt/gh-aw/actions + - name: Download agent artifacts + continue-on-error: true + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + with: + name: agent-artifacts + path: /tmp/gh-aw/threat-detection/ + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + with: + name: agent-output + path: /tmp/gh-aw/threat-detection/ + - name: Echo agent output types + env: + AGENT_OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} + run: | + echo "Agent output-types: $AGENT_OUTPUT_TYPES" + - name: Setup threat detection + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + WORKFLOW_NAME: "Memory Safety Analysis Report Generator" + WORKFLOW_DESCRIPTION: "Generates a detailed Memory Safety report for Z3 by analyzing ASan/UBSan sanitizer logs from the memory-safety workflow, posting findings as a GitHub Discussion." + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/setup_threat_detection.cjs'); + await main(); + - name: Ensure threat-detection directory and log + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.410 + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool shell(cat) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(jq) + # --allow-tool shell(ls) + # --allow-tool shell(tail) + # --allow-tool shell(wc) + timeout-minutes: 20 + run: | + set -o pipefail + COPILOT_CLI_INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" + mkdir -p /tmp/ + mkdir -p /tmp/gh-aw/ + mkdir -p /tmp/gh-aw/agent/ + mkdir -p /tmp/gh-aw/sandbox/agent/logs/ + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION"${GH_AW_MODEL_DETECTION_COPILOT:+ --model "$GH_AW_MODEL_DETECTION_COPILOT"} 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + GH_AW_MODEL_DETECTION_COPILOT: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || '' }} + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Parse threat detection results + id: parse_results + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/parse_threat_detection_results.cjs'); + await main(); + - name: Upload threat detection log + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: threat-detection.log + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + + pre_activation: + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 + with: + destination: /opt/gh-aw/actions + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REQUIRED_ROLES: admin,maintainer,write + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/check_membership.cjs'); + await main(); + + safe_outputs: + needs: + - agent + - detection + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.detection.outputs.success == 'true') + runs-on: ubuntu-slim + permissions: + contents: read + discussions: write + issues: write + timeout-minutes: 15 + env: + GH_AW_ENGINE_ID: "copilot" + GH_AW_WORKFLOW_ID: "memory-safety-report" + GH_AW_WORKFLOW_NAME: "Memory Safety Analysis Report Generator" + outputs: + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"agentic workflows\",\"close_older_discussions\":true,\"expires\":168,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[Memory Safety] \"},\"missing_data\":{},\"missing_tool\":{}}" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + + update_cache_memory: + needs: + - agent + - detection + if: always() && needs.detection.outputs.success == 'true' + runs-on: ubuntu-latest + permissions: {} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 + with: + destination: /opt/gh-aw/actions + - name: Download cache-memory artifact (default) + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + continue-on-error: true + with: + name: cache-memory + path: /tmp/gh-aw/cache-memory + - name: Save cache-memory to cache (default) + uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + with: + key: memory-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }} + path: /tmp/gh-aw/cache-memory + diff --git a/.github/workflows/memory-safety-report.md b/.github/workflows/memory-safety-report.md index 5b614966c..ccc6467fd 100644 --- a/.github/workflows/memory-safety-report.md +++ b/.github/workflows/memory-safety-report.md @@ -15,7 +15,7 @@ timeout-minutes: 30 permissions: actions: read contents: read - discussions: write + discussions: read env: GH_TOKEN: ${{ github.token }} @@ -205,4 +205,4 @@ Store the current run's results in cache memory for future comparison: - **DO NOT** attempt to fix the findings automatically. - **DO** close older Memory Safety discussions automatically (configured via `close-older-discussions: true`). - **DO** always report the commit SHA so findings can be correlated with specific code versions. -- **DO** use cache memory to track trends over multiple runs. +- **DO** use cache memory to track trends over multiple runs. \ No newline at end of file diff --git a/.github/workflows/memory-safety.yml b/.github/workflows/memory-safety.yml index d701542f0..ad1095438 100644 --- a/.github/workflows/memory-safety.yml +++ b/.github/workflows/memory-safety.yml @@ -34,7 +34,7 @@ jobs: ASAN_OPTIONS: "detect_leaks=1:halt_on_error=0:print_stats=1:log_path=/tmp/asan" steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v5 @@ -107,7 +107,7 @@ jobs: - name: Upload ASan reports if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: asan-reports path: /tmp/asan-reports/ @@ -124,7 +124,7 @@ jobs: UBSAN_OPTIONS: "print_stacktrace=1:halt_on_error=0:log_path=/tmp/ubsan" steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v5 @@ -140,8 +140,8 @@ jobs: cd build-ubsan CC=clang CXX=clang++ cmake \ -DCMAKE_BUILD_TYPE=Debug \ - -DCMAKE_C_FLAGS="-fsanitize=undefined -fno-omit-frame-pointer -fno-sanitize-recover=all" \ - -DCMAKE_CXX_FLAGS="-fsanitize=undefined -fno-omit-frame-pointer -fno-sanitize-recover=all" \ + -DCMAKE_C_FLAGS="-fsanitize=undefined -fno-omit-frame-pointer -fsanitize-recover=all" \ + -DCMAKE_CXX_FLAGS="-fsanitize=undefined -fno-omit-frame-pointer -fsanitize-recover=all" \ -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=undefined" \ -DCMAKE_SHARED_LINKER_FLAGS="-fsanitize=undefined" \ -G Ninja ../ @@ -197,7 +197,7 @@ jobs: - name: Upload UBSan reports if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ubsan-reports path: /tmp/ubsan-reports/ @@ -213,7 +213,7 @@ jobs: if: always() steps: - name: Download all artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: path: reports/ diff --git a/.github/workflows/msvc-static-build-clang-cl.yml b/.github/workflows/msvc-static-build-clang-cl.yml index f57bbbaa7..e13b3ddf1 100644 --- a/.github/workflows/msvc-static-build-clang-cl.yml +++ b/.github/workflows/msvc-static-build-clang-cl.yml @@ -14,7 +14,7 @@ jobs: BUILD_TYPE: Release steps: - name: Checkout Repo - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Build run: | diff --git a/.github/workflows/msvc-static-build.yml b/.github/workflows/msvc-static-build.yml index 379dad1d1..f37f9804b 100644 --- a/.github/workflows/msvc-static-build.yml +++ b/.github/workflows/msvc-static-build.yml @@ -14,7 +14,7 @@ jobs: BUILD_TYPE: Release steps: - name: Checkout Repo - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Build run: | diff --git a/.github/workflows/nightly-validation.yml b/.github/workflows/nightly-validation.yml index 2cb6f4233..013481e42 100644 --- a/.github/workflows/nightly-validation.yml +++ b/.github/workflows/nightly-validation.yml @@ -27,7 +27,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup .NET uses: actions/setup-dotnet@v5 @@ -87,7 +87,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup .NET uses: actions/setup-dotnet@v5 @@ -142,7 +142,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup .NET uses: actions/setup-dotnet@v5 @@ -214,7 +214,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup .NET uses: actions/setup-dotnet@v5 @@ -290,7 +290,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Download Windows x64 build from release env: @@ -326,7 +326,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Download Windows x86 build from release env: @@ -362,7 +362,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Download Ubuntu x64 build from release env: @@ -395,7 +395,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Download macOS x64 build from release env: @@ -428,7 +428,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Download macOS ARM64 build from release env: @@ -465,7 +465,7 @@ jobs: timeout-minutes: 60 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -504,7 +504,7 @@ jobs: timeout-minutes: 60 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -544,7 +544,7 @@ jobs: timeout-minutes: 60 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -587,7 +587,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -616,7 +616,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -645,7 +645,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -674,7 +674,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -710,7 +710,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Download macOS x64 build from release env: @@ -762,7 +762,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Download macOS ARM64 build from release env: diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index a3f28e1a8..0ac90fe8f 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -35,7 +35,7 @@ jobs: timeout-minutes: 90 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -46,7 +46,7 @@ jobs: run: python scripts/mk_unix_dist.py --dotnet-key=$GITHUB_WORKSPACE/resources/z3.snk --arch=x64 - name: Upload artifact - uses: actions/upload-artifact@v7.0.0 + uses: actions/upload-artifact@v7 with: name: macOsBuild path: dist/*.zip @@ -58,7 +58,7 @@ jobs: timeout-minutes: 90 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -69,7 +69,7 @@ jobs: run: python scripts/mk_unix_dist.py --dotnet-key=$GITHUB_WORKSPACE/resources/z3.snk --arch=arm64 - name: Upload artifact - uses: actions/upload-artifact@v7.0.0 + uses: actions/upload-artifact@v7 with: name: MacArm64 path: dist/*.zip @@ -86,10 +86,10 @@ jobs: timeout-minutes: 15 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Download macOS x64 Build - uses: actions/download-artifact@v8.0.0 + uses: actions/download-artifact@v8 with: name: macOsBuild path: artifacts @@ -134,10 +134,10 @@ jobs: timeout-minutes: 15 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Download macOS ARM64 Build - uses: actions/download-artifact@v8.0.0 + uses: actions/download-artifact@v8 with: name: MacArm64 path: artifacts @@ -181,7 +181,7 @@ jobs: timeout-minutes: 90 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -198,7 +198,7 @@ jobs: run: python z3test/scripts/test_benchmarks.py build-dist/z3 z3test/regressions/smt2 - name: Upload artifact - uses: actions/upload-artifact@v7.0.0 + uses: actions/upload-artifact@v7 with: name: UbuntuBuild path: dist/*.zip @@ -210,7 +210,7 @@ jobs: timeout-minutes: 90 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -233,7 +233,7 @@ jobs: python scripts/mk_unix_dist.py --nodotnet --arch=arm64 - name: Upload artifact - uses: actions/upload-artifact@v7.0.0 + uses: actions/upload-artifact@v7 with: name: UbuntuArm64 path: dist/*.zip @@ -245,7 +245,7 @@ jobs: timeout-minutes: 90 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -288,7 +288,7 @@ jobs: run: zip -r z3doc.zip doc/api - name: Upload artifact - uses: actions/upload-artifact@v7.0.0 + uses: actions/upload-artifact@v7 with: name: UbuntuDoc path: z3doc.zip @@ -301,7 +301,7 @@ jobs: container: quay.io/pypa/manylinux_2_28_x86_64:latest steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python environment run: | @@ -318,7 +318,7 @@ jobs: run: pip install ./src/api/python/wheelhouse/*.whl && python - "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat "/opt/gh-aw/prompts/xpia.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" + cat "/opt/gh-aw/prompts/markdown.md" >> "$GH_AW_PROMPT" + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GitHub API Access Instructions + + The gh CLI is NOT authenticated. Do NOT use gh commands for GitHub operations. + + + To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. + + Temporary IDs: Some safe output tools support a temporary ID field (usually named temporary_id) so you can reference newly-created items elsewhere in the SAME agent output (for example, using #aw_abc1 in a later body). + + **IMPORTANT - temporary_id format rules:** + - If you DON'T need to reference the item later, OMIT the temporary_id field entirely (it will be auto-generated if needed) + - If you DO need cross-references/chaining, you MUST match this EXACT validation regex: /^aw_[A-Za-z0-9]{3,8}$/i + - Format: aw_ prefix followed by 3 to 8 alphanumeric characters (A-Z, a-z, 0-9, case-insensitive) + - Valid alphanumeric characters: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 + - INVALID examples: aw_ab (too short), aw_123456789 (too long), aw_test-id (contains hyphen), aw_id_123 (contains underscore) + - VALID examples: aw_abc, aw_abc1, aw_Test123, aw_A1B2C3D4, aw_12345678 + - To generate valid IDs: use 3-8 random alphanumeric characters or omit the field to let the system auto-generate + + Do NOT invent other aw_* formats — downstream steps will reject them with validation errors matching against /^aw_[A-Za-z0-9]{3,8}$/i. + + Discover available tools from the safeoutputs MCP server. + + **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. + + **Note**: If you made no other safe output tool calls during this workflow execution, call the "noop" tool to provide a status message indicating completion or that no actions were needed. + + + + The following GitHub context information is available for this workflow: + {{#if __GH_AW_GITHUB_ACTOR__ }} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if __GH_AW_GITHUB_REPOSITORY__ }} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if __GH_AW_GITHUB_WORKSPACE__ }} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} + - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} + - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} + - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} + - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{/if}} + {{#if __GH_AW_GITHUB_RUN_ID__ }} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT" + {{#runtime-import .github/workflows/qf-s-benchmark.md}} + GH_AW_PROMPT_EOF + - name: Interpolate variables and render templates + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND: ${{ needs.pre_activation.outputs.matched_command }} + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + + const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, + GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, + GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, + GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED, + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_MATCHED_COMMAND + } + }); + - name: Validate prompt placeholders + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/print_prompt_summary.sh + - name: Upload prompt artifact + if: success() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts/prompt.txt + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: read-all + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + GH_AW_SAFE_OUTPUTS: /opt/gh-aw/safeoutputs/outputs.jsonl + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json + GH_AW_WORKFLOW_ID_SANITIZED: qfsbenchmark + outputs: + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + model: ${{ steps.generate_aw_info.outputs.model }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 + with: + destination: /opt/gh-aw/actions + - name: Create gh-aw temp directory + run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh + - name: Checkout c3 branch + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 1 + persist-credentials: false + ref: c3 + + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Generate agentic run info + id: generate_aw_info + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const fs = require('fs'); + + const awInfo = { + engine_id: "copilot", + engine_name: "GitHub Copilot CLI", + model: process.env.GH_AW_MODEL_AGENT_COPILOT || "", + version: "", + agent_version: "0.0.410", + cli_version: "v0.45.6", + workflow_name: "ZIPT Benchmark", + experimental: false, + supports_tools_allowlist: true, + run_id: context.runId, + run_number: context.runNumber, + run_attempt: process.env.GITHUB_RUN_ATTEMPT, + repository: context.repo.owner + '/' + context.repo.repo, + ref: context.ref, + sha: context.sha, + actor: context.actor, + event_name: context.eventName, + staged: false, + allowed_domains: ["defaults"], + firewall_enabled: true, + awf_version: "v0.19.1", + awmg_version: "v0.1.4", + steps: { + firewall: "squid" + }, + created_at: new Date().toISOString() + }; + + // Write to /tmp/gh-aw directory to avoid inclusion in PR + const tmpPath = '/tmp/gh-aw/aw_info.json'; + fs.writeFileSync(tmpPath, JSON.stringify(awInfo, null, 2)); + console.log('Generated aw_info.json at:', tmpPath); + console.log(JSON.stringify(awInfo, null, 2)); + + // Set model as output for reuse in other steps/jobs + core.setOutput('model', awInfo.model); + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.410 + - name: Install awf binary + run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.19.1 + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + with: + script: | + const determineAutomaticLockdown = require('/opt/gh-aw/actions/determine_automatic_lockdown.cjs'); + await determineAutomaticLockdown(github, context, core); + - name: Download container images + run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/gh-aw-firewall/agent:0.19.1 ghcr.io/github/gh-aw-firewall/squid:0.19.1 ghcr.io/github/gh-aw-mcpg:v0.1.4 ghcr.io/github/github-mcp-server:v0.30.3 node:lts-alpine + - name: Write Safe Outputs Config + run: | + mkdir -p /opt/gh-aw/safeoutputs + mkdir -p /tmp/gh-aw/safeoutputs + mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs + cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' + {"create_discussion":{"expires":168,"max":1},"create_missing_tool_issue":{"max":1,"title_prefix":"[missing tool]"},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + GH_AW_SAFE_OUTPUTS_CONFIG_EOF + cat > /opt/gh-aw/safeoutputs/tools.json << 'GH_AW_SAFE_OUTPUTS_TOOLS_EOF' + [ + { + "description": "Create a GitHub discussion for announcements, Q\u0026A, reports, status updates, or community conversations. Use this for content that benefits from threaded replies, doesn't require task tracking, or serves as documentation. For actionable work items that need assignment and status tracking, use create_issue instead. CONSTRAINTS: Maximum 1 discussion(s) can be created. Title will be prefixed with \"[ZIPT Benchmark] \". Discussions will be created in category \"agentic workflows\".", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Discussion content in Markdown. Do NOT repeat the title as a heading since it already appears as the discussion's h1. Include all relevant context, findings, or questions.", + "type": "string" + }, + "category": { + "description": "Discussion category by name (e.g., 'General'), slug (e.g., 'general'), or ID. If omitted, uses the first available category. Category must exist in the repository.", + "type": "string" + }, + "title": { + "description": "Concise discussion title summarizing the topic. The title appears as the main heading, so keep it brief and descriptive.", + "type": "string" + } + }, + "required": [ + "title", + "body" + ], + "type": "object" + }, + "name": "create_discussion" + }, + { + "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "reason": { + "description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).", + "type": "string" + }, + "tool": { + "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", + "type": "string" + } + }, + "required": [ + "reason" + ], + "type": "object" + }, + "name": "missing_tool" + }, + { + "description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "message": { + "description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').", + "type": "string" + } + }, + "required": [ + "message" + ], + "type": "object" + }, + "name": "noop" + }, + { + "description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "context": { + "description": "Additional context about the missing data or where it should come from (max 256 characters).", + "type": "string" + }, + "data_type": { + "description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.", + "type": "string" + }, + "reason": { + "description": "Explanation of why this data is needed to complete the task (max 256 characters).", + "type": "string" + } + }, + "required": [], + "type": "object" + }, + "name": "missing_data" + } + ] + GH_AW_SAFE_OUTPUTS_TOOLS_EOF + cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' + { + "create_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "category": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "repo": { + "type": "string", + "maxLength": 256 + }, + "title": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + } + } + GH_AW_SAFE_OUTPUTS_VALIDATION_EOF + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash /opt/gh-aw/actions/start_safe_outputs_server.sh + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export DEBUG="*" + + export GH_AW_ENGINE="copilot" + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -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_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_LOCKDOWN -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 GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -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 ghcr.io/github/gh-aw-mcpg:v0.1.4' + + mkdir -p /home/runner/.copilot + cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh + { + "mcpServers": { + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.30.3", + "env": { + "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" + } + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_EOF + - name: Generate workflow overview + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); + await generateWorkflowOverview(core); + - name: Download prompt artifact + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + with: + name: prompt + path: /tmp/gh-aw/aw-prompts + - name: Clean git credentials + run: bash /opt/gh-aw/actions/clean_git_credentials.sh + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 90 + run: | + set -o pipefail + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.19.1 --skip-pull \ + -- /bin/bash -c '/usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --add-dir "${GITHUB_WORKSPACE}" --disable-builtin-mcps --allow-all-tools --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"${GH_AW_MODEL_AGENT_COPILOT:+ --model "$GH_AW_MODEL_AGENT_COPILOT"}' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_MODEL_AGENT_COPILOT: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '' }} + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: | + # Copy Copilot session state files to logs folder for artifact collection + # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them + SESSION_STATE_DIR="$HOME/.copilot/session-state" + LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" + + if [ -d "$SESSION_STATE_DIR" ]; then + echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" + mkdir -p "$LOGS_DIR" + cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true + echo "Session state files copied successfully" + else + echo "No session-state directory found at $SESSION_STATE_DIR" + fi + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Upload Safe Outputs + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: safe-output + path: ${{ env.GH_AW_SAFE_OUTPUTS }} + if-no-files-found: warn + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/collect_ndjson_output.cjs'); + await main(); + - name: Upload sanitized agent output + if: always() && env.GH_AW_AGENT_OUTPUT + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: agent-output + path: ${{ env.GH_AW_AGENT_OUTPUT }} + if-no-files-found: warn + - name: Upload engine output files + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: agent_outputs + path: | + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + if-no-files-found: ignore + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/parse_copilot_log.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: agent-artifacts + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/sandbox/firewall/logs/ + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/ + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - detection + - safe_outputs + if: (always()) && (needs.agent.result != 'skipped') + runs-on: ubuntu-slim + permissions: + contents: read + discussions: write + issues: write + outputs: + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process No-Op Messages + id: noop + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: 1 + GH_AW_WORKFLOW_NAME: "ZIPT Benchmark" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/noop.cjs'); + await main(); + - name: Record Missing Tool + id: missing_tool + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_MISSING_TOOL_CREATE_ISSUE: "true" + GH_AW_MISSING_TOOL_TITLE_PREFIX: "[missing tool]" + GH_AW_WORKFLOW_NAME: "ZIPT Benchmark" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Handle Agent Failure + id: handle_agent_failure + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "ZIPT Benchmark" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_WORKFLOW_ID: "qf-s-benchmark" + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.agent.outputs.secret_verification_result }} + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_CREATE_DISCUSSION_ERRORS: ${{ needs.safe_outputs.outputs.create_discussion_errors }} + GH_AW_CREATE_DISCUSSION_ERROR_COUNT: ${{ needs.safe_outputs.outputs.create_discussion_error_count }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + - name: Handle No-Op Message + id: handle_noop_message + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "ZIPT Benchmark" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_NOOP_MESSAGE: ${{ steps.noop.outputs.noop_message }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); + await main(); + + detection: + needs: agent + if: needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true' + runs-on: ubuntu-latest + permissions: {} + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + timeout-minutes: 10 + outputs: + success: ${{ steps.parse_results.outputs.success }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 + with: + destination: /opt/gh-aw/actions + - name: Download agent artifacts + continue-on-error: true + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + with: + name: agent-artifacts + path: /tmp/gh-aw/threat-detection/ + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + with: + name: agent-output + path: /tmp/gh-aw/threat-detection/ + - name: Echo agent output types + env: + AGENT_OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} + run: | + echo "Agent output-types: $AGENT_OUTPUT_TYPES" + - name: Setup threat detection + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + WORKFLOW_NAME: "ZIPT Benchmark" + WORKFLOW_DESCRIPTION: "Run Z3 string solver benchmarks (seq vs nseq) on QF_S test suite from the c3 branch and post results as a GitHub discussion" + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/setup_threat_detection.cjs'); + await main(); + - name: Ensure threat-detection directory and log + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.410 + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool shell(cat) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(jq) + # --allow-tool shell(ls) + # --allow-tool shell(tail) + # --allow-tool shell(wc) + timeout-minutes: 20 + run: | + set -o pipefail + COPILOT_CLI_INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" + mkdir -p /tmp/ + mkdir -p /tmp/gh-aw/ + mkdir -p /tmp/gh-aw/agent/ + mkdir -p /tmp/gh-aw/sandbox/agent/logs/ + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool 'shell(cat)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(jq)' --allow-tool 'shell(ls)' --allow-tool 'shell(tail)' --allow-tool 'shell(wc)' --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION"${GH_AW_MODEL_DETECTION_COPILOT:+ --model "$GH_AW_MODEL_DETECTION_COPILOT"} 2>&1 | tee /tmp/gh-aw/threat-detection/detection.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + GH_AW_MODEL_DETECTION_COPILOT: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || '' }} + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Parse threat detection results + id: parse_results + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/parse_threat_detection_results.cjs'); + await main(); + - name: Upload threat detection log + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: threat-detection.log + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + + safe_outputs: + needs: + - agent + - detection + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.detection.outputs.success == 'true') + runs-on: ubuntu-slim + permissions: + contents: read + discussions: write + issues: write + timeout-minutes: 15 + env: + GH_AW_ENGINE_ID: "copilot" + GH_AW_WORKFLOW_ID: "qf-s-benchmark" + GH_AW_WORKFLOW_NAME: "ZIPT Benchmark" + outputs: + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + continue-on-error: true + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"agentic workflows\",\"close_older_discussions\":true,\"expires\":168,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[ZIPT Benchmark] \"},\"missing_data\":{},\"missing_tool\":{}}" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + diff --git a/.github/workflows/qf-s-benchmark.md b/.github/workflows/qf-s-benchmark.md new file mode 100644 index 000000000..60c59a9aa --- /dev/null +++ b/.github/workflows/qf-s-benchmark.md @@ -0,0 +1,38 @@ +--- +description: Run Z3 string solver benchmarks (seq vs nseq) on QF_S test suite from the c3 branch and post results as a GitHub discussion + +on: + schedule: weekly + workflow_dispatch: + +permissions: read-all + +network: defaults + +tools: + bash: true + github: + toolsets: [default] + +safe-outputs: + create-discussion: + title-prefix: "[ZIPT Benchmark] " + category: "Agentic Workflows" + close-older-discussions: true + missing-tool: + create-issue: true + +timeout-minutes: 90 + +steps: + - name: Checkout c3 branch + uses: actions/checkout@v5 + with: + ref: c3 + fetch-depth: 1 + persist-credentials: false + +--- + + +@./agentics/qf-s-benchmark.md diff --git a/.github/workflows/release-notes-updater.lock.yml b/.github/workflows/release-notes-updater.lock.yml index d4576d055..11fac1eb2 100644 --- a/.github/workflows/release-notes-updater.lock.yml +++ b/.github/workflows/release-notes-updater.lock.yml @@ -49,7 +49,7 @@ jobs: comment_repo: "" steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Checkout .github and .agents folders @@ -247,7 +247,7 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Create gh-aw temp directory @@ -799,7 +799,7 @@ jobs: total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent output artifact @@ -890,7 +890,7 @@ jobs: success: ${{ steps.parse_results.outputs.success }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent artifacts @@ -1001,7 +1001,7 @@ jobs: process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} steps: - name: Setup Scripts - uses: github/gh-aw/actions/setup@33cd6c7f1fee588654ef19def2e6a4174be66197 # v0.51.6 + uses: github/gh-aw/actions/setup@902845080df391b1f71845fcd7c303dfc0ac90b3 # v0.57.0 with: destination: /opt/gh-aw/actions - name: Download agent output artifact diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b9f3eb8cb..9e983c77d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -36,7 +36,7 @@ jobs: timeout-minutes: 90 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -53,7 +53,7 @@ jobs: run: python z3test/scripts/test_benchmarks.py build-dist/z3 z3test/regressions/smt2 - name: Upload artifact - uses: actions/upload-artifact@v7.0.0 + uses: actions/upload-artifact@v7 with: name: macOsBuild path: dist/*.zip @@ -65,7 +65,7 @@ jobs: timeout-minutes: 90 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -79,7 +79,7 @@ jobs: run: git clone https://github.com/z3prover/z3test z3test - name: Upload artifact - uses: actions/upload-artifact@v7.0.0 + uses: actions/upload-artifact@v7 with: name: MacArm64 path: dist/*.zip @@ -96,10 +96,10 @@ jobs: timeout-minutes: 15 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Download macOS x64 Build - uses: actions/download-artifact@v8.0.0 + uses: actions/download-artifact@v8 with: name: macOsBuild path: artifacts @@ -144,10 +144,10 @@ jobs: timeout-minutes: 15 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Download macOS ARM64 Build - uses: actions/download-artifact@v8.0.0 + uses: actions/download-artifact@v8 with: name: MacArm64 path: artifacts @@ -191,7 +191,7 @@ jobs: timeout-minutes: 90 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -208,7 +208,7 @@ jobs: run: python z3test/scripts/test_benchmarks.py build-dist/z3 z3test/regressions/smt2 - name: Upload artifact - uses: actions/upload-artifact@v7.0.0 + uses: actions/upload-artifact@v7 with: name: UbuntuBuild path: dist/*.zip @@ -220,7 +220,7 @@ jobs: timeout-minutes: 90 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -243,7 +243,7 @@ jobs: python scripts/mk_unix_dist.py --nodotnet --arch=arm64 - name: Upload artifact - uses: actions/upload-artifact@v7.0.0 + uses: actions/upload-artifact@v7 with: name: UbuntuArm64 path: dist/*.zip @@ -255,7 +255,7 @@ jobs: timeout-minutes: 90 steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 @@ -298,7 +298,7 @@ jobs: run: zip -r z3doc.zip doc/api - name: Upload artifact - uses: actions/upload-artifact@v7.0.0 + uses: actions/upload-artifact@v7 with: name: UbuntuDoc path: z3doc.zip @@ -311,7 +311,7 @@ jobs: container: quay.io/pypa/manylinux_2_28_x86_64:latest steps: - name: Checkout code - uses: actions/checkout@v6.0.2 + uses: actions/checkout@v6 - name: Setup Python environment run: | @@ -328,7 +328,7 @@ jobs: run: pip install ./src/api/python/wheelhouse/*.whl && python - = product_of_consecutive_ints 0) to true +- Fix #7951: add cancellation checks to polynomial gcd_prs and HNF computation +- Fix #7677: treat FC_CONTINUE from check_nla as FEASIBLE in maximize +- Fix assertion violation in q_mbi diagnostic output +- Fix memory leaks in model_based_opt def ref-counting +- Fix NoSuchFieldError in JNI for BoolPtr: use Z field descriptor and SetBooleanField +- Fix TypeScript Array.fromFunc to use f.ptr instead of f.ast for Z3_func_decl type +- Fix intblast ubv_to_int bug: add bv2int axioms for compound expressions +- Fix static analysis findings: uninitialized variables, bitwise shift undefined behavior, and null pointer dereferences +- Convert bv1-blast and blast-term-ite tactics to also expose as simplifiers for more flexible integration +- Change default of param lws_subs_witness_disc to true for improved NLSAT performance. Thanks to Lev Nachmanson. Version 4.16.0 ============== diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 4ec3d5dbd..67a2fca63 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1919,11 +1919,8 @@ class JavaDLLComponent(Component): if IS_WINDOWS: # On Windows, CL creates a .lib file to link against. out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3java$(SO_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(LIB_EXT)\n' % os.path.join('api', 'java', 'Native')) - elif IS_OSX and IS_ARCH_ARM64: - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3java$(SO_EXT) $(SLINK_FLAGS) -arch arm64 %s$(OBJ_EXT) libz3$(SO_EXT)\n' % - os.path.join('api', 'java', 'Native')) else: - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3java$(SO_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % + out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3java$(SO_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT) $(SLINK_EXTRA_FLAGS)\n' % os.path.join('api', 'java', 'Native')) out.write('%s.jar: libz3java$(SO_EXT) ' % self.package_name) deps = '' diff --git a/scripts/tests/test_jni_arch_flags.py b/scripts/tests/test_jni_arch_flags.py new file mode 100644 index 000000000..2796b156d --- /dev/null +++ b/scripts/tests/test_jni_arch_flags.py @@ -0,0 +1,278 @@ +############################################ +# Copyright (c) 2024 Microsoft Corporation +# +# Unit tests for JNI architecture flags in Makefile generation. +# +# Regression tests for: +# "JNI bindings use wrong architecture in macOS cross-compilation (arm64 to x64)" +# +# The fix ensures that libz3java.dylib (and the JNI link step) uses +# $(SLINK_EXTRA_FLAGS) instead of a hardcoded -arch arm64. +# $(SLINK_EXTRA_FLAGS) is populated correctly in mk_config() for: +# - Native ARM64 builds: SLINK_EXTRA_FLAGS contains -arch arm64 +# - Cross-compile to x86_64: SLINK_EXTRA_FLAGS contains -arch x86_64 +# - Other platforms: SLINK_EXTRA_FLAGS has no -arch flag +############################################ +import io +import os +import sys +import unittest +from unittest.mock import patch, MagicMock + +# Add the scripts directory to the path so we can import mk_util +_SCRIPTS_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +if _SCRIPTS_DIR not in sys.path: + sys.path.insert(0, _SCRIPTS_DIR) + +import mk_util + + +class TestJNIArchitectureFlagsInMakefile(unittest.TestCase): + """ + Tests that JavaDLLComponent.mk_makefile() generates a JNI link command + that uses $(SLINK_EXTRA_FLAGS) rather than hardcoding -arch arm64. + + $(SLINK_EXTRA_FLAGS) is set by mk_config() to contain the correct -arch + flag for the TARGET architecture (not the host), so using it ensures + cross-compilation works correctly. + """ + + def setUp(self): + """Save mk_util global state before each test.""" + self._saved_components = list(mk_util._Components) + self._saved_names = set(mk_util._ComponentNames) + self._saved_name2component = dict(mk_util._Name2Component) + self._saved_id = mk_util._Id + self._saved_javac = mk_util.JAVAC + self._saved_jar = mk_util.JAR + + def tearDown(self): + """Restore mk_util global state after each test.""" + mk_util._Components[:] = self._saved_components + mk_util._ComponentNames.clear() + mk_util._ComponentNames.update(self._saved_names) + mk_util._Name2Component.clear() + mk_util._Name2Component.update(self._saved_name2component) + mk_util._Id = self._saved_id + mk_util.JAVAC = self._saved_javac + mk_util.JAR = self._saved_jar + + def _make_java_dll_component(self): + """ + Create a JavaDLLComponent instance bypassing the registry check so + that tests remain independent of each other. + """ + # Register a stub 'api' component that provides to_src_dir + api_stub = MagicMock() + api_stub.to_src_dir = '../src/api' + mk_util._Name2Component['api'] = api_stub + mk_util._ComponentNames.add('api') + + # Build the component without going through the full Component.__init__ + # registration path (which enforces uniqueness globally). + comp = mk_util.JavaDLLComponent.__new__(mk_util.JavaDLLComponent) + comp.name = 'java' + comp.dll_name = 'libz3java' + comp.package_name = 'com.microsoft.z3' + comp.manifest_file = None + comp.to_src_dir = '../src/api/java' + comp.src_dir = 'src/api/java' + comp.deps = [] + comp.install = True + return comp + + def _generate_makefile(self, comp, *, is_windows, is_osx, is_arch_arm64): + """ + Call mk_makefile() with the given platform flags and return the + generated Makefile text. + """ + buf = io.StringIO() + with patch.object(mk_util, 'JAVA_ENABLED', True), \ + patch.object(mk_util, 'IS_WINDOWS', is_windows), \ + patch.object(mk_util, 'IS_OSX', is_osx), \ + patch.object(mk_util, 'IS_ARCH_ARM64', is_arch_arm64), \ + patch.object(mk_util, 'JNI_HOME', '/path/to/jni'), \ + patch.object(mk_util, 'JAVAC', 'javac'), \ + patch.object(mk_util, 'JAR', 'jar'), \ + patch.object(mk_util, 'BUILD_DIR', '/tmp/test_build'), \ + patch('mk_util.mk_dir'), \ + patch('mk_util.get_java_files', return_value=[]): + comp.mk_makefile(buf) + return buf.getvalue() + + def _find_jni_link_lines(self, makefile_text): + """Return lines that contain the JNI library link command.""" + return [ + line for line in makefile_text.splitlines() + if 'libz3java$(SO_EXT)' in line and 'SLINK' in line + ] + + # ------------------------------------------------------------------ + # Tests for non-Windows platforms (where SLINK_EXTRA_FLAGS matters) + # ------------------------------------------------------------------ + + def test_macos_arm64_native_uses_slink_extra_flags(self): + """ + On native ARM64 macOS builds, the JNI link command must use + $(SLINK_EXTRA_FLAGS) so that the -arch arm64 flag added to + SLINK_EXTRA_FLAGS by mk_config() is respected. + """ + comp = self._make_java_dll_component() + text = self._generate_makefile( + comp, is_windows=False, is_osx=True, is_arch_arm64=True + ) + link_lines = self._find_jni_link_lines(text) + self.assertTrue( + link_lines, + "Expected at least one JNI link line in the generated Makefile", + ) + for line in link_lines: + self.assertIn( + '$(SLINK_EXTRA_FLAGS)', line, + "JNI link command must use $(SLINK_EXTRA_FLAGS) so the " + "correct target architecture flag is applied", + ) + + def test_macos_arm64_native_no_hardcoded_arch_arm64(self): + """ + The JNI link command must NOT hardcode -arch arm64. + Hardcoding -arch arm64 breaks cross-compilation from an ARM64 host + to an x86_64 target, which is the bug this fix addresses. + """ + comp = self._make_java_dll_component() + text = self._generate_makefile( + comp, is_windows=False, is_osx=True, is_arch_arm64=True + ) + link_lines = self._find_jni_link_lines(text) + self.assertTrue(link_lines, "Expected at least one JNI link line") + for line in link_lines: + self.assertNotIn( + '-arch arm64', line, + "JNI link command must not hardcode '-arch arm64'. " + "Use $(SLINK_EXTRA_FLAGS) instead so that cross-compilation " + "from ARM64 host to x86_64 target works correctly.", + ) + + def test_macos_x86_64_uses_slink_extra_flags(self): + """ + When building for x86_64 on macOS (e.g. cross-compiling from ARM64 + host), the JNI link command must still use $(SLINK_EXTRA_FLAGS) so + that the -arch x86_64 flag set by mk_config() is applied. + """ + comp = self._make_java_dll_component() + text = self._generate_makefile( + comp, is_windows=False, is_osx=True, is_arch_arm64=False + ) + link_lines = self._find_jni_link_lines(text) + self.assertTrue(link_lines, "Expected at least one JNI link line") + for line in link_lines: + self.assertIn( + '$(SLINK_EXTRA_FLAGS)', line, + "JNI link command must use $(SLINK_EXTRA_FLAGS)", + ) + + def test_linux_uses_slink_extra_flags(self): + """On Linux, the JNI link command must use $(SLINK_EXTRA_FLAGS).""" + comp = self._make_java_dll_component() + text = self._generate_makefile( + comp, is_windows=False, is_osx=False, is_arch_arm64=False + ) + link_lines = self._find_jni_link_lines(text) + self.assertTrue(link_lines, "Expected at least one JNI link line") + for line in link_lines: + self.assertIn( + '$(SLINK_EXTRA_FLAGS)', line, + "JNI link command must use $(SLINK_EXTRA_FLAGS) on Linux", + ) + + # ------------------------------------------------------------------ + # Tests for Windows (different codepath - links against LIB_EXT) + # ------------------------------------------------------------------ + + def test_windows_links_against_lib_ext(self): + """ + On Windows the JNI library is linked against the import library + (libz3$(LIB_EXT)), not the shared library, and SLINK_EXTRA_FLAGS is + handled differently by the VS build system. + """ + comp = self._make_java_dll_component() + text = self._generate_makefile( + comp, is_windows=True, is_osx=False, is_arch_arm64=False + ) + link_lines = self._find_jni_link_lines(text) + self.assertTrue(link_lines, "Expected at least one JNI link line") + for line in link_lines: + self.assertIn( + '$(LIB_EXT)', line, + "Windows JNI link command must link against LIB_EXT " + "(the import library)", + ) + + # ------------------------------------------------------------------ + # Consistency check: SLINK_EXTRA_FLAGS in mk_config for cross-compile + # ------------------------------------------------------------------ + + def test_slibextraflags_contains_x86_64_when_cross_compiling(self): + """ + When mk_config() runs on an ARM64 macOS host with IS_ARCH_ARM64=False + (i.e. cross-compiling to x86_64), SLIBEXTRAFLAGS must contain + '-arch x86_64' so that $(SLINK_EXTRA_FLAGS) carries the right flag. + + This validates the mk_config() logic that feeds into $(SLINK_EXTRA_FLAGS). + """ + # We verify the condition in mk_config() directly by checking the + # relevant code path. The cross-compile path in mk_config() is: + # + # elif IS_OSX and os.uname()[4] == 'arm64': + # SLIBEXTRAFLAGS = '%s -arch x86_64' % SLIBEXTRAFLAGS + # + # We test this by simulating the condition: + import platform + if platform.system() != 'Darwin' or platform.machine() != 'arm64': + self.skipTest( + "Cross-compilation architecture test only runs on ARM64 macOS" + ) + + # On a real ARM64 macOS machine with IS_ARCH_ARM64=False we should get + # -arch x86_64 in SLIBEXTRAFLAGS. Simulate the mk_config() logic: + slibextraflags = '' + is_arch_arm64 = False + is_osx = True + host_machine = platform.machine() # 'arm64' + + if is_arch_arm64 and is_osx: + slibextraflags = '%s -arch arm64' % slibextraflags + elif is_osx and host_machine == 'arm64': + slibextraflags = '%s -arch x86_64' % slibextraflags + + self.assertIn( + '-arch x86_64', slibextraflags, + "When cross-compiling from ARM64 macOS to x86_64, " + "SLIBEXTRAFLAGS must contain '-arch x86_64'", + ) + + def test_slibextraflags_contains_arm64_for_native_arm64_build(self): + """ + When mk_config() runs on a native ARM64 macOS build (IS_ARCH_ARM64=True), + SLIBEXTRAFLAGS must contain '-arch arm64'. + """ + import platform + if platform.system() != 'Darwin': + self.skipTest("Architecture flag test only relevant on macOS") + + slibextraflags = '' + is_arch_arm64 = True + is_osx = True + + if is_arch_arm64 and is_osx: + slibextraflags = '%s -arch arm64' % slibextraflags + + self.assertIn( + '-arch arm64', slibextraflags, + "For a native ARM64 macOS build, SLIBEXTRAFLAGS must contain " + "'-arch arm64' so that $(SLINK_EXTRA_FLAGS) carries the correct flag", + ) + + +if __name__ == '__main__': + unittest.main() diff --git a/src/api/go/bitvec.go b/src/api/go/bitvec.go index e98596160..8dcf0f23d 100644 --- a/src/api/go/bitvec.go +++ b/src/api/go/bitvec.go @@ -159,6 +159,21 @@ func (c *Context) MkZeroExt(i uint, expr *Expr) *Expr { return newExpr(c, C.Z3_mk_zero_ext(c.ptr, C.uint(i), expr.ptr)) } +// MkBVRotateLeft rotates the bits of t to the left by i positions. +func (c *Context) MkBVRotateLeft(i uint, t *Expr) *Expr { + return newExpr(c, C.Z3_mk_rotate_left(c.ptr, C.uint(i), t.ptr)) +} + +// MkBVRotateRight rotates the bits of t to the right by i positions. +func (c *Context) MkBVRotateRight(i uint, t *Expr) *Expr { + return newExpr(c, C.Z3_mk_rotate_right(c.ptr, C.uint(i), t.ptr)) +} + +// MkRepeat repeats the given bit-vector t a total of i times. +func (c *Context) MkRepeat(i uint, t *Expr) *Expr { + return newExpr(c, C.Z3_mk_repeat(c.ptr, C.uint(i), t.ptr)) +} + // MkBVAddNoOverflow creates a predicate that checks that the bit-wise addition // of t1 and t2 does not overflow. If isSigned is true, checks for signed overflow. func (c *Context) MkBVAddNoOverflow(t1, t2 *Expr, isSigned bool) *Expr { diff --git a/src/ast/euf/euf_mam.cpp b/src/ast/euf/euf_mam.cpp index 00d9c0726..cce838c61 100644 --- a/src/ast/euf/euf_mam.cpp +++ b/src/ast/euf/euf_mam.cpp @@ -1402,6 +1402,7 @@ namespace euf { // to check it again. get_check_mark(reg) == NOT_CHECKED && is_ground(m_registers[reg]) && + instr->m_enode != nullptr && get_pat_lbl_hash(reg) == instr->m_enode->get_lbl_hash(); } diff --git a/src/ast/rewriter/seq_eq_solver.cpp b/src/ast/rewriter/seq_eq_solver.cpp index c6778c45e..e1ffae743 100644 --- a/src/ast/rewriter/seq_eq_solver.cpp +++ b/src/ast/rewriter/seq_eq_solver.cpp @@ -226,7 +226,6 @@ namespace seq { return e.ls.size() == 1 && e.rs.size() == 1 && seq.str.is_ubv2s(e.ls[0], a) && seq.str.is_ubv2s(e.rs[0], b); - return false; } bool eq_solver::reduce_ubv2s1(eqr const& e, eq_ptr& r) { diff --git a/src/ast/sls/sls_euf_plugin.cpp b/src/ast/sls/sls_euf_plugin.cpp index d1d135d1e..ff1a72748 100644 --- a/src/ast/sls/sls_euf_plugin.cpp +++ b/src/ast/sls/sls_euf_plugin.cpp @@ -287,27 +287,36 @@ namespace sls { if (m.is_eq(e)) { a = g.find(to_app(e)->get_arg(0)); b = g.find(to_app(e)->get_arg(1)); - } - if (lit.sign() && m.is_eq(e)) { - if (a->get_root() == b->get_root()) { - IF_VERBOSE(0, verbose_stream() << "not disequal " << lit << " " << mk_pp(e, m) << "\n"); - ctx.display(verbose_stream()); - UNREACHABLE(); + if (lit.sign()) { + if (a && b && a->get_root() == b->get_root()) { + IF_VERBOSE(0, verbose_stream() << "not disequal " << lit << " " << mk_pp(e, m) << "\n"); + ctx.display(verbose_stream()); + UNREACHABLE(); + } + } + else { + if (a && b && a->get_root() != b->get_root()) { + IF_VERBOSE(0, verbose_stream() << "not equal " << lit << " " << mk_pp(e, m) << "\n"); + //UNREACHABLE(); + } } } - else if (!lit.sign() && m.is_eq(e)) { - if (a->get_root() != b->get_root()) { - IF_VERBOSE(0, verbose_stream() << "not equal " << lit << " " << mk_pp(e, m) << "\n"); - //UNREACHABLE(); + else if (to_app(e)->get_family_id() != basic_family_id) { + auto* ne = g.find(e); + if (lit.sign()) { + auto* nf = g.find(m.mk_false()); + if (ne && nf && ne->get_root() != nf->get_root()) { + IF_VERBOSE(0, verbose_stream() << "not false " << lit << " " << mk_pp(e, m) << "\n"); + //UNREACHABLE(); + } + } + else { + auto* nt = g.find(m.mk_true()); + if (ne && nt && ne->get_root() != nt->get_root()) { + IF_VERBOSE(0, verbose_stream() << "not true " << lit << " " << mk_pp(e, m) << "\n"); + //UNREACHABLE(); + } } - } - else if (to_app(e)->get_family_id() != basic_family_id && lit.sign() && g.find(e)->get_root() != g.find(m.mk_false())->get_root()) { - IF_VERBOSE(0, verbose_stream() << "not alse " << lit << " " << mk_pp(e, m) << "\n"); - //UNREACHABLE(); - } - else if (to_app(e)->get_family_id() != basic_family_id && !lit.sign() && g.find(e)->get_root() != g.find(m.mk_true())->get_root()) { - IF_VERBOSE(0, verbose_stream() << "not true " << lit << " " << mk_pp(e, m) << "\n"); - //UNREACHABLE(); } } diff --git a/src/math/lp/lar_core_solver.h b/src/math/lp/lar_core_solver.h index 1773317be..258bfdad2 100644 --- a/src/math/lp/lar_core_solver.h +++ b/src/math/lp/lar_core_solver.h @@ -81,8 +81,8 @@ public: void backup_x() { m_backup_x = m_r_x; } void restore_x() { + SASSERT(m_backup_x.size() == m_r_A.column_count()); m_r_x = m_backup_x; - m_r_x.reserve(m_m()); } vector const& r_x() const { return m_r_x; } diff --git a/src/math/realclosure/realclosure.cpp b/src/math/realclosure/realclosure.cpp index 80e6420bd..4ba1c11fa 100644 --- a/src/math/realclosure/realclosure.cpp +++ b/src/math/realclosure/realclosure.cpp @@ -3448,16 +3448,23 @@ namespace realclosure { return true; } - unsigned get_sign_condition_size(numeral const &a, unsigned i) { - algebraic * ext = to_algebraic(to_rational_function(a)->ext()); + sign_condition* get_ith_sign_condition(algebraic* ext, unsigned i) { const sign_det * sdt = ext->sdt(); if (!sdt) - return 0; + return nullptr; sign_condition * sc = sdt->sc(ext->sc_idx()); - while (i) { - if (sc) sc = sc->prev(); + while (i && sc) { + sc = sc->prev(); i--; } + return sc; + } + + unsigned get_sign_condition_size(numeral const &a, unsigned i) { + algebraic * ext = to_algebraic(to_rational_function(a)->ext()); + sign_condition * sc = get_ith_sign_condition(ext, i); + if (!sc) + return 0; return ext->sdt()->qs()[sc->qidx()].size(); } @@ -3466,14 +3473,9 @@ namespace realclosure { if (!is_algebraic(a)) return 0; algebraic * ext = to_algebraic(to_rational_function(a)->ext()); - const sign_det * sdt = ext->sdt(); - if (!sdt) + sign_condition * sc = get_ith_sign_condition(ext, i); + if (!sc) return 0; - sign_condition * sc = sdt->sc(ext->sc_idx()); - while (i) { - if (sc) sc = sc->prev(); - i--; - } const polynomial & q = ext->sdt()->qs()[sc->qidx()]; return q.size(); } @@ -3483,14 +3485,9 @@ namespace realclosure { if (!is_algebraic(a)) return numeral(); algebraic * ext = to_algebraic(to_rational_function(a)->ext()); - const sign_det * sdt = ext->sdt(); - if (!sdt) + sign_condition * sc = get_ith_sign_condition(ext, i); + if (!sc) return numeral(); - sign_condition * sc = sdt->sc(ext->sc_idx()); - while (i) { - if (sc) sc = sc->prev(); - i--; - } const polynomial & q = ext->sdt()->qs()[sc->qidx()]; if (j >= q.size()) return numeral(); diff --git a/src/muz/rel/udoc_relation.cpp b/src/muz/rel/udoc_relation.cpp index 068af24b6..17d68660e 100644 --- a/src/muz/rel/udoc_relation.cpp +++ b/src/muz/rel/udoc_relation.cpp @@ -54,6 +54,7 @@ namespace datalog { col = column_idx(orig[i]); limit = col + column_num_bits(orig[i]); } else { + SASSERT(other); unsigned idx = orig[i] - get_num_cols(); col = get_num_bits() + other->column_idx(idx); limit = col + other->column_num_bits(idx); diff --git a/src/muz/spacer/spacer_context.cpp b/src/muz/spacer/spacer_context.cpp index cf27f23cb..3f46dadb4 100644 --- a/src/muz/spacer/spacer_context.cpp +++ b/src/muz/spacer/spacer_context.cpp @@ -3330,7 +3330,7 @@ bool context::is_reachable(pob &n) model_ref mdl; // used in case n is reachable - bool is_concrete; + bool is_concrete = false; const datalog::rule * r = nullptr; // denotes which predecessor's (along r) reach facts are used bool_vector reach_pred_used; @@ -3521,7 +3521,7 @@ lbool context::expand_pob(pob& n, pob_ref_buffer &out) model_ref model; // used in case n is reachable - bool is_concrete; + bool is_concrete = false; const datalog::rule * r = nullptr; // denotes which predecessor's (along r) reach facts are used bool_vector reach_pred_used; diff --git a/src/smt/mam.cpp b/src/smt/mam.cpp index a27fc293f..3719f30c9 100644 --- a/src/smt/mam.cpp +++ b/src/smt/mam.cpp @@ -1360,6 +1360,7 @@ namespace { // to check it again. get_check_mark(reg) == NOT_CHECKED && is_ground(m_registers[reg]) && + instr->m_enode != nullptr && get_pat_lbl_hash(reg) == instr->m_enode->get_lbl_hash(); } diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index 05053f4ea..91c47bbf8 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -3988,6 +3988,7 @@ public: lp::impq term_max; lp::lp_status st; lpvar vi = 0; + unsigned size_of_backup = lp().column_count(); if (has_int()) { lp().backup_x(); } @@ -4008,7 +4009,8 @@ public: if (has_int() && lp().has_inf_int()) { st = lp::lp_status::FEASIBLE; - lp().restore_x(); + if (lp().column_count() == size_of_backup) + lp().restore_x(); } if (m_nla && (st == lp::lp_status::OPTIMAL || st == lp::lp_status::UNBOUNDED)) { switch (check_nla(level)) { @@ -4020,7 +4022,8 @@ public: st = lp::lp_status::UNBOUNDED; break; } - lp().restore_x(); + if (lp().column_count() == size_of_backup) + lp().restore_x(); } } switch (st) { diff --git a/src/test/dl_relation.cpp b/src/test/dl_relation.cpp index 1646350f2..709712bc3 100644 --- a/src/test/dl_relation.cpp +++ b/src/test/dl_relation.cpp @@ -111,6 +111,7 @@ namespace datalog { i5->deallocate(); dealloc(join1); dealloc(proj1); + dealloc(proj2); dealloc(ren1); dealloc(union1); dealloc(filterId1); @@ -281,6 +282,7 @@ namespace datalog { i5->deallocate(); dealloc(join1); dealloc(proj1); + dealloc(proj2); dealloc(ren1); dealloc(union1); dealloc(filterId1); diff --git a/src/test/simplifier.cpp b/src/test/simplifier.cpp index f3a5ba8b2..a4da49861 100644 --- a/src/test/simplifier.cpp +++ b/src/test/simplifier.cpp @@ -138,6 +138,7 @@ static void test_skolemize_bug() { Z3_ast f3 = Z3_simplify(ctx, f2); std::cout << Z3_ast_to_string(ctx, f3) << "\n"; + Z3_del_context(ctx); }