From 8830c55b208ba30f6c52c20ce58bbb05ad1854f6 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 14 May 2026 16:01:05 -0500 Subject: [PATCH 01/16] Add nightly-fix-finder agentic workflow Adds a gh aw workflow that runs nightly to scan the codebase for random improvement opportunities across 10 categories (TODO comments, nullable gaps, large files, obsolete APIs, test coverage, etc.). Each night it picks one category, finds a specific actionable issue, files a GitHub issue, and assigns Copilot with Claude Opus 4.6 via the assign-to-agent safe-output. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/nightly-fix-finder.lock.yml | 1247 +++++++++++++++++ .github/workflows/nightly-fix-finder.md | 278 ++++ 2 files changed, 1525 insertions(+) create mode 100644 .github/workflows/nightly-fix-finder.lock.yml create mode 100644 .github/workflows/nightly-fix-finder.md diff --git a/.github/workflows/nightly-fix-finder.lock.yml b/.github/workflows/nightly-fix-finder.lock.yml new file mode 100644 index 00000000000..3b1e11ac854 --- /dev/null +++ b/.github/workflows/nightly-fix-finder.lock.yml @@ -0,0 +1,1247 @@ +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"f593c7325f465f3042f769b37df8ccffdcb8682b6451a09e7799cc710c246cb8","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} +# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_AGENT_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw (v0.68.3). 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/ +# +# Nightly scan for random code improvement opportunities, files issues assigned to Copilot +# +# Secrets used: +# - COPILOT_GITHUB_TOKEN +# - GH_AW_AGENT_TOKEN +# - GH_AW_GITHUB_MCP_SERVER_TOKEN +# - GH_AW_GITHUB_TOKEN +# - GITHUB_TOKEN +# +# Custom actions used: +# - actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 +# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 +# - actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 +# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 +# - github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 +# +# Container images used: +# - ghcr.io/github/gh-aw-firewall/agent:0.25.20 +# - ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 +# - ghcr.io/github/gh-aw-firewall/squid:0.25.20 +# - ghcr.io/github/gh-aw-mcpg:v0.2.19 +# - ghcr.io/github/github-mcp-server:v0.32.0 +# - node:lts-alpine + +name: "Nightly Fix Finder" +"on": + schedule: + - cron: "34 1 * * *" + # Friendly format: daily around 02:00 (scattered) + workflow_dispatch: + inputs: + aw_context: + default: "" + description: Agent caller context (used internally by Agentic Workflows). + required: false + type: string + +permissions: {} + +concurrency: + group: "gh-aw-${{ github.workflow }}" + +run-name: "Nightly Fix Finder" + +jobs: + activation: + runs-on: ubuntu-slim + permissions: + actions: read + contents: read + outputs: + comment_id: "" + comment_repo: "" + lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} + model: ${{ steps.generate_aw_info.outputs.model }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + - name: Generate agentic run info + id: generate_aw_info + env: + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" + GH_AW_INFO_MODEL: "claude-opus-4.6" + GH_AW_INFO_VERSION: "1.0.21" + GH_AW_INFO_AGENT_VERSION: "1.0.21" + GH_AW_INFO_CLI_VERSION: "v0.68.3" + GH_AW_INFO_WORKFLOW_NAME: "Nightly Fix Finder" + GH_AW_INFO_EXPERIMENTAL: "false" + GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" + GH_AW_INFO_STAGED: "false" + GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","github","dotnet"]' + GH_AW_INFO_FIREWALL_ENABLED: "true" + GH_AW_INFO_AWF_VERSION: "v0.25.20" + GH_AW_INFO_AWMG_VERSION: "" + GH_AW_INFO_FIREWALL_TYPE: "squid" + GH_AW_COMPILED_STRICT: "true" + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs'); + await main(core, context); + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Checkout .github and .agents folders + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + sparse-checkout: | + .github + .agents + sparse-checkout-cone-mode: true + fetch-depth: 1 + - name: Check workflow lock file + id: check-lock-file + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_WORKFLOW_FILE: "nightly-fix-finder.lock.yml" + GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); + await main(); + - name: Check compile-agentic version + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_COMPILED_VERSION: "v0.68.3" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_version_updates.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: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl + 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 }} + # poutine:ignore untrusted_checkout_exec + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" + { + cat << 'GH_AW_PROMPT_e92035eaf9a77dc8_EOF' + + GH_AW_PROMPT_e92035eaf9a77dc8_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" + cat << 'GH_AW_PROMPT_e92035eaf9a77dc8_EOF' + + Tools: create_issue, assign_to_agent, missing_tool, missing_data, noop + + + 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_e92035eaf9a77dc8_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" + cat << 'GH_AW_PROMPT_e92035eaf9a77dc8_EOF' + + {{#runtime-import .github/workflows/nightly-fix-finder.md}} + GH_AW_PROMPT_e92035eaf9a77dc8_EOF + } > "$GH_AW_PROMPT" + - name: Interpolate variables and render templates + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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 }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + + const substitutePlaceholders = require('${{ runner.temp }}/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 + } + }); + - name: Validate prompt placeholders + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh" + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh" + - name: Upload activation artifact + if: success() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: activation + path: | + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/github_rate_limits.jsonl + if-no-files-found: ignore + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + contents: read + issues: 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_WORKFLOW_ID_SANITIZED: nightlyfixfinder + outputs: + agentic_engine_timeout: ${{ steps.detect-copilot-errors.outputs.agentic_engine_timeout || 'false' }} + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + inference_access_error: ${{ steps.detect-copilot-errors.outputs.inference_access_error || 'false' }} + mcp_policy_error: ${{ steps.detect-copilot-errors.outputs.mcp_policy_error || 'false' }} + model: ${{ needs.activation.outputs.model }} + model_not_supported_error: ${{ steps.detect-copilot-errors.outputs.model_not_supported_error || 'false' }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + - name: Set runtime paths + id: set-runtime-paths + run: | + { + echo "GH_AW_SAFE_OUTPUTS=${RUNNER_TEMP}/gh-aw/safeoutputs/outputs.jsonl" + echo "GH_AW_SAFE_OUTPUTS_CONFIG_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" + echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json" + } >> "$GITHUB_OUTPUT" + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Create gh-aw temp directory + run: bash "${RUNNER_TEMP}/gh-aw/actions/create_gh_aw_tmp_dir.sh" + - name: Configure gh CLI for GitHub Enterprise + run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh" + env: + GH_TOKEN: ${{ github.token }} + - name: Collect codebase metrics + run: "mkdir -p /tmp/gh-aw/agent\n{\n echo \"## Scan Category Seed\"\n echo \"Date seed: $(date +%j)\"\n CATEGORY_INDEX=$(( $(date +%j) % 10 ))\n echo \"Selected category index: $CATEGORY_INDEX\"\n\n echo \"\"\n echo \"## Category 0: TODO/FIXME/HACK Comments\"\n echo \"### Sample TODO/FIXME/HACK comments in src/\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" src/ 2>/dev/null | grep -v \"obj/\" | grep -v \"bin/\" | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" src/ 2>/dev/null | grep -v \"obj/\" | grep -v \"bin/\" | wc -l\n\n echo \"\"\n echo \"## Category 1: Files Missing Nullable Enable\"\n echo \"### C# files in src/ without #nullable enable (sample)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' -exec grep -rL '#nullable enable' {} \\; 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' -exec grep -rL '#nullable enable' {} \\; 2>/dev/null | wc -l\n\n echo \"\"\n echo \"## Category 2: Obsolete API Usage\"\n echo \"### Files using [Obsolete] or #pragma warning disable CS0618 (sample)\"\n grep -rn \"\\[Obsolete\\]\\|CS0618\\|CS0612\" --include=\"*.cs\" src/ 2>/dev/null | grep -v \"obj/\" | grep -v \"bin/\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 3: Large Files\"\n echo \"### Largest C# source files in src/ (top 20)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' | xargs wc -l 2>/dev/null | sort -rn | head -21 | tail -20\n\n echo \"\"\n echo \"## Category 4: Missing XML Documentation\"\n echo \"### Public classes/methods without XML doc comments (sample)\"\n grep -rn \"public \" --include=\"*.cs\" src/ 2>/dev/null | grep -v \"obj/\" | grep -v \"bin/\" | grep -v \"///\" | grep -v \"Designer.cs\" | grep -v \"AssemblyInfo.cs\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 5: Code Style Issues\"\n echo \"### Files with leading spaces instead of tabs (sample)\"\n grep -rlP \"^ [^ ]\" --include=\"*.cs\" src/ 2>/dev/null | grep -v \"obj/\" | grep -v \"bin/\" | grep -v \"Designer.cs\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 6: Test Coverage Gaps\"\n echo \"### Source files in Xamarin.Android.Build.Tasks without corresponding test\"\n for f in $(find src/Xamarin.Android.Build.Tasks -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name '*Test*' ! -name 'Resources.Designer.cs' 2>/dev/null | shuf | head -20); do\n basename=$(basename \"$f\" .cs)\n if ! find tests -name \"${basename}*Test*.cs\" -o -name \"*Test*${basename}*.cs\" 2>/dev/null | grep -q .; then\n echo \" No test found for: $f\"\n fi\n done\n\n echo \"\"\n echo \"## Category 7: Unused Using Directives\"\n echo \"### Files with many using directives (potential cleanup, sample)\"\n for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do\n count=$(grep -c \"^using \" \"$f\" 2>/dev/null || echo 0)\n if [ \"$count\" -gt 10 ]; then\n echo \" $f: $count using directives\"\n fi\n done\n\n echo \"\"\n echo \"## Category 8: Error Handling\"\n echo \"### Bare catch blocks that may swallow exceptions (sample)\"\n grep -rn \"catch\\s*(Exception\\b\" --include=\"*.cs\" src/ 2>/dev/null | grep -v \"obj/\" | grep -v \"bin/\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 9: String Literals in Error Messages\"\n echo \"### Hardcoded error strings that could be in Resources.resx (sample)\"\n grep -rn 'Log\\.\\(Error\\|Warning\\)\\|LogError\\|LogWarning\\|LogCodedError\\|LogCodedWarning' --include=\"*.cs\" src/ 2>/dev/null | grep '\"' | grep -v \"Properties.Resources\" | grep -v \"obj/\" | grep -v \"bin/\" | shuf | head -20 || echo \"None found\"\n} > /tmp/gh-aw/agent/scan-results.md\necho \"✅ Codebase scan complete → /tmp/gh-aw/agent/scan-results.md\"\n" + + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GITHUB_TOKEN: ${{ github.token }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # 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 || github.event.issue.pull_request + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Install GitHub Copilot CLI + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.21 + env: + GH_HOST: github.com + - name: Install AWF binary + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.20 + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + 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('${{ runner.temp }}/gh-aw/actions/determine_automatic_lockdown.cjs'); + await determineAutomaticLockdown(github, context, core); + - name: Download container images + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.20 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 ghcr.io/github/gh-aw-firewall/squid:0.25.20 ghcr.io/github/gh-aw-mcpg:v0.2.19 ghcr.io/github/github-mcp-server:v0.32.0 node:lts-alpine + - name: Write Safe Outputs Config + run: | + mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" + mkdir -p /tmp/gh-aw/safeoutputs + mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_b4eb31dc778c9568_EOF' + {"assign_to_agent":{"max":1,"model":"claude-opus-4.6","target":"*"},"create_issue":{"close_older_issues":true,"expires":168,"labels":["automated","code-quality"],"max":1,"title_prefix":"[fix-finder] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} + GH_AW_SAFE_OUTPUTS_CONFIG_b4eb31dc778c9568_EOF + - name: Write Safe Outputs Tools + env: + GH_AW_TOOLS_META_JSON: | + { + "description_suffixes": { + "assign_to_agent": " CONSTRAINTS: Maximum 1 issue(s) can be assigned to agent.", + "create_issue": " CONSTRAINTS: Maximum 1 issue(s) can be created. Title will be prefixed with \"[fix-finder] \". Labels [\"automated\" \"code-quality\"] will be automatically added." + }, + "repo_params": {}, + "dynamic_tools": [] + } + GH_AW_VALIDATION_JSON: | + { + "assign_to_agent": { + "defaultMax": 1, + "fields": { + "agent": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "issue_number": { + "issueNumberOrTemporaryId": true + }, + "pull_number": { + "optionalPositiveInteger": true + }, + "pull_request_repo": { + "type": "string", + "maxLength": 256 + }, + "repo": { + "type": "string", + "maxLength": 256 + } + }, + "customValidation": "requiresOneOf:issue_number,pull_number" + }, + "create_issue": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "labels": { + "type": "array", + "itemType": "string", + "itemSanitize": true, + "itemMaxLength": 128 + }, + "parent": { + "issueOrPRNumber": true + }, + "repo": { + "type": "string", + "maxLength": 256 + }, + "temporary_id": { + "type": "string" + }, + "title": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "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 + } + } + }, + "report_incomplete": { + "defaultMax": 5, + "fields": { + "details": { + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 1024 + } + } + } + } + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_safe_outputs_tools.cjs'); + await main(); + - 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: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + 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: ${{ runner.temp }}/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ runner.temp }}/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 + 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 "${RUNNER_TEMP}/gh-aw/actions/start_safe_outputs_server.sh" + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.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_GUARD_MIN_INTEGRITY: ${{ steps.determine-automatic-lockdown.outputs.min_integrity }} + GITHUB_MCP_GUARD_REPOS: ${{ steps.determine-automatic-lockdown.outputs.repos }} + 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 MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" + 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 MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e 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.2.19' + + mkdir -p /home/runner/.copilot + cat << GH_AW_MCP_CONFIG_b808ac1d73c0c8b2_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + { + "mcpServers": { + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.32.0", + "env": { + "GITHUB_HOST": "\${GITHUB_SERVER_URL}", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "repos,issues" + }, + "guard-policies": { + "allow-only": { + "min-integrity": "$GITHUB_MCP_GUARD_MIN_INTEGRITY", + "repos": "$GITHUB_MCP_GUARD_REPOS" + } + } + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + }, + "guard-policies": { + "write-sink": { + "accept": [ + "*" + ] + } + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_b808ac1d73c0c8b2_EOF + - name: Download activation artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: activation + path: /tmp/gh-aw + - name: Clean git credentials + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool github + # --allow-tool safeoutputs + # --allow-tool shell(awk:*) + # --allow-tool shell(cat) + # --allow-tool shell(cat:*) + # --allow-tool shell(date) + # --allow-tool shell(date:*) + # --allow-tool shell(echo) + # --allow-tool shell(find src -name '*.cs' -type f) + # --allow-tool shell(grep) + # --allow-tool shell(grep:*) + # --allow-tool shell(head) + # --allow-tool shell(head:*) + # --allow-tool shell(ls) + # --allow-tool shell(pwd) + # --allow-tool shell(sed:*) + # --allow-tool shell(shuf:*) + # --allow-tool shell(sort) + # --allow-tool shell(sort:*) + # --allow-tool shell(tail) + # --allow-tool shell(tail:*) + # --allow-tool shell(uniq) + # --allow-tool shell(wc) + # --allow-tool shell(wc:*) + # --allow-tool shell(xargs:*) + # --allow-tool shell(yq) + # --allow-tool write + timeout-minutes: 30 + run: | + set -o pipefail + touch /tmp/gh-aw/agent-step-summary.md + (umask 177 && touch /tmp/gh-aw/agent-stdio.log) + # shellcheck disable=SC1003 + sudo -E awf --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --allow-domains '*.githubusercontent.com,*.vsblob.vsassets.io,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.nuget.org,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,builds.dotnet.microsoft.com,ci.dot.net,codeload.github.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,dc.services.visualstudio.com,dist.nuget.org,docs.github.com,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,objects.githubusercontent.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,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkgs.dev.azure.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.microsoft.com' --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --image-tag 0.25.20 --skip-pull --enable-api-proxy \ + -- /bin/bash -c 'node ${RUNNER_TEMP}/gh-aw/actions/copilot_driver.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --allow-tool '\''shell(awk:*)'\'' --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(cat:*)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(date:*)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(find src -name '\''\'\'''\''*.cs'\''\'\'''\'' -type f)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(grep:*)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(head:*)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(sed:*)'\'' --allow-tool '\''shell(shuf:*)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(sort:*)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(tail:*)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(wc:*)'\'' --allow-tool '\''shell(xargs:*)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: claude-opus-4.6 + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_PHASE: agent + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_VERSION: v0.68.3 + GITHUB_API_URL: ${{ github.api_url }} + GITHUB_AW: true + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md + GITHUB_WORKSPACE: ${{ github.workspace }} + GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_AUTHOR_NAME: github-actions[bot] + GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_NAME: github-actions[bot] + XDG_CONFIG_HOME: /home/runner + - name: Detect Copilot errors + id: detect-copilot-errors + if: always() + continue-on-error: true + run: node "${RUNNER_TEMP}/gh-aw/actions/detect_copilot_errors.cjs" + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GITHUB_TOKEN: ${{ github.token }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # 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: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh" + - 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 "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/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: Append agent step summary + if: always() + run: bash "${RUNNER_TEMP}/gh-aw/actions/append_agent_step_summary.sh" + - name: Copy Safe Outputs + if: always() + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + run: | + mkdir -p /tmp/gh-aw + cp "$GH_AW_SAFE_OUTPUTS" /tmp/gh-aw/safeoutputs.jsonl 2>/dev/null || true + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.vsblob.vsassets.io,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.nuget.org,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,builds.dotnet.microsoft.com,ci.dot.net,codeload.github.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,dc.services.visualstudio.com,dist.nuget.org,docs.github.com,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,objects.githubusercontent.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,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkgs.dev.azure.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.microsoft.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/collect_ndjson_output.cjs'); + await main(); + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + id: parse-mcp-gateway + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/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: Parse token usage for step summary + if: always() + continue-on-error: true + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_token_usage.cjs'); + await main(); + - name: Write agent output placeholder if missing + if: always() + run: | + if [ ! -f /tmp/gh-aw/agent_output.json ]; then + echo '{"items":[]}' > /tmp/gh-aw/agent_output.json + fi + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: agent + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/agent_usage.json + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/ + /tmp/gh-aw/github_rate_limits.jsonl + /tmp/gh-aw/safeoutputs.jsonl + /tmp/gh-aw/agent_output.json + /tmp/gh-aw/aw-*.patch + /tmp/gh-aw/aw-*.bundle + /tmp/gh-aw/sandbox/firewall/logs/ + /tmp/gh-aw/sandbox/firewall/audit/ + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - detection + - safe_outputs + if: > + always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' || + needs.activation.outputs.stale_lock_file_failed == 'true') + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + concurrency: + group: "gh-aw-conclusion-nightly-fix-finder" + cancel-in-progress: false + outputs: + incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }} + 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 + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Process no-op messages + id: noop + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: "1" + GH_AW_WORKFLOW_NAME: "Nightly Fix Finder" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_noop_message.cjs'); + await main(); + - name: Log detection run + id: detection_runs + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Nightly Fix Finder" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} + GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_detection_runs.cjs'); + await main(); + - name: Record missing tool + id: missing_tool + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_MISSING_TOOL_CREATE_ISSUE: "true" + GH_AW_WORKFLOW_NAME: "Nightly Fix Finder" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Record incomplete + id: report_incomplete + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true" + GH_AW_WORKFLOW_NAME: "Nightly Fix Finder" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/report_incomplete_handler.cjs'); + await main(); + - name: Handle agent failure + id: handle_agent_failure + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Nightly Fix Finder" + 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: "nightly-fix-finder" + GH_AW_ENGINE_ID: "copilot" + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }} + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }} + GH_AW_MCP_POLICY_ERROR: ${{ needs.agent.outputs.mcp_policy_error }} + GH_AW_AGENTIC_ENGINE_TIMEOUT: ${{ needs.agent.outputs.agentic_engine_timeout }} + GH_AW_MODEL_NOT_SUPPORTED_ERROR: ${{ needs.agent.outputs.model_not_supported_error }} + GH_AW_ASSIGNMENT_ERRORS: ${{ needs.safe_outputs.outputs.assign_to_agent_assignment_errors }} + GH_AW_ASSIGNMENT_ERROR_COUNT: ${{ needs.safe_outputs.outputs.assign_to_agent_assignment_error_count }} + GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} + GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} + GH_AW_GROUP_REPORTS: "false" + GH_AW_FAILURE_REPORT_AS_ISSUE: "true" + GH_AW_TIMEOUT_MINUTES: "30" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + + detection: + needs: + - activation + - agent + if: > + always() && needs.agent.result != 'skipped' && (needs.agent.outputs.output_types != '' || needs.agent.outputs.has_patch == 'true') + runs-on: ubuntu-latest + permissions: + contents: read + outputs: + detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }} + detection_reason: ${{ steps.detection_conclusion.outputs.reason }} + detection_success: ${{ steps.detection_conclusion.outputs.success }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Checkout repository for patch context + if: needs.agent.outputs.has_patch == 'true' + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + # --- Threat Detection --- + - name: Clean stale firewall files from agent artifact + run: | + rm -rf /tmp/gh-aw/sandbox/firewall/logs + rm -rf /tmp/gh-aw/sandbox/firewall/audit + - name: Download container images + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.20 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 ghcr.io/github/gh-aw-firewall/squid:0.25.20 + - name: Check if detection needed + id: detection_guard + if: always() + env: + OUTPUT_TYPES: ${{ needs.agent.outputs.output_types }} + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + run: | + if [[ -n "$OUTPUT_TYPES" || "$HAS_PATCH" == "true" ]]; then + echo "run_detection=true" >> "$GITHUB_OUTPUT" + echo "Detection will run: output_types=$OUTPUT_TYPES, has_patch=$HAS_PATCH" + else + echo "run_detection=false" >> "$GITHUB_OUTPUT" + echo "Detection skipped: no agent outputs or patches to analyze" + fi + - name: Clear MCP configuration for detection + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + rm -f /tmp/gh-aw/mcp-config/mcp-servers.json + rm -f /home/runner/.copilot/mcp-config.json + rm -f "$GITHUB_WORKSPACE/.gemini/settings.json" + - name: Prepare threat detection files + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + mkdir -p /tmp/gh-aw/threat-detection/aw-prompts + cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true + cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true + for f in /tmp/gh-aw/aw-*.patch; do + [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true + done + for f in /tmp/gh-aw/aw-*.bundle; do + [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true + done + echo "Prepared threat detection files:" + ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true + - name: Setup threat detection + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + WORKFLOW_NAME: "Nightly Fix Finder" + WORKFLOW_DESCRIPTION: "Nightly scan for random code improvement opportunities, files issues assigned to Copilot" + HAS_PATCH: ${{ needs.agent.outputs.has_patch }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/setup_threat_detection.cjs'); + await main(); + - name: Ensure threat-detection directory and log + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Install GitHub Copilot CLI + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.21 + env: + GH_HOST: github.com + - name: Install AWF binary + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.20 + - name: Execute GitHub Copilot CLI + if: always() && steps.detection_guard.outputs.run_detection == 'true' + id: detection_agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 20 + run: | + set -o pipefail + touch /tmp/gh-aw/agent-step-summary.md + (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log) + # shellcheck disable=SC1003 + sudo -E awf --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --env-all --exclude-env COPILOT_GITHUB_TOKEN --allow-domains api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,github.com,host.docker.internal,telemetry.enterprise.githubcopilot.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --image-tag 0.25.20 --skip-pull --enable-api-proxy \ + -- /bin/bash -c 'node ${RUNNER_TEMP}/gh-aw/actions/copilot_driver.cjs /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --add-dir "${GITHUB_WORKSPACE}" --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: claude-opus-4.6 + GH_AW_PHASE: detection + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_VERSION: v0.68.3 + GITHUB_API_URL: ${{ github.api_url }} + GITHUB_AW: true + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md + GITHUB_WORKSPACE: ${{ github.workspace }} + GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_AUTHOR_NAME: github-actions[bot] + GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_NAME: github-actions[bot] + XDG_CONFIG_HOME: /home/runner + - name: Upload threat detection log + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: detection + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + - name: Parse and conclude threat detection + id: detection_conclusion + if: always() + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }} + GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs'); + await main(); + + safe_outputs: + needs: + - activation + - agent + - detection + if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success' + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + timeout-minutes: 15 + env: + GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/nightly-fix-finder" + GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} + GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} + GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: "claude-opus-4.6" + GH_AW_WORKFLOW_ID: "nightly-fix-finder" + GH_AW_WORKFLOW_NAME: "Nightly Fix Finder" + outputs: + assign_to_agent_assigned: ${{ steps.process_safe_outputs.outputs.assign_to_agent_assigned }} + assign_to_agent_assignment_error_count: ${{ steps.process_safe_outputs.outputs.assign_to_agent_assignment_error_count }} + assign_to_agent_assignment_errors: ${{ steps.process_safe_outputs.outputs.assign_to_agent_assignment_errors }} + code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }} + code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }} + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + created_issue_number: ${{ steps.process_safe_outputs.outputs.created_issue_number }} + created_issue_url: ${{ steps.process_safe_outputs.outputs.created_issue_url }} + 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 + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Configure GH_HOST for enterprise compatibility + id: ghes-host-config + shell: bash + run: | + # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct + # GitHub instance (GHES/GHEC). On github.com this is a harmless no-op. + GH_HOST="${GITHUB_SERVER_URL#https://}" + GH_HOST="${GH_HOST#http://}" + echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.vsblob.vsassets.io,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.nuget.org,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,builds.dotnet.microsoft.com,ci.dot.net,codeload.github.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,dc.services.visualstudio.com,dist.nuget.org,docs.github.com,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,objects.githubusercontent.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,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkgs.dev.azure.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.microsoft.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"assign_to_agent\":{\"max\":1,\"model\":\"claude-opus-4.6\",\"target\":\"*\"},\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"labels\":[\"automated\",\"code-quality\"],\"max\":1,\"title_prefix\":\"[fix-finder] \"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" + GH_AW_ASSIGN_TO_AGENT_TOKEN: ${{ secrets.GH_AW_AGENT_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload Safe Outputs Items + if: always() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: safe-outputs-items + path: | + /tmp/gh-aw/safe-output-items.jsonl + /tmp/gh-aw/temporary-id-map.json + if-no-files-found: ignore + diff --git a/.github/workflows/nightly-fix-finder.md b/.github/workflows/nightly-fix-finder.md new file mode 100644 index 00000000000..47c483dcb08 --- /dev/null +++ b/.github/workflows/nightly-fix-finder.md @@ -0,0 +1,278 @@ +--- +description: Nightly scan for random code improvement opportunities, files issues assigned to Copilot +on: + schedule: + - cron: "daily around 02:00" + workflow_dispatch: +permissions: + contents: read + issues: read +engine: + id: copilot + model: claude-opus-4.6 +network: + allowed: + - defaults + - github + - dotnet +tools: + github: + toolsets: [repos, issues] + bash: + - "find src -name '*.cs' -type f" + - "grep:*" + - "wc:*" + - "head:*" + - "tail:*" + - "sort:*" + - "cat:*" + - "awk:*" + - "sed:*" + - "shuf:*" + - "date:*" + - "xargs:*" +safe-outputs: + create-issue: + title-prefix: "[fix-finder] " + labels: [automated, code-quality] + expires: 7d + close-older-issues: true + assign-to-agent: + model: "claude-opus-4.6" + target: "*" + noop: +timeout-minutes: 30 +strict: true +steps: + - name: Collect codebase metrics + run: | + mkdir -p /tmp/gh-aw/agent + { + echo "## Scan Category Seed" + echo "Date seed: $(date +%j)" + CATEGORY_INDEX=$(( $(date +%j) % 10 )) + echo "Selected category index: $CATEGORY_INDEX" + + echo "" + echo "## Category 0: TODO/FIXME/HACK Comments" + echo "### Sample TODO/FIXME/HACK comments in src/" + grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.cs" src/ 2>/dev/null | grep -v "obj/" | grep -v "bin/" | shuf | head -20 || echo "None found" + echo "### Total count" + grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.cs" src/ 2>/dev/null | grep -v "obj/" | grep -v "bin/" | wc -l + + echo "" + echo "## Category 1: Files Missing Nullable Enable" + echo "### C# files in src/ without #nullable enable (sample)" + find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' -exec grep -rL '#nullable enable' {} \; 2>/dev/null | shuf | head -20 || echo "None found" + echo "### Total count" + find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' -exec grep -rL '#nullable enable' {} \; 2>/dev/null | wc -l + + echo "" + echo "## Category 2: Obsolete API Usage" + echo "### Files using [Obsolete] or #pragma warning disable CS0618 (sample)" + grep -rn "\[Obsolete\]\|CS0618\|CS0612" --include="*.cs" src/ 2>/dev/null | grep -v "obj/" | grep -v "bin/" | shuf | head -20 || echo "None found" + + echo "" + echo "## Category 3: Large Files" + echo "### Largest C# source files in src/ (top 20)" + find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' | xargs wc -l 2>/dev/null | sort -rn | head -21 | tail -20 + + echo "" + echo "## Category 4: Missing XML Documentation" + echo "### Public classes/methods without XML doc comments (sample)" + grep -rn "public " --include="*.cs" src/ 2>/dev/null | grep -v "obj/" | grep -v "bin/" | grep -v "///" | grep -v "Designer.cs" | grep -v "AssemblyInfo.cs" | shuf | head -20 || echo "None found" + + echo "" + echo "## Category 5: Code Style Issues" + echo "### Files with leading spaces instead of tabs (sample)" + grep -rlP "^ [^ ]" --include="*.cs" src/ 2>/dev/null | grep -v "obj/" | grep -v "bin/" | grep -v "Designer.cs" | shuf | head -20 || echo "None found" + + echo "" + echo "## Category 6: Test Coverage Gaps" + echo "### Source files in Xamarin.Android.Build.Tasks without corresponding test" + for f in $(find src/Xamarin.Android.Build.Tasks -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name '*Test*' ! -name 'Resources.Designer.cs' 2>/dev/null | shuf | head -20); do + basename=$(basename "$f" .cs) + if ! find tests -name "${basename}*Test*.cs" -o -name "*Test*${basename}*.cs" 2>/dev/null | grep -q .; then + echo " No test found for: $f" + fi + done + + echo "" + echo "## Category 7: Unused Using Directives" + echo "### Files with many using directives (potential cleanup, sample)" + for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do + count=$(grep -c "^using " "$f" 2>/dev/null || echo 0) + if [ "$count" -gt 10 ]; then + echo " $f: $count using directives" + fi + done + + echo "" + echo "## Category 8: Error Handling" + echo "### Bare catch blocks that may swallow exceptions (sample)" + grep -rn "catch\s*(Exception\b" --include="*.cs" src/ 2>/dev/null | grep -v "obj/" | grep -v "bin/" | shuf | head -20 || echo "None found" + + echo "" + echo "## Category 9: String Literals in Error Messages" + echo "### Hardcoded error strings that could be in Resources.resx (sample)" + grep -rn 'Log\.\(Error\|Warning\)\|LogError\|LogWarning\|LogCodedError\|LogCodedWarning' --include="*.cs" src/ 2>/dev/null | grep '"' | grep -v "Properties.Resources" | grep -v "obj/" | grep -v "bin/" | shuf | head -20 || echo "None found" + } > /tmp/gh-aw/agent/scan-results.md + echo "✅ Codebase scan complete → /tmp/gh-aw/agent/scan-results.md" +--- + +# Nightly Fix Finder + +You are the Nightly Fix Finder Agent — an expert system that scans the dotnet/android repository each night for random code improvement opportunities and files actionable issues for Copilot to fix. + +## Mission + +Each night, select one scan category, analyze the pre-collected data, find one specific actionable improvement, create a well-scoped issue, and assign Copilot to fix it. + +## Current Context + +- **Repository**: ${{ github.repository }} +- **Run Date**: $(date +%Y-%m-%d) +- **Pre-computed scan results**: `/tmp/gh-aw/agent/scan-results.md` + +## Phase 1: Load Scan Results and Select Category + +### 1.1 Read Pre-computed Data + +Read `/tmp/gh-aw/agent/scan-results.md` which contains pre-collected metrics for all 10 categories. The category index for today is already computed using the day-of-year as a seed. + +### 1.2 Determine Today's Category + +The scan results include a `Selected category index` value (0-9). Use that to pick today's focus: + +| Index | Category | Description | +|-------|----------|-------------| +| 0 | TODO/FIXME/HACK Comments | Find stale TODO/FIXME/HACK comments that should be resolved | +| 1 | Nullable Reference Types | Find C# files missing `#nullable enable` that should be opted in | +| 2 | Obsolete API Usage | Find uses of `[Obsolete]` members that should be updated | +| 3 | Large Files | Find oversized C# files (>800 lines) that should be split | +| 4 | Missing XML Documentation | Find public APIs without XML doc comments | +| 5 | Code Style Issues | Find formatting inconsistencies (spaces vs tabs, Mono style violations) | +| 6 | Test Coverage Gaps | Find source files without corresponding test files | +| 7 | Unused Using Directives | Find files with excessive using directives that could be cleaned up | +| 8 | Error Handling | Find bare `catch (Exception)` blocks that swallow errors | +| 9 | String Literals | Find hardcoded error strings that should be in `Properties.Resources` | + +If the selected category has no actionable findings in the scan results, move to the next category (wrapping around) until you find one with data. + +## Phase 2: Deep Analysis + +Using the pre-collected sample data for the selected category, pick **one specific, well-scoped improvement**. Then do a deeper investigation: + +1. **Read the actual source file(s)** involved to understand the full context +2. **Verify the issue is real** — not a false positive +3. **Determine the fix** — what specifically needs to change +4. **Scope it appropriately** — one issue should be completable in a single PR + +### Category-Specific Guidance + +#### TODO/FIXME/HACK Comments (Category 0) +- Pick a TODO that is clearly stale or has a concrete action +- Check if the TODO references an old bug number or feature that's already done +- The issue should ask to either implement the TODO or remove it if no longer relevant + +#### Nullable Reference Types (Category 1) +- Pick a file that's a good candidate for `#nullable enable` +- Prefer files in `src/Xamarin.Android.Build.Tasks/` as they follow clear patterns +- Follow the repo's nullable conventions: no `!` operator, use `IsNullOrEmpty()` extension methods +- The issue should reference the repo's nullable guidelines + +#### Obsolete API Usage (Category 2) +- Find calls to deprecated APIs and suggest the modern replacement +- Check if the obsolete message suggests an alternative + +#### Large Files (Category 3) +- Pick a file over 800 lines +- Suggest specific logical splits based on the file's content +- Each new file should have a clear single responsibility + +#### Missing XML Documentation (Category 4) +- Focus on public API surface in `src/Mono.Android/` +- The issue should provide example doc comments for the specific APIs + +#### Code Style Issues (Category 5) +- Focus on spaces-vs-tabs since the repo uses tabs +- Reference `.editorconfig` patterns: space before `(` and `[` +- The issue should list specific files and line ranges + +#### Test Coverage Gaps (Category 6) +- Find an MSBuild task or utility class with no test coverage +- The issue should suggest specific test scenarios + +#### Unused Using Directives (Category 7) +- Pick files with >10 using directives that likely have unused ones +- The issue should ask to clean up unnecessary usings + +#### Error Handling (Category 8) +- Find `catch (Exception)` blocks that don't log or rethrow +- The issue should suggest proper error handling patterns + +#### String Literals (Category 9) +- Find hardcoded strings in `LogError`/`LogWarning` calls +- The issue should ask to move them to `Properties.Resources` with proper `XA####` error codes + +## Phase 3: Create Issue + +Create exactly **one** well-scoped issue using `create_issue`. The issue must be specific enough that Copilot can implement the fix without ambiguity. + +### Issue Template + +Use this structure: + +```markdown +### Problem + +[1-2 sentences describing what's wrong and why it matters] + +### Location + +- **File(s)**: `path/to/file.cs` +- **Line(s)**: [specific lines if applicable] + +### Current Code + +[Show the relevant code snippet] + +### Suggested Fix + +[Describe exactly what should change, with example code if possible] + +### Guidelines + +- [Any repo-specific conventions to follow] +- [Reference to relevant documentation] + +### Acceptance Criteria + +- [ ] [Specific, verifiable criteria] +- [ ] All tests pass +- [ ] No new warnings introduced +``` + +## Phase 4: Assign to Copilot + +After creating the issue, use `assign_to_agent` to assign Copilot to work on it. The safe-output is configured with `model: "claude-opus-4.6"` so Copilot will use Claude Opus 4.6 to implement the fix. + +## Rules + +1. **One issue per run** — Create exactly one issue, not multiple +2. **Be specific** — The issue must be implementable from the description alone +3. **Verify before filing** — Read the actual source to confirm the issue is real +4. **Skip non-actionable findings** — If nothing good is found in any category, call `noop` +5. **Respect repo conventions** — Follow dotnet/android formatting and coding style +6. **Don't duplicate** — Search for existing issues with similar titles before creating + +## Important + +You **MUST** end by calling exactly one set of safe output tools: + +- **`create_issue` + `assign_to_agent`**: When a valid improvement is found +- **`noop`**: When no actionable improvement was found after checking all categories + +```json +{"noop": {"message": "No actionable improvements found today after scanning all 10 categories."}} +``` From 8416cdd2be534f059573d8030081c5f3b848dee4 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 14 May 2026 16:11:29 -0500 Subject: [PATCH 02/16] Add pull_request trigger for workflow file changes Automatically runs the nightly-fix-finder workflow when PRs modify either the .md source or .lock.yml compiled file. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/nightly-fix-finder.lock.yml | 78 +++++++++++++++---- .github/workflows/nightly-fix-finder.md | 4 + 2 files changed, 67 insertions(+), 15 deletions(-) diff --git a/.github/workflows/nightly-fix-finder.lock.yml b/.github/workflows/nightly-fix-finder.lock.yml index 3b1e11ac854..cf78b968334 100644 --- a/.github/workflows/nightly-fix-finder.lock.yml +++ b/.github/workflows/nightly-fix-finder.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"f593c7325f465f3042f769b37df8ccffdcb8682b6451a09e7799cc710c246cb8","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"a62fc50c0b59a6cc9afe61b027d85468a73d42bbff04f0ac1b8d6f8243ea9e68","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_AGENT_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) @@ -48,6 +48,10 @@ name: "Nightly Fix Finder" "on": + pull_request: + paths: + - .github/workflows/nightly-fix-finder.md + - .github/workflows/nightly-fix-finder.lock.yml schedule: - cron: "34 1 * * *" # Friendly format: daily around 02:00 (scattered) @@ -62,17 +66,22 @@ name: "Nightly Fix Finder" permissions: {} concurrency: - group: "gh-aw-${{ github.workflow }}" + group: "gh-aw-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref || github.run_id }}" + cancel-in-progress: true run-name: "Nightly Fix Finder" jobs: activation: + needs: pre_activation + if: > + needs.pre_activation.outputs.activated == 'true' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id) runs-on: ubuntu-slim permissions: actions: read contents: read outputs: + body: ${{ steps.sanitized.outputs.body }} comment_id: "" comment_repo: "" lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} @@ -80,6 +89,8 @@ jobs: secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} setup-trace-id: ${{ steps.setup.outputs.trace-id }} stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} + text: ${{ steps.sanitized.outputs.text }} + title: ${{ steps.sanitized.outputs.title }} steps: - name: Setup Scripts id: setup @@ -87,6 +98,7 @@ jobs: with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} + trace-id: ${{ needs.pre_activation.outputs.setup-trace-id }} - name: Generate agentic run info id: generate_aw_info env: @@ -149,6 +161,15 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/check_version_updates.cjs'); await main(); + - name: Compute current body text + id: sanitized + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/compute_text.cjs'); + await main(); - name: Create prompt with built-in context env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt @@ -165,14 +186,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_e92035eaf9a77dc8_EOF' + cat << 'GH_AW_PROMPT_aaf5b2e15433c659_EOF' - GH_AW_PROMPT_e92035eaf9a77dc8_EOF + GH_AW_PROMPT_aaf5b2e15433c659_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_e92035eaf9a77dc8_EOF' + cat << 'GH_AW_PROMPT_aaf5b2e15433c659_EOF' Tools: create_issue, assign_to_agent, missing_tool, missing_data, noop @@ -204,12 +225,12 @@ jobs: {{/if}} - GH_AW_PROMPT_e92035eaf9a77dc8_EOF + GH_AW_PROMPT_aaf5b2e15433c659_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_e92035eaf9a77dc8_EOF' + cat << 'GH_AW_PROMPT_aaf5b2e15433c659_EOF' {{#runtime-import .github/workflows/nightly-fix-finder.md}} - GH_AW_PROMPT_e92035eaf9a77dc8_EOF + GH_AW_PROMPT_aaf5b2e15433c659_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -234,6 +255,7 @@ jobs: 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 }} with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -252,7 +274,8 @@ jobs: 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_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED } }); - name: Validate prompt placeholders @@ -283,8 +306,6 @@ jobs: permissions: contents: read issues: read - concurrency: - group: "gh-aw-copilot-${{ github.workflow }}" env: DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} GH_AW_ASSETS_ALLOWED_EXTS: "" @@ -383,9 +404,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_b4eb31dc778c9568_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_3a5777c0cb8d3bfb_EOF' {"assign_to_agent":{"max":1,"model":"claude-opus-4.6","target":"*"},"create_issue":{"close_older_issues":true,"expires":168,"labels":["automated","code-quality"],"max":1,"title_prefix":"[fix-finder] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_b4eb31dc778c9568_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_3a5777c0cb8d3bfb_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -606,7 +627,7 @@ jobs: 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 MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e 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.2.19' mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_b808ac1d73c0c8b2_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_00174ff6726b6845_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -647,7 +668,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_b808ac1d73c0c8b2_EOF + GH_AW_MCP_CONFIG_00174ff6726b6845_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: @@ -1155,6 +1176,33 @@ jobs: const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs'); await main(); + pre_activation: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + matched_command: '' + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@ba90f2186d7ad780ec640f364005fa24e797b360 # v0.68.3 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + env: + GH_AW_REQUIRED_ROLES: "admin,maintainer,write" + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_membership.cjs'); + await main(); + safe_outputs: needs: - activation diff --git a/.github/workflows/nightly-fix-finder.md b/.github/workflows/nightly-fix-finder.md index 47c483dcb08..f7bcf9c0e99 100644 --- a/.github/workflows/nightly-fix-finder.md +++ b/.github/workflows/nightly-fix-finder.md @@ -3,6 +3,10 @@ description: Nightly scan for random code improvement opportunities, files issue on: schedule: - cron: "daily around 02:00" + pull_request: + paths: + - ".github/workflows/nightly-fix-finder.md" + - ".github/workflows/nightly-fix-finder.lock.yml" workflow_dispatch: permissions: contents: read From 518dbbaae8af393442131c0cffa201295c4e12d5 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 14 May 2026 16:12:35 -0500 Subject: [PATCH 03/16] Address review feedback on nightly-fix-finder workflow - Use --exclude-dir=obj/bin instead of piping through grep -v - Replace slow find -exec grep per-file with grep -rL batch - Fix Category 8 regex: add grep -P for \s and \b support - Fix Category 4: adjust description since same-line /// check is unreliable, let the agent verify docs on preceding lines - Remove $(date) from prompt (not a shell context), reference the pre-computed scan results instead Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/nightly-fix-finder.lock.yml | 24 +++++++++---------- .github/workflows/nightly-fix-finder.md | 22 ++++++++--------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/nightly-fix-finder.lock.yml b/.github/workflows/nightly-fix-finder.lock.yml index cf78b968334..27e05511ec1 100644 --- a/.github/workflows/nightly-fix-finder.lock.yml +++ b/.github/workflows/nightly-fix-finder.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"a62fc50c0b59a6cc9afe61b027d85468a73d42bbff04f0ac1b8d6f8243ea9e68","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"f2c89c08b11e74618ca80711adffba984916425e495a47b543fda905799696e8","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_AGENT_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) @@ -186,14 +186,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_aaf5b2e15433c659_EOF' + cat << 'GH_AW_PROMPT_f74216f77a4d7fd8_EOF' - GH_AW_PROMPT_aaf5b2e15433c659_EOF + GH_AW_PROMPT_f74216f77a4d7fd8_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_aaf5b2e15433c659_EOF' + cat << 'GH_AW_PROMPT_f74216f77a4d7fd8_EOF' Tools: create_issue, assign_to_agent, missing_tool, missing_data, noop @@ -225,12 +225,12 @@ jobs: {{/if}} - GH_AW_PROMPT_aaf5b2e15433c659_EOF + GH_AW_PROMPT_f74216f77a4d7fd8_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_aaf5b2e15433c659_EOF' + cat << 'GH_AW_PROMPT_f74216f77a4d7fd8_EOF' {{#runtime-import .github/workflows/nightly-fix-finder.md}} - GH_AW_PROMPT_aaf5b2e15433c659_EOF + GH_AW_PROMPT_f74216f77a4d7fd8_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -352,7 +352,7 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Collect codebase metrics - run: "mkdir -p /tmp/gh-aw/agent\n{\n echo \"## Scan Category Seed\"\n echo \"Date seed: $(date +%j)\"\n CATEGORY_INDEX=$(( $(date +%j) % 10 ))\n echo \"Selected category index: $CATEGORY_INDEX\"\n\n echo \"\"\n echo \"## Category 0: TODO/FIXME/HACK Comments\"\n echo \"### Sample TODO/FIXME/HACK comments in src/\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" src/ 2>/dev/null | grep -v \"obj/\" | grep -v \"bin/\" | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" src/ 2>/dev/null | grep -v \"obj/\" | grep -v \"bin/\" | wc -l\n\n echo \"\"\n echo \"## Category 1: Files Missing Nullable Enable\"\n echo \"### C# files in src/ without #nullable enable (sample)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' -exec grep -rL '#nullable enable' {} \\; 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' -exec grep -rL '#nullable enable' {} \\; 2>/dev/null | wc -l\n\n echo \"\"\n echo \"## Category 2: Obsolete API Usage\"\n echo \"### Files using [Obsolete] or #pragma warning disable CS0618 (sample)\"\n grep -rn \"\\[Obsolete\\]\\|CS0618\\|CS0612\" --include=\"*.cs\" src/ 2>/dev/null | grep -v \"obj/\" | grep -v \"bin/\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 3: Large Files\"\n echo \"### Largest C# source files in src/ (top 20)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' | xargs wc -l 2>/dev/null | sort -rn | head -21 | tail -20\n\n echo \"\"\n echo \"## Category 4: Missing XML Documentation\"\n echo \"### Public classes/methods without XML doc comments (sample)\"\n grep -rn \"public \" --include=\"*.cs\" src/ 2>/dev/null | grep -v \"obj/\" | grep -v \"bin/\" | grep -v \"///\" | grep -v \"Designer.cs\" | grep -v \"AssemblyInfo.cs\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 5: Code Style Issues\"\n echo \"### Files with leading spaces instead of tabs (sample)\"\n grep -rlP \"^ [^ ]\" --include=\"*.cs\" src/ 2>/dev/null | grep -v \"obj/\" | grep -v \"bin/\" | grep -v \"Designer.cs\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 6: Test Coverage Gaps\"\n echo \"### Source files in Xamarin.Android.Build.Tasks without corresponding test\"\n for f in $(find src/Xamarin.Android.Build.Tasks -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name '*Test*' ! -name 'Resources.Designer.cs' 2>/dev/null | shuf | head -20); do\n basename=$(basename \"$f\" .cs)\n if ! find tests -name \"${basename}*Test*.cs\" -o -name \"*Test*${basename}*.cs\" 2>/dev/null | grep -q .; then\n echo \" No test found for: $f\"\n fi\n done\n\n echo \"\"\n echo \"## Category 7: Unused Using Directives\"\n echo \"### Files with many using directives (potential cleanup, sample)\"\n for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do\n count=$(grep -c \"^using \" \"$f\" 2>/dev/null || echo 0)\n if [ \"$count\" -gt 10 ]; then\n echo \" $f: $count using directives\"\n fi\n done\n\n echo \"\"\n echo \"## Category 8: Error Handling\"\n echo \"### Bare catch blocks that may swallow exceptions (sample)\"\n grep -rn \"catch\\s*(Exception\\b\" --include=\"*.cs\" src/ 2>/dev/null | grep -v \"obj/\" | grep -v \"bin/\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 9: String Literals in Error Messages\"\n echo \"### Hardcoded error strings that could be in Resources.resx (sample)\"\n grep -rn 'Log\\.\\(Error\\|Warning\\)\\|LogError\\|LogWarning\\|LogCodedError\\|LogCodedWarning' --include=\"*.cs\" src/ 2>/dev/null | grep '\"' | grep -v \"Properties.Resources\" | grep -v \"obj/\" | grep -v \"bin/\" | shuf | head -20 || echo \"None found\"\n} > /tmp/gh-aw/agent/scan-results.md\necho \"✅ Codebase scan complete → /tmp/gh-aw/agent/scan-results.md\"\n" + run: "mkdir -p /tmp/gh-aw/agent\n{\n echo \"## Scan Category Seed\"\n echo \"Date seed: $(date +%j)\"\n CATEGORY_INDEX=$(( $(date +%j) % 10 ))\n echo \"Selected category index: $CATEGORY_INDEX\"\n\n echo \"\"\n echo \"## Category 0: TODO/FIXME/HACK Comments\"\n echo \"### Sample TODO/FIXME/HACK comments in src/\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l\n\n echo \"\"\n echo \"## Category 1: Files Missing Nullable Enable\"\n echo \"### C# files in src/ without #nullable enable (sample)\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l\n\n echo \"\"\n echo \"## Category 2: Obsolete API Usage\"\n echo \"### Files using [Obsolete] or #pragma warning disable CS0618 (sample)\"\n grep -rn \"\\[Obsolete\\]\\|CS0618\\|CS0612\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 3: Large Files\"\n echo \"### Largest C# source files in src/ (top 20)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' | xargs wc -l 2>/dev/null | sort -rn | head -21 | tail -20\n\n echo \"\"\n echo \"## Category 4: Missing XML Documentation\"\n echo \"### Public declarations (the agent should verify if XML docs exist on preceding lines)\"\n grep -rn \"public \" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v \"Designer.cs\" | grep -v \"AssemblyInfo.cs\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 5: Code Style Issues\"\n echo \"### Files with leading spaces instead of tabs (sample)\"\n grep -rlP \"^ [^ ]\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v \"Designer.cs\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 6: Test Coverage Gaps\"\n echo \"### Source files in Xamarin.Android.Build.Tasks without corresponding test\"\n for f in $(find src/Xamarin.Android.Build.Tasks -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name '*Test*' ! -name 'Resources.Designer.cs' 2>/dev/null | shuf | head -20); do\n basename=$(basename \"$f\" .cs)\n if ! find tests -name \"${basename}*Test*.cs\" -o -name \"*Test*${basename}*.cs\" 2>/dev/null | grep -q .; then\n echo \" No test found for: $f\"\n fi\n done\n\n echo \"\"\n echo \"## Category 7: Unused Using Directives\"\n echo \"### Files with many using directives (potential cleanup, sample)\"\n for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do\n count=$(grep -c \"^using \" \"$f\" 2>/dev/null || echo 0)\n if [ \"$count\" -gt 10 ]; then\n echo \" $f: $count using directives\"\n fi\n done\n\n echo \"\"\n echo \"## Category 8: Error Handling\"\n echo \"### Bare catch blocks that may swallow exceptions (sample)\"\n grep -rnP \"catch\\s*\\(Exception\\b\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 9: String Literals in Error Messages\"\n echo \"### Hardcoded error strings that could be in Resources.resx (sample)\"\n grep -rn 'Log\\.\\(Error\\|Warning\\)\\|LogError\\|LogWarning\\|LogCodedError\\|LogCodedWarning' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '\"' | grep -v \"Properties.Resources\" | shuf | head -20 || echo \"None found\"\n} > /tmp/gh-aw/agent/scan-results.md\necho \"✅ Codebase scan complete → /tmp/gh-aw/agent/scan-results.md\"\n" - name: Configure Git credentials env: @@ -404,9 +404,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_3a5777c0cb8d3bfb_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_85f033508e097f1c_EOF' {"assign_to_agent":{"max":1,"model":"claude-opus-4.6","target":"*"},"create_issue":{"close_older_issues":true,"expires":168,"labels":["automated","code-quality"],"max":1,"title_prefix":"[fix-finder] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_3a5777c0cb8d3bfb_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_85f033508e097f1c_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -627,7 +627,7 @@ jobs: 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 MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e 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.2.19' mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_00174ff6726b6845_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_5881758dfb395167_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -668,7 +668,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_00174ff6726b6845_EOF + GH_AW_MCP_CONFIG_5881758dfb395167_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: diff --git a/.github/workflows/nightly-fix-finder.md b/.github/workflows/nightly-fix-finder.md index f7bcf9c0e99..e5feefb7a54 100644 --- a/.github/workflows/nightly-fix-finder.md +++ b/.github/workflows/nightly-fix-finder.md @@ -60,21 +60,21 @@ steps: echo "" echo "## Category 0: TODO/FIXME/HACK Comments" echo "### Sample TODO/FIXME/HACK comments in src/" - grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.cs" src/ 2>/dev/null | grep -v "obj/" | grep -v "bin/" | shuf | head -20 || echo "None found" + grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo "None found" echo "### Total count" - grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.cs" src/ 2>/dev/null | grep -v "obj/" | grep -v "bin/" | wc -l + grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l echo "" echo "## Category 1: Files Missing Nullable Enable" echo "### C# files in src/ without #nullable enable (sample)" - find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' -exec grep -rL '#nullable enable' {} \; 2>/dev/null | shuf | head -20 || echo "None found" + grep -rL '#nullable enable' --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo "None found" echo "### Total count" - find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' -exec grep -rL '#nullable enable' {} \; 2>/dev/null | wc -l + grep -rL '#nullable enable' --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l echo "" echo "## Category 2: Obsolete API Usage" echo "### Files using [Obsolete] or #pragma warning disable CS0618 (sample)" - grep -rn "\[Obsolete\]\|CS0618\|CS0612" --include="*.cs" src/ 2>/dev/null | grep -v "obj/" | grep -v "bin/" | shuf | head -20 || echo "None found" + grep -rn "\[Obsolete\]\|CS0618\|CS0612" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo "None found" echo "" echo "## Category 3: Large Files" @@ -83,13 +83,13 @@ steps: echo "" echo "## Category 4: Missing XML Documentation" - echo "### Public classes/methods without XML doc comments (sample)" - grep -rn "public " --include="*.cs" src/ 2>/dev/null | grep -v "obj/" | grep -v "bin/" | grep -v "///" | grep -v "Designer.cs" | grep -v "AssemblyInfo.cs" | shuf | head -20 || echo "None found" + echo "### Public declarations (the agent should verify if XML docs exist on preceding lines)" + grep -rn "public " --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v "Designer.cs" | grep -v "AssemblyInfo.cs" | shuf | head -20 || echo "None found" echo "" echo "## Category 5: Code Style Issues" echo "### Files with leading spaces instead of tabs (sample)" - grep -rlP "^ [^ ]" --include="*.cs" src/ 2>/dev/null | grep -v "obj/" | grep -v "bin/" | grep -v "Designer.cs" | shuf | head -20 || echo "None found" + grep -rlP "^ [^ ]" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v "Designer.cs" | shuf | head -20 || echo "None found" echo "" echo "## Category 6: Test Coverage Gaps" @@ -114,12 +114,12 @@ steps: echo "" echo "## Category 8: Error Handling" echo "### Bare catch blocks that may swallow exceptions (sample)" - grep -rn "catch\s*(Exception\b" --include="*.cs" src/ 2>/dev/null | grep -v "obj/" | grep -v "bin/" | shuf | head -20 || echo "None found" + grep -rnP "catch\s*\(Exception\b" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo "None found" echo "" echo "## Category 9: String Literals in Error Messages" echo "### Hardcoded error strings that could be in Resources.resx (sample)" - grep -rn 'Log\.\(Error\|Warning\)\|LogError\|LogWarning\|LogCodedError\|LogCodedWarning' --include="*.cs" src/ 2>/dev/null | grep '"' | grep -v "Properties.Resources" | grep -v "obj/" | grep -v "bin/" | shuf | head -20 || echo "None found" + grep -rn 'Log\.\(Error\|Warning\)\|LogError\|LogWarning\|LogCodedError\|LogCodedWarning' --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '"' | grep -v "Properties.Resources" | shuf | head -20 || echo "None found" } > /tmp/gh-aw/agent/scan-results.md echo "✅ Codebase scan complete → /tmp/gh-aw/agent/scan-results.md" --- @@ -135,7 +135,7 @@ Each night, select one scan category, analyze the pre-collected data, find one s ## Current Context - **Repository**: ${{ github.repository }} -- **Run Date**: $(date +%Y-%m-%d) +- **Run Date**: The date seed is in the pre-computed scan results below - **Pre-computed scan results**: `/tmp/gh-aw/agent/scan-results.md` ## Phase 1: Load Scan Results and Select Category From 48faaabe35a03df5098ae4698351bd59ae7b6fc8 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 14 May 2026 16:25:21 -0500 Subject: [PATCH 04/16] Fix assign_to_agent: agent must pass issue_number The first run showed the agent called assign_to_agent with only temporary_id but no issue_number, causing the assignment to be silently skipped. Updated the prompt to explicitly instruct the agent to pass issue_number referencing the create_issue temporary_id. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/nightly-fix-finder.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/nightly-fix-finder.md b/.github/workflows/nightly-fix-finder.md index e5feefb7a54..35f0c59bb82 100644 --- a/.github/workflows/nightly-fix-finder.md +++ b/.github/workflows/nightly-fix-finder.md @@ -259,7 +259,11 @@ Use this structure: ## Phase 4: Assign to Copilot -After creating the issue, use `assign_to_agent` to assign Copilot to work on it. The safe-output is configured with `model: "claude-opus-4.6"` so Copilot will use Claude Opus 4.6 to implement the fix. +After creating the issue, use `assign_to_agent` to assign Copilot to work on it. You **MUST** pass the `issue_number` parameter — use the `temporary_id` from the `create_issue` call (e.g., `"issue_number": "#aw_myid"`). The safe-output is configured with `model: "claude-opus-4.6"` so Copilot will use Claude Opus 4.6 to implement the fix. + +Example call sequence: +1. `create_issue` with `temporary_id: "aw_fix123"`, `title`, `body` +2. `assign_to_agent` with `issue_number: "#aw_fix123"` ## Rules From f519c978e03af467369803608f0614fd137573ed Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 14 May 2026 16:27:14 -0500 Subject: [PATCH 05/16] Set min-integrity: none for GitHub tools Allows the agent to read all issues (including community-filed) when checking for duplicates before filing a new issue. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/nightly-fix-finder.lock.yml | 48 +++++++++---------- .github/workflows/nightly-fix-finder.md | 1 + 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/.github/workflows/nightly-fix-finder.lock.yml b/.github/workflows/nightly-fix-finder.lock.yml index 27e05511ec1..dd89e45bb17 100644 --- a/.github/workflows/nightly-fix-finder.lock.yml +++ b/.github/workflows/nightly-fix-finder.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"f2c89c08b11e74618ca80711adffba984916425e495a47b543fda905799696e8","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"e6647fc6cff134ac0cfb781d0964381414ab1183a0b857551193a337b46222d6","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_AGENT_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) @@ -186,14 +186,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_f74216f77a4d7fd8_EOF' + cat << 'GH_AW_PROMPT_560fb5973b38e79b_EOF' - GH_AW_PROMPT_f74216f77a4d7fd8_EOF + GH_AW_PROMPT_560fb5973b38e79b_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_f74216f77a4d7fd8_EOF' + cat << 'GH_AW_PROMPT_560fb5973b38e79b_EOF' Tools: create_issue, assign_to_agent, missing_tool, missing_data, noop @@ -225,12 +225,12 @@ jobs: {{/if}} - GH_AW_PROMPT_f74216f77a4d7fd8_EOF + GH_AW_PROMPT_560fb5973b38e79b_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_f74216f77a4d7fd8_EOF' + cat << 'GH_AW_PROMPT_560fb5973b38e79b_EOF' {{#runtime-import .github/workflows/nightly-fix-finder.md}} - GH_AW_PROMPT_f74216f77a4d7fd8_EOF + GH_AW_PROMPT_560fb5973b38e79b_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -387,16 +387,13 @@ jobs: GH_HOST: github.com - name: Install AWF binary run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.25.20 - - name: Determine automatic lockdown mode for GitHub MCP Server - id: determine-automatic-lockdown - uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 + - name: Parse integrity filter lists + id: parse-guard-vars 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('${{ runner.temp }}/gh-aw/actions/determine_automatic_lockdown.cjs'); - await determineAutomaticLockdown(github, context, core); + GH_AW_BLOCKED_USERS_VAR: ${{ vars.GH_AW_GITHUB_BLOCKED_USERS || '' }} + GH_AW_TRUSTED_USERS_VAR: ${{ vars.GH_AW_GITHUB_TRUSTED_USERS || '' }} + GH_AW_APPROVAL_LABELS_VAR: ${{ vars.GH_AW_GITHUB_APPROVAL_LABELS || '' }} + run: bash "${RUNNER_TEMP}/gh-aw/actions/parse_guard_list.sh" - name: Download container images run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.20 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 ghcr.io/github/gh-aw-firewall/squid:0.25.20 ghcr.io/github/gh-aw-mcpg:v0.2.19 ghcr.io/github/github-mcp-server:v0.32.0 node:lts-alpine - name: Write Safe Outputs Config @@ -404,9 +401,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_85f033508e097f1c_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_3f1d53f89b5fa768_EOF' {"assign_to_agent":{"max":1,"model":"claude-opus-4.6","target":"*"},"create_issue":{"close_older_issues":true,"expires":168,"labels":["automated","code-quality"],"max":1,"title_prefix":"[fix-finder] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_85f033508e097f1c_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_3f1d53f89b5fa768_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -605,8 +602,6 @@ jobs: GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.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_GUARD_MIN_INTEGRITY: ${{ steps.determine-automatic-lockdown.outputs.min_integrity }} - GITHUB_MCP_GUARD_REPOS: ${{ steps.determine-automatic-lockdown.outputs.repos }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} run: | set -eo pipefail @@ -627,7 +622,7 @@ jobs: 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 MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e 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.2.19' mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_5881758dfb395167_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_2adfde71c8c6d2ae_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -641,8 +636,11 @@ jobs: }, "guard-policies": { "allow-only": { - "min-integrity": "$GITHUB_MCP_GUARD_MIN_INTEGRITY", - "repos": "$GITHUB_MCP_GUARD_REPOS" + "approval-labels": ${{ steps.parse-guard-vars.outputs.approval_labels }}, + "blocked-users": ${{ steps.parse-guard-vars.outputs.blocked_users }}, + "min-integrity": "none", + "repos": "all", + "trusted-users": ${{ steps.parse-guard-vars.outputs.trusted_users }} } } }, @@ -668,7 +666,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_5881758dfb395167_EOF + GH_AW_MCP_CONFIG_2adfde71c8c6d2ae_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: @@ -871,6 +869,8 @@ jobs: /tmp/gh-aw/sandbox/agent/logs/ /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent_usage.json /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/agent/ diff --git a/.github/workflows/nightly-fix-finder.md b/.github/workflows/nightly-fix-finder.md index 35f0c59bb82..44349685d8e 100644 --- a/.github/workflows/nightly-fix-finder.md +++ b/.github/workflows/nightly-fix-finder.md @@ -22,6 +22,7 @@ network: tools: github: toolsets: [repos, issues] + min-integrity: none bash: - "find src -name '*.cs' -type f" - "grep:*" From 080f9bb74345ec109a9d035b9999f2e994bb6d04 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 14 May 2026 16:42:22 -0500 Subject: [PATCH 06/16] Fix assign_to_agent: remove # prefix from temporary_id reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The agent passed issue_number: "#aw_xdoc1" but the validator requires just "aw_xdoc1" (no # prefix) for temporary IDs. Also scope Category 4 (XML docs) to src/Mono.Android/ only — internal build tasks/tools do not need XML documentation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/nightly-fix-finder.lock.yml | 24 +++++++++---------- .github/workflows/nightly-fix-finder.md | 13 +++++----- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/.github/workflows/nightly-fix-finder.lock.yml b/.github/workflows/nightly-fix-finder.lock.yml index dd89e45bb17..9e3227f078c 100644 --- a/.github/workflows/nightly-fix-finder.lock.yml +++ b/.github/workflows/nightly-fix-finder.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"e6647fc6cff134ac0cfb781d0964381414ab1183a0b857551193a337b46222d6","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"5f8bfacfe10beb1caf87078ec80751630310aadf91264d42c6d7986c814d3cd0","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_AGENT_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) @@ -186,14 +186,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_560fb5973b38e79b_EOF' + cat << 'GH_AW_PROMPT_35d4508822b47443_EOF' - GH_AW_PROMPT_560fb5973b38e79b_EOF + GH_AW_PROMPT_35d4508822b47443_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_560fb5973b38e79b_EOF' + cat << 'GH_AW_PROMPT_35d4508822b47443_EOF' Tools: create_issue, assign_to_agent, missing_tool, missing_data, noop @@ -225,12 +225,12 @@ jobs: {{/if}} - GH_AW_PROMPT_560fb5973b38e79b_EOF + GH_AW_PROMPT_35d4508822b47443_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_560fb5973b38e79b_EOF' + cat << 'GH_AW_PROMPT_35d4508822b47443_EOF' {{#runtime-import .github/workflows/nightly-fix-finder.md}} - GH_AW_PROMPT_560fb5973b38e79b_EOF + GH_AW_PROMPT_35d4508822b47443_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -352,7 +352,7 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Collect codebase metrics - run: "mkdir -p /tmp/gh-aw/agent\n{\n echo \"## Scan Category Seed\"\n echo \"Date seed: $(date +%j)\"\n CATEGORY_INDEX=$(( $(date +%j) % 10 ))\n echo \"Selected category index: $CATEGORY_INDEX\"\n\n echo \"\"\n echo \"## Category 0: TODO/FIXME/HACK Comments\"\n echo \"### Sample TODO/FIXME/HACK comments in src/\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l\n\n echo \"\"\n echo \"## Category 1: Files Missing Nullable Enable\"\n echo \"### C# files in src/ without #nullable enable (sample)\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l\n\n echo \"\"\n echo \"## Category 2: Obsolete API Usage\"\n echo \"### Files using [Obsolete] or #pragma warning disable CS0618 (sample)\"\n grep -rn \"\\[Obsolete\\]\\|CS0618\\|CS0612\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 3: Large Files\"\n echo \"### Largest C# source files in src/ (top 20)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' | xargs wc -l 2>/dev/null | sort -rn | head -21 | tail -20\n\n echo \"\"\n echo \"## Category 4: Missing XML Documentation\"\n echo \"### Public declarations (the agent should verify if XML docs exist on preceding lines)\"\n grep -rn \"public \" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v \"Designer.cs\" | grep -v \"AssemblyInfo.cs\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 5: Code Style Issues\"\n echo \"### Files with leading spaces instead of tabs (sample)\"\n grep -rlP \"^ [^ ]\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v \"Designer.cs\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 6: Test Coverage Gaps\"\n echo \"### Source files in Xamarin.Android.Build.Tasks without corresponding test\"\n for f in $(find src/Xamarin.Android.Build.Tasks -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name '*Test*' ! -name 'Resources.Designer.cs' 2>/dev/null | shuf | head -20); do\n basename=$(basename \"$f\" .cs)\n if ! find tests -name \"${basename}*Test*.cs\" -o -name \"*Test*${basename}*.cs\" 2>/dev/null | grep -q .; then\n echo \" No test found for: $f\"\n fi\n done\n\n echo \"\"\n echo \"## Category 7: Unused Using Directives\"\n echo \"### Files with many using directives (potential cleanup, sample)\"\n for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do\n count=$(grep -c \"^using \" \"$f\" 2>/dev/null || echo 0)\n if [ \"$count\" -gt 10 ]; then\n echo \" $f: $count using directives\"\n fi\n done\n\n echo \"\"\n echo \"## Category 8: Error Handling\"\n echo \"### Bare catch blocks that may swallow exceptions (sample)\"\n grep -rnP \"catch\\s*\\(Exception\\b\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 9: String Literals in Error Messages\"\n echo \"### Hardcoded error strings that could be in Resources.resx (sample)\"\n grep -rn 'Log\\.\\(Error\\|Warning\\)\\|LogError\\|LogWarning\\|LogCodedError\\|LogCodedWarning' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '\"' | grep -v \"Properties.Resources\" | shuf | head -20 || echo \"None found\"\n} > /tmp/gh-aw/agent/scan-results.md\necho \"✅ Codebase scan complete → /tmp/gh-aw/agent/scan-results.md\"\n" + run: "mkdir -p /tmp/gh-aw/agent\n{\n echo \"## Scan Category Seed\"\n echo \"Date seed: $(date +%j)\"\n CATEGORY_INDEX=$(( $(date +%j) % 10 ))\n echo \"Selected category index: $CATEGORY_INDEX\"\n\n echo \"\"\n echo \"## Category 0: TODO/FIXME/HACK Comments\"\n echo \"### Sample TODO/FIXME/HACK comments in src/\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l\n\n echo \"\"\n echo \"## Category 1: Files Missing Nullable Enable\"\n echo \"### C# files in src/ without #nullable enable (sample)\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l\n\n echo \"\"\n echo \"## Category 2: Obsolete API Usage\"\n echo \"### Files using [Obsolete] or #pragma warning disable CS0618 (sample)\"\n grep -rn \"\\[Obsolete\\]\\|CS0618\\|CS0612\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 3: Large Files\"\n echo \"### Largest C# source files in src/ (top 20)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' | xargs wc -l 2>/dev/null | sort -rn | head -21 | tail -20\n\n echo \"\"\n echo \"## Category 4: Missing XML Documentation (src/Mono.Android/ only)\"\n echo \"### Public declarations in Mono.Android (shipped product) without XML docs\"\n grep -rn \"public \" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v \"Designer.cs\" | grep -v \"AssemblyInfo.cs\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 5: Code Style Issues\"\n echo \"### Files with leading spaces instead of tabs (sample)\"\n grep -rlP \"^ [^ ]\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v \"Designer.cs\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 6: Test Coverage Gaps\"\n echo \"### Source files in Xamarin.Android.Build.Tasks without corresponding test\"\n for f in $(find src/Xamarin.Android.Build.Tasks -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name '*Test*' ! -name 'Resources.Designer.cs' 2>/dev/null | shuf | head -20); do\n basename=$(basename \"$f\" .cs)\n if ! find tests -name \"${basename}*Test*.cs\" -o -name \"*Test*${basename}*.cs\" 2>/dev/null | grep -q .; then\n echo \" No test found for: $f\"\n fi\n done\n\n echo \"\"\n echo \"## Category 7: Unused Using Directives\"\n echo \"### Files with many using directives (potential cleanup, sample)\"\n for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do\n count=$(grep -c \"^using \" \"$f\" 2>/dev/null || echo 0)\n if [ \"$count\" -gt 10 ]; then\n echo \" $f: $count using directives\"\n fi\n done\n\n echo \"\"\n echo \"## Category 8: Error Handling\"\n echo \"### Bare catch blocks that may swallow exceptions (sample)\"\n grep -rnP \"catch\\s*\\(Exception\\b\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 9: String Literals in Error Messages\"\n echo \"### Hardcoded error strings that could be in Resources.resx (sample)\"\n grep -rn 'Log\\.\\(Error\\|Warning\\)\\|LogError\\|LogWarning\\|LogCodedError\\|LogCodedWarning' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '\"' | grep -v \"Properties.Resources\" | shuf | head -20 || echo \"None found\"\n} > /tmp/gh-aw/agent/scan-results.md\necho \"✅ Codebase scan complete → /tmp/gh-aw/agent/scan-results.md\"\n" - name: Configure Git credentials env: @@ -401,9 +401,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_3f1d53f89b5fa768_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_3f5f94f60ff7e8fb_EOF' {"assign_to_agent":{"max":1,"model":"claude-opus-4.6","target":"*"},"create_issue":{"close_older_issues":true,"expires":168,"labels":["automated","code-quality"],"max":1,"title_prefix":"[fix-finder] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_3f1d53f89b5fa768_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_3f5f94f60ff7e8fb_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -622,7 +622,7 @@ jobs: 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 MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e 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.2.19' mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_2adfde71c8c6d2ae_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_51dece5c1a8fbad1_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -666,7 +666,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_2adfde71c8c6d2ae_EOF + GH_AW_MCP_CONFIG_51dece5c1a8fbad1_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: diff --git a/.github/workflows/nightly-fix-finder.md b/.github/workflows/nightly-fix-finder.md index 44349685d8e..4c4bc1fde18 100644 --- a/.github/workflows/nightly-fix-finder.md +++ b/.github/workflows/nightly-fix-finder.md @@ -83,9 +83,9 @@ steps: find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' | xargs wc -l 2>/dev/null | sort -rn | head -21 | tail -20 echo "" - echo "## Category 4: Missing XML Documentation" - echo "### Public declarations (the agent should verify if XML docs exist on preceding lines)" - grep -rn "public " --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v "Designer.cs" | grep -v "AssemblyInfo.cs" | shuf | head -20 || echo "None found" + echo "## Category 4: Missing XML Documentation (src/Mono.Android/ only)" + echo "### Public declarations in Mono.Android (shipped product) without XML docs" + grep -rn "public " --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v "Designer.cs" | grep -v "AssemblyInfo.cs" | shuf | head -20 || echo "None found" echo "" echo "## Category 5: Code Style Issues" @@ -196,7 +196,8 @@ Using the pre-collected sample data for the selected category, pick **one specif - Each new file should have a clear single responsibility #### Missing XML Documentation (Category 4) -- Focus on public API surface in `src/Mono.Android/` +- **ONLY** look at public APIs in `src/Mono.Android/` — this is the shipped product (Mono.Android.dll) +- Do NOT file issues for XML docs in build tasks, tools, or test code — those are internal - The issue should provide example doc comments for the specific APIs #### Code Style Issues (Category 5) @@ -260,11 +261,11 @@ Use this structure: ## Phase 4: Assign to Copilot -After creating the issue, use `assign_to_agent` to assign Copilot to work on it. You **MUST** pass the `issue_number` parameter — use the `temporary_id` from the `create_issue` call (e.g., `"issue_number": "#aw_myid"`). The safe-output is configured with `model: "claude-opus-4.6"` so Copilot will use Claude Opus 4.6 to implement the fix. +After creating the issue, use `assign_to_agent` to assign Copilot to work on it. You **MUST** pass the `issue_number` parameter — use the `temporary_id` from the `create_issue` call (**without** the `#` prefix). The safe-output is configured with `model: "claude-opus-4.6"` so Copilot will use Claude Opus 4.6 to implement the fix. Example call sequence: 1. `create_issue` with `temporary_id: "aw_fix123"`, `title`, `body` -2. `assign_to_agent` with `issue_number: "#aw_fix123"` +2. `assign_to_agent` with `issue_number: "aw_fix123"` ## Rules From 5bbd4a5346b623922ffdd3aac053aa9cb00c8199 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 14 May 2026 16:51:59 -0500 Subject: [PATCH 07/16] Use ANDROID_TEAM_PAT for assign-to-agent The default GITHUB_TOKEN lacks permission to assign the Copilot coding agent via GraphQL. Use ANDROID_TEAM_PAT which has the required scopes (same pattern as dotnet/android-libraries#1389). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/nightly-fix-finder.lock.yml | 37 ++++++++++--------- .github/workflows/nightly-fix-finder.md | 1 + 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/.github/workflows/nightly-fix-finder.lock.yml b/.github/workflows/nightly-fix-finder.lock.yml index 9e3227f078c..60b93cb53c2 100644 --- a/.github/workflows/nightly-fix-finder.lock.yml +++ b/.github/workflows/nightly-fix-finder.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"5f8bfacfe10beb1caf87078ec80751630310aadf91264d42c6d7986c814d3cd0","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} -# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_AGENT_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"e8f2eb12a1058c79e8c0ac366e2d26a9aa655e715121ef21cd97367b1365d5d2","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} +# gh-aw-manifest: {"version":1,"secrets":["ANDROID_TEAM_PAT","COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -25,8 +25,8 @@ # Nightly scan for random code improvement opportunities, files issues assigned to Copilot # # Secrets used: +# - ANDROID_TEAM_PAT # - COPILOT_GITHUB_TOKEN -# - GH_AW_AGENT_TOKEN # - GH_AW_GITHUB_MCP_SERVER_TOKEN # - GH_AW_GITHUB_TOKEN # - GITHUB_TOKEN @@ -186,14 +186,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_35d4508822b47443_EOF' + cat << 'GH_AW_PROMPT_bc53a58da92769c7_EOF' - GH_AW_PROMPT_35d4508822b47443_EOF + GH_AW_PROMPT_bc53a58da92769c7_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_35d4508822b47443_EOF' + cat << 'GH_AW_PROMPT_bc53a58da92769c7_EOF' Tools: create_issue, assign_to_agent, missing_tool, missing_data, noop @@ -225,12 +225,12 @@ jobs: {{/if}} - GH_AW_PROMPT_35d4508822b47443_EOF + GH_AW_PROMPT_bc53a58da92769c7_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_35d4508822b47443_EOF' + cat << 'GH_AW_PROMPT_bc53a58da92769c7_EOF' {{#runtime-import .github/workflows/nightly-fix-finder.md}} - GH_AW_PROMPT_35d4508822b47443_EOF + GH_AW_PROMPT_bc53a58da92769c7_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -397,13 +397,15 @@ jobs: - name: Download container images run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.25.20 ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20 ghcr.io/github/gh-aw-firewall/squid:0.25.20 ghcr.io/github/gh-aw-mcpg:v0.2.19 ghcr.io/github/github-mcp-server:v0.32.0 node:lts-alpine - name: Write Safe Outputs Config + env: + ANDROID_TEAM_PAT: ${{ secrets.ANDROID_TEAM_PAT }} run: | mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_3f5f94f60ff7e8fb_EOF' - {"assign_to_agent":{"max":1,"model":"claude-opus-4.6","target":"*"},"create_issue":{"close_older_issues":true,"expires":168,"labels":["automated","code-quality"],"max":1,"title_prefix":"[fix-finder] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_3f5f94f60ff7e8fb_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_1016ca737b9a0df3_EOF + {"assign_to_agent":{"github-token":"${ANDROID_TEAM_PAT}","max":1,"model":"claude-opus-4.6","target":"*"},"create_issue":{"close_older_issues":true,"expires":168,"labels":["automated","code-quality"],"max":1,"title_prefix":"[fix-finder] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} + GH_AW_SAFE_OUTPUTS_CONFIG_1016ca737b9a0df3_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -622,7 +624,7 @@ jobs: 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 MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e 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.2.19' mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_51dece5c1a8fbad1_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_8d7630506eff1777_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -666,7 +668,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_51dece5c1a8fbad1_EOF + GH_AW_MCP_CONFIG_8d7630506eff1777_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: @@ -776,7 +778,8 @@ jobs: const { main } = require('${{ runner.temp }}/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' + GH_AW_SECRET_NAMES: 'ANDROID_TEAM_PAT,COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_ANDROID_TEAM_PAT: ${{ secrets.ANDROID_TEAM_PAT }} 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 }} @@ -1274,8 +1277,8 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.vsblob.vsassets.io,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.nuget.org,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,builds.dotnet.microsoft.com,ci.dot.net,codeload.github.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,dc.services.visualstudio.com,dist.nuget.org,docs.github.com,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,objects.githubusercontent.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,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkgs.dev.azure.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.microsoft.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"assign_to_agent\":{\"max\":1,\"model\":\"claude-opus-4.6\",\"target\":\"*\"},\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"labels\":[\"automated\",\"code-quality\"],\"max\":1,\"title_prefix\":\"[fix-finder] \"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" - GH_AW_ASSIGN_TO_AGENT_TOKEN: ${{ secrets.GH_AW_AGENT_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"assign_to_agent\":{\"github-token\":\"${{ secrets.ANDROID_TEAM_PAT }}\",\"max\":1,\"model\":\"claude-opus-4.6\",\"target\":\"*\"},\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"labels\":[\"automated\",\"code-quality\"],\"max\":1,\"title_prefix\":\"[fix-finder] \"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" + GH_AW_ASSIGN_TO_AGENT_TOKEN: ${{ secrets.ANDROID_TEAM_PAT }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/nightly-fix-finder.md b/.github/workflows/nightly-fix-finder.md index 4c4bc1fde18..891d36aaac3 100644 --- a/.github/workflows/nightly-fix-finder.md +++ b/.github/workflows/nightly-fix-finder.md @@ -45,6 +45,7 @@ safe-outputs: assign-to-agent: model: "claude-opus-4.6" target: "*" + github-token: ${{ secrets.ANDROID_TEAM_PAT }} noop: timeout-minutes: 30 strict: true From 09ab60e5d8c211e981b5dc36f06edfc51fb5f240 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 14 May 2026 16:57:26 -0500 Subject: [PATCH 08/16] Exclude Android.Runtime and Java.Interop from Category 4 scan These are plumbing/bridge types (InputStreamInvoker, JNIEnv, etc.) that developers never interact with directly. Focus XML doc suggestions on user-facing APIs like Android.App, Android.Widget. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/nightly-fix-finder.lock.yml | 24 +++++++++---------- .github/workflows/nightly-fix-finder.md | 6 ++++- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/.github/workflows/nightly-fix-finder.lock.yml b/.github/workflows/nightly-fix-finder.lock.yml index 60b93cb53c2..d47d65cde88 100644 --- a/.github/workflows/nightly-fix-finder.lock.yml +++ b/.github/workflows/nightly-fix-finder.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"e8f2eb12a1058c79e8c0ac366e2d26a9aa655e715121ef21cd97367b1365d5d2","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"d41123606a5f6e41f46e66cc9e383263e95c1826b78e0bf39c4cb297526e123a","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} # gh-aw-manifest: {"version":1,"secrets":["ANDROID_TEAM_PAT","COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) @@ -186,14 +186,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_bc53a58da92769c7_EOF' + cat << 'GH_AW_PROMPT_7cc7f147fac5faa7_EOF' - GH_AW_PROMPT_bc53a58da92769c7_EOF + GH_AW_PROMPT_7cc7f147fac5faa7_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_bc53a58da92769c7_EOF' + cat << 'GH_AW_PROMPT_7cc7f147fac5faa7_EOF' Tools: create_issue, assign_to_agent, missing_tool, missing_data, noop @@ -225,12 +225,12 @@ jobs: {{/if}} - GH_AW_PROMPT_bc53a58da92769c7_EOF + GH_AW_PROMPT_7cc7f147fac5faa7_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_bc53a58da92769c7_EOF' + cat << 'GH_AW_PROMPT_7cc7f147fac5faa7_EOF' {{#runtime-import .github/workflows/nightly-fix-finder.md}} - GH_AW_PROMPT_bc53a58da92769c7_EOF + GH_AW_PROMPT_7cc7f147fac5faa7_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -352,7 +352,7 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Collect codebase metrics - run: "mkdir -p /tmp/gh-aw/agent\n{\n echo \"## Scan Category Seed\"\n echo \"Date seed: $(date +%j)\"\n CATEGORY_INDEX=$(( $(date +%j) % 10 ))\n echo \"Selected category index: $CATEGORY_INDEX\"\n\n echo \"\"\n echo \"## Category 0: TODO/FIXME/HACK Comments\"\n echo \"### Sample TODO/FIXME/HACK comments in src/\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l\n\n echo \"\"\n echo \"## Category 1: Files Missing Nullable Enable\"\n echo \"### C# files in src/ without #nullable enable (sample)\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l\n\n echo \"\"\n echo \"## Category 2: Obsolete API Usage\"\n echo \"### Files using [Obsolete] or #pragma warning disable CS0618 (sample)\"\n grep -rn \"\\[Obsolete\\]\\|CS0618\\|CS0612\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 3: Large Files\"\n echo \"### Largest C# source files in src/ (top 20)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' | xargs wc -l 2>/dev/null | sort -rn | head -21 | tail -20\n\n echo \"\"\n echo \"## Category 4: Missing XML Documentation (src/Mono.Android/ only)\"\n echo \"### Public declarations in Mono.Android (shipped product) without XML docs\"\n grep -rn \"public \" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v \"Designer.cs\" | grep -v \"AssemblyInfo.cs\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 5: Code Style Issues\"\n echo \"### Files with leading spaces instead of tabs (sample)\"\n grep -rlP \"^ [^ ]\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v \"Designer.cs\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 6: Test Coverage Gaps\"\n echo \"### Source files in Xamarin.Android.Build.Tasks without corresponding test\"\n for f in $(find src/Xamarin.Android.Build.Tasks -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name '*Test*' ! -name 'Resources.Designer.cs' 2>/dev/null | shuf | head -20); do\n basename=$(basename \"$f\" .cs)\n if ! find tests -name \"${basename}*Test*.cs\" -o -name \"*Test*${basename}*.cs\" 2>/dev/null | grep -q .; then\n echo \" No test found for: $f\"\n fi\n done\n\n echo \"\"\n echo \"## Category 7: Unused Using Directives\"\n echo \"### Files with many using directives (potential cleanup, sample)\"\n for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do\n count=$(grep -c \"^using \" \"$f\" 2>/dev/null || echo 0)\n if [ \"$count\" -gt 10 ]; then\n echo \" $f: $count using directives\"\n fi\n done\n\n echo \"\"\n echo \"## Category 8: Error Handling\"\n echo \"### Bare catch blocks that may swallow exceptions (sample)\"\n grep -rnP \"catch\\s*\\(Exception\\b\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 9: String Literals in Error Messages\"\n echo \"### Hardcoded error strings that could be in Resources.resx (sample)\"\n grep -rn 'Log\\.\\(Error\\|Warning\\)\\|LogError\\|LogWarning\\|LogCodedError\\|LogCodedWarning' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '\"' | grep -v \"Properties.Resources\" | shuf | head -20 || echo \"None found\"\n} > /tmp/gh-aw/agent/scan-results.md\necho \"✅ Codebase scan complete → /tmp/gh-aw/agent/scan-results.md\"\n" + run: "mkdir -p /tmp/gh-aw/agent\n{\n echo \"## Scan Category Seed\"\n echo \"Date seed: $(date +%j)\"\n CATEGORY_INDEX=$(( $(date +%j) % 10 ))\n echo \"Selected category index: $CATEGORY_INDEX\"\n\n echo \"\"\n echo \"## Category 0: TODO/FIXME/HACK Comments\"\n echo \"### Sample TODO/FIXME/HACK comments in src/\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l\n\n echo \"\"\n echo \"## Category 1: Files Missing Nullable Enable\"\n echo \"### C# files in src/ without #nullable enable (sample)\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l\n\n echo \"\"\n echo \"## Category 2: Obsolete API Usage\"\n echo \"### Files using [Obsolete] or #pragma warning disable CS0618 (sample)\"\n grep -rn \"\\[Obsolete\\]\\|CS0618\\|CS0612\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 3: Large Files\"\n echo \"### Largest C# source files in src/ (top 20)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' | xargs wc -l 2>/dev/null | sort -rn | head -21 | tail -20\n\n echo \"\"\n echo \"## Category 4: Missing XML Documentation (src/Mono.Android/ only)\"\n echo \"### Public declarations in Mono.Android (shipped product) without XML docs\"\n echo \"### NOTE: Excludes Android.Runtime (plumbing), Java.Interop (bridge), and generated code\"\n grep -rn \"public \" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v \"Designer.cs\" | grep -v \"AssemblyInfo.cs\" | grep -v \"Android.Runtime\" | grep -v \"Java.Interop\" | grep -v \"/obj/\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 5: Code Style Issues\"\n echo \"### Files with leading spaces instead of tabs (sample)\"\n grep -rlP \"^ [^ ]\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v \"Designer.cs\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 6: Test Coverage Gaps\"\n echo \"### Source files in Xamarin.Android.Build.Tasks without corresponding test\"\n for f in $(find src/Xamarin.Android.Build.Tasks -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name '*Test*' ! -name 'Resources.Designer.cs' 2>/dev/null | shuf | head -20); do\n basename=$(basename \"$f\" .cs)\n if ! find tests -name \"${basename}*Test*.cs\" -o -name \"*Test*${basename}*.cs\" 2>/dev/null | grep -q .; then\n echo \" No test found for: $f\"\n fi\n done\n\n echo \"\"\n echo \"## Category 7: Unused Using Directives\"\n echo \"### Files with many using directives (potential cleanup, sample)\"\n for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do\n count=$(grep -c \"^using \" \"$f\" 2>/dev/null || echo 0)\n if [ \"$count\" -gt 10 ]; then\n echo \" $f: $count using directives\"\n fi\n done\n\n echo \"\"\n echo \"## Category 8: Error Handling\"\n echo \"### Bare catch blocks that may swallow exceptions (sample)\"\n grep -rnP \"catch\\s*\\(Exception\\b\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 9: String Literals in Error Messages\"\n echo \"### Hardcoded error strings that could be in Resources.resx (sample)\"\n grep -rn 'Log\\.\\(Error\\|Warning\\)\\|LogError\\|LogWarning\\|LogCodedError\\|LogCodedWarning' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '\"' | grep -v \"Properties.Resources\" | shuf | head -20 || echo \"None found\"\n} > /tmp/gh-aw/agent/scan-results.md\necho \"✅ Codebase scan complete → /tmp/gh-aw/agent/scan-results.md\"\n" - name: Configure Git credentials env: @@ -403,9 +403,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_1016ca737b9a0df3_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_1e70d990ecbffac4_EOF {"assign_to_agent":{"github-token":"${ANDROID_TEAM_PAT}","max":1,"model":"claude-opus-4.6","target":"*"},"create_issue":{"close_older_issues":true,"expires":168,"labels":["automated","code-quality"],"max":1,"title_prefix":"[fix-finder] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_1016ca737b9a0df3_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_1e70d990ecbffac4_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -624,7 +624,7 @@ jobs: 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 MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e 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.2.19' mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_8d7630506eff1777_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_467a97bec8ec113d_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -668,7 +668,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_8d7630506eff1777_EOF + GH_AW_MCP_CONFIG_467a97bec8ec113d_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: diff --git a/.github/workflows/nightly-fix-finder.md b/.github/workflows/nightly-fix-finder.md index 891d36aaac3..41838103f93 100644 --- a/.github/workflows/nightly-fix-finder.md +++ b/.github/workflows/nightly-fix-finder.md @@ -86,7 +86,8 @@ steps: echo "" echo "## Category 4: Missing XML Documentation (src/Mono.Android/ only)" echo "### Public declarations in Mono.Android (shipped product) without XML docs" - grep -rn "public " --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v "Designer.cs" | grep -v "AssemblyInfo.cs" | shuf | head -20 || echo "None found" + echo "### NOTE: Excludes Android.Runtime (plumbing), Java.Interop (bridge), and generated code" + grep -rn "public " --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v "Designer.cs" | grep -v "AssemblyInfo.cs" | grep -v "Android.Runtime" | grep -v "Java.Interop" | grep -v "/obj/" | shuf | head -20 || echo "None found" echo "" echo "## Category 5: Code Style Issues" @@ -198,6 +199,9 @@ Using the pre-collected sample data for the selected category, pick **one specif #### Missing XML Documentation (Category 4) - **ONLY** look at public APIs in `src/Mono.Android/` — this is the shipped product (Mono.Android.dll) +- **EXCLUDE** `Android.Runtime` namespace (plumbing/bridge types like `InputStreamInvoker`, `JNIEnv`) +- **EXCLUDE** `Java.Interop` namespace (low-level interop, not user-facing) +- Focus on types developers actually use: `Android.App`, `Android.Widget`, `Android.Views`, etc. - Do NOT file issues for XML docs in build tasks, tools, or test code — those are internal - The issue should provide example doc comments for the specific APIs From 3492e3f235a178d27f776999c97acdeb573a134a Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 14 May 2026 16:59:13 -0500 Subject: [PATCH 09/16] Disable report-failure-as-issue for safe-outputs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/nightly-fix-finder.lock.yml | 24 +++++++++---------- .github/workflows/nightly-fix-finder.md | 1 + 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/.github/workflows/nightly-fix-finder.lock.yml b/.github/workflows/nightly-fix-finder.lock.yml index d47d65cde88..9583d5b7d00 100644 --- a/.github/workflows/nightly-fix-finder.lock.yml +++ b/.github/workflows/nightly-fix-finder.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"d41123606a5f6e41f46e66cc9e383263e95c1826b78e0bf39c4cb297526e123a","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"80c8f4c82ca1e12e623a0a466ed2fa7885c4ae914dd2467d5548a6bddb5bed69","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} # gh-aw-manifest: {"version":1,"secrets":["ANDROID_TEAM_PAT","COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) @@ -186,14 +186,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_7cc7f147fac5faa7_EOF' + cat << 'GH_AW_PROMPT_97f50970d84bf8fe_EOF' - GH_AW_PROMPT_7cc7f147fac5faa7_EOF + GH_AW_PROMPT_97f50970d84bf8fe_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_7cc7f147fac5faa7_EOF' + cat << 'GH_AW_PROMPT_97f50970d84bf8fe_EOF' Tools: create_issue, assign_to_agent, missing_tool, missing_data, noop @@ -225,12 +225,12 @@ jobs: {{/if}} - GH_AW_PROMPT_7cc7f147fac5faa7_EOF + GH_AW_PROMPT_97f50970d84bf8fe_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_7cc7f147fac5faa7_EOF' + cat << 'GH_AW_PROMPT_97f50970d84bf8fe_EOF' {{#runtime-import .github/workflows/nightly-fix-finder.md}} - GH_AW_PROMPT_7cc7f147fac5faa7_EOF + GH_AW_PROMPT_97f50970d84bf8fe_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -403,9 +403,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_1e70d990ecbffac4_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_4f99e248586472bb_EOF {"assign_to_agent":{"github-token":"${ANDROID_TEAM_PAT}","max":1,"model":"claude-opus-4.6","target":"*"},"create_issue":{"close_older_issues":true,"expires":168,"labels":["automated","code-quality"],"max":1,"title_prefix":"[fix-finder] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_1e70d990ecbffac4_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_4f99e248586472bb_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -624,7 +624,7 @@ jobs: 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 MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e 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.2.19' mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_467a97bec8ec113d_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_71e1ca49f89a3338_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -668,7 +668,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_467a97bec8ec113d_EOF + GH_AW_MCP_CONFIG_71e1ca49f89a3338_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: @@ -1012,7 +1012,7 @@ jobs: GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} GH_AW_GROUP_REPORTS: "false" - GH_AW_FAILURE_REPORT_AS_ISSUE: "true" + GH_AW_FAILURE_REPORT_AS_ISSUE: "false" GH_AW_TIMEOUT_MINUTES: "30" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/nightly-fix-finder.md b/.github/workflows/nightly-fix-finder.md index 41838103f93..58a4d1dfe96 100644 --- a/.github/workflows/nightly-fix-finder.md +++ b/.github/workflows/nightly-fix-finder.md @@ -37,6 +37,7 @@ tools: - "date:*" - "xargs:*" safe-outputs: + report-failure-as-issue: false create-issue: title-prefix: "[fix-finder] " labels: [automated, code-quality] From e4c23d97e234aa8b94fe052dde21d36d5213b449 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 14 May 2026 17:08:18 -0500 Subject: [PATCH 10/16] Use RANDOM for category selection, fix bash pipefail issues - Replace deterministic date-based category (day%10) with \%10 so it doesn't pick the same category every run on the same day - Add || true to grep|wc -l pipelines to avoid pipefail abort - Fix grep -c || echo 0 double-output bug with || true + default Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/nightly-fix-finder.lock.yml | 24 +++++++++---------- .github/workflows/nightly-fix-finder.md | 13 +++++----- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/.github/workflows/nightly-fix-finder.lock.yml b/.github/workflows/nightly-fix-finder.lock.yml index 9583d5b7d00..d4fd23030b7 100644 --- a/.github/workflows/nightly-fix-finder.lock.yml +++ b/.github/workflows/nightly-fix-finder.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"80c8f4c82ca1e12e623a0a466ed2fa7885c4ae914dd2467d5548a6bddb5bed69","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"792179d05b32219b4a9d7332001bba9dcef91f1be9d4c6f7680e9494caf1d693","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} # gh-aw-manifest: {"version":1,"secrets":["ANDROID_TEAM_PAT","COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) @@ -186,14 +186,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_97f50970d84bf8fe_EOF' + cat << 'GH_AW_PROMPT_d396895ae4ca836e_EOF' - GH_AW_PROMPT_97f50970d84bf8fe_EOF + GH_AW_PROMPT_d396895ae4ca836e_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_97f50970d84bf8fe_EOF' + cat << 'GH_AW_PROMPT_d396895ae4ca836e_EOF' Tools: create_issue, assign_to_agent, missing_tool, missing_data, noop @@ -225,12 +225,12 @@ jobs: {{/if}} - GH_AW_PROMPT_97f50970d84bf8fe_EOF + GH_AW_PROMPT_d396895ae4ca836e_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_97f50970d84bf8fe_EOF' + cat << 'GH_AW_PROMPT_d396895ae4ca836e_EOF' {{#runtime-import .github/workflows/nightly-fix-finder.md}} - GH_AW_PROMPT_97f50970d84bf8fe_EOF + GH_AW_PROMPT_d396895ae4ca836e_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -352,7 +352,7 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Collect codebase metrics - run: "mkdir -p /tmp/gh-aw/agent\n{\n echo \"## Scan Category Seed\"\n echo \"Date seed: $(date +%j)\"\n CATEGORY_INDEX=$(( $(date +%j) % 10 ))\n echo \"Selected category index: $CATEGORY_INDEX\"\n\n echo \"\"\n echo \"## Category 0: TODO/FIXME/HACK Comments\"\n echo \"### Sample TODO/FIXME/HACK comments in src/\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l\n\n echo \"\"\n echo \"## Category 1: Files Missing Nullable Enable\"\n echo \"### C# files in src/ without #nullable enable (sample)\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l\n\n echo \"\"\n echo \"## Category 2: Obsolete API Usage\"\n echo \"### Files using [Obsolete] or #pragma warning disable CS0618 (sample)\"\n grep -rn \"\\[Obsolete\\]\\|CS0618\\|CS0612\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 3: Large Files\"\n echo \"### Largest C# source files in src/ (top 20)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' | xargs wc -l 2>/dev/null | sort -rn | head -21 | tail -20\n\n echo \"\"\n echo \"## Category 4: Missing XML Documentation (src/Mono.Android/ only)\"\n echo \"### Public declarations in Mono.Android (shipped product) without XML docs\"\n echo \"### NOTE: Excludes Android.Runtime (plumbing), Java.Interop (bridge), and generated code\"\n grep -rn \"public \" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v \"Designer.cs\" | grep -v \"AssemblyInfo.cs\" | grep -v \"Android.Runtime\" | grep -v \"Java.Interop\" | grep -v \"/obj/\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 5: Code Style Issues\"\n echo \"### Files with leading spaces instead of tabs (sample)\"\n grep -rlP \"^ [^ ]\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v \"Designer.cs\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 6: Test Coverage Gaps\"\n echo \"### Source files in Xamarin.Android.Build.Tasks without corresponding test\"\n for f in $(find src/Xamarin.Android.Build.Tasks -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name '*Test*' ! -name 'Resources.Designer.cs' 2>/dev/null | shuf | head -20); do\n basename=$(basename \"$f\" .cs)\n if ! find tests -name \"${basename}*Test*.cs\" -o -name \"*Test*${basename}*.cs\" 2>/dev/null | grep -q .; then\n echo \" No test found for: $f\"\n fi\n done\n\n echo \"\"\n echo \"## Category 7: Unused Using Directives\"\n echo \"### Files with many using directives (potential cleanup, sample)\"\n for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do\n count=$(grep -c \"^using \" \"$f\" 2>/dev/null || echo 0)\n if [ \"$count\" -gt 10 ]; then\n echo \" $f: $count using directives\"\n fi\n done\n\n echo \"\"\n echo \"## Category 8: Error Handling\"\n echo \"### Bare catch blocks that may swallow exceptions (sample)\"\n grep -rnP \"catch\\s*\\(Exception\\b\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 9: String Literals in Error Messages\"\n echo \"### Hardcoded error strings that could be in Resources.resx (sample)\"\n grep -rn 'Log\\.\\(Error\\|Warning\\)\\|LogError\\|LogWarning\\|LogCodedError\\|LogCodedWarning' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '\"' | grep -v \"Properties.Resources\" | shuf | head -20 || echo \"None found\"\n} > /tmp/gh-aw/agent/scan-results.md\necho \"✅ Codebase scan complete → /tmp/gh-aw/agent/scan-results.md\"\n" + run: "mkdir -p /tmp/gh-aw/agent\n{\n echo \"## Scan Category Seed\"\n CATEGORY_INDEX=$(( RANDOM % 10 ))\n echo \"Selected category index: $CATEGORY_INDEX\"\n\n echo \"\"\n echo \"## Category 0: TODO/FIXME/HACK Comments\"\n echo \"### Sample TODO/FIXME/HACK comments in src/\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true\n\n echo \"\"\n echo \"## Category 1: Files Missing Nullable Enable\"\n echo \"### C# files in src/ without #nullable enable (sample)\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true\n\n echo \"\"\n echo \"## Category 2: Obsolete API Usage\"\n echo \"### Files using [Obsolete] or #pragma warning disable CS0618 (sample)\"\n grep -rn \"\\[Obsolete\\]\\|CS0618\\|CS0612\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 3: Large Files\"\n echo \"### Largest C# source files in src/ (top 20)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' | xargs wc -l 2>/dev/null | sort -rn | head -21 | tail -20\n\n echo \"\"\n echo \"## Category 4: Missing XML Documentation (src/Mono.Android/ only)\"\n echo \"### Public declarations in Mono.Android (shipped product) without XML docs\"\n echo \"### NOTE: Excludes Android.Runtime (plumbing), Java.Interop (bridge), and generated code\"\n grep -rn \"public \" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v \"Designer.cs\" | grep -v \"AssemblyInfo.cs\" | grep -v \"Android.Runtime\" | grep -v \"Java.Interop\" | grep -v \"/obj/\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 5: Code Style Issues\"\n echo \"### Files with leading spaces instead of tabs (sample)\"\n grep -rlP \"^ [^ ]\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v \"Designer.cs\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 6: Test Coverage Gaps\"\n echo \"### Source files in Xamarin.Android.Build.Tasks without corresponding test\"\n for f in $(find src/Xamarin.Android.Build.Tasks -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name '*Test*' ! -name 'Resources.Designer.cs' 2>/dev/null | shuf | head -20); do\n basename=$(basename \"$f\" .cs)\n if ! find tests -name \"${basename}*Test*.cs\" -o -name \"*Test*${basename}*.cs\" 2>/dev/null | grep -q .; then\n echo \" No test found for: $f\"\n fi\n done\n\n echo \"\"\n echo \"## Category 7: Unused Using Directives\"\n echo \"### Files with many using directives (potential cleanup, sample)\"\n for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do\n count=$(grep -c \"^using \" \"$f\" 2>/dev/null || true)\n if [ \"${count:-0}\" -gt 10 ]; then\n echo \" $f: $count using directives\"\n fi\n done\n\n echo \"\"\n echo \"## Category 8: Error Handling\"\n echo \"### Bare catch blocks that may swallow exceptions (sample)\"\n grep -rnP \"catch\\s*\\(Exception\\b\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 9: String Literals in Error Messages\"\n echo \"### Hardcoded error strings that could be in Resources.resx (sample)\"\n grep -rn 'Log\\.\\(Error\\|Warning\\)\\|LogError\\|LogWarning\\|LogCodedError\\|LogCodedWarning' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '\"' | grep -v \"Properties.Resources\" | shuf | head -20 || echo \"None found\"\n} > /tmp/gh-aw/agent/scan-results.md\necho \"✅ Codebase scan complete → /tmp/gh-aw/agent/scan-results.md\"\n" - name: Configure Git credentials env: @@ -403,9 +403,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_4f99e248586472bb_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_63c52d45730f7de1_EOF {"assign_to_agent":{"github-token":"${ANDROID_TEAM_PAT}","max":1,"model":"claude-opus-4.6","target":"*"},"create_issue":{"close_older_issues":true,"expires":168,"labels":["automated","code-quality"],"max":1,"title_prefix":"[fix-finder] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_4f99e248586472bb_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_63c52d45730f7de1_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -624,7 +624,7 @@ jobs: 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 MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e 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.2.19' mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_71e1ca49f89a3338_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_4cf376c3d1425e22_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -668,7 +668,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_71e1ca49f89a3338_EOF + GH_AW_MCP_CONFIG_4cf376c3d1425e22_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: diff --git a/.github/workflows/nightly-fix-finder.md b/.github/workflows/nightly-fix-finder.md index 58a4d1dfe96..4fe63f68ba5 100644 --- a/.github/workflows/nightly-fix-finder.md +++ b/.github/workflows/nightly-fix-finder.md @@ -56,8 +56,7 @@ steps: mkdir -p /tmp/gh-aw/agent { echo "## Scan Category Seed" - echo "Date seed: $(date +%j)" - CATEGORY_INDEX=$(( $(date +%j) % 10 )) + CATEGORY_INDEX=$(( RANDOM % 10 )) echo "Selected category index: $CATEGORY_INDEX" echo "" @@ -65,14 +64,14 @@ steps: echo "### Sample TODO/FIXME/HACK comments in src/" grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo "None found" echo "### Total count" - grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l + grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true echo "" echo "## Category 1: Files Missing Nullable Enable" echo "### C# files in src/ without #nullable enable (sample)" grep -rL '#nullable enable' --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo "None found" echo "### Total count" - grep -rL '#nullable enable' --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l + grep -rL '#nullable enable' --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true echo "" echo "## Category 2: Obsolete API Usage" @@ -109,8 +108,8 @@ steps: echo "## Category 7: Unused Using Directives" echo "### Files with many using directives (potential cleanup, sample)" for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do - count=$(grep -c "^using " "$f" 2>/dev/null || echo 0) - if [ "$count" -gt 10 ]; then + count=$(grep -c "^using " "$f" 2>/dev/null || true) + if [ "${count:-0}" -gt 10 ]; then echo " $f: $count using directives" fi done @@ -139,7 +138,7 @@ Each night, select one scan category, analyze the pre-collected data, find one s ## Current Context - **Repository**: ${{ github.repository }} -- **Run Date**: The date seed is in the pre-computed scan results below +- **Run Date**: Each run picks a random category (0-9) using $RANDOM - **Pre-computed scan results**: `/tmp/gh-aw/agent/scan-results.md` ## Phase 1: Load Scan Results and Select Category From cdb2494e6bd25bbc976dec6802785e4187e2237d Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 14 May 2026 17:16:56 -0500 Subject: [PATCH 11/16] Only scan one random category per run, not all 10 The agent was ignoring the category index and always picking XML docs (Category 4) because it saw data for all categories. Now the bash step uses a case statement to only collect data for the randomly selected category, forcing the agent to work with whatever it gets. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/nightly-fix-finder.lock.yml | 24 +-- .github/workflows/nightly-fix-finder.md | 147 +++++++++--------- 2 files changed, 87 insertions(+), 84 deletions(-) diff --git a/.github/workflows/nightly-fix-finder.lock.yml b/.github/workflows/nightly-fix-finder.lock.yml index d4fd23030b7..957e3891fc8 100644 --- a/.github/workflows/nightly-fix-finder.lock.yml +++ b/.github/workflows/nightly-fix-finder.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"792179d05b32219b4a9d7332001bba9dcef91f1be9d4c6f7680e9494caf1d693","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"0b74de2e11907aa4c0940c55ba8b100e7495b6153f2f2d8e2f30b5c68f376f14","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} # gh-aw-manifest: {"version":1,"secrets":["ANDROID_TEAM_PAT","COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) @@ -186,14 +186,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_d396895ae4ca836e_EOF' + cat << 'GH_AW_PROMPT_204ee20489506f1a_EOF' - GH_AW_PROMPT_d396895ae4ca836e_EOF + GH_AW_PROMPT_204ee20489506f1a_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_d396895ae4ca836e_EOF' + cat << 'GH_AW_PROMPT_204ee20489506f1a_EOF' Tools: create_issue, assign_to_agent, missing_tool, missing_data, noop @@ -225,12 +225,12 @@ jobs: {{/if}} - GH_AW_PROMPT_d396895ae4ca836e_EOF + GH_AW_PROMPT_204ee20489506f1a_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_d396895ae4ca836e_EOF' + cat << 'GH_AW_PROMPT_204ee20489506f1a_EOF' {{#runtime-import .github/workflows/nightly-fix-finder.md}} - GH_AW_PROMPT_d396895ae4ca836e_EOF + GH_AW_PROMPT_204ee20489506f1a_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -352,7 +352,7 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Collect codebase metrics - run: "mkdir -p /tmp/gh-aw/agent\n{\n echo \"## Scan Category Seed\"\n CATEGORY_INDEX=$(( RANDOM % 10 ))\n echo \"Selected category index: $CATEGORY_INDEX\"\n\n echo \"\"\n echo \"## Category 0: TODO/FIXME/HACK Comments\"\n echo \"### Sample TODO/FIXME/HACK comments in src/\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true\n\n echo \"\"\n echo \"## Category 1: Files Missing Nullable Enable\"\n echo \"### C# files in src/ without #nullable enable (sample)\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true\n\n echo \"\"\n echo \"## Category 2: Obsolete API Usage\"\n echo \"### Files using [Obsolete] or #pragma warning disable CS0618 (sample)\"\n grep -rn \"\\[Obsolete\\]\\|CS0618\\|CS0612\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 3: Large Files\"\n echo \"### Largest C# source files in src/ (top 20)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' | xargs wc -l 2>/dev/null | sort -rn | head -21 | tail -20\n\n echo \"\"\n echo \"## Category 4: Missing XML Documentation (src/Mono.Android/ only)\"\n echo \"### Public declarations in Mono.Android (shipped product) without XML docs\"\n echo \"### NOTE: Excludes Android.Runtime (plumbing), Java.Interop (bridge), and generated code\"\n grep -rn \"public \" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v \"Designer.cs\" | grep -v \"AssemblyInfo.cs\" | grep -v \"Android.Runtime\" | grep -v \"Java.Interop\" | grep -v \"/obj/\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 5: Code Style Issues\"\n echo \"### Files with leading spaces instead of tabs (sample)\"\n grep -rlP \"^ [^ ]\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v \"Designer.cs\" | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 6: Test Coverage Gaps\"\n echo \"### Source files in Xamarin.Android.Build.Tasks without corresponding test\"\n for f in $(find src/Xamarin.Android.Build.Tasks -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name '*Test*' ! -name 'Resources.Designer.cs' 2>/dev/null | shuf | head -20); do\n basename=$(basename \"$f\" .cs)\n if ! find tests -name \"${basename}*Test*.cs\" -o -name \"*Test*${basename}*.cs\" 2>/dev/null | grep -q .; then\n echo \" No test found for: $f\"\n fi\n done\n\n echo \"\"\n echo \"## Category 7: Unused Using Directives\"\n echo \"### Files with many using directives (potential cleanup, sample)\"\n for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do\n count=$(grep -c \"^using \" \"$f\" 2>/dev/null || true)\n if [ \"${count:-0}\" -gt 10 ]; then\n echo \" $f: $count using directives\"\n fi\n done\n\n echo \"\"\n echo \"## Category 8: Error Handling\"\n echo \"### Bare catch blocks that may swallow exceptions (sample)\"\n grep -rnP \"catch\\s*\\(Exception\\b\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n\n echo \"\"\n echo \"## Category 9: String Literals in Error Messages\"\n echo \"### Hardcoded error strings that could be in Resources.resx (sample)\"\n grep -rn 'Log\\.\\(Error\\|Warning\\)\\|LogError\\|LogWarning\\|LogCodedError\\|LogCodedWarning' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '\"' | grep -v \"Properties.Resources\" | shuf | head -20 || echo \"None found\"\n} > /tmp/gh-aw/agent/scan-results.md\necho \"✅ Codebase scan complete → /tmp/gh-aw/agent/scan-results.md\"\n" + run: "mkdir -p /tmp/gh-aw/agent\nCATEGORY_INDEX=$(( RANDOM % 10 ))\n{\n echo \"## Selected Category: $CATEGORY_INDEX\"\n echo \"\"\n\n case $CATEGORY_INDEX in\n 0)\n echo \"## Category 0: TODO/FIXME/HACK Comments\"\n echo \"### Sample TODO/FIXME/HACK comments in src/\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true\n ;;\n 1)\n echo \"## Category 1: Files Missing Nullable Enable\"\n echo \"### C# files in src/ without #nullable enable (sample)\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true\n ;;\n 2)\n echo \"## Category 2: Obsolete API Usage\"\n echo \"### Files using [Obsolete] or #pragma warning disable CS0618 (sample)\"\n grep -rn \"\\[Obsolete\\]\\|CS0618\\|CS0612\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n ;;\n 3)\n echo \"## Category 3: Large Files\"\n echo \"### Largest C# source files in src/ (top 20)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' | xargs wc -l 2>/dev/null | sort -rn | head -21 | tail -20\n ;;\n 4)\n echo \"## Category 4: Missing XML Documentation (src/Mono.Android/ only)\"\n echo \"### Public declarations in Mono.Android (shipped product) without XML docs\"\n echo \"### NOTE: Excludes Android.Runtime (plumbing), Java.Interop (bridge), and generated code\"\n grep -rn \"public \" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v \"Designer.cs\" | grep -v \"AssemblyInfo.cs\" | grep -v \"Android.Runtime\" | grep -v \"Java.Interop\" | grep -v \"/obj/\" | shuf | head -20 || echo \"None found\"\n ;;\n 5)\n echo \"## Category 5: Code Style Issues\"\n echo \"### Files with leading spaces instead of tabs (sample)\"\n grep -rlP \"^ [^ ]\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v \"Designer.cs\" | shuf | head -20 || echo \"None found\"\n ;;\n 6)\n echo \"## Category 6: Test Coverage Gaps\"\n echo \"### Source files in Xamarin.Android.Build.Tasks without corresponding test\"\n for f in $(find src/Xamarin.Android.Build.Tasks -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name '*Test*' ! -name 'Resources.Designer.cs' 2>/dev/null | shuf | head -20); do\n basename=$(basename \"$f\" .cs)\n if ! find tests -name \"${basename}*Test*.cs\" -o -name \"*Test*${basename}*.cs\" 2>/dev/null | grep -q .; then\n echo \" No test found for: $f\"\n fi\n done\n ;;\n 7)\n echo \"## Category 7: Unused Using Directives\"\n echo \"### Files with many using directives (potential cleanup, sample)\"\n for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do\n count=$(grep -c \"^using \" \"$f\" 2>/dev/null || true)\n if [ \"${count:-0}\" -gt 10 ]; then\n echo \" $f: $count using directives\"\n fi\n done\n ;;\n 8)\n echo \"## Category 8: Error Handling\"\n echo \"### Bare catch blocks that may swallow exceptions (sample)\"\n grep -rnP \"catch\\s*\\(Exception\\b\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n ;;\n 9)\n echo \"## Category 9: String Literals in Error Messages\"\n echo \"### Hardcoded error strings that could be in Resources.resx (sample)\"\n grep -rn 'Log\\.\\(Error\\|Warning\\)\\|LogError\\|LogWarning\\|LogCodedError\\|LogCodedWarning' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '\"' | grep -v \"Properties.Resources\" | shuf | head -20 || echo \"None found\"\n ;;\n esac\n} > /tmp/gh-aw/agent/scan-results.md\necho \"✅ Category $CATEGORY_INDEX scan complete → /tmp/gh-aw/agent/scan-results.md\"\n" - name: Configure Git credentials env: @@ -403,9 +403,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_63c52d45730f7de1_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_e0fdcd6a13f611e4_EOF {"assign_to_agent":{"github-token":"${ANDROID_TEAM_PAT}","max":1,"model":"claude-opus-4.6","target":"*"},"create_issue":{"close_older_issues":true,"expires":168,"labels":["automated","code-quality"],"max":1,"title_prefix":"[fix-finder] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_63c52d45730f7de1_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_e0fdcd6a13f611e4_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -624,7 +624,7 @@ jobs: 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 MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e 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.2.19' mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_4cf376c3d1425e22_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_cd5ef2e2a3c1ab40_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -668,7 +668,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_4cf376c3d1425e22_EOF + GH_AW_MCP_CONFIG_cd5ef2e2a3c1ab40_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: diff --git a/.github/workflows/nightly-fix-finder.md b/.github/workflows/nightly-fix-finder.md index 4fe63f68ba5..9bc56cf701b 100644 --- a/.github/workflows/nightly-fix-finder.md +++ b/.github/workflows/nightly-fix-finder.md @@ -54,77 +54,80 @@ steps: - name: Collect codebase metrics run: | mkdir -p /tmp/gh-aw/agent + CATEGORY_INDEX=$(( RANDOM % 10 )) { - echo "## Scan Category Seed" - CATEGORY_INDEX=$(( RANDOM % 10 )) - echo "Selected category index: $CATEGORY_INDEX" - - echo "" - echo "## Category 0: TODO/FIXME/HACK Comments" - echo "### Sample TODO/FIXME/HACK comments in src/" - grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo "None found" - echo "### Total count" - grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true - - echo "" - echo "## Category 1: Files Missing Nullable Enable" - echo "### C# files in src/ without #nullable enable (sample)" - grep -rL '#nullable enable' --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo "None found" - echo "### Total count" - grep -rL '#nullable enable' --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true - - echo "" - echo "## Category 2: Obsolete API Usage" - echo "### Files using [Obsolete] or #pragma warning disable CS0618 (sample)" - grep -rn "\[Obsolete\]\|CS0618\|CS0612" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo "None found" - - echo "" - echo "## Category 3: Large Files" - echo "### Largest C# source files in src/ (top 20)" - find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' | xargs wc -l 2>/dev/null | sort -rn | head -21 | tail -20 - + echo "## Selected Category: $CATEGORY_INDEX" echo "" - echo "## Category 4: Missing XML Documentation (src/Mono.Android/ only)" - echo "### Public declarations in Mono.Android (shipped product) without XML docs" - echo "### NOTE: Excludes Android.Runtime (plumbing), Java.Interop (bridge), and generated code" - grep -rn "public " --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v "Designer.cs" | grep -v "AssemblyInfo.cs" | grep -v "Android.Runtime" | grep -v "Java.Interop" | grep -v "/obj/" | shuf | head -20 || echo "None found" - echo "" - echo "## Category 5: Code Style Issues" - echo "### Files with leading spaces instead of tabs (sample)" - grep -rlP "^ [^ ]" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v "Designer.cs" | shuf | head -20 || echo "None found" - - echo "" - echo "## Category 6: Test Coverage Gaps" - echo "### Source files in Xamarin.Android.Build.Tasks without corresponding test" - for f in $(find src/Xamarin.Android.Build.Tasks -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name '*Test*' ! -name 'Resources.Designer.cs' 2>/dev/null | shuf | head -20); do - basename=$(basename "$f" .cs) - if ! find tests -name "${basename}*Test*.cs" -o -name "*Test*${basename}*.cs" 2>/dev/null | grep -q .; then - echo " No test found for: $f" - fi - done - - echo "" - echo "## Category 7: Unused Using Directives" - echo "### Files with many using directives (potential cleanup, sample)" - for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do - count=$(grep -c "^using " "$f" 2>/dev/null || true) - if [ "${count:-0}" -gt 10 ]; then - echo " $f: $count using directives" - fi - done - - echo "" - echo "## Category 8: Error Handling" - echo "### Bare catch blocks that may swallow exceptions (sample)" - grep -rnP "catch\s*\(Exception\b" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo "None found" - - echo "" - echo "## Category 9: String Literals in Error Messages" - echo "### Hardcoded error strings that could be in Resources.resx (sample)" - grep -rn 'Log\.\(Error\|Warning\)\|LogError\|LogWarning\|LogCodedError\|LogCodedWarning' --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '"' | grep -v "Properties.Resources" | shuf | head -20 || echo "None found" + case $CATEGORY_INDEX in + 0) + echo "## Category 0: TODO/FIXME/HACK Comments" + echo "### Sample TODO/FIXME/HACK comments in src/" + grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo "None found" + echo "### Total count" + grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true + ;; + 1) + echo "## Category 1: Files Missing Nullable Enable" + echo "### C# files in src/ without #nullable enable (sample)" + grep -rL '#nullable enable' --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo "None found" + echo "### Total count" + grep -rL '#nullable enable' --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true + ;; + 2) + echo "## Category 2: Obsolete API Usage" + echo "### Files using [Obsolete] or #pragma warning disable CS0618 (sample)" + grep -rn "\[Obsolete\]\|CS0618\|CS0612" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo "None found" + ;; + 3) + echo "## Category 3: Large Files" + echo "### Largest C# source files in src/ (top 20)" + find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' | xargs wc -l 2>/dev/null | sort -rn | head -21 | tail -20 + ;; + 4) + echo "## Category 4: Missing XML Documentation (src/Mono.Android/ only)" + echo "### Public declarations in Mono.Android (shipped product) without XML docs" + echo "### NOTE: Excludes Android.Runtime (plumbing), Java.Interop (bridge), and generated code" + grep -rn "public " --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v "Designer.cs" | grep -v "AssemblyInfo.cs" | grep -v "Android.Runtime" | grep -v "Java.Interop" | grep -v "/obj/" | shuf | head -20 || echo "None found" + ;; + 5) + echo "## Category 5: Code Style Issues" + echo "### Files with leading spaces instead of tabs (sample)" + grep -rlP "^ [^ ]" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v "Designer.cs" | shuf | head -20 || echo "None found" + ;; + 6) + echo "## Category 6: Test Coverage Gaps" + echo "### Source files in Xamarin.Android.Build.Tasks without corresponding test" + for f in $(find src/Xamarin.Android.Build.Tasks -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name '*Test*' ! -name 'Resources.Designer.cs' 2>/dev/null | shuf | head -20); do + basename=$(basename "$f" .cs) + if ! find tests -name "${basename}*Test*.cs" -o -name "*Test*${basename}*.cs" 2>/dev/null | grep -q .; then + echo " No test found for: $f" + fi + done + ;; + 7) + echo "## Category 7: Unused Using Directives" + echo "### Files with many using directives (potential cleanup, sample)" + for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do + count=$(grep -c "^using " "$f" 2>/dev/null || true) + if [ "${count:-0}" -gt 10 ]; then + echo " $f: $count using directives" + fi + done + ;; + 8) + echo "## Category 8: Error Handling" + echo "### Bare catch blocks that may swallow exceptions (sample)" + grep -rnP "catch\s*\(Exception\b" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo "None found" + ;; + 9) + echo "## Category 9: String Literals in Error Messages" + echo "### Hardcoded error strings that could be in Resources.resx (sample)" + grep -rn 'Log\.\(Error\|Warning\)\|LogError\|LogWarning\|LogCodedError\|LogCodedWarning' --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '"' | grep -v "Properties.Resources" | shuf | head -20 || echo "None found" + ;; + esac } > /tmp/gh-aw/agent/scan-results.md - echo "✅ Codebase scan complete → /tmp/gh-aw/agent/scan-results.md" + echo "✅ Category $CATEGORY_INDEX scan complete → /tmp/gh-aw/agent/scan-results.md" --- # Nightly Fix Finder @@ -141,15 +144,15 @@ Each night, select one scan category, analyze the pre-collected data, find one s - **Run Date**: Each run picks a random category (0-9) using $RANDOM - **Pre-computed scan results**: `/tmp/gh-aw/agent/scan-results.md` -## Phase 1: Load Scan Results and Select Category +## Phase 1: Load Scan Results ### 1.1 Read Pre-computed Data -Read `/tmp/gh-aw/agent/scan-results.md` which contains pre-collected metrics for all 10 categories. The category index for today is already computed using the day-of-year as a seed. +Read `/tmp/gh-aw/agent/scan-results.md` which contains pre-collected metrics for **one randomly selected category**. The file header tells you which category was selected. -### 1.2 Determine Today's Category +### 1.2 Identify the Category -The scan results include a `Selected category index` value (0-9). Use that to pick today's focus: +The scan results start with `## Selected Category: N` where N is 0-9. The file ONLY contains data for that one category — you MUST work with whatever category was selected: | Index | Category | Description | |-------|----------|-------------| @@ -164,7 +167,7 @@ The scan results include a `Selected category index` value (0-9). Use that to pi | 8 | Error Handling | Find bare `catch (Exception)` blocks that swallow errors | | 9 | String Literals | Find hardcoded error strings that should be in `Properties.Resources` | -If the selected category has no actionable findings in the scan results, move to the next category (wrapping around) until you find one with data. +If the selected category has no actionable findings in the scan results, call `noop` — do NOT switch to a different category. ## Phase 2: Deep Analysis From 23b863e46d62d83fc8e317eddbd6a41ec8a6aa24 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 14 May 2026 17:19:25 -0500 Subject: [PATCH 12/16] Use -print0/xargs -0 for filename safety in Category 3 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/nightly-fix-finder.lock.yml | 24 +++++++++---------- .github/workflows/nightly-fix-finder.md | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/nightly-fix-finder.lock.yml b/.github/workflows/nightly-fix-finder.lock.yml index 957e3891fc8..b5e928f8699 100644 --- a/.github/workflows/nightly-fix-finder.lock.yml +++ b/.github/workflows/nightly-fix-finder.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"0b74de2e11907aa4c0940c55ba8b100e7495b6153f2f2d8e2f30b5c68f376f14","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"907b8ceaaaeb08edea94f98a95f28a58bf542137ed37a49b0530e0a6705444d8","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} # gh-aw-manifest: {"version":1,"secrets":["ANDROID_TEAM_PAT","COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) @@ -186,14 +186,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_204ee20489506f1a_EOF' + cat << 'GH_AW_PROMPT_fe14f12be075dde7_EOF' - GH_AW_PROMPT_204ee20489506f1a_EOF + GH_AW_PROMPT_fe14f12be075dde7_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_204ee20489506f1a_EOF' + cat << 'GH_AW_PROMPT_fe14f12be075dde7_EOF' Tools: create_issue, assign_to_agent, missing_tool, missing_data, noop @@ -225,12 +225,12 @@ jobs: {{/if}} - GH_AW_PROMPT_204ee20489506f1a_EOF + GH_AW_PROMPT_fe14f12be075dde7_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_204ee20489506f1a_EOF' + cat << 'GH_AW_PROMPT_fe14f12be075dde7_EOF' {{#runtime-import .github/workflows/nightly-fix-finder.md}} - GH_AW_PROMPT_204ee20489506f1a_EOF + GH_AW_PROMPT_fe14f12be075dde7_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -352,7 +352,7 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Collect codebase metrics - run: "mkdir -p /tmp/gh-aw/agent\nCATEGORY_INDEX=$(( RANDOM % 10 ))\n{\n echo \"## Selected Category: $CATEGORY_INDEX\"\n echo \"\"\n\n case $CATEGORY_INDEX in\n 0)\n echo \"## Category 0: TODO/FIXME/HACK Comments\"\n echo \"### Sample TODO/FIXME/HACK comments in src/\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true\n ;;\n 1)\n echo \"## Category 1: Files Missing Nullable Enable\"\n echo \"### C# files in src/ without #nullable enable (sample)\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true\n ;;\n 2)\n echo \"## Category 2: Obsolete API Usage\"\n echo \"### Files using [Obsolete] or #pragma warning disable CS0618 (sample)\"\n grep -rn \"\\[Obsolete\\]\\|CS0618\\|CS0612\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n ;;\n 3)\n echo \"## Category 3: Large Files\"\n echo \"### Largest C# source files in src/ (top 20)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' | xargs wc -l 2>/dev/null | sort -rn | head -21 | tail -20\n ;;\n 4)\n echo \"## Category 4: Missing XML Documentation (src/Mono.Android/ only)\"\n echo \"### Public declarations in Mono.Android (shipped product) without XML docs\"\n echo \"### NOTE: Excludes Android.Runtime (plumbing), Java.Interop (bridge), and generated code\"\n grep -rn \"public \" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v \"Designer.cs\" | grep -v \"AssemblyInfo.cs\" | grep -v \"Android.Runtime\" | grep -v \"Java.Interop\" | grep -v \"/obj/\" | shuf | head -20 || echo \"None found\"\n ;;\n 5)\n echo \"## Category 5: Code Style Issues\"\n echo \"### Files with leading spaces instead of tabs (sample)\"\n grep -rlP \"^ [^ ]\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v \"Designer.cs\" | shuf | head -20 || echo \"None found\"\n ;;\n 6)\n echo \"## Category 6: Test Coverage Gaps\"\n echo \"### Source files in Xamarin.Android.Build.Tasks without corresponding test\"\n for f in $(find src/Xamarin.Android.Build.Tasks -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name '*Test*' ! -name 'Resources.Designer.cs' 2>/dev/null | shuf | head -20); do\n basename=$(basename \"$f\" .cs)\n if ! find tests -name \"${basename}*Test*.cs\" -o -name \"*Test*${basename}*.cs\" 2>/dev/null | grep -q .; then\n echo \" No test found for: $f\"\n fi\n done\n ;;\n 7)\n echo \"## Category 7: Unused Using Directives\"\n echo \"### Files with many using directives (potential cleanup, sample)\"\n for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do\n count=$(grep -c \"^using \" \"$f\" 2>/dev/null || true)\n if [ \"${count:-0}\" -gt 10 ]; then\n echo \" $f: $count using directives\"\n fi\n done\n ;;\n 8)\n echo \"## Category 8: Error Handling\"\n echo \"### Bare catch blocks that may swallow exceptions (sample)\"\n grep -rnP \"catch\\s*\\(Exception\\b\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n ;;\n 9)\n echo \"## Category 9: String Literals in Error Messages\"\n echo \"### Hardcoded error strings that could be in Resources.resx (sample)\"\n grep -rn 'Log\\.\\(Error\\|Warning\\)\\|LogError\\|LogWarning\\|LogCodedError\\|LogCodedWarning' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '\"' | grep -v \"Properties.Resources\" | shuf | head -20 || echo \"None found\"\n ;;\n esac\n} > /tmp/gh-aw/agent/scan-results.md\necho \"✅ Category $CATEGORY_INDEX scan complete → /tmp/gh-aw/agent/scan-results.md\"\n" + run: "mkdir -p /tmp/gh-aw/agent\nCATEGORY_INDEX=$(( RANDOM % 10 ))\n{\n echo \"## Selected Category: $CATEGORY_INDEX\"\n echo \"\"\n\n case $CATEGORY_INDEX in\n 0)\n echo \"## Category 0: TODO/FIXME/HACK Comments\"\n echo \"### Sample TODO/FIXME/HACK comments in src/\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true\n ;;\n 1)\n echo \"## Category 1: Files Missing Nullable Enable\"\n echo \"### C# files in src/ without #nullable enable (sample)\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true\n ;;\n 2)\n echo \"## Category 2: Obsolete API Usage\"\n echo \"### Files using [Obsolete] or #pragma warning disable CS0618 (sample)\"\n grep -rn \"\\[Obsolete\\]\\|CS0618\\|CS0612\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n ;;\n 3)\n echo \"## Category 3: Large Files\"\n echo \"### Largest C# source files in src/ (top 20)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' -print0 | xargs -0 wc -l 2>/dev/null | sort -rn | head -21 | tail -20\n ;;\n 4)\n echo \"## Category 4: Missing XML Documentation (src/Mono.Android/ only)\"\n echo \"### Public declarations in Mono.Android (shipped product) without XML docs\"\n echo \"### NOTE: Excludes Android.Runtime (plumbing), Java.Interop (bridge), and generated code\"\n grep -rn \"public \" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v \"Designer.cs\" | grep -v \"AssemblyInfo.cs\" | grep -v \"Android.Runtime\" | grep -v \"Java.Interop\" | grep -v \"/obj/\" | shuf | head -20 || echo \"None found\"\n ;;\n 5)\n echo \"## Category 5: Code Style Issues\"\n echo \"### Files with leading spaces instead of tabs (sample)\"\n grep -rlP \"^ [^ ]\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v \"Designer.cs\" | shuf | head -20 || echo \"None found\"\n ;;\n 6)\n echo \"## Category 6: Test Coverage Gaps\"\n echo \"### Source files in Xamarin.Android.Build.Tasks without corresponding test\"\n for f in $(find src/Xamarin.Android.Build.Tasks -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name '*Test*' ! -name 'Resources.Designer.cs' 2>/dev/null | shuf | head -20); do\n basename=$(basename \"$f\" .cs)\n if ! find tests -name \"${basename}*Test*.cs\" -o -name \"*Test*${basename}*.cs\" 2>/dev/null | grep -q .; then\n echo \" No test found for: $f\"\n fi\n done\n ;;\n 7)\n echo \"## Category 7: Unused Using Directives\"\n echo \"### Files with many using directives (potential cleanup, sample)\"\n for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do\n count=$(grep -c \"^using \" \"$f\" 2>/dev/null || true)\n if [ \"${count:-0}\" -gt 10 ]; then\n echo \" $f: $count using directives\"\n fi\n done\n ;;\n 8)\n echo \"## Category 8: Error Handling\"\n echo \"### Bare catch blocks that may swallow exceptions (sample)\"\n grep -rnP \"catch\\s*\\(Exception\\b\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n ;;\n 9)\n echo \"## Category 9: String Literals in Error Messages\"\n echo \"### Hardcoded error strings that could be in Resources.resx (sample)\"\n grep -rn 'Log\\.\\(Error\\|Warning\\)\\|LogError\\|LogWarning\\|LogCodedError\\|LogCodedWarning' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '\"' | grep -v \"Properties.Resources\" | shuf | head -20 || echo \"None found\"\n ;;\n esac\n} > /tmp/gh-aw/agent/scan-results.md\necho \"✅ Category $CATEGORY_INDEX scan complete → /tmp/gh-aw/agent/scan-results.md\"\n" - name: Configure Git credentials env: @@ -403,9 +403,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_e0fdcd6a13f611e4_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_62ac7275a18d756e_EOF {"assign_to_agent":{"github-token":"${ANDROID_TEAM_PAT}","max":1,"model":"claude-opus-4.6","target":"*"},"create_issue":{"close_older_issues":true,"expires":168,"labels":["automated","code-quality"],"max":1,"title_prefix":"[fix-finder] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_e0fdcd6a13f611e4_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_62ac7275a18d756e_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -624,7 +624,7 @@ jobs: 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 MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e 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.2.19' mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_cd5ef2e2a3c1ab40_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_67a7e39651d943bb_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -668,7 +668,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_cd5ef2e2a3c1ab40_EOF + GH_AW_MCP_CONFIG_67a7e39651d943bb_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: diff --git a/.github/workflows/nightly-fix-finder.md b/.github/workflows/nightly-fix-finder.md index 9bc56cf701b..e8779878907 100644 --- a/.github/workflows/nightly-fix-finder.md +++ b/.github/workflows/nightly-fix-finder.md @@ -82,7 +82,7 @@ steps: 3) echo "## Category 3: Large Files" echo "### Largest C# source files in src/ (top 20)" - find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' | xargs wc -l 2>/dev/null | sort -rn | head -21 | tail -20 + find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' -print0 | xargs -0 wc -l 2>/dev/null | sort -rn | head -21 | tail -20 ;; 4) echo "## Category 4: Missing XML Documentation (src/Mono.Android/ only)" From 91f9cf871c8a254bbf98892fd7c23dd6cddbc867 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 15 May 2026 12:12:45 -0500 Subject: [PATCH 13/16] Require XA error code docs in reviewer and fix-finder - msbuild-rules.md: Specify that new XA#### codes need a markdown doc at Documentation/docs-mobile/messages/xa####.md and an entry in index.md (was vague 'must have a documentation entry') - nightly-fix-finder.md: Category 9 guidance now instructs the agent to include error code doc requirements in filed issues Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/skills/android-reviewer/references/msbuild-rules.md | 2 +- .github/workflows/nightly-fix-finder.md | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/skills/android-reviewer/references/msbuild-rules.md b/.github/skills/android-reviewer/references/msbuild-rules.md index a2ececcb223..62c9f86b741 100644 --- a/.github/skills/android-reviewer/references/msbuild-rules.md +++ b/.github/skills/android-reviewer/references/msbuild-rules.md @@ -16,7 +16,7 @@ causes broken builds for every .NET Android developer. | **Use `AsyncTask` for background work** | Tasks that need `async`/`await` should extend `AsyncTask` and override `RunTaskAsync()`. It handles `Yield()`, `try`/`finally`, and `Reacquire()` automatically. Use `AsyncTask.Log*` helpers for logging from the background thread — calling `Log.LogMessage` directly can cause IDE hangs. Use full paths on background threads (`Environment.CurrentDirectory` may differ if the task is on another MSBuild node). Leverage the `WhenAll` extension for parallel work over `ITaskItem[]`. | | **Return `!Log.HasLoggedErrors`** | `RunTask()` must return `!Log.HasLoggedErrors`. Do not return `true`/`false` directly — it skips the centralized error-tracking mechanism. | | **Use `Log.LogCoded*` methods** | Errors and warnings must use `Log.LogCodedError("XA####", …)` or `Log.LogCodedWarning("XA####", …)` — never bare `Log.LogError` without a code. Error messages should come from `Properties.Resources`. | -| **XA error codes** | Error codes follow `XA####` (4+ digits). New codes must not collide with existing ones. Check `Properties/Resources.cs.resx` for used codes. Every new code must have a documentation entry and be localized. (Postmortem `#10`) | +| **XA error codes** | Error codes follow `XA####` (4+ digits). New codes must not collide with existing ones. Check `Properties/Resources.cs.resx` for used codes. Every new code must have a corresponding markdown documentation file at `Documentation/docs-mobile/messages/xa####.md` (following the existing format with frontmatter, example messages, issue explanation, and solution), and the code must be added to the table of contents in `Documentation/docs-mobile/messages/index.md`. (Postmortem `#10`) | | **`[Required]` properties** | `[Required]` properties must be non-nullable with a default: `public string Foo { get; set; } = "";` or `public ITaskItem[] Bar { get; set; } = [];`. Non-`[Required]` and `[Output]` properties must be nullable (`string?`, `ITaskItem[]?`). Mark properties `[Required]` when the task crashes without them. (Postmortem `#51`) | | **`UsingTask` for internal tasks** | `` elements for `xa-prep-tasks` and `BootstrapTasks` (internal, not shipped) must use `TaskFactory="TaskHostFactory"` and `Runtime="NET"`. Do NOT add these attributes to shipped task definitions in `Xamarin.Android.Common.targets` or `Microsoft.Android.Sdk/*.targets`. | | **Caching with `RegisterTaskObject`** | Use `BuildEngine4.RegisterTaskObject()` (via the `RegisterTaskObjectAssemblyLocal()` extension method) instead of `static` variables for sharing data between tasks or across builds. Use `as` for casts to avoid `InvalidCastException`. Cache keys should include context that invalidates properly (device target, file path, version). Cache primitive/small values only. | diff --git a/.github/workflows/nightly-fix-finder.md b/.github/workflows/nightly-fix-finder.md index e8779878907..8277a32e25e 100644 --- a/.github/workflows/nightly-fix-finder.md +++ b/.github/workflows/nightly-fix-finder.md @@ -228,6 +228,9 @@ Using the pre-collected sample data for the selected category, pick **one specif #### String Literals (Category 9) - Find hardcoded strings in `LogError`/`LogWarning` calls - The issue should ask to move them to `Properties.Resources` with proper `XA####` error codes +- **Important**: When new `XA####` error codes are created, the issue MUST also instruct to: + 1. Create a markdown doc file at `Documentation/docs-mobile/messages/xa####.md` (following the existing format: frontmatter with title/description/date/f1_keywords, then sections for Example messages, Issue explanation, and Solution) + 2. Add the new code to the table of contents in `Documentation/docs-mobile/messages/index.md` ## Phase 3: Create Issue From 0a7523bed20efd4b631315ab6e51bf8fcc58c6ed Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 15 May 2026 12:22:44 -0500 Subject: [PATCH 14/16] Disable close-older-issues to avoid orphaning active PRs The close-older-issues: true setting was closing issues that already had PRs in progress (e.g. #11365 closed while #11366 was active). The expires: 7d setting already handles stale unclaimed issues. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/nightly-fix-finder.lock.yml | 26 +++++++++---------- .github/workflows/nightly-fix-finder.md | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/nightly-fix-finder.lock.yml b/.github/workflows/nightly-fix-finder.lock.yml index b5e928f8699..0acfc6600da 100644 --- a/.github/workflows/nightly-fix-finder.lock.yml +++ b/.github/workflows/nightly-fix-finder.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"907b8ceaaaeb08edea94f98a95f28a58bf542137ed37a49b0530e0a6705444d8","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"e4b6fa33a4bcd910c21b40abb2bba5dce6d2bc660f491c4e078e76ab94e3674f","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} # gh-aw-manifest: {"version":1,"secrets":["ANDROID_TEAM_PAT","COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) @@ -186,14 +186,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_fe14f12be075dde7_EOF' + cat << 'GH_AW_PROMPT_96b24afe33657626_EOF' - GH_AW_PROMPT_fe14f12be075dde7_EOF + GH_AW_PROMPT_96b24afe33657626_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_fe14f12be075dde7_EOF' + cat << 'GH_AW_PROMPT_96b24afe33657626_EOF' Tools: create_issue, assign_to_agent, missing_tool, missing_data, noop @@ -225,12 +225,12 @@ jobs: {{/if}} - GH_AW_PROMPT_fe14f12be075dde7_EOF + GH_AW_PROMPT_96b24afe33657626_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_fe14f12be075dde7_EOF' + cat << 'GH_AW_PROMPT_96b24afe33657626_EOF' {{#runtime-import .github/workflows/nightly-fix-finder.md}} - GH_AW_PROMPT_fe14f12be075dde7_EOF + GH_AW_PROMPT_96b24afe33657626_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -403,9 +403,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_62ac7275a18d756e_EOF - {"assign_to_agent":{"github-token":"${ANDROID_TEAM_PAT}","max":1,"model":"claude-opus-4.6","target":"*"},"create_issue":{"close_older_issues":true,"expires":168,"labels":["automated","code-quality"],"max":1,"title_prefix":"[fix-finder] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_62ac7275a18d756e_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_340893cd627924f3_EOF + {"assign_to_agent":{"github-token":"${ANDROID_TEAM_PAT}","max":1,"model":"claude-opus-4.6","target":"*"},"create_issue":{"close_older_issues":false,"expires":168,"labels":["automated","code-quality"],"max":1,"title_prefix":"[fix-finder] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} + GH_AW_SAFE_OUTPUTS_CONFIG_340893cd627924f3_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -624,7 +624,7 @@ jobs: 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 MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e 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.2.19' mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_67a7e39651d943bb_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_d27b9d72c1223451_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -668,7 +668,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_67a7e39651d943bb_EOF + GH_AW_MCP_CONFIG_d27b9d72c1223451_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: @@ -1277,7 +1277,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.vsblob.vsassets.io,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.nuget.org,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,builds.dotnet.microsoft.com,ci.dot.net,codeload.github.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,dc.services.visualstudio.com,dist.nuget.org,docs.github.com,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,objects.githubusercontent.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,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkgs.dev.azure.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.microsoft.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"assign_to_agent\":{\"github-token\":\"${{ secrets.ANDROID_TEAM_PAT }}\",\"max\":1,\"model\":\"claude-opus-4.6\",\"target\":\"*\"},\"create_issue\":{\"close_older_issues\":true,\"expires\":168,\"labels\":[\"automated\",\"code-quality\"],\"max\":1,\"title_prefix\":\"[fix-finder] \"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"assign_to_agent\":{\"github-token\":\"${{ secrets.ANDROID_TEAM_PAT }}\",\"max\":1,\"model\":\"claude-opus-4.6\",\"target\":\"*\"},\"create_issue\":{\"close_older_issues\":false,\"expires\":168,\"labels\":[\"automated\",\"code-quality\"],\"max\":1,\"title_prefix\":\"[fix-finder] \"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" GH_AW_ASSIGN_TO_AGENT_TOKEN: ${{ secrets.ANDROID_TEAM_PAT }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/nightly-fix-finder.md b/.github/workflows/nightly-fix-finder.md index 8277a32e25e..83ebc2b4df6 100644 --- a/.github/workflows/nightly-fix-finder.md +++ b/.github/workflows/nightly-fix-finder.md @@ -42,7 +42,7 @@ safe-outputs: title-prefix: "[fix-finder] " labels: [automated, code-quality] expires: 7d - close-older-issues: true + close-older-issues: false assign-to-agent: model: "claude-opus-4.6" target: "*" From 306551c1651de4545cc8fcddde7191e911639a3c Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 15 May 2026 14:01:00 -0500 Subject: [PATCH 15/16] Remove Test Coverage Gaps category from fix-finder The auto-generated test suggestions were not useful. Removed Category 6 and renumbered remaining categories (now 0-8, RANDOM % 9). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/nightly-fix-finder.lock.yml | 24 ++++++------ .github/workflows/nightly-fix-finder.md | 39 ++++++------------- 2 files changed, 24 insertions(+), 39 deletions(-) diff --git a/.github/workflows/nightly-fix-finder.lock.yml b/.github/workflows/nightly-fix-finder.lock.yml index 0acfc6600da..7033da5fd03 100644 --- a/.github/workflows/nightly-fix-finder.lock.yml +++ b/.github/workflows/nightly-fix-finder.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"e4b6fa33a4bcd910c21b40abb2bba5dce6d2bc660f491c4e078e76ab94e3674f","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"21c3f678f88a54c5d7eaaa8634f5a1ac9926f63f48ec9b84ff3f0b4f829d45a0","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} # gh-aw-manifest: {"version":1,"secrets":["ANDROID_TEAM_PAT","COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) @@ -186,14 +186,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_96b24afe33657626_EOF' + cat << 'GH_AW_PROMPT_0b28397fb296ac80_EOF' - GH_AW_PROMPT_96b24afe33657626_EOF + GH_AW_PROMPT_0b28397fb296ac80_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_96b24afe33657626_EOF' + cat << 'GH_AW_PROMPT_0b28397fb296ac80_EOF' Tools: create_issue, assign_to_agent, missing_tool, missing_data, noop @@ -225,12 +225,12 @@ jobs: {{/if}} - GH_AW_PROMPT_96b24afe33657626_EOF + GH_AW_PROMPT_0b28397fb296ac80_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_96b24afe33657626_EOF' + cat << 'GH_AW_PROMPT_0b28397fb296ac80_EOF' {{#runtime-import .github/workflows/nightly-fix-finder.md}} - GH_AW_PROMPT_96b24afe33657626_EOF + GH_AW_PROMPT_0b28397fb296ac80_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -352,7 +352,7 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Collect codebase metrics - run: "mkdir -p /tmp/gh-aw/agent\nCATEGORY_INDEX=$(( RANDOM % 10 ))\n{\n echo \"## Selected Category: $CATEGORY_INDEX\"\n echo \"\"\n\n case $CATEGORY_INDEX in\n 0)\n echo \"## Category 0: TODO/FIXME/HACK Comments\"\n echo \"### Sample TODO/FIXME/HACK comments in src/\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true\n ;;\n 1)\n echo \"## Category 1: Files Missing Nullable Enable\"\n echo \"### C# files in src/ without #nullable enable (sample)\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true\n ;;\n 2)\n echo \"## Category 2: Obsolete API Usage\"\n echo \"### Files using [Obsolete] or #pragma warning disable CS0618 (sample)\"\n grep -rn \"\\[Obsolete\\]\\|CS0618\\|CS0612\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n ;;\n 3)\n echo \"## Category 3: Large Files\"\n echo \"### Largest C# source files in src/ (top 20)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' -print0 | xargs -0 wc -l 2>/dev/null | sort -rn | head -21 | tail -20\n ;;\n 4)\n echo \"## Category 4: Missing XML Documentation (src/Mono.Android/ only)\"\n echo \"### Public declarations in Mono.Android (shipped product) without XML docs\"\n echo \"### NOTE: Excludes Android.Runtime (plumbing), Java.Interop (bridge), and generated code\"\n grep -rn \"public \" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v \"Designer.cs\" | grep -v \"AssemblyInfo.cs\" | grep -v \"Android.Runtime\" | grep -v \"Java.Interop\" | grep -v \"/obj/\" | shuf | head -20 || echo \"None found\"\n ;;\n 5)\n echo \"## Category 5: Code Style Issues\"\n echo \"### Files with leading spaces instead of tabs (sample)\"\n grep -rlP \"^ [^ ]\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v \"Designer.cs\" | shuf | head -20 || echo \"None found\"\n ;;\n 6)\n echo \"## Category 6: Test Coverage Gaps\"\n echo \"### Source files in Xamarin.Android.Build.Tasks without corresponding test\"\n for f in $(find src/Xamarin.Android.Build.Tasks -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name '*Test*' ! -name 'Resources.Designer.cs' 2>/dev/null | shuf | head -20); do\n basename=$(basename \"$f\" .cs)\n if ! find tests -name \"${basename}*Test*.cs\" -o -name \"*Test*${basename}*.cs\" 2>/dev/null | grep -q .; then\n echo \" No test found for: $f\"\n fi\n done\n ;;\n 7)\n echo \"## Category 7: Unused Using Directives\"\n echo \"### Files with many using directives (potential cleanup, sample)\"\n for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do\n count=$(grep -c \"^using \" \"$f\" 2>/dev/null || true)\n if [ \"${count:-0}\" -gt 10 ]; then\n echo \" $f: $count using directives\"\n fi\n done\n ;;\n 8)\n echo \"## Category 8: Error Handling\"\n echo \"### Bare catch blocks that may swallow exceptions (sample)\"\n grep -rnP \"catch\\s*\\(Exception\\b\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n ;;\n 9)\n echo \"## Category 9: String Literals in Error Messages\"\n echo \"### Hardcoded error strings that could be in Resources.resx (sample)\"\n grep -rn 'Log\\.\\(Error\\|Warning\\)\\|LogError\\|LogWarning\\|LogCodedError\\|LogCodedWarning' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '\"' | grep -v \"Properties.Resources\" | shuf | head -20 || echo \"None found\"\n ;;\n esac\n} > /tmp/gh-aw/agent/scan-results.md\necho \"✅ Category $CATEGORY_INDEX scan complete → /tmp/gh-aw/agent/scan-results.md\"\n" + run: "mkdir -p /tmp/gh-aw/agent\nCATEGORY_INDEX=$(( RANDOM % 9 ))\n{\n echo \"## Selected Category: $CATEGORY_INDEX\"\n echo \"\"\n\n case $CATEGORY_INDEX in\n 0)\n echo \"## Category 0: TODO/FIXME/HACK Comments\"\n echo \"### Sample TODO/FIXME/HACK comments in src/\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true\n ;;\n 1)\n echo \"## Category 1: Files Missing Nullable Enable\"\n echo \"### C# files in src/ without #nullable enable (sample)\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true\n ;;\n 2)\n echo \"## Category 2: Obsolete API Usage\"\n echo \"### Files using [Obsolete] or #pragma warning disable CS0618 (sample)\"\n grep -rn \"\\[Obsolete\\]\\|CS0618\\|CS0612\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n ;;\n 3)\n echo \"## Category 3: Large Files\"\n echo \"### Largest C# source files in src/ (top 20)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' -print0 | xargs -0 wc -l 2>/dev/null | sort -rn | head -21 | tail -20\n ;;\n 4)\n echo \"## Category 4: Missing XML Documentation (src/Mono.Android/ only)\"\n echo \"### Public declarations in Mono.Android (shipped product) without XML docs\"\n echo \"### NOTE: Excludes Android.Runtime (plumbing), Java.Interop (bridge), and generated code\"\n grep -rn \"public \" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v \"Designer.cs\" | grep -v \"AssemblyInfo.cs\" | grep -v \"Android.Runtime\" | grep -v \"Java.Interop\" | grep -v \"/obj/\" | shuf | head -20 || echo \"None found\"\n ;;\n 5)\n echo \"## Category 5: Code Style Issues\"\n echo \"### Files with leading spaces instead of tabs (sample)\"\n grep -rlP \"^ [^ ]\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v \"Designer.cs\" | shuf | head -20 || echo \"None found\"\n ;;\n 6)\n echo \"## Category 6: Unused Using Directives\"\n echo \"### Files with many using directives (potential cleanup, sample)\"\n for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do\n count=$(grep -c \"^using \" \"$f\" 2>/dev/null || true)\n if [ \"${count:-0}\" -gt 10 ]; then\n echo \" $f: $count using directives\"\n fi\n done\n ;;\n 7)\n echo \"## Category 7: Error Handling\"\n echo \"### Bare catch blocks that may swallow exceptions (sample)\"\n grep -rnP \"catch\\s*\\(Exception\\b\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n ;;\n 8)\n echo \"## Category 8: String Literals in Error Messages\"\n echo \"### Hardcoded error strings that could be in Resources.resx (sample)\"\n grep -rn 'Log\\.\\(Error\\|Warning\\)\\|LogError\\|LogWarning\\|LogCodedError\\|LogCodedWarning' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '\"' | grep -v \"Properties.Resources\" | shuf | head -20 || echo \"None found\"\n ;;\n esac\n} > /tmp/gh-aw/agent/scan-results.md\necho \"✅ Category $CATEGORY_INDEX scan complete → /tmp/gh-aw/agent/scan-results.md\"\n" - name: Configure Git credentials env: @@ -403,9 +403,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_340893cd627924f3_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_f8d969fd126d1092_EOF {"assign_to_agent":{"github-token":"${ANDROID_TEAM_PAT}","max":1,"model":"claude-opus-4.6","target":"*"},"create_issue":{"close_older_issues":false,"expires":168,"labels":["automated","code-quality"],"max":1,"title_prefix":"[fix-finder] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_340893cd627924f3_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_f8d969fd126d1092_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -624,7 +624,7 @@ jobs: 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 MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e 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.2.19' mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_d27b9d72c1223451_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_9397d8b73cafee5c_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -668,7 +668,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_d27b9d72c1223451_EOF + GH_AW_MCP_CONFIG_9397d8b73cafee5c_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: diff --git a/.github/workflows/nightly-fix-finder.md b/.github/workflows/nightly-fix-finder.md index 83ebc2b4df6..999fcba7fec 100644 --- a/.github/workflows/nightly-fix-finder.md +++ b/.github/workflows/nightly-fix-finder.md @@ -54,7 +54,7 @@ steps: - name: Collect codebase metrics run: | mkdir -p /tmp/gh-aw/agent - CATEGORY_INDEX=$(( RANDOM % 10 )) + CATEGORY_INDEX=$(( RANDOM % 9 )) { echo "## Selected Category: $CATEGORY_INDEX" echo "" @@ -96,17 +96,7 @@ steps: grep -rlP "^ [^ ]" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v "Designer.cs" | shuf | head -20 || echo "None found" ;; 6) - echo "## Category 6: Test Coverage Gaps" - echo "### Source files in Xamarin.Android.Build.Tasks without corresponding test" - for f in $(find src/Xamarin.Android.Build.Tasks -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name '*Test*' ! -name 'Resources.Designer.cs' 2>/dev/null | shuf | head -20); do - basename=$(basename "$f" .cs) - if ! find tests -name "${basename}*Test*.cs" -o -name "*Test*${basename}*.cs" 2>/dev/null | grep -q .; then - echo " No test found for: $f" - fi - done - ;; - 7) - echo "## Category 7: Unused Using Directives" + echo "## Category 6: Unused Using Directives" echo "### Files with many using directives (potential cleanup, sample)" for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do count=$(grep -c "^using " "$f" 2>/dev/null || true) @@ -115,13 +105,13 @@ steps: fi done ;; - 8) - echo "## Category 8: Error Handling" + 7) + echo "## Category 7: Error Handling" echo "### Bare catch blocks that may swallow exceptions (sample)" grep -rnP "catch\s*\(Exception\b" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo "None found" ;; - 9) - echo "## Category 9: String Literals in Error Messages" + 8) + echo "## Category 8: String Literals in Error Messages" echo "### Hardcoded error strings that could be in Resources.resx (sample)" grep -rn 'Log\.\(Error\|Warning\)\|LogError\|LogWarning\|LogCodedError\|LogCodedWarning' --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '"' | grep -v "Properties.Resources" | shuf | head -20 || echo "None found" ;; @@ -162,10 +152,9 @@ The scan results start with `## Selected Category: N` where N is 0-9. The file O | 3 | Large Files | Find oversized C# files (>800 lines) that should be split | | 4 | Missing XML Documentation | Find public APIs without XML doc comments | | 5 | Code Style Issues | Find formatting inconsistencies (spaces vs tabs, Mono style violations) | -| 6 | Test Coverage Gaps | Find source files without corresponding test files | -| 7 | Unused Using Directives | Find files with excessive using directives that could be cleaned up | -| 8 | Error Handling | Find bare `catch (Exception)` blocks that swallow errors | -| 9 | String Literals | Find hardcoded error strings that should be in `Properties.Resources` | +| 6 | Unused Using Directives | Find files with excessive using directives that could be cleaned up | +| 7 | Error Handling | Find bare `catch (Exception)` blocks that swallow errors | +| 8 | String Literals | Find hardcoded error strings that should be in `Properties.Resources` | If the selected category has no actionable findings in the scan results, call `noop` — do NOT switch to a different category. @@ -213,19 +202,15 @@ Using the pre-collected sample data for the selected category, pick **one specif - Reference `.editorconfig` patterns: space before `(` and `[` - The issue should list specific files and line ranges -#### Test Coverage Gaps (Category 6) -- Find an MSBuild task or utility class with no test coverage -- The issue should suggest specific test scenarios - -#### Unused Using Directives (Category 7) +#### Unused Using Directives (Category 6) - Pick files with >10 using directives that likely have unused ones - The issue should ask to clean up unnecessary usings -#### Error Handling (Category 8) +#### Error Handling (Category 7) - Find `catch (Exception)` blocks that don't log or rethrow - The issue should suggest proper error handling patterns -#### String Literals (Category 9) +#### String Literals (Category 8) - Find hardcoded strings in `LogError`/`LogWarning` calls - The issue should ask to move them to `Properties.Resources` with proper `XA####` error codes - **Important**: When new `XA####` error codes are created, the issue MUST also instruct to: From 5826d1886942ee7318c2284117935c24b53bab95 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 15 May 2026 15:42:36 -0500 Subject: [PATCH 16/16] Replace Code Style category with General Mistakes Instead of finding whitespace issues (not useful), pick random source files and look for real bugs, logic errors, and code smells. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/nightly-fix-finder.lock.yml | 24 +++++++++---------- .github/workflows/nightly-fix-finder.md | 18 +++++++------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/.github/workflows/nightly-fix-finder.lock.yml b/.github/workflows/nightly-fix-finder.lock.yml index 7033da5fd03..bcf7133201a 100644 --- a/.github/workflows/nightly-fix-finder.lock.yml +++ b/.github/workflows/nightly-fix-finder.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"21c3f678f88a54c5d7eaaa8634f5a1ac9926f63f48ec9b84ff3f0b4f829d45a0","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"e5b7209e55b782aad58ee79eea7e4494a85ee02e20dccf04a7d5243b7de34feb","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot","agent_model":"claude-opus-4.6"} # gh-aw-manifest: {"version":1,"secrets":["ANDROID_TEAM_PAT","COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) @@ -186,14 +186,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_0b28397fb296ac80_EOF' + cat << 'GH_AW_PROMPT_652ea396a8ae88f7_EOF' - GH_AW_PROMPT_0b28397fb296ac80_EOF + GH_AW_PROMPT_652ea396a8ae88f7_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_0b28397fb296ac80_EOF' + cat << 'GH_AW_PROMPT_652ea396a8ae88f7_EOF' Tools: create_issue, assign_to_agent, missing_tool, missing_data, noop @@ -225,12 +225,12 @@ jobs: {{/if}} - GH_AW_PROMPT_0b28397fb296ac80_EOF + GH_AW_PROMPT_652ea396a8ae88f7_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_0b28397fb296ac80_EOF' + cat << 'GH_AW_PROMPT_652ea396a8ae88f7_EOF' {{#runtime-import .github/workflows/nightly-fix-finder.md}} - GH_AW_PROMPT_0b28397fb296ac80_EOF + GH_AW_PROMPT_652ea396a8ae88f7_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -352,7 +352,7 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Collect codebase metrics - run: "mkdir -p /tmp/gh-aw/agent\nCATEGORY_INDEX=$(( RANDOM % 9 ))\n{\n echo \"## Selected Category: $CATEGORY_INDEX\"\n echo \"\"\n\n case $CATEGORY_INDEX in\n 0)\n echo \"## Category 0: TODO/FIXME/HACK Comments\"\n echo \"### Sample TODO/FIXME/HACK comments in src/\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true\n ;;\n 1)\n echo \"## Category 1: Files Missing Nullable Enable\"\n echo \"### C# files in src/ without #nullable enable (sample)\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true\n ;;\n 2)\n echo \"## Category 2: Obsolete API Usage\"\n echo \"### Files using [Obsolete] or #pragma warning disable CS0618 (sample)\"\n grep -rn \"\\[Obsolete\\]\\|CS0618\\|CS0612\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n ;;\n 3)\n echo \"## Category 3: Large Files\"\n echo \"### Largest C# source files in src/ (top 20)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' -print0 | xargs -0 wc -l 2>/dev/null | sort -rn | head -21 | tail -20\n ;;\n 4)\n echo \"## Category 4: Missing XML Documentation (src/Mono.Android/ only)\"\n echo \"### Public declarations in Mono.Android (shipped product) without XML docs\"\n echo \"### NOTE: Excludes Android.Runtime (plumbing), Java.Interop (bridge), and generated code\"\n grep -rn \"public \" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v \"Designer.cs\" | grep -v \"AssemblyInfo.cs\" | grep -v \"Android.Runtime\" | grep -v \"Java.Interop\" | grep -v \"/obj/\" | shuf | head -20 || echo \"None found\"\n ;;\n 5)\n echo \"## Category 5: Code Style Issues\"\n echo \"### Files with leading spaces instead of tabs (sample)\"\n grep -rlP \"^ [^ ]\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v \"Designer.cs\" | shuf | head -20 || echo \"None found\"\n ;;\n 6)\n echo \"## Category 6: Unused Using Directives\"\n echo \"### Files with many using directives (potential cleanup, sample)\"\n for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do\n count=$(grep -c \"^using \" \"$f\" 2>/dev/null || true)\n if [ \"${count:-0}\" -gt 10 ]; then\n echo \" $f: $count using directives\"\n fi\n done\n ;;\n 7)\n echo \"## Category 7: Error Handling\"\n echo \"### Bare catch blocks that may swallow exceptions (sample)\"\n grep -rnP \"catch\\s*\\(Exception\\b\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n ;;\n 8)\n echo \"## Category 8: String Literals in Error Messages\"\n echo \"### Hardcoded error strings that could be in Resources.resx (sample)\"\n grep -rn 'Log\\.\\(Error\\|Warning\\)\\|LogError\\|LogWarning\\|LogCodedError\\|LogCodedWarning' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '\"' | grep -v \"Properties.Resources\" | shuf | head -20 || echo \"None found\"\n ;;\n esac\n} > /tmp/gh-aw/agent/scan-results.md\necho \"✅ Category $CATEGORY_INDEX scan complete → /tmp/gh-aw/agent/scan-results.md\"\n" + run: "mkdir -p /tmp/gh-aw/agent\nCATEGORY_INDEX=$(( RANDOM % 9 ))\n{\n echo \"## Selected Category: $CATEGORY_INDEX\"\n echo \"\"\n\n case $CATEGORY_INDEX in\n 0)\n echo \"## Category 0: TODO/FIXME/HACK Comments\"\n echo \"### Sample TODO/FIXME/HACK comments in src/\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rn \"TODO\\|FIXME\\|HACK\\|XXX\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true\n ;;\n 1)\n echo \"## Category 1: Files Missing Nullable Enable\"\n echo \"### C# files in src/ without #nullable enable (sample)\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n echo \"### Total count\"\n grep -rL '#nullable enable' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | wc -l || true\n ;;\n 2)\n echo \"## Category 2: Obsolete API Usage\"\n echo \"### Files using [Obsolete] or #pragma warning disable CS0618 (sample)\"\n grep -rn \"\\[Obsolete\\]\\|CS0618\\|CS0612\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n ;;\n 3)\n echo \"## Category 3: Large Files\"\n echo \"### Largest C# source files in src/ (top 20)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' -print0 | xargs -0 wc -l 2>/dev/null | sort -rn | head -21 | tail -20\n ;;\n 4)\n echo \"## Category 4: Missing XML Documentation (src/Mono.Android/ only)\"\n echo \"### Public declarations in Mono.Android (shipped product) without XML docs\"\n echo \"### NOTE: Excludes Android.Runtime (plumbing), Java.Interop (bridge), and generated code\"\n grep -rn \"public \" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v \"Designer.cs\" | grep -v \"AssemblyInfo.cs\" | grep -v \"Android.Runtime\" | grep -v \"Java.Interop\" | grep -v \"/obj/\" | shuf | head -20 || echo \"None found\"\n ;;\n 5)\n echo \"## Category 5: General Mistakes\"\n echo \"### Random C# source files in src/ for general review (sample)\"\n find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' ! -name 'AssemblyInfo.cs' 2>/dev/null | shuf | head -5\n ;;\n 6)\n echo \"## Category 6: Unused Using Directives\"\n echo \"### Files with many using directives (potential cleanup, sample)\"\n for f in $(find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' 2>/dev/null | shuf | head -30); do\n count=$(grep -c \"^using \" \"$f\" 2>/dev/null || true)\n if [ \"${count:-0}\" -gt 10 ]; then\n echo \" $f: $count using directives\"\n fi\n done\n ;;\n 7)\n echo \"## Category 7: Error Handling\"\n echo \"### Bare catch blocks that may swallow exceptions (sample)\"\n grep -rnP \"catch\\s*\\(Exception\\b\" --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | shuf | head -20 || echo \"None found\"\n ;;\n 8)\n echo \"## Category 8: String Literals in Error Messages\"\n echo \"### Hardcoded error strings that could be in Resources.resx (sample)\"\n grep -rn 'Log\\.\\(Error\\|Warning\\)\\|LogError\\|LogWarning\\|LogCodedError\\|LogCodedWarning' --include=\"*.cs\" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep '\"' | grep -v \"Properties.Resources\" | shuf | head -20 || echo \"None found\"\n ;;\n esac\n} > /tmp/gh-aw/agent/scan-results.md\necho \"✅ Category $CATEGORY_INDEX scan complete → /tmp/gh-aw/agent/scan-results.md\"\n" - name: Configure Git credentials env: @@ -403,9 +403,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_f8d969fd126d1092_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << GH_AW_SAFE_OUTPUTS_CONFIG_d2e55a1f37318840_EOF {"assign_to_agent":{"github-token":"${ANDROID_TEAM_PAT}","max":1,"model":"claude-opus-4.6","target":"*"},"create_issue":{"close_older_issues":false,"expires":168,"labels":["automated","code-quality"],"max":1,"title_prefix":"[fix-finder] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_f8d969fd126d1092_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_d2e55a1f37318840_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -624,7 +624,7 @@ jobs: 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 MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -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_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e 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.2.19' mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_9397d8b73cafee5c_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_931e9fd7ec08739a_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -668,7 +668,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_9397d8b73cafee5c_EOF + GH_AW_MCP_CONFIG_931e9fd7ec08739a_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: diff --git a/.github/workflows/nightly-fix-finder.md b/.github/workflows/nightly-fix-finder.md index 999fcba7fec..7956eb1d0f0 100644 --- a/.github/workflows/nightly-fix-finder.md +++ b/.github/workflows/nightly-fix-finder.md @@ -91,9 +91,9 @@ steps: grep -rn "public " --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/Mono.Android/ 2>/dev/null | grep -v "Designer.cs" | grep -v "AssemblyInfo.cs" | grep -v "Android.Runtime" | grep -v "Java.Interop" | grep -v "/obj/" | shuf | head -20 || echo "None found" ;; 5) - echo "## Category 5: Code Style Issues" - echo "### Files with leading spaces instead of tabs (sample)" - grep -rlP "^ [^ ]" --include="*.cs" --exclude-dir=obj --exclude-dir=bin src/ 2>/dev/null | grep -v "Designer.cs" | shuf | head -20 || echo "None found" + echo "## Category 5: General Mistakes" + echo "### Random C# source files in src/ for general review (sample)" + find src -name '*.cs' -type f ! -path '*/obj/*' ! -path '*/bin/*' ! -name 'Designer.cs' ! -name 'AssemblyInfo.cs' 2>/dev/null | shuf | head -5 ;; 6) echo "## Category 6: Unused Using Directives" @@ -151,7 +151,7 @@ The scan results start with `## Selected Category: N` where N is 0-9. The file O | 2 | Obsolete API Usage | Find uses of `[Obsolete]` members that should be updated | | 3 | Large Files | Find oversized C# files (>800 lines) that should be split | | 4 | Missing XML Documentation | Find public APIs without XML doc comments | -| 5 | Code Style Issues | Find formatting inconsistencies (spaces vs tabs, Mono style violations) | +| 5 | General Mistakes | Read random source files and find real bugs, logic errors, or code smells | | 6 | Unused Using Directives | Find files with excessive using directives that could be cleaned up | | 7 | Error Handling | Find bare `catch (Exception)` blocks that swallow errors | | 8 | String Literals | Find hardcoded error strings that should be in `Properties.Resources` | @@ -197,10 +197,12 @@ Using the pre-collected sample data for the selected category, pick **one specif - Do NOT file issues for XML docs in build tasks, tools, or test code — those are internal - The issue should provide example doc comments for the specific APIs -#### Code Style Issues (Category 5) -- Focus on spaces-vs-tabs since the repo uses tabs -- Reference `.editorconfig` patterns: space before `(` and `[` -- The issue should list specific files and line ranges +#### General Mistakes (Category 5) +- Read the randomly selected source files thoroughly +- Look for real bugs: logic errors, off-by-one, null dereferences, race conditions, resource leaks +- Look for code smells: dead code, unreachable branches, copy-paste errors, incorrect exception handling +- Do NOT file issues about formatting, whitespace, or style — those are not actionable +- The issue should describe the actual bug or problem with concrete evidence #### Unused Using Directives (Category 6) - Pick files with >10 using directives that likely have unused ones