diff --git a/.github/workflows/agentics-maintenance.yml b/.github/workflows/agentics-maintenance.yml index 48a2a894..e897fe9c 100644 --- a/.github/workflows/agentics-maintenance.yml +++ b/.github/workflows/agentics-maintenance.yml @@ -42,9 +42,9 @@ on: description: 'Optional maintenance operation to run' required: false type: choice - default: '' + default: 'none' options: - - '' + - 'none' - 'disable' - 'enable' - 'update' @@ -54,7 +54,7 @@ permissions: {} jobs: close-expired-entities: - if: ${{ !github.event.repository.fork && (github.event_name != 'workflow_dispatch' || github.event.inputs.operation == '') }} + if: ${{ !github.event.repository.fork && (github.event_name != 'workflow_dispatch' || github.event.inputs.operation == 'none') }} runs-on: ubuntu-slim permissions: discussions: write @@ -94,7 +94,7 @@ jobs: await main(); run_operation: - if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.operation != '' && !github.event.repository.fork }} + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.operation != 'none' && !github.event.repository.fork }} runs-on: ubuntu-slim permissions: actions: write diff --git a/.github/workflows/downstream-users.md b/.github/workflows/downstream-users.md deleted file mode 100644 index c444d584..00000000 --- a/.github/workflows/downstream-users.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -inlined-imports: true -name: "Internal: Downstream Users" -description: "Track downstream public repo usage of elastic/ai-github-actions and update data" -imports: - - gh-aw-fragments/elastic-tools.md - - gh-aw-fragments/runtime-setup.md - - gh-aw-fragments/formatting.md - - gh-aw-fragments/rigor.md - - gh-aw-fragments/mcp-pagination.md - - gh-aw-fragments/workflow-edit-guardrails.md - - gh-aw-fragments/messages-footer.md - - gh-aw-fragments/safe-output-create-pr.md -engine: - id: copilot - model: gpt-5.3-codex -on: - schedule: - - cron: "weekly on Monday around 10:00" - workflow_dispatch: - roles: [admin, maintainer, write] - bots: - - "github-actions[bot]" -concurrency: - group: ${{ github.workflow }}-downstream-users - cancel-in-progress: true -permissions: - contents: read - issues: read - pull-requests: read -tools: - github: - toolsets: [repos, issues, pull_requests, search] - bash: true - web-fetch: -network: - allowed: - - defaults - - github - - go - - node - - python - - ruby -strict: false -safe-outputs: - max-patch-size: 10240 - create-pull-request: - draft: false - noop: -timeout-minutes: 90 ---- - -# Downstream Users Tracking - -Maintain a canonical list of public downstream repositories using elastic/ai-github-actions, including which workflows they consume. - -## Context - -- **Repository**: ${{ github.repository }} -- **Output file**: `data/downstream-users.json` - -## Constraints - -- **CAN**: Read files, search GitHub, modify files locally, run commands, create a pull request. -- **CANNOT**: Directly push to the repository — use `create_pull_request`. -- **Only one PR per run.** -- Do not modify files under `.github/workflows/`. -- Keep the JSON output stable and sorted to minimize diff noise. - -## Step 1: Gather Context - -1. Read the current `data/downstream-users.json` file (if it exists). - -## Step 2: Discover Downstream Usage - -1. Use the `public-code-search` MCP server to find public repositories that reference this repo in workflow files. - - Search for `uses: elastic/ai-github-actions` in `*.yml` and `*.yaml` files. - - Example query input for `search_code`: - - `patterns`: `uses:\\s*elastic/ai-github-actions/` - - `include_globs`: `**/*.yml`, `**/*.yaml` - - Exclude `elastic/ai-github-actions` itself. - -1. For each unique repo + path pair returned: - - Fetch the workflow file using `github-get_file_contents`. - - Extract every `uses: elastic/ai-github-actions/...` line. - - Normalize each entry by removing the leading `elastic/ai-github-actions/` and any `@version` suffix. - -## Step 3: Build the Data File - -Write `data/downstream-users.json` with this structure: - -````markdown -```json -{ - "generated_at": "", - "source": { - "query": "", - "notes": "" - }, - "repos": [ - { - "repo": "owner/repo", - "workflows": ["workflows/mention-in-issue/rwxp", "..."] - } - ] -} -``` -```` - -Guidelines: -- Sort `repos` by `repo`. -- Sort each `workflows` list alphabetically. -- Use UTC timestamps with a `Z` suffix. - -## Step 4: Create the PR - -1. If the file is unchanged, call `noop` with: `Downstream users list already up to date.` -2. Otherwise, commit the updated JSON and call `create_pull_request`. - - Title: `"[downstream] Update downstream users list"` - - Body: - - Summary of repo count and workflow count - - The search query used - - Any exclusions (self repo, archived/forks if excluded) - diff --git a/.github/workflows/gh-aw-bug-hunter.lock.yml b/.github/workflows/gh-aw-bug-hunter.lock.yml index f2d5641f..d311d90d 100644 --- a/.github/workflows/gh-aw-bug-hunter.lock.yml +++ b/.github/workflows/gh-aw-bug-hunter.lock.yml @@ -40,7 +40,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"e5ac0affd3d3aeb5bcc7e9f7d2e40606cd6df3fc3d30ff59c21856bb9c327d22"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"a2d93fa7f0564c5bb591ed99410ae77a281e75f1b1ad516779d2a9ad262650e1"} name: "Bug Hunter" "on": @@ -402,7 +402,7 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' - Find a single reproducible, user-impacting bug in the repository that can be covered by a minimal failing test. + Find a single reproducible, user-impacting bug in the repository that can be covered by a minimal failing test. Not a number field accepting "ABC", but a real and impactful bug. **The bar is high: you must actually reproduce the bug before filing.** Most runs should end with `noop` — that means the codebase is healthy. diff --git a/.github/workflows/gh-aw-bug-hunter.md b/.github/workflows/gh-aw-bug-hunter.md index c4713600..04f5a6e7 100644 --- a/.github/workflows/gh-aw-bug-hunter.md +++ b/.github/workflows/gh-aw-bug-hunter.md @@ -88,7 +88,7 @@ steps: run: eval "$SETUP_COMMANDS" --- -Find a single reproducible, user-impacting bug in the repository that can be covered by a minimal failing test. +Find a single reproducible, user-impacting bug in the repository that can be covered by a minimal failing test. Not a number field accepting "ABC", but a real and impactful bug. **The bar is high: you must actually reproduce the bug before filing.** Most runs should end with `noop` — that means the codebase is healthy. diff --git a/.github/workflows/gh-aw-code-duplication-detector.lock.yml b/.github/workflows/gh-aw-code-duplication-detector.lock.yml index 0ffcc65c..9d22f6a3 100644 --- a/.github/workflows/gh-aw-code-duplication-detector.lock.yml +++ b/.github/workflows/gh-aw-code-duplication-detector.lock.yml @@ -25,6 +25,7 @@ # # Resolved workflow manifest: # Imports: +# - gh-aw-fragments/code-quality-audit.md # - gh-aw-fragments/elastic-tools.md # - gh-aw-fragments/formatting.md # - gh-aw-fragments/mcp-pagination.md @@ -39,7 +40,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"484fa62f5169d31748cdbeb2c3647a70a241876e36bc334235fddb9fb7cf8c38"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"2dc67edf4fece4caf2fb75c65ed9ed29a98e31849dde837182a665d3433fac86"} name: "Code Duplication Detector" "on": @@ -80,6 +81,11 @@ name: "Code Duplication Detector" description: Shell commands to run before the agent starts (dependency install, build, etc.) required: false type: string + severity-threshold: + default: medium + description: Minimum severity to include in the report. 'high' = only duplications causing active maintenance problems. 'medium' (default) = also include clear consolidation opportunities. 'low' = also include minor near-duplicates. + required: false + type: string title-prefix: default: "[refactor]" description: Title prefix for created issues (e.g. '[refactor]') @@ -171,6 +177,7 @@ jobs: env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_EXPR_08E89BCD: ${{ inputs.severity-threshold }} GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} GH_AW_EXPR_F67C4209: ${{ inputs.file-globs }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} @@ -410,6 +417,55 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + Analyze the codebase for quality issues and file a structured report when concrete, actionable findings exist. + + **The bar is high: only report issues backed by specific code evidence.** Most runs should end with `noop` — that means the code is in good shape for the dimension being audited. Filing nothing is a success when there is nothing worth filing. + + ### Severity Threshold: `__GH_AW_EXPR_08E89BCD__` + + Only include findings at or above the configured severity. Severity labels and meanings are defined by the importing workflow; this fragment uses the importing workflow's `__GH_AW_EXPR_08E89BCD__` semantics. + + ### Evidence Standard + + Every finding must include **all** of the following. Findings missing any element must be dropped: + + 1. **Location** — File path(s) and precise location context (line numbers when available or another unambiguous locator required by the importing workflow). + 2. **Evidence** — The specific code or configuration that exhibits the issue. + 3. **What is wrong** — A clear, concrete explanation of the problem. Not "this could be better" but "this does X when it should do Y" or "this violates [specific standard/guideline]." + 4. **Why it matters** — Concrete impact: who is affected, what breaks, what degrades, or what standard is violated. Reference the specific standard, guideline, or documentation (e.g., WCAG 2.1 SC 4.1.2, React docs on exhaustive-deps, framework migration guide). + 5. **Suggested fix** — A concrete code change or approach, not a vague recommendation. + + ### Verification Pass (Required) + + After gathering findings from sub-agents, verify each one yourself: + + 1. Read the file at the cited path and confirm the line numbers are accurate. + 2. Confirm the code snippet matches what is actually in the file. + 3. Confirm the issue is real — not a false positive from misunderstanding the code's intent. + 4. Confirm the suggested fix would not break existing behavior. + 5. Drop any finding where verification fails. + + ### Quality Gate — When to Noop + + Call `noop` if any of these are true: + - No findings survive the verification pass. + - All findings are below the severity threshold. + - All findings are already tracked by open issues. + - All findings are subjective style preferences rather than concrete quality issues. + - You cannot provide specific file paths and line numbers for any finding. + + ### Consolidation Rules + + - Group related findings (e.g., the same anti-pattern in multiple files) into a single numbered section. + - Prefer fewer, denser issues over frequent thin issues. + - If a pattern appears in many files, do a completeness pass: search the repo for all occurrences and list them, so maintainers can fix the whole family at once. + + ### Output Contract + + Follow the importing workflow's issue title/body template. This shared fragment defines quality gates and evidence requirements only; per-workflow report schemas remain source-of-truth for final output format. + GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' Analyze source code to identify semantic function clusters, misplaced functions, and duplicate implementations that warrant refactoring. @@ -519,6 +575,7 @@ jobs: env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_INPUTS_MODEL: ${{ inputs.model }} + GH_AW_EXPR_08E89BCD: ${{ inputs.severity-threshold }} GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} GH_AW_EXPR_F67C4209: ${{ inputs.file-globs }} @@ -533,6 +590,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_08E89BCD: ${{ inputs.severity-threshold }} GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} GH_AW_EXPR_F67C4209: ${{ inputs.file-globs }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} @@ -557,6 +615,7 @@ jobs: return await substitutePlaceholders({ file: process.env.GH_AW_PROMPT, substitutions: { + GH_AW_EXPR_08E89BCD: process.env.GH_AW_EXPR_08E89BCD, GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, GH_AW_EXPR_F67C4209: process.env.GH_AW_EXPR_F67C4209, GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, diff --git a/.github/workflows/gh-aw-code-duplication-detector.md b/.github/workflows/gh-aw-code-duplication-detector.md index b91154f4..93d5ba9d 100644 --- a/.github/workflows/gh-aw-code-duplication-detector.md +++ b/.github/workflows/gh-aw-code-duplication-detector.md @@ -14,6 +14,7 @@ imports: - gh-aw-fragments/pick-three-keep-many.md - gh-aw-fragments/scheduled-audit.md - gh-aw-fragments/network-ecosystems.md + - gh-aw-fragments/code-quality-audit.md engine: id: copilot model: ${{ inputs.model }} @@ -55,6 +56,11 @@ on: type: string required: false default: "" + severity-threshold: + description: "Minimum severity to include in the report. 'high' = only duplications causing active maintenance problems. 'medium' (default) = also include clear consolidation opportunities. 'low' = also include minor near-duplicates." + type: string + required: false + default: "medium" title-prefix: description: "Title prefix for created issues (e.g. '[refactor]')" type: string diff --git a/.github/workflows/gh-aw-code-quality-audit.lock.yml b/.github/workflows/gh-aw-code-quality-audit.lock.yml new file mode 100644 index 00000000..6108eb54 --- /dev/null +++ b/.github/workflows/gh-aw-code-quality-audit.lock.yml @@ -0,0 +1,1554 @@ +# +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw. 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/ +# +# Analyze code for quality issues — anti-patterns, accessibility violations, performance problems, best-practices deviations — and file a structured report +# +# Resolved workflow manifest: +# Imports: +# - gh-aw-fragments/code-quality-audit.md +# - gh-aw-fragments/elastic-tools.md +# - gh-aw-fragments/ensure-full-history.md +# - gh-aw-fragments/formatting.md +# - gh-aw-fragments/mcp-pagination.md +# - gh-aw-fragments/messages-footer.md +# - gh-aw-fragments/network-ecosystems.md +# - gh-aw-fragments/pick-three-keep-many.md +# - gh-aw-fragments/previous-findings.md +# - gh-aw-fragments/rigor.md +# - gh-aw-fragments/runtime-setup.md +# - gh-aw-fragments/safe-output-create-issue.md +# - gh-aw-fragments/scheduled-audit.md +# +# inlined-imports: true +# +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"aa075d90c9f7cdafcb0419d391208d8d1f88de8d54136c0f0fab418e32489506"} + +name: "Code Quality Audit" +"on": + workflow_call: + inputs: + additional-instructions: + description: Domain-specific audit criteria — what to look for, what to skip, and how to evaluate findings. This is the core of the audit and should define the categories, severity standards, and evidence expectations for the specific quality dimension being audited. + required: true + type: string + allowed-bot-users: + default: github-actions[bot] + description: Allowlisted bot actor usernames (comma-separated) + required: false + type: string + messages-footer: + default: "" + description: Footer appended to all agent comments and reviews + required: false + type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string + setup-commands: + default: "" + description: Shell commands to run before the agent starts (dependency install, build, etc.) + required: false + type: string + severity-threshold: + default: medium + description: Minimum severity to include in the report. 'high' = only report issues with clear user impact or correctness problems. 'medium' (default) = also include issues that degrade quality or maintainability. 'low' = also include minor deviations from best practices. + required: false + type: string + title-prefix: + description: Title prefix for created issues (e.g. '[react-accessibility]') + required: true + type: string + outputs: + created_issue_number: + description: Number of the first created issue + value: ${{ jobs.safe_outputs.outputs.created_issue_number }} + created_issue_url: + description: URL of the first created issue + value: ${{ jobs.safe_outputs.outputs.created_issue_url }} + secrets: + COPILOT_GITHUB_TOKEN: + required: true + +permissions: {} + +concurrency: + cancel-in-progress: true + group: ${{ github.workflow }}-code-quality-audit + +run-name: "Code Quality Audit" + +jobs: + activation: + needs: pre_activation + if: needs.pre_activation.outputs.activated == 'true' + runs-on: ubuntu-slim + permissions: + contents: read + outputs: + comment_id: "" + comment_repo: "" + model: ${{ steps.generate_aw_info.outputs.model }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@956f874e40e831c08a8b01ec76f5d49ae3fe8387 # v0.53.6 + with: + destination: /opt/gh-aw/actions + - 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: "${{ inputs.model }}" + GH_AW_INFO_VERSION: "" + GH_AW_INFO_AGENT_VERSION: "0.0.421" + GH_AW_INFO_WORKFLOW_NAME: "Code Quality Audit" + GH_AW_INFO_EXPERIMENTAL: "false" + GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" + GH_AW_INFO_STAGED: "false" + GH_AW_INFO_ALLOWED_DOMAINS: '["agents-md-generator.fastmcp.app","artifacts.elastic.co","clojure","cloud.elastic.co","containers","dart","defaults","dotnet","ela.st","elastic.co","elastic.dev","elastic.github.io","elixir","fonts","github","github-actions","go","haskell","java","kotlin","linux-distros","node","node-cdns","perl","php","playwright","public-code-search.fastmcp.app","python","ruby","rust","scala","swift","terraform","www.elastic.co","zig"]' + GH_AW_INFO_FIREWALL_ENABLED: "true" + GH_AW_INFO_AWF_VERSION: "v0.23.0" + GH_AW_INFO_AWMG_VERSION: "" + GH_AW_INFO_FIREWALL_TYPE: "squid" + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { main } = require('/opt/gh-aw/actions/generate_aw_info.cjs'); + await main(core, context); + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Checkout .github and .agents folders + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: | + .github + .agents + sparse-checkout-cone-mode: true + fetch-depth: 1 + persist-credentials: false + - name: Check workflow file timestamps + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_WORKFLOW_FILE: "gh-aw-code-quality-audit.lock.yml" + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/check_workflow_timestamp_api.cjs'); + await main(); + - name: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_EXPR_08E89BCD: ${{ inputs.severity-threshold }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_BF503D80: ${{ inputs.title-prefix }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_INPUTS_MODEL: ${{ inputs.model }} + run: | + bash /opt/gh-aw/actions/create_prompt_first.sh + { + cat << 'GH_AW_PROMPT_EOF' + + GH_AW_PROMPT_EOF + cat "/opt/gh-aw/prompts/xpia.md" + cat "/opt/gh-aw/prompts/temp_folder_prompt.md" + cat "/opt/gh-aw/prompts/markdown.md" + cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" + cat << 'GH_AW_PROMPT_EOF' + + Tools: create_issue, 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_EOF + cat << 'GH_AW_PROMPT_EOF' + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + ## MCP Servers + + - **`search_code`** — grep-style search across public GitHub repositories. Use for finding usage patterns in upstream libraries, reference implementations, or examples in open-source projects. This searches *public GitHub repos*, not the local codebase — if available you can use `grep` and file reading for local code. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + Repository conventions are pre-fetched to `/tmp/agents.md`. Read this file early in your task to understand the codebase's conventions, guidelines, and patterns. If the file doesn't exist, continue without it. When spawning sub-agents, include the contents of `/tmp/agents.md` in each sub-agent's prompt (or tell the sub-agent to read the file directly). + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + ## Formatting Guidelines + + - Lead with the most important information — your first sentence should be the key takeaway + - Be concise and actionable — no filler or praise + - Use `
` and `` tags for long sections to keep responses scannable + - Wrap branch names and @-references in backticks to avoid pinging users + - Include code snippets with file paths and line numbers when referencing the codebase + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + ## Rigor + + **Silence is better than noise. A false positive wastes a human's time and erodes trust in every future report.** + + - If you claim something is missing or broken, show the exact evidence in the code — file path, line number, and what you observed. + - If a conclusion depends on assumptions you haven't confirmed, do not assert it. Verify first; if you cannot verify, do not report. + - "I don't know" is better than a wrong answer. `noop` is better than a speculative finding. + - It's worth the time to verify now versus guessing and forcing someone else to verify later. + - Before submitting any output, re-read it as a skeptical reviewer. Ask: "Would a senior engineer on this team find this useful, or would they close it immediately?" If the answer is "close," call `noop` instead. + - Only report findings you would confidently defend in a code review. If you feel the need to hedge with "might," "could," or "possibly," the finding is not ready to file. + - Be thorough, spend the time to investigate and verify. There is no rush. Do your best work. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + ## MCP Pagination + + MCP tool responses have a **25,000 token limit**. When responses exceed this limit, the call fails and you must retry with pagination — wasting turns and tokens. Use proactive pagination to stay under the limit. + + ### Recommended `perPage` Values + + - **5-10**: For detailed items (PR diffs, files with patches, issues with comments) + - **20-30**: For medium-detail lists (commits, review comments, issue lists) + - **50-100**: For simple list operations (branches, labels, tags) + + ### Pagination Pattern + + When you need all results from a paginated API: + + 1. Fetch the first page with a conservative `perPage` value + 2. Process the results before fetching the next page + 3. Continue fetching pages until you receive fewer results than `perPage` (indicating the last page) + + ### Error Recovery + + If you see an error like: + - `MCP tool response exceeds maximum allowed tokens (25000)` + - `Response too large for tool [tool_name]` + + Retry the same call with a smaller `perPage` value (halve it). + + ### Tips + + - **Start small**: It's better to make multiple small requests than one that fails + - **Fetch incrementally**: Get an overview first, then details for specific items + - **Use filters**: Combine `perPage` with state, label, or date filters to reduce result size + - **Process as you go**: Don't accumulate all pages before acting — process each batch immediately + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + ## Message Footer + + A footer is automatically appended to all comments and reviews. Do not add your own footer or sign-off — the runtime handles this. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + ## create-issue Limitations + + - **Title**: Max 128 characters. Sanitized (special characters escaped). + - **Labels**: Max 10 labels per issue. Each label max 64 characters. Labels containing only `-` are rejected. + - **Assignees**: Max 5 assignees per issue. + - **Body**: No strict character limit beyond GitHub's API limit (~65,536 characters), but fields over 16,000 tokens are written to a file reference instead of inlined. + - **Bot triggers**: References like `fixes #123` or `closes #456` in the body are neutralized to prevent unintended issue closures. + - **Mentions**: `@mentions` in the body are neutralized (backticked). + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + ## Previous Findings + + Before filing a new issue, check `/tmp/previous-findings.json` for issues this agent has already filed. + + - Run `cat /tmp/previous-findings.json` to read the list of previously filed issue numbers and titles. + - If your finding closely matches an open or recently-closed issue in that list, call `noop` instead of filing a duplicate. + - Only file a new issue when the finding is genuinely distinct from all previous findings. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + ### Pick Three, Keep Many + + Parallelize your work using sub-agents. Spawn multiple sub-agents, each approaching the task from a different angle — e.g., different focus areas, different heuristics, or different parts of the codebase. Each sub-agent works independently and should return its own list of findings. + + **How to spawn sub-agents:** Call `runSubagent` with the `agentType` and `model` specified by the workflow instructions below (defaulting to `agentType: "general-purpose"` and `model: "__GH_AW_INPUTS_MODEL__"` if none are specified). Sub-agents cannot see your conversation history, the other sub-agents' results, or any context you have gathered so far. Each prompt must be **fully self-contained** — include everything the sub-agent needs: + + - The full task description and objective (restate it, don't summarize) + - All repository context, conventions, and constraints you've gathered (e.g., from `/tmp/agents.md`) + - Any relevant data the sub-agent needs to do its job (diffs, file contents, existing threads) + - The quality criteria and output format you expect + - The specific angle that distinguishes this sub-agent from the others + + Err on the side of providing too much context rather than too little. A well-informed sub-agent with a 10,000-token prompt will produce far better results than one that has to rediscover the codebase from scratch. + + **Wait for all sub-agents to complete.** Do not proceed until every sub-agent has returned its result. + + **Merge and deduplicate findings** across all sub-agents: + 1. If multiple sub-agents flagged the same issue, keep the version with the strongest evidence and clearest explanation. + 2. If a finding is unique to one sub-agent, include it only if it passes the quality gate on its own merits — a finding flagged by only one sub-agent deserves extra scrutiny. + 3. Drop any finding that does not meet the verification criteria. + + **Filter aggressively for quality.** Your job as the parent agent is to be the quality gate. Sub-agents cast a wide net; you decide what's worth keeping. For each surviving finding, verify it yourself — check that file paths exist, line numbers are accurate, the problem is real, and the finding is actionable. Discard anything vague, speculative, or already addressed. If no findings survive filtering, call `noop`. + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + You run on a schedule to investigate the repository and file an issue when something needs attention. Your specific assignment is described in the **Report Assignment** section below. + + ## Constraints + + This workflow is for detection and reporting only. You can read files, search code, run commands, and read PR/issue details — but your only output is either a single issue or a noop. + + ## Process + + Follow these steps in order. + + ### Step 1: Gather Context + + 1. Read `/tmp/agents.md` for the repository's coding guidelines and conventions (skip if missing). + 2. Follow the data gathering instructions in the **Report Assignment** section. + + ### Step 2: Analyze + + Follow the analysis instructions in the **Report Assignment** section to determine whether an issue should be filed. The Report Assignment defines: + - What data to gather and how + - What to look for + - What constitutes a finding worth reporting + - What to skip or ignore + + ### Step 3: Self-Review (Quality Gate) + + Before filing anything, critically evaluate every finding against these criteria: + + 1. **Evidence is concrete** — you can point to exact file paths, line numbers, commit SHAs, or command outputs. No "I believe" or "it seems." + 2. **Finding is actionable** — a maintainer reading the issue can act on it without re-investigating from scratch. + 3. **Finding is not already tracked** — you checked open issues and recent PRs for duplicates. + 4. **Finding is worth a human's time** — the issue is material enough that a maintainer would thank you for filing it, not close it as noise. + + If zero findings pass all four criteria, call `noop` with a brief reason and stop. **Noop is the expected outcome most days.** Filing nothing is a success when there is nothing worth filing. + + ### Step 4: Report + + If there are findings that pass the quality gate, call `create_issue` with a structured report. Use the issue format specified in the Report Assignment if one is provided, otherwise use this default format: + + **Issue title:** Brief summary of findings + + **Issue body:** + + > ## Findings + > + > ### 1. [Brief description] + > + > **Evidence:** [Links, references, or data supporting the finding] + > **Action needed:** [What should be done] + > + > ## Suggested Actions + > + > - [ ] [Actionable checkbox for each finding] + + **Guidelines:** + - Group related findings together + - Be specific about what needs to happen + - Include links and references where possible + - Make suggested actions concrete enough to act on without re-investigating + - If a finding is ambiguous, it does not pass the quality gate — drop it + + **Report Assignment:** + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + Analyze the codebase for quality issues and file a structured report when concrete, actionable findings exist. + + **The bar is high: only report issues backed by specific code evidence.** Most runs should end with `noop` — that means the code is in good shape for the dimension being audited. Filing nothing is a success when there is nothing worth filing. + + ### Severity Threshold: `__GH_AW_EXPR_08E89BCD__` + + Only include findings at or above the configured severity. Severity labels and meanings are defined by the importing workflow; this fragment uses the importing workflow's `__GH_AW_EXPR_08E89BCD__` semantics. + + ### Evidence Standard + + Every finding must include **all** of the following. Findings missing any element must be dropped: + + 1. **Location** — File path(s) and precise location context (line numbers when available or another unambiguous locator required by the importing workflow). + 2. **Evidence** — The specific code or configuration that exhibits the issue. + 3. **What is wrong** — A clear, concrete explanation of the problem. Not "this could be better" but "this does X when it should do Y" or "this violates [specific standard/guideline]." + 4. **Why it matters** — Concrete impact: who is affected, what breaks, what degrades, or what standard is violated. Reference the specific standard, guideline, or documentation (e.g., WCAG 2.1 SC 4.1.2, React docs on exhaustive-deps, framework migration guide). + 5. **Suggested fix** — A concrete code change or approach, not a vague recommendation. + + ### Verification Pass (Required) + + After gathering findings from sub-agents, verify each one yourself: + + 1. Read the file at the cited path and confirm the line numbers are accurate. + 2. Confirm the code snippet matches what is actually in the file. + 3. Confirm the issue is real — not a false positive from misunderstanding the code's intent. + 4. Confirm the suggested fix would not break existing behavior. + 5. Drop any finding where verification fails. + + ### Quality Gate — When to Noop + + Call `noop` if any of these are true: + - No findings survive the verification pass. + - All findings are below the severity threshold. + - All findings are already tracked by open issues. + - All findings are subjective style preferences rather than concrete quality issues. + - You cannot provide specific file paths and line numbers for any finding. + + ### Consolidation Rules + + - Group related findings (e.g., the same anti-pattern in multiple files) into a single numbered section. + - Prefer fewer, denser issues over frequent thin issues. + - If a pattern appears in many files, do a completeness pass: search the repo for all occurrences and list them, so maintainers can fix the whole family at once. + + ### Output Contract + + Follow the importing workflow's issue title/body template. This shared fragment defines quality gates and evidence requirements only; per-workflow report schemas remain source-of-truth for final output format. + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + ### Data Gathering + + 1. Understand the project: + - Read `README.md`, `CONTRIBUTING.md`, `DEVELOPING.md`, and any docs directory. + - Read `package.json`, `go.mod`, `pyproject.toml`, or equivalent to identify the tech stack and versions. + - Skim the directory structure to understand the codebase layout. + + 2. Use the **Pick Three, Keep Many** pattern for the audit: + - Spawn 3 `general-purpose` sub-agents, each auditing from a different angle as defined in the **Audit Criteria** section below. + - Each sub-agent prompt must include: the full audit criteria, the tech stack info, relevant file paths, and the severity threshold. + - Each sub-agent should return all findings that meet the severity threshold, with specific file paths, line numbers, and code snippets. + - Wait for all sub-agents to complete, then merge and deduplicate. + + 3. Check for duplicates: + - Read `/tmp/previous-findings.json` for issues already filed by this agent. + - Search open issues: `repo:{owner}/{repo} is:issue is:open in:title "__GH_AW_EXPR_BF503D80__"`. + - Drop any finding that closely matches an existing open issue. + + ### Labeling + + - If a label matching the title prefix (without brackets) exists (check with `github-get_label`), include it in the `create_issue` call; otherwise, rely on the `__GH_AW_EXPR_BF503D80__` title prefix only. + + ## Audit Criteria + + __GH_AW_EXPR_49B959F1__ + + GH_AW_PROMPT_EOF + } > "$GH_AW_PROMPT" + - name: Interpolate variables and render templates + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_INPUTS_MODEL: ${{ inputs.model }} + GH_AW_EXPR_08E89BCD: ${{ inputs.severity-threshold }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_BF503D80: ${{ inputs.title-prefix }} + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_08E89BCD: ${{ inputs.severity-threshold }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_BF503D80: ${{ inputs.title-prefix }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_INPUTS_MODEL: ${{ inputs.model }} + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + + const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_EXPR_08E89BCD: process.env.GH_AW_EXPR_08E89BCD, + GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, + GH_AW_EXPR_BF503D80: process.env.GH_AW_EXPR_BF503D80, + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, + GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, + GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, + GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, + GH_AW_INPUTS_MODEL: process.env.GH_AW_INPUTS_MODEL, + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED + } + }); + - name: Validate prompt placeholders + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/validate_prompt_placeholders.sh + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/print_prompt_summary.sh + - name: Upload activation artifact + if: success() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 + with: + name: activation + path: | + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/aw-prompts/prompt.txt + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + issues: read + pull-requests: read + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + GH_AW_SAFE_OUTPUTS: /opt/gh-aw/safeoutputs/outputs.jsonl + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json + GH_AW_WORKFLOW_ID_SANITIZED: ghawcodequalityaudit + outputs: + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }} + detection_success: ${{ steps.detection_conclusion.outputs.success }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + inference_access_error: ${{ steps.detect-inference-error.outputs.inference_access_error || 'false' }} + model: ${{ needs.activation.outputs.model }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@956f874e40e831c08a8b01ec76f5d49ae3fe8387 # v0.53.6 + with: + destination: /opt/gh-aw/actions + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Create gh-aw temp directory + run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh + - if: hashFiles('go.mod') != '' + name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 + with: + cache: true + go-version-file: go.mod + - if: hashFiles('.python-version') != '' + name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version-file: .python-version + - if: hashFiles('.node-version') != '' + name: Setup Node.js (.node-version) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .node-version + - if: hashFiles('.node-version') == '' && hashFiles('.nvmrc') != '' + name: Setup Node.js (.nvmrc) + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 + with: + node-version-file: .nvmrc + - if: hashFiles('.ruby-version') != '' + name: Setup Ruby + uses: ruby/setup-ruby@19a43a6a2428d455dbd1b85344698725179c9d8c # v1 + with: + bundler-cache: true + ruby-version: .ruby-version + - id: setup-uv + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Setup uv + uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + - env: + UV_PATH: ${{ steps.setup-uv.outputs.uv-path }} + WORKSPACE: ${{ github.workspace }} + if: hashFiles('pyproject.toml', 'uv.lock') != '' + name: Expose uv in workspace + run: | + set -euo pipefail + install_dir="$WORKSPACE/.gh-aw-tools/bin" + mkdir -p "$install_dir" + cp "$UV_PATH" "$install_dir/uv" + chmod +x "$install_dir/uv" + echo "$install_dir" >> "$GITHUB_PATH" + shell: bash + - name: Configure Copilot CLI settings + run: "set -euo pipefail\nmkdir -p ~/.copilot\nCONFIG=\"$HOME/.copilot/config.json\"\nif [ -f \"$CONFIG\" ]; then\n jq '. + {\"chat.customAgentInSubagent.enabled\": true}' \"$CONFIG\" > \"$CONFIG.tmp\" && mv \"$CONFIG.tmp\" \"$CONFIG\"\nelse\n echo '{\"chat.customAgentInSubagent.enabled\":true}' > \"$CONFIG\"\nfi\n" + shell: bash + - env: + GITHUB_REPOSITORY: ${{ github.repository }} + name: Fetch repository conventions + run: "set -euo pipefail\nif [ -f \"AGENTS.md\" ]; then\n cp AGENTS.md /tmp/agents.md\n echo \"Repository conventions copied from AGENTS.md to /tmp/agents.md\"\nelse\n OWNER=\"${GITHUB_REPOSITORY%/*}\"\n REPO=\"${GITHUB_REPOSITORY#*/}\"\n summary=$(curl -sf --max-time 15 -X POST https://agents-md-generator.fastmcp.app/mcp \\\n -H \"Content-Type: application/json\" \\\n -H \"Accept: application/json, text/event-stream\" \\\n -d \"{\\\"jsonrpc\\\":\\\"2.0\\\",\\\"id\\\":1,\\\"method\\\":\\\"tools/call\\\",\\\"params\\\":{\\\"name\\\":\\\"generate_agents_md\\\",\\\"arguments\\\":{\\\"owner\\\":\\\"${OWNER}\\\",\\\"repo\\\":\\\"${REPO}\\\"}}}\" \\\n | sed 's/^data: //' \\\n | jq -r '.result.structuredContent.summary // empty' 2>/dev/null) || true\n if [ -n \"$summary\" ]; then\n echo \"$summary\" > /tmp/agents.md\n echo \"Repository conventions written to /tmp/agents.md\"\n else\n echo \"::warning::Could not fetch repository conventions; continuing without them\"\n fi\nfi" + shell: bash + - env: + GITHUB_TOKEN: ${{ github.token }} + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + name: Ensure full history + run: "if git rev-parse --is-shallow-repository | grep -q true; then\n SERVER_URL_STRIPPED=\"${SERVER_URL#https://}\"\n git remote set-url origin \"https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git\"\n git fetch --unshallow --quiet\nfi" + - env: + GH_TOKEN: ${{ github.token }} + TITLE_PREFIX: ${{ inputs.title-prefix }} + name: List previous findings + run: "set -euo pipefail\ngh issue list \\\n --repo \"$GITHUB_REPOSITORY\" \\\n --search \"in:title \\\"$TITLE_PREFIX\\\"\" \\\n --state all \\\n --limit 100 \\\n --json number,title,state \\\n > /tmp/previous-findings.json || { echo \"::warning::Failed to fetch previous findings — dedup will be skipped\"; echo \"[]\" > /tmp/previous-findings.json; }" + - env: + SEVERITY_THRESHOLD: ${{ inputs.severity-threshold }} + name: Validate severity threshold + run: "case \"$SEVERITY_THRESHOLD\" in\n high|medium|low) ;;\n *)\n echo \"Invalid severity-threshold: '$SEVERITY_THRESHOLD'. Expected one of: high, medium, low.\"\n exit 1\n ;;\nesac\n" + - env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + if: ${{ inputs.setup-commands != '' }} + name: Repo-specific setup + run: eval "$SETUP_COMMANDS" + + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + 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@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Install GitHub Copilot CLI + run: /opt/gh-aw/actions/install_copilot_cli.sh 0.0.421 + - name: Install awf binary + run: bash /opt/gh-aw/actions/install_awf_binary.sh v0.23.0 + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + with: + script: | + const determineAutomaticLockdown = require('/opt/gh-aw/actions/determine_automatic_lockdown.cjs'); + await determineAutomaticLockdown(github, context, core); + - name: Download container images + run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/gh-aw-firewall/agent:0.23.0 ghcr.io/github/gh-aw-firewall/api-proxy:0.23.0 ghcr.io/github/gh-aw-firewall/squid:0.23.0 ghcr.io/github/gh-aw-mcpg:v0.1.8 ghcr.io/github/github-mcp-server:v0.31.0 node:lts-alpine + - name: Write Safe Outputs Config + run: | + mkdir -p /opt/gh-aw/safeoutputs + mkdir -p /tmp/gh-aw/safeoutputs + mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs + cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' + {"create_issue":{"expires":168,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + GH_AW_SAFE_OUTPUTS_CONFIG_EOF + cat > /opt/gh-aw/safeoutputs/tools.json << 'GH_AW_SAFE_OUTPUTS_TOOLS_EOF' + [ + { + "description": "Create a new GitHub issue for tracking bugs, feature requests, or tasks. Use this for actionable work items that need assignment, labeling, and status tracking. For reports, announcements, or status updates that don't require task tracking, use create_discussion instead. CONSTRAINTS: Maximum 1 issue(s) can be created. Title will be prefixed with \"${{ inputs.title-prefix }} \".", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Detailed issue description in Markdown. Do NOT repeat the title as a heading since it already appears as the issue's h1. Include context, reproduction steps, or acceptance criteria as appropriate.", + "type": "string" + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "labels": { + "description": "Labels to categorize the issue (e.g., 'bug', 'enhancement'). Labels must exist in the repository.", + "items": { + "type": "string" + }, + "type": "array" + }, + "parent": { + "description": "Parent issue number for creating sub-issues. This is the numeric ID from the GitHub URL (e.g., 42 in github.com/owner/repo/issues/42). Can also be a temporary_id (e.g., 'aw_abc123', 'aw_Test123') from a previously created issue in the same workflow run.", + "type": [ + "number", + "string" + ] + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + }, + "temporary_id": { + "description": "Unique temporary identifier for referencing this issue before it's created. Format: 'aw_' followed by 3 to 12 alphanumeric characters (e.g., 'aw_abc1', 'aw_Test123'). Use '#aw_ID' in body text to reference other issues by their temporary_id; these are replaced with actual issue numbers after creation.", + "pattern": "^aw_[A-Za-z0-9]{3,12}$", + "type": "string" + }, + "title": { + "description": "Concise issue title summarizing the bug, feature, or task. The title appears as the main heading, so keep it brief and descriptive.", + "type": "string" + } + }, + "required": [ + "title", + "body" + ], + "type": "object" + }, + "name": "create_issue" + }, + { + "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Explanation of why this tool is needed or what information you want to share about the limitation (max 256 characters).", + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + }, + "tool": { + "description": "Optional: Name or description of the missing tool or capability (max 128 characters). Be specific about what functionality is needed.", + "type": "string" + } + }, + "required": [ + "reason" + ], + "type": "object" + }, + "name": "missing_tool" + }, + { + "description": "Log a transparency message when no significant actions are needed. Use this to confirm workflow completion and provide visibility when analysis is complete but no changes or outputs are required (e.g., 'No issues found', 'All checks passed'). This ensures the workflow produces human-visible output even when no other actions are taken.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "message": { + "description": "Status or completion message to log. Should explain what was analyzed and the outcome (e.g., 'Code review complete - no issues found', 'Analysis complete - all tests passing').", + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "message" + ], + "type": "object" + }, + "name": "noop" + }, + { + "description": "Report that data or information needed to complete the task is not available. Use this when you cannot accomplish what was requested because required data, context, or information is missing.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Any workarounds, manual steps, or alternative approaches the user could take (max 256 characters).", + "type": "string" + }, + "context": { + "description": "Additional context about the missing data or where it should come from (max 256 characters).", + "type": "string" + }, + "data_type": { + "description": "Type or description of the missing data or information (max 128 characters). Be specific about what data is needed.", + "type": "string" + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Explanation of why this data is needed to complete the task (max 256 characters).", + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [], + "type": "object" + }, + "name": "missing_data" + } + ] + GH_AW_SAFE_OUTPUTS_TOOLS_EOF + cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' + { + "create_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 + } + } + } + } + GH_AW_SAFE_OUTPUTS_VALIDATION_EOF + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash /opt/gh-aw/actions/start_safe_outputs_server.sh + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export 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_LOCKDOWN -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.1.8' + + mkdir -p /home/runner/.copilot + cat << GH_AW_MCP_CONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh + { + "mcpServers": { + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.31.0", + "env": { + "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "repos,issues,pull_requests,search,labels,actions" + } + }, + "public-code-search": { + "type": "http", + "url": "https://public-code-search.fastmcp.app/mcp", + "tools": [ + "search_code" + ] + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_EOF + - name: Download activation artifact + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8 + with: + name: activation + path: /tmp/gh-aw + - name: Clean git credentials + run: bash /opt/gh-aw/actions/clean_git_credentials.sh + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 90 + run: | + set -o pipefail + touch /tmp/gh-aw/agent-step-summary.md + # shellcheck disable=SC1003 + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains "*.docker.com,*.docker.io,*.githubusercontent.com,*.hackage.haskell.org,*.jsr.io,*.pythonhosted.org,*.rvm.io,*.vsblob.vsassets.io,adoptium.net,agents-md-generator.fastmcp.app,anaconda.org,api.adoptium.net,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.foojay.io,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.nuget.org,api.rubygems.org,api.snapcraft.io,apt.llvm.org,apt.releases.hashicorp.com,archive.apache.org,archive.ubuntu.com,archlinux.org,artifacts.elastic.co,auth.docker.io,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,binstar.org,bitbucket.org,bootstrap.pypa.io,builds.dotnet.microsoft.com,builds.hex.pm,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.azul.com,cdn.cocoapods.org,cdn.hex.pm,cdn.jsdelivr.net,cdn.playwright.dev,cdn.redhat.com,cdn.sheetjs.com,central.sonatype.com,ci.dot.net,clojars.org,cloud.elastic.co,cocoapods.org,code.jquery.com,codeload.github.com,conda.anaconda.org,conda.binstar.org,cpan.metacpan.org,cpan.org,crates.io,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,data.jsdelivr.com,dc.services.visualstudio.com,deb.debian.org,deb.nodesource.com,debian.map.fastlydns.net,deno.land,dist.nuget.org,dl-cdn.alpinelinux.org,dl.bintray.com,dl.fedoraproject.org,dl.google.com,dl.k8s.io,dlcdn.apache.org,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,download.eclipse.org,download.fedoraproject.org,download.java.net,download.opensuse.org,download.oracle.com,download.swift.org,downloads.gradle-dn.com,downloads.haskell.org,ela.st,elastic.co,elastic.dev,elastic.github.io,esm.sh,fastly.hex.pm,files.pythonhosted.org,fonts.googleapis.com,fonts.gstatic.com,gcr.io,ge.jetbrains.com,gems.rubyforge.org,gems.rubyonrails.org,get-ghcup.haskell.org,get.pnpm.io,getcomposer.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,gradle.org,haskell.org,hex.pm,host.docker.internal,index.crates.io,index.rubygems.org,jcenter.bintray.com,jdk.java.net,jitpack.io,json-schema.org,json.schemastore.org,jsr.io,keyring.debian.org,keyserver.ubuntu.com,kotlin.bintray.com,lfs.github.com,maven.apache.org,maven.google.com,maven.oracle.com,maven.pkg.github.com,mcr.microsoft.com,metacpan.org,mirror.archlinux.org,mirror.centos.org,mirrors.fedoraproject.org,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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.debian.org,packages.jetbrains.team,packages.microsoft.com,packagist.org,pip.pypa.io,pkg.alpinelinux.org,pkg.go.dev,pkg.machengine.org,pkgs.dev.azure.com,pkgs.k8s.io,playwright.download.prss.microsoft.com,plugins-artifacts.gradle.org,plugins.gradle.org,ppa.launchpad.net,production.cloudflare.docker.com,productionresultssa0.blob.core.windows.net,productionresultssa1.blob.core.windows.net,productionresultssa10.blob.core.windows.net,productionresultssa11.blob.core.windows.net,productionresultssa12.blob.core.windows.net,productionresultssa13.blob.core.windows.net,productionresultssa14.blob.core.windows.net,productionresultssa15.blob.core.windows.net,productionresultssa16.blob.core.windows.net,productionresultssa17.blob.core.windows.net,productionresultssa18.blob.core.windows.net,productionresultssa19.blob.core.windows.net,productionresultssa2.blob.core.windows.net,productionresultssa3.blob.core.windows.net,productionresultssa4.blob.core.windows.net,productionresultssa5.blob.core.windows.net,productionresultssa6.blob.core.windows.net,productionresultssa7.blob.core.windows.net,productionresultssa8.blob.core.windows.net,productionresultssa9.blob.core.windows.net,proxy.golang.org,pub.dartlang.org,pub.dev,public-code-search.fastmcp.app,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.clojars.org,repo.continuum.io,repo.gradle.org,repo.grails.org,repo.hex.pm,repo.maven.apache.org,repo.packagist.org,repo.scala-sbt.org,repo.spring.io,repo.typesafe.com,repo.yarnpkg.com,repo1.maven.org,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,scala-ci.typesafe.com,security.debian.org,security.ubuntu.com,services.gradle.org,sh.rustup.rs,skimdb.npmjs.com,static.crates.io,static.rust-lang.org,storage.googleapis.com,sum.golang.org,swift.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,vault.centos.org,www.cpan.org,www.elastic.co,www.java.com,www.microsoft.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com,ziglang.org" --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.23.0 --skip-pull --enable-api-proxy \ + -- /bin/bash -c '/usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --add-dir "${GITHUB_WORKSPACE}" --disable-builtin-mcps --allow-all-tools --allow-all-paths --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: ${{ inputs.model }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GITHUB_API_URL: ${{ github.api_url }} + 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 }} + XDG_CONFIG_HOME: /home/runner + - name: Detect inference access error + id: detect-inference-error + if: always() + continue-on-error: true + run: bash /opt/gh-aw/actions/detect_inference_access_error.sh + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + 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: | + # Copy Copilot session state files to logs folder for artifact collection + # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them + SESSION_STATE_DIR="$HOME/.copilot/session-state" + LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" + + if [ -d "$SESSION_STATE_DIR" ]; then + echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" + mkdir -p "$LOGS_DIR" + cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true + echo "Session state files copied successfully" + else + echo "No session-state directory found at $SESSION_STATE_DIR" + fi + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash /opt/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Append agent step summary + if: always() + run: bash /opt/gh-aw/actions/append_agent_step_summary.sh + - name: Upload Safe Outputs + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 + with: + name: safe-output + path: ${{ env.GH_AW_SAFE_OUTPUTS }} + if-no-files-found: warn + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.hackage.haskell.org,*.jsr.io,*.pythonhosted.org,*.rvm.io,*.vsblob.vsassets.io,adoptium.net,agents-md-generator.fastmcp.app,anaconda.org,api.adoptium.net,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.foojay.io,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.nuget.org,api.rubygems.org,api.snapcraft.io,apt.llvm.org,apt.releases.hashicorp.com,archive.apache.org,archive.ubuntu.com,archlinux.org,artifacts.elastic.co,auth.docker.io,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,binstar.org,bitbucket.org,bootstrap.pypa.io,builds.dotnet.microsoft.com,builds.hex.pm,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.azul.com,cdn.cocoapods.org,cdn.hex.pm,cdn.jsdelivr.net,cdn.playwright.dev,cdn.redhat.com,cdn.sheetjs.com,central.sonatype.com,ci.dot.net,clojars.org,cloud.elastic.co,cocoapods.org,code.jquery.com,codeload.github.com,conda.anaconda.org,conda.binstar.org,cpan.metacpan.org,cpan.org,crates.io,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,data.jsdelivr.com,dc.services.visualstudio.com,deb.debian.org,deb.nodesource.com,debian.map.fastlydns.net,deno.land,dist.nuget.org,dl-cdn.alpinelinux.org,dl.bintray.com,dl.fedoraproject.org,dl.google.com,dl.k8s.io,dlcdn.apache.org,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,download.eclipse.org,download.fedoraproject.org,download.java.net,download.opensuse.org,download.oracle.com,download.swift.org,downloads.gradle-dn.com,downloads.haskell.org,ela.st,elastic.co,elastic.dev,elastic.github.io,esm.sh,fastly.hex.pm,files.pythonhosted.org,fonts.googleapis.com,fonts.gstatic.com,gcr.io,ge.jetbrains.com,gems.rubyforge.org,gems.rubyonrails.org,get-ghcup.haskell.org,get.pnpm.io,getcomposer.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,gradle.org,haskell.org,hex.pm,host.docker.internal,index.crates.io,index.rubygems.org,jcenter.bintray.com,jdk.java.net,jitpack.io,json-schema.org,json.schemastore.org,jsr.io,keyring.debian.org,keyserver.ubuntu.com,kotlin.bintray.com,lfs.github.com,maven.apache.org,maven.google.com,maven.oracle.com,maven.pkg.github.com,mcr.microsoft.com,metacpan.org,mirror.archlinux.org,mirror.centos.org,mirrors.fedoraproject.org,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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.debian.org,packages.jetbrains.team,packages.microsoft.com,packagist.org,pip.pypa.io,pkg.alpinelinux.org,pkg.go.dev,pkg.machengine.org,pkgs.dev.azure.com,pkgs.k8s.io,playwright.download.prss.microsoft.com,plugins-artifacts.gradle.org,plugins.gradle.org,ppa.launchpad.net,production.cloudflare.docker.com,productionresultssa0.blob.core.windows.net,productionresultssa1.blob.core.windows.net,productionresultssa10.blob.core.windows.net,productionresultssa11.blob.core.windows.net,productionresultssa12.blob.core.windows.net,productionresultssa13.blob.core.windows.net,productionresultssa14.blob.core.windows.net,productionresultssa15.blob.core.windows.net,productionresultssa16.blob.core.windows.net,productionresultssa17.blob.core.windows.net,productionresultssa18.blob.core.windows.net,productionresultssa19.blob.core.windows.net,productionresultssa2.blob.core.windows.net,productionresultssa3.blob.core.windows.net,productionresultssa4.blob.core.windows.net,productionresultssa5.blob.core.windows.net,productionresultssa6.blob.core.windows.net,productionresultssa7.blob.core.windows.net,productionresultssa8.blob.core.windows.net,productionresultssa9.blob.core.windows.net,proxy.golang.org,pub.dartlang.org,pub.dev,public-code-search.fastmcp.app,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.clojars.org,repo.continuum.io,repo.gradle.org,repo.grails.org,repo.hex.pm,repo.maven.apache.org,repo.packagist.org,repo.scala-sbt.org,repo.spring.io,repo.typesafe.com,repo.yarnpkg.com,repo1.maven.org,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,scala-ci.typesafe.com,security.debian.org,security.ubuntu.com,services.gradle.org,sh.rustup.rs,skimdb.npmjs.com,static.crates.io,static.rust-lang.org,storage.googleapis.com,sum.golang.org,swift.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,vault.centos.org,www.cpan.org,www.elastic.co,www.java.com,www.microsoft.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com,ziglang.org" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/collect_ndjson_output.cjs'); + await main(); + - name: Upload sanitized agent output + if: always() && env.GH_AW_AGENT_OUTPUT + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 + with: + name: agent-output + path: ${{ env.GH_AW_AGENT_OUTPUT }} + if-no-files-found: warn + - name: Upload engine output files + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 + with: + name: agent_outputs + path: | + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + if-no-files-found: ignore + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/parse_copilot_log.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 + with: + name: agent-artifacts + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/sandbox/firewall/logs/ + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/ + if-no-files-found: ignore + # --- Threat Detection (inline) --- + - name: Check if detection needed + id: detection_guard + if: always() + env: + OUTPUT_TYPES: ${{ steps.collect_output.outputs.output_types }} + HAS_PATCH: ${{ steps.collect_output.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 + 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@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + WORKFLOW_NAME: "Code Quality Audit" + WORKFLOW_DESCRIPTION: "Analyze code for quality issues — anti-patterns, accessibility violations, performance problems, best-practices deviations — and file a structured report" + HAS_PATCH: ${{ steps.collect_output.outputs.has_patch }} + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/setup_threat_detection.cjs'); + await main(); + - name: Ensure threat-detection directory and log + 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: Execute GitHub Copilot CLI + if: always() && steps.detection_guard.outputs.run_detection == 'true' + id: detection_agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool shell(cat) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(jq) + # --allow-tool shell(ls) + # --allow-tool shell(tail) + # --allow-tool shell(wc) + timeout-minutes: 20 + run: | + set -o pipefail + touch /tmp/gh-aw/agent-step-summary.md + # shellcheck disable=SC1003 + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,github.com,host.docker.internal,raw.githubusercontent.com,registry.npmjs.org,telemetry.enterprise.githubcopilot.com" --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.23.0 --skip-pull --enable-api-proxy \ + -- /bin/bash -c '/usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --add-dir "${GITHUB_WORKSPACE}" --disable-builtin-mcps --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(wc)'\'' --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: ${{ inputs.model }} + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GITHUB_API_URL: ${{ github.api_url }} + 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 }} + XDG_CONFIG_HOME: /home/runner + - name: Parse threat detection results + id: parse_detection_results + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/parse_threat_detection_results.cjs'); + await main(); + - name: Upload threat detection log + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 + with: + name: threat-detection.log + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + - name: Set detection conclusion + id: detection_conclusion + if: always() + env: + RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }} + DETECTION_SUCCESS: ${{ steps.parse_detection_results.outputs.success }} + run: | + if [[ "$RUN_DETECTION" != "true" ]]; then + echo "conclusion=skipped" >> "$GITHUB_OUTPUT" + echo "success=true" >> "$GITHUB_OUTPUT" + echo "Detection was not needed, marking as skipped" + elif [[ "$DETECTION_SUCCESS" == "true" ]]; then + echo "conclusion=success" >> "$GITHUB_OUTPUT" + echo "success=true" >> "$GITHUB_OUTPUT" + echo "Detection passed successfully" + else + echo "conclusion=failure" >> "$GITHUB_OUTPUT" + echo "success=false" >> "$GITHUB_OUTPUT" + echo "Detection found issues" + fi + + conclusion: + needs: + - activation + - agent + - safe_outputs + if: (always()) && (needs.agent.result != 'skipped') + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + concurrency: + group: "gh-aw-conclusion-gh-aw-code-quality-audit" + cancel-in-progress: false + outputs: + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@956f874e40e831c08a8b01ec76f5d49ae3fe8387 # v0.53.6 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process No-Op Messages + id: noop + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: "1" + GH_AW_WORKFLOW_NAME: "Code Quality Audit" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/noop.cjs'); + await main(); + - name: Record Missing Tool + id: missing_tool + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Code Quality Audit" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Handle Agent Failure + id: handle_agent_failure + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Code Quality Audit" + 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: "gh-aw-code-quality-audit" + 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_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || format('---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {0}]({{run_url}})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.', github.workflow) }}\",\"activationComments\":\"false\"}" + GH_AW_GROUP_REPORTS: "false" + GH_AW_TIMEOUT_MINUTES: "90" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + - name: Handle No-Op Message + id: handle_noop_message + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Code Quality Audit" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_NOOP_MESSAGE: ${{ steps.noop.outputs.noop_message }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); + await main(); + + pre_activation: + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + matched_command: '' + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@956f874e40e831c08a8b01ec76f5d49ae3fe8387 # v0.53.6 + with: + destination: /opt/gh-aw/actions + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REQUIRED_ROLES: admin,maintainer,write + GH_AW_ALLOWED_BOTS: ${{ inputs.allowed-bot-users }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/check_membership.cjs'); + await main(); + + safe_outputs: + needs: agent + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.agent.outputs.detection_success == 'true') + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + timeout-minutes: 15 + env: + GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/gh-aw-code-quality-audit" + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || format('---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {0}]({{run_url}})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.', github.workflow) }}\",\"activationComments\":\"false\"}" + GH_AW_WORKFLOW_ID: "gh-aw-code-quality-audit" + GH_AW_WORKFLOW_NAME: "Code Quality Audit" + outputs: + 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 + uses: github/gh-aw/actions/setup@956f874e40e831c08a8b01ec76f5d49ae3fe8387 # v0.53.6 + with: + destination: /opt/gh-aw/actions + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8 + with: + name: agent-output + path: /tmp/gh-aw/safeoutputs/ + - name: Setup agent output environment variable + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/safeoutputs/ + find "/tmp/gh-aw/safeoutputs/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/safeoutputs/agent_output.json" >> "$GITHUB_ENV" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.hackage.haskell.org,*.jsr.io,*.pythonhosted.org,*.rvm.io,*.vsblob.vsassets.io,adoptium.net,agents-md-generator.fastmcp.app,anaconda.org,api.adoptium.net,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.foojay.io,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.nuget.org,api.rubygems.org,api.snapcraft.io,apt.llvm.org,apt.releases.hashicorp.com,archive.apache.org,archive.ubuntu.com,archlinux.org,artifacts.elastic.co,auth.docker.io,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,binstar.org,bitbucket.org,bootstrap.pypa.io,builds.dotnet.microsoft.com,builds.hex.pm,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.azul.com,cdn.cocoapods.org,cdn.hex.pm,cdn.jsdelivr.net,cdn.playwright.dev,cdn.redhat.com,cdn.sheetjs.com,central.sonatype.com,ci.dot.net,clojars.org,cloud.elastic.co,cocoapods.org,code.jquery.com,codeload.github.com,conda.anaconda.org,conda.binstar.org,cpan.metacpan.org,cpan.org,crates.io,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,data.jsdelivr.com,dc.services.visualstudio.com,deb.debian.org,deb.nodesource.com,debian.map.fastlydns.net,deno.land,dist.nuget.org,dl-cdn.alpinelinux.org,dl.bintray.com,dl.fedoraproject.org,dl.google.com,dl.k8s.io,dlcdn.apache.org,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,download.eclipse.org,download.fedoraproject.org,download.java.net,download.opensuse.org,download.oracle.com,download.swift.org,downloads.gradle-dn.com,downloads.haskell.org,ela.st,elastic.co,elastic.dev,elastic.github.io,esm.sh,fastly.hex.pm,files.pythonhosted.org,fonts.googleapis.com,fonts.gstatic.com,gcr.io,ge.jetbrains.com,gems.rubyforge.org,gems.rubyonrails.org,get-ghcup.haskell.org,get.pnpm.io,getcomposer.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,gradle.org,haskell.org,hex.pm,host.docker.internal,index.crates.io,index.rubygems.org,jcenter.bintray.com,jdk.java.net,jitpack.io,json-schema.org,json.schemastore.org,jsr.io,keyring.debian.org,keyserver.ubuntu.com,kotlin.bintray.com,lfs.github.com,maven.apache.org,maven.google.com,maven.oracle.com,maven.pkg.github.com,mcr.microsoft.com,metacpan.org,mirror.archlinux.org,mirror.centos.org,mirrors.fedoraproject.org,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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.debian.org,packages.jetbrains.team,packages.microsoft.com,packagist.org,pip.pypa.io,pkg.alpinelinux.org,pkg.go.dev,pkg.machengine.org,pkgs.dev.azure.com,pkgs.k8s.io,playwright.download.prss.microsoft.com,plugins-artifacts.gradle.org,plugins.gradle.org,ppa.launchpad.net,production.cloudflare.docker.com,productionresultssa0.blob.core.windows.net,productionresultssa1.blob.core.windows.net,productionresultssa10.blob.core.windows.net,productionresultssa11.blob.core.windows.net,productionresultssa12.blob.core.windows.net,productionresultssa13.blob.core.windows.net,productionresultssa14.blob.core.windows.net,productionresultssa15.blob.core.windows.net,productionresultssa16.blob.core.windows.net,productionresultssa17.blob.core.windows.net,productionresultssa18.blob.core.windows.net,productionresultssa19.blob.core.windows.net,productionresultssa2.blob.core.windows.net,productionresultssa3.blob.core.windows.net,productionresultssa4.blob.core.windows.net,productionresultssa5.blob.core.windows.net,productionresultssa6.blob.core.windows.net,productionresultssa7.blob.core.windows.net,productionresultssa8.blob.core.windows.net,productionresultssa9.blob.core.windows.net,proxy.golang.org,pub.dartlang.org,pub.dev,public-code-search.fastmcp.app,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.clojars.org,repo.continuum.io,repo.gradle.org,repo.grails.org,repo.hex.pm,repo.maven.apache.org,repo.packagist.org,repo.scala-sbt.org,repo.spring.io,repo.typesafe.com,repo.yarnpkg.com,repo1.maven.org,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,scala-ci.typesafe.com,security.debian.org,security.ubuntu.com,services.gradle.org,sh.rustup.rs,skimdb.npmjs.com,static.crates.io,static.rust-lang.org,storage.googleapis.com,sum.golang.org,swift.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,vault.centos.org,www.cpan.org,www.elastic.co,www.java.com,www.microsoft.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com,ziglang.org" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":false,\"expires\":168,\"max\":1,\"title_prefix\":\"${{ inputs.title-prefix }} \"},\"missing_data\":{},\"missing_tool\":{}}" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload safe output items manifest + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 + with: + name: safe-output-items + path: /tmp/safe-output-items.jsonl + if-no-files-found: warn + diff --git a/.github/workflows/gh-aw-code-quality-audit.md b/.github/workflows/gh-aw-code-quality-audit.md new file mode 100644 index 00000000..f06eb667 --- /dev/null +++ b/.github/workflows/gh-aw-code-quality-audit.md @@ -0,0 +1,130 @@ +--- +inlined-imports: true +name: "Code Quality Audit" +description: "Analyze code for quality issues — anti-patterns, accessibility violations, performance problems, best-practices deviations — and file a structured report" +imports: + - gh-aw-fragments/elastic-tools.md + - gh-aw-fragments/runtime-setup.md + - gh-aw-fragments/ensure-full-history.md + - gh-aw-fragments/formatting.md + - gh-aw-fragments/rigor.md + - gh-aw-fragments/mcp-pagination.md + - gh-aw-fragments/messages-footer.md + - gh-aw-fragments/safe-output-create-issue.md + - gh-aw-fragments/previous-findings.md + - gh-aw-fragments/pick-three-keep-many.md + - gh-aw-fragments/scheduled-audit.md + - gh-aw-fragments/network-ecosystems.md + - gh-aw-fragments/code-quality-audit.md +engine: + id: copilot + model: ${{ inputs.model }} +on: + workflow_call: + inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" + additional-instructions: + description: "Domain-specific audit criteria — what to look for, what to skip, and how to evaluate findings. This is the core of the audit and should define the categories, severity standards, and evidence expectations for the specific quality dimension being audited." + type: string + required: true + setup-commands: + description: "Shell commands to run before the agent starts (dependency install, build, etc.)" + type: string + required: false + default: "" + allowed-bot-users: + description: "Allowlisted bot actor usernames (comma-separated)" + type: string + required: false + default: "github-actions[bot]" + messages-footer: + description: "Footer appended to all agent comments and reviews" + type: string + required: false + default: "" + title-prefix: + description: "Title prefix for created issues (e.g. '[react-accessibility]')" + type: string + required: true + severity-threshold: + description: "Minimum severity to include in the report. 'high' = only report issues with clear user impact or correctness problems. 'medium' (default) = also include issues that degrade quality or maintainability. 'low' = also include minor deviations from best practices." + type: string + required: false + default: "medium" + secrets: + COPILOT_GITHUB_TOKEN: + required: true + roles: [admin, maintainer, write] + bots: + - "${{ inputs.allowed-bot-users }}" +concurrency: + group: ${{ github.workflow }}-code-quality-audit + cancel-in-progress: true +permissions: + actions: read + contents: read + issues: read + pull-requests: read +tools: + github: + toolsets: [repos, issues, pull_requests, search, labels, actions] + bash: true + web-fetch: +strict: false +safe-outputs: + activation-comments: false + noop: + create-issue: + max: 1 + title-prefix: "${{ inputs.title-prefix }} " + close-older-issues: false + expires: 7d +timeout-minutes: 90 +steps: + - name: Validate severity threshold + env: + SEVERITY_THRESHOLD: ${{ inputs.severity-threshold }} + run: | + case "$SEVERITY_THRESHOLD" in + high|medium|low) ;; + *) + echo "Invalid severity-threshold: '$SEVERITY_THRESHOLD'. Expected one of: high, medium, low." + exit 1 + ;; + esac + - name: Repo-specific setup + if: ${{ inputs.setup-commands != '' }} + env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + run: eval "$SETUP_COMMANDS" +--- + +### Data Gathering + +1. Understand the project: + - Read `README.md`, `CONTRIBUTING.md`, `DEVELOPING.md`, and any docs directory. + - Read `package.json`, `go.mod`, `pyproject.toml`, or equivalent to identify the tech stack and versions. + - Skim the directory structure to understand the codebase layout. + +2. Use the **Pick Three, Keep Many** pattern for the audit: + - Spawn 3 `general-purpose` sub-agents, each auditing from a different angle as defined in the **Audit Criteria** section below. + - Each sub-agent prompt must include: the full audit criteria, the tech stack info, relevant file paths, and the severity threshold. + - Each sub-agent should return all findings that meet the severity threshold, with specific file paths, line numbers, and code snippets. + - Wait for all sub-agents to complete, then merge and deduplicate. + +3. Check for duplicates: + - Read `/tmp/previous-findings.json` for issues already filed by this agent. + - Search open issues: `repo:{owner}/{repo} is:issue is:open in:title "${{ inputs.title-prefix }}"`. + - Drop any finding that closely matches an existing open issue. + +### Labeling + +- If a label matching the title prefix (without brackets) exists (check with `github-get_label`), include it in the `create_issue` call; otherwise, rely on the `${{ inputs.title-prefix }}` title prefix only. + +## Audit Criteria + +${{ inputs.additional-instructions }} diff --git a/.github/workflows/downstream-users.lock.yml b/.github/workflows/gh-aw-create-pr-from-issue.lock.yml similarity index 70% rename from .github/workflows/downstream-users.lock.yml rename to .github/workflows/gh-aw-create-pr-from-issue.lock.yml index 54ba5492..b5b52937 100644 --- a/.github/workflows/downstream-users.lock.yml +++ b/.github/workflows/gh-aw-create-pr-from-issue.lock.yml @@ -21,7 +21,7 @@ # # For more information: https://github.github.com/gh-aw/introduction/overview/ # -# Track downstream public repo usage of elastic/ai-github-actions and update data +# Implement an issue and open a pull request # # Resolved workflow manifest: # Imports: @@ -29,38 +29,87 @@ # - gh-aw-fragments/formatting.md # - gh-aw-fragments/mcp-pagination.md # - gh-aw-fragments/messages-footer.md +# - gh-aw-fragments/network-ecosystems.md +# - gh-aw-fragments/playwright-mcp-explorer.md # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md +# - gh-aw-fragments/safe-output-add-comment-issue.md # - gh-aw-fragments/safe-output-create-pr.md # - gh-aw-fragments/workflow-edit-guardrails.md # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"0d66a4cb599c3247fe8c3533e3358d727c5c56c64267d301e63100d2bf4686da"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"5420f6374562f0e3e57f7a036e8ce5eb3e301d07287fed37726a6ca21470d4e6"} -name: "Internal: Downstream Users" +name: "Create PR From Issue" "on": - # bots: # Bots processed as bot check in pre-activation job - # - github-actions[bot] # Bots processed as bot check in pre-activation job - # roles: # Roles processed as role check in pre-activation job - # - admin # Roles processed as role check in pre-activation job - # - maintainer # Roles processed as role check in pre-activation job - # - write # Roles processed as role check in pre-activation job - schedule: - - cron: "4 9 * * 1" - # Friendly format: weekly on Monday around 10:00 (scattered) - workflow_dispatch: + workflow_call: + inputs: + additional-instructions: + default: "" + description: Repo-specific instructions appended to the agent prompt + required: false + type: string + draft-prs: + default: true + description: Whether to create pull requests as drafts + required: false + type: boolean + messages-footer: + default: "" + description: Footer appended to all agent comments and reviews + required: false + type: string + model: + default: gpt-5.3-codex + description: AI model to use + required: false + type: string + prompt: + default: "" + description: Additional implementation instructions + required: false + type: string + setup-commands: + default: "" + description: Shell commands to run before the agent starts (dependency install, build, etc.) + required: false + type: string + target-issue-number: + description: Issue number to implement + required: true + type: string + outputs: + comment_id: + description: ID of the first added comment + value: ${{ jobs.safe_outputs.outputs.comment_id }} + comment_url: + description: URL of the first added comment + value: ${{ jobs.safe_outputs.outputs.comment_url }} + created_pr_number: + description: Number of the first created pull request + value: ${{ jobs.safe_outputs.outputs.created_pr_number }} + created_pr_url: + description: URL of the first created pull request + value: ${{ jobs.safe_outputs.outputs.created_pr_url }} + secrets: + COPILOT_GITHUB_TOKEN: + required: true + EXTRA_COMMIT_GITHUB_TOKEN: + required: false permissions: {} concurrency: cancel-in-progress: true - group: ${{ github.workflow }}-downstream-users + group: ${{ github.workflow }}-create-pr-from-issue-${{ inputs.target-issue-number }} -run-name: "Internal: Downstream Users" +run-name: "Create PR From Issue" jobs: activation: + needs: pre_activation + if: needs.pre_activation.outputs.activated == 'true' runs-on: ubuntu-slim permissions: contents: read @@ -79,14 +128,14 @@ jobs: env: GH_AW_INFO_ENGINE_ID: "copilot" GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" - GH_AW_INFO_MODEL: "gpt-5.3-codex" + GH_AW_INFO_MODEL: "${{ inputs.model }}" GH_AW_INFO_VERSION: "" GH_AW_INFO_AGENT_VERSION: "0.0.421" - GH_AW_INFO_WORKFLOW_NAME: "Internal: Downstream Users" + GH_AW_INFO_WORKFLOW_NAME: "Create PR From Issue" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" - GH_AW_INFO_ALLOWED_DOMAINS: '["artifacts.elastic.co","cloud.elastic.co","defaults","ela.st","elastic.co","github","go","node","public-code-search.fastmcp.app","python","ruby","www.elastic.co"]' + GH_AW_INFO_ALLOWED_DOMAINS: '["agents-md-generator.fastmcp.app","artifacts.elastic.co","clojure","cloud.elastic.co","containers","dart","defaults","dotnet","ela.st","elastic.co","elastic.dev","elastic.github.io","elixir","fonts","github","github-actions","go","haskell","java","kotlin","linux-distros","node","node-cdns","perl","php","playwright","public-code-search.fastmcp.app","python","ruby","rust","scala","swift","terraform","www.elastic.co","zig"]' GH_AW_INFO_FIREWALL_ENABLED: "true" GH_AW_INFO_AWF_VERSION: "v0.23.0" GH_AW_INFO_AWMG_VERSION: "" @@ -113,7 +162,7 @@ jobs: - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - GH_AW_WORKFLOW_FILE: "downstream-users.lock.yml" + GH_AW_WORKFLOW_FILE: "gh-aw-create-pr-from-issue.lock.yml" with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -124,6 +173,8 @@ jobs: env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_EA5D66D8: ${{ inputs.target-issue-number }} 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 }} @@ -132,6 +183,7 @@ jobs: GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_INPUTS_PROMPT: ${{ inputs.prompt }} run: | bash /opt/gh-aw/actions/create_prompt_first.sh { @@ -141,10 +193,11 @@ jobs: cat "/opt/gh-aw/prompts/xpia.md" cat "/opt/gh-aw/prompts/temp_folder_prompt.md" cat "/opt/gh-aw/prompts/markdown.md" + cat "/opt/gh-aw/prompts/playwright_prompt.md" cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_pull_request, missing_tool, missing_data, noop + Tools: add_comment, create_pull_request, missing_tool, missing_data, noop GH_AW_PROMPT_EOF cat "/opt/gh-aw/prompts/safe_outputs_create_pull_request.md" cat << 'GH_AW_PROMPT_EOF' @@ -260,6 +313,23 @@ jobs: A footer is automatically appended to all comments and reviews. Do not add your own footer or sign-off — the runtime handles this. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + ## Playwright MCP Tools + + Playwright MCP tools are available for interactive browser automation. Full instructions are in `/tmp/playwright-instructions.md` — read it before using any Playwright tools. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + ## add-comment Limitations + + - **Body**: Max 65,536 characters (including any footer added by gh-aw). Keep well under this limit. + - **Mentions**: Max 10 `@` mentions per comment. + - **Links**: Max 50 URLs per comment. + - **HTML**: Only safe tags allowed (`details`, `summary`, `code`, `pre`, `blockquote`, `table`, `b`, `em`, `strong`, `h1`–`h6`, `hr`, `br`, `li`, `ol`, `ul`, `p`, `sub`, `sup`). Other tags are converted to parentheses. + - **URLs**: Only HTTPS URLs to allowed domains. Non-HTTPS and non-allowed domains are redacted. + - **Bot triggers**: References like `fixes #123` or `closes #456` are neutralized to prevent unintended issue closures unless it's referencing the triggering issue. + + If you exceed 10 mentions or 50 links, the comment will be rejected. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' Before calling `create_pull_request`, call `ready_to_make_pr` and apply its checklist. ## create-pull-request Limitations @@ -274,77 +344,34 @@ jobs: - You may not submit code that modifies files in `.github/workflows/`. Doing so will cause the submission to be rejected. If asked to modify workflow files, propose the change in a copy placed in a `github/` folder (without the leading period) and note in the PR that the file needs to be relocated by someone with workflow write access. GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' - # Downstream Users Tracking - Maintain a canonical list of public downstream repositories using elastic/ai-github-actions, including which workflows they consume. + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + # Create PR From Issue + + Implement issue #__GH_AW_EXPR_EA5D66D8__ on __GH_AW_GITHUB_REPOSITORY__ and open a pull request. ## Context - **Repository**: __GH_AW_GITHUB_REPOSITORY__ - - **Output file**: `data/downstream-users.json` + - **Issue**: #__GH_AW_EXPR_EA5D66D8__ + - **Additional request**: "__GH_AW_INPUTS_PROMPT__" ## Constraints - - **CAN**: Read files, search GitHub, modify files locally, run commands, create a pull request. - - **CANNOT**: Directly push to the repository — use `create_pull_request`. - - **Only one PR per run.** - - Do not modify files under `.github/workflows/`. - - Keep the JSON output stable and sorted to minimize diff noise. - - ## Step 1: Gather Context - - 1. Read the current `data/downstream-users.json` file (if it exists). + - **CAN**: Read files, search code, modify files locally, run tests and commands, comment on the targeted issue, create pull requests + - **CANNOT**: Directly push or commit to the repository — use `ready_to_make_pr` then `create_pull_request` to propose changes - ## Step 2: Discover Downstream Usage + ## Instructions - 1. Use the `public-code-search` MCP server to find public repositories that reference this repo in workflow files. - - Search for `uses: elastic/ai-github-actions` in `*.yml` and `*.yaml` files. - - Example query input for `search_code`: - - `patterns`: `uses:\\s*elastic/ai-github-actions/` - - `include_globs`: `**/*.yml`, `**/*.yaml` - - Exclude `elastic/ai-github-actions` itself. + 1. Read issue #__GH_AW_EXPR_EA5D66D8__ first to understand requirements and acceptance criteria. + 2. Investigate the relevant code paths and implement a focused fix for the issue. + 3. Run required repo checks (lint/build/test) relevant to your change. If required commands cannot run, explain why and do not open a PR. + 4. Call `ready_to_make_pr` and apply its checklist. + 5. Call `create_pull_request` with a clear title/body that references and closes issue #__GH_AW_EXPR_EA5D66D8__. + 6. If implementation is blocked or unclear, call `add_comment` on the issue with a concise status update and concrete next step. - 1. For each unique repo + path pair returned: - - Fetch the workflow file using `github-get_file_contents`. - - Extract every `uses: elastic/ai-github-actions/...` line. - - Normalize each entry by removing the leading `elastic/ai-github-actions/` and any `@version` suffix. - - ## Step 3: Build the Data File - - Write `data/downstream-users.json` with this structure: - - ````markdown - ```json - { - "generated_at": "", - "source": { - "query": "", - "notes": "" - }, - "repos": [ - { - "repo": "owner/repo", - "workflows": ["workflows/mention-in-issue/rwxp", "..."] - } - ] - } - ``` - ```` - - Guidelines: - - Sort `repos` by `repo`. - - Sort each `workflows` list alphabetically. - - Use UTC timestamps with a `Z` suffix. - - ## Step 4: Create the PR - - 1. If the file is unchanged, call `noop` with: `Downstream users list already up to date.` - 2. Otherwise, commit the updated JSON and call `create_pull_request`. - - Title: `"[downstream] Update downstream users list"` - - Body: - - Summary of repo count and workflow count - - The search query used - - Any exclusions (self repo, archived/forks if excluded) + __GH_AW_EXPR_49B959F1__ GH_AW_PROMPT_EOF } > "$GH_AW_PROMPT" @@ -353,6 +380,9 @@ jobs: env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_INPUTS_PROMPT: ${{ inputs.prompt }} + GH_AW_EXPR_EA5D66D8: ${{ inputs.target-issue-number }} with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -363,6 +393,8 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_EA5D66D8: ${{ inputs.target-issue-number }} 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 }} @@ -371,6 +403,8 @@ jobs: GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_INPUTS_PROMPT: ${{ inputs.prompt }} + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -382,6 +416,8 @@ jobs: return await substitutePlaceholders({ file: process.env.GH_AW_PROMPT, substitutions: { + GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, + GH_AW_EXPR_EA5D66D8: process.env.GH_AW_EXPR_EA5D66D8, 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, @@ -389,7 +425,9 @@ 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_INPUTS_PROMPT: process.env.GH_AW_INPUTS_PROMPT, + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED } }); - name: Validate prompt placeholders @@ -414,11 +452,12 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: + actions: read contents: read issues: read pull-requests: read concurrency: - group: "gh-aw-copilot-${{ github.workflow }}" + group: "gh-aw-copilot-${{ github.workflow }}-create-pr-from-issue-${{ inputs.target-issue-number }}" env: DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} GH_AW_ASSETS_ALLOWED_EXTS: "" @@ -428,7 +467,7 @@ jobs: GH_AW_SAFE_OUTPUTS: /opt/gh-aw/safeoutputs/outputs.jsonl GH_AW_SAFE_OUTPUTS_CONFIG_PATH: /opt/gh-aw/safeoutputs/config.json GH_AW_SAFE_OUTPUTS_TOOLS_PATH: /opt/gh-aw/safeoutputs/tools.json - GH_AW_WORKFLOW_ID_SANITIZED: downstreamusers + GH_AW_WORKFLOW_ID_SANITIZED: ghawcreateprfromissue outputs: checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }} @@ -447,14 +486,14 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false + - name: Setup Go + uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 + with: + go-version: '1.25' + - name: Capture GOROOT for AWF chroot mode + run: echo "GOROOT=$(go env GOROOT)" >> "$GITHUB_ENV" - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - - if: hashFiles('go.mod') != '' - name: Setup Go - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 - with: - cache: true - go-version-file: go.mod - if: hashFiles('.python-version') != '' name: Setup Python uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 @@ -501,6 +540,13 @@ jobs: name: Fetch repository conventions run: "set -euo pipefail\nif [ -f \"AGENTS.md\" ]; then\n cp AGENTS.md /tmp/agents.md\n echo \"Repository conventions copied from AGENTS.md to /tmp/agents.md\"\nelse\n OWNER=\"${GITHUB_REPOSITORY%/*}\"\n REPO=\"${GITHUB_REPOSITORY#*/}\"\n summary=$(curl -sf --max-time 15 -X POST https://agents-md-generator.fastmcp.app/mcp \\\n -H \"Content-Type: application/json\" \\\n -H \"Accept: application/json, text/event-stream\" \\\n -d \"{\\\"jsonrpc\\\":\\\"2.0\\\",\\\"id\\\":1,\\\"method\\\":\\\"tools/call\\\",\\\"params\\\":{\\\"name\\\":\\\"generate_agents_md\\\",\\\"arguments\\\":{\\\"owner\\\":\\\"${OWNER}\\\",\\\"repo\\\":\\\"${REPO}\\\"}}}\" \\\n | sed 's/^data: //' \\\n | jq -r '.result.structuredContent.summary // empty' 2>/dev/null) || true\n if [ -n \"$summary\" ]; then\n echo \"$summary\" > /tmp/agents.md\n echo \"Repository conventions written to /tmp/agents.md\"\n else\n echo \"::warning::Could not fetch repository conventions; continuing without them\"\n fi\nfi" shell: bash + - name: Write Playwright instructions to disk + run: "cat > /tmp/playwright-instructions.md << 'EOF'\n# Playwright MCP Tools\n\nUse Playwright MCP tools for interactive browser automation.\nUse these tools to explore the app step by step — do NOT write Node.js scripts.\n\n## Available tools\n\n- `browser_navigate` — go to a URL\n- `browser_click` — click an element\n- `browser_type` — type text into an input\n- `browser_snapshot` — get an accessibility tree (YAML) of the current page\n- `browser_take_screenshot` — capture a screenshot\n- `browser_console_execute` — run JavaScript in the browser console\n\n## Why MCP tools instead of scripts\n\nMCP tools are interactive: you see the page state after each action and\ndecide what to do next. This is ideal for exploratory testing where you\nneed to adapt based on what you find. Scripts are fire-and-forget — if\na selector is wrong, you don't find out until the script fails.\n\n## Measuring DOM properties\n\nFor programmatic checks (e.g. element heights, contrast), use\n`browser_console_execute`:\n\n```javascript\n(() => {\n const els = document.querySelectorAll('input, button, [role=\"combobox\"], [role=\"button\"]');\n return JSON.stringify(Array.from(els)\n .map(el => {\n const r = el.getBoundingClientRect();\n return { tag: el.tagName, h: Math.round(r.height), top: Math.round(r.top), text: el.textContent?.trim().slice(0, 20) };\n })\n .filter(el => el.top > 50 && el.top < 250));\n})()\n```\n\n## Handling failures\n\n- Do not retry the same action more than twice — the page is in a different state than expected.\n- Diagnose before moving on: use `browser_take_screenshot` and `browser_snapshot` to see what's on the page.\n- Adapt (different selector, different path) or report the failure as a finding.\n- Never claim you verified something you didn't — if it failed and you skipped it, say so.\nEOF" + - env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + if: ${{ inputs.setup-commands != '' }} + name: Repo-specific setup + run: eval "$SETUP_COMMANDS" - name: Configure Git credentials env: @@ -543,17 +589,54 @@ jobs: const determineAutomaticLockdown = require('/opt/gh-aw/actions/determine_automatic_lockdown.cjs'); await determineAutomaticLockdown(github, context, core); - name: Download container images - run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/gh-aw-firewall/agent:0.23.0 ghcr.io/github/gh-aw-firewall/api-proxy:0.23.0 ghcr.io/github/gh-aw-firewall/squid:0.23.0 ghcr.io/github/gh-aw-mcpg:v0.1.8 ghcr.io/github/github-mcp-server:v0.31.0 node:lts-alpine + run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/gh-aw-firewall/agent:0.23.0 ghcr.io/github/gh-aw-firewall/api-proxy:0.23.0 ghcr.io/github/gh-aw-firewall/squid:0.23.0 ghcr.io/github/gh-aw-mcpg:v0.1.8 ghcr.io/github/github-mcp-server:v0.31.0 mcr.microsoft.com/playwright/mcp node:lts-alpine - name: Write Safe Outputs Config run: | mkdir -p /opt/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_pull_request":{"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"add_comment":{"max":1,"target":"${{ inputs.target-issue-number }}"},"create_pull_request":{"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF cat > /opt/gh-aw/safeoutputs/tools.json << 'GH_AW_SAFE_OUTPUTS_TOOLS_EOF' [ + { + "description": "Add a comment to an existing GitHub issue, pull request, or discussion. Use this to provide feedback, answer questions, or add information to an existing conversation. For creating new items, use create_issue, create_discussion, or create_pull_request instead. IMPORTANT: Comments are subject to validation constraints enforced by the MCP server - maximum 65536 characters for the complete comment (including footer which is added automatically), 10 mentions (@username), and 50 links. Exceeding these limits will result in an immediate error with specific guidance. NOTE: By default, this tool requires discussions:write permission. If your GitHub App lacks Discussions permission, set 'discussions: false' in the workflow's safe-outputs.add-comment configuration to exclude this permission. CONSTRAINTS: Maximum 1 comment(s) can be added. Target: ${{ inputs.target-issue-number }}.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "The comment text in Markdown format. This is the 'body' field - do not use 'comment_body' or other variations. Provide helpful, relevant information that adds value to the conversation. CONSTRAINTS: The complete comment (your body text + automatically added footer) must not exceed 65536 characters total. Maximum 10 mentions (@username), maximum 50 links (http/https URLs). A footer (~200-500 characters) is automatically appended with workflow attribution, so leave adequate space. If these limits are exceeded, the tool call will fail with a detailed error message indicating which constraint was violated.", + "type": "string" + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "item_number": { + "description": "The issue, pull request, or discussion number to comment on. This is the numeric ID from the GitHub URL (e.g., 123 in github.com/owner/repo/issues/123). Can also be a temporary_id (e.g., 'aw_abc123') from a previously created issue in the same workflow run. If omitted, the tool auto-targets the issue, PR, or discussion that triggered this workflow. Auto-targeting only works for issue, pull_request, discussion, and comment event triggers — it does NOT work for schedule, workflow_dispatch, push, or workflow_run triggers. For those trigger types, always provide item_number explicitly, or the tool call will fail with an error.", + "type": [ + "number", + "string" + ] + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + }, + "temporary_id": { + "description": "Unique temporary identifier for this comment. Format: 'aw_' followed by 3 to 12 alphanumeric characters (e.g., 'aw_abc1', 'aw_Test123'). Auto-generated if not provided. The temporary ID is returned in the tool response so you can reference this comment later.", + "pattern": "^aw_[A-Za-z0-9]{3,12}$", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "add_comment" + }, { "description": "Create a new GitHub pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created.", "inputSchema": { @@ -700,6 +783,24 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "add_comment": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "item_number": { + "issueOrPRNumber": true + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_pull_request": { "defaultMax": 1, "fields": { @@ -1066,6 +1167,7 @@ jobs: run: | set -eo pipefail mkdir -p /tmp/gh-aw/mcp-config + mkdir -p /tmp/gh-aw/mcp-logs/playwright # Export gateway environment variables for MCP config and gateway script export MCP_GATEWAY_PORT="80" @@ -1092,9 +1194,16 @@ jobs: "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", "GITHUB_READ_ONLY": "1", - "GITHUB_TOOLSETS": "repos,issues,pull_requests,search" + "GITHUB_TOOLSETS": "repos,issues,pull_requests,search,actions" } }, + "playwright": { + "type": "stdio", + "container": "mcr.microsoft.com/playwright/mcp", + "args": ["--init", "--network", "host", "--security-opt", "seccomp=unconfined", "--ipc=host"], + "entrypointArgs": ["--output-dir", "/tmp/gh-aw/mcp-logs/playwright", "--no-sandbox"], + "mounts": ["/tmp/gh-aw/mcp-logs:/tmp/gh-aw/mcp-logs:rw"] + }, "public-code-search": { "type": "http", "url": "https://public-code-search.fastmcp.app/mcp", @@ -1135,17 +1244,17 @@ jobs: - name: Execute GitHub Copilot CLI id: agentic_execution # Copilot CLI tool arguments (sorted): - timeout-minutes: 90 + timeout-minutes: 60 run: | set -o pipefail touch /tmp/gh-aw/agent-step-summary.md # shellcheck disable=SC1003 - sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains "*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com" --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.23.0 --skip-pull --enable-api-proxy \ + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --allow-domains "*.docker.com,*.docker.io,*.githubusercontent.com,*.hackage.haskell.org,*.jsr.io,*.pythonhosted.org,*.rvm.io,*.vsblob.vsassets.io,adoptium.net,agents-md-generator.fastmcp.app,anaconda.org,api.adoptium.net,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.foojay.io,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.nuget.org,api.rubygems.org,api.snapcraft.io,apt.llvm.org,apt.releases.hashicorp.com,archive.apache.org,archive.ubuntu.com,archlinux.org,artifacts.elastic.co,auth.docker.io,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,binstar.org,bitbucket.org,bootstrap.pypa.io,builds.dotnet.microsoft.com,builds.hex.pm,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.azul.com,cdn.cocoapods.org,cdn.hex.pm,cdn.jsdelivr.net,cdn.playwright.dev,cdn.redhat.com,cdn.sheetjs.com,central.sonatype.com,ci.dot.net,clojars.org,cloud.elastic.co,cocoapods.org,code.jquery.com,codeload.github.com,conda.anaconda.org,conda.binstar.org,cpan.metacpan.org,cpan.org,crates.io,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,data.jsdelivr.com,dc.services.visualstudio.com,deb.debian.org,deb.nodesource.com,debian.map.fastlydns.net,deno.land,dist.nuget.org,dl-cdn.alpinelinux.org,dl.bintray.com,dl.fedoraproject.org,dl.google.com,dl.k8s.io,dlcdn.apache.org,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,download.eclipse.org,download.fedoraproject.org,download.java.net,download.opensuse.org,download.oracle.com,download.swift.org,downloads.gradle-dn.com,downloads.haskell.org,ela.st,elastic.co,elastic.dev,elastic.github.io,esm.sh,fastly.hex.pm,files.pythonhosted.org,fonts.googleapis.com,fonts.gstatic.com,gcr.io,ge.jetbrains.com,gems.rubyforge.org,gems.rubyonrails.org,get-ghcup.haskell.org,get.pnpm.io,getcomposer.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,gradle.org,haskell.org,hex.pm,host.docker.internal,index.crates.io,index.rubygems.org,jcenter.bintray.com,jdk.java.net,jitpack.io,json-schema.org,json.schemastore.org,jsr.io,keyring.debian.org,keyserver.ubuntu.com,kotlin.bintray.com,lfs.github.com,maven.apache.org,maven.google.com,maven.oracle.com,maven.pkg.github.com,mcr.microsoft.com,metacpan.org,mirror.archlinux.org,mirror.centos.org,mirrors.fedoraproject.org,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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.debian.org,packages.jetbrains.team,packages.microsoft.com,packagist.org,pip.pypa.io,pkg.alpinelinux.org,pkg.go.dev,pkg.machengine.org,pkgs.dev.azure.com,pkgs.k8s.io,playwright.download.prss.microsoft.com,plugins-artifacts.gradle.org,plugins.gradle.org,ppa.launchpad.net,production.cloudflare.docker.com,productionresultssa0.blob.core.windows.net,productionresultssa1.blob.core.windows.net,productionresultssa10.blob.core.windows.net,productionresultssa11.blob.core.windows.net,productionresultssa12.blob.core.windows.net,productionresultssa13.blob.core.windows.net,productionresultssa14.blob.core.windows.net,productionresultssa15.blob.core.windows.net,productionresultssa16.blob.core.windows.net,productionresultssa17.blob.core.windows.net,productionresultssa18.blob.core.windows.net,productionresultssa19.blob.core.windows.net,productionresultssa2.blob.core.windows.net,productionresultssa3.blob.core.windows.net,productionresultssa4.blob.core.windows.net,productionresultssa5.blob.core.windows.net,productionresultssa6.blob.core.windows.net,productionresultssa7.blob.core.windows.net,productionresultssa8.blob.core.windows.net,productionresultssa9.blob.core.windows.net,proxy.golang.org,pub.dartlang.org,pub.dev,public-code-search.fastmcp.app,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.clojars.org,repo.continuum.io,repo.gradle.org,repo.grails.org,repo.hex.pm,repo.maven.apache.org,repo.packagist.org,repo.scala-sbt.org,repo.spring.io,repo.typesafe.com,repo.yarnpkg.com,repo1.maven.org,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,scala-ci.typesafe.com,security.debian.org,security.ubuntu.com,services.gradle.org,sh.rustup.rs,skimdb.npmjs.com,static.crates.io,static.rust-lang.org,storage.googleapis.com,sum.golang.org,swift.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,vault.centos.org,www.cpan.org,www.elastic.co,www.java.com,www.microsoft.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com,ziglang.org" --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.23.0 --skip-pull --enable-api-proxy \ -- /bin/bash -c '/usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --add-dir "${GITHUB_WORKSPACE}" --disable-builtin-mcps --allow-all-tools --allow-all-paths --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: gpt-5.3-codex + COPILOT_MODEL: ${{ inputs.model }} GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} @@ -1231,7 +1340,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} - GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com" + GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.hackage.haskell.org,*.jsr.io,*.pythonhosted.org,*.rvm.io,*.vsblob.vsassets.io,adoptium.net,agents-md-generator.fastmcp.app,anaconda.org,api.adoptium.net,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.foojay.io,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.nuget.org,api.rubygems.org,api.snapcraft.io,apt.llvm.org,apt.releases.hashicorp.com,archive.apache.org,archive.ubuntu.com,archlinux.org,artifacts.elastic.co,auth.docker.io,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,binstar.org,bitbucket.org,bootstrap.pypa.io,builds.dotnet.microsoft.com,builds.hex.pm,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.azul.com,cdn.cocoapods.org,cdn.hex.pm,cdn.jsdelivr.net,cdn.playwright.dev,cdn.redhat.com,cdn.sheetjs.com,central.sonatype.com,ci.dot.net,clojars.org,cloud.elastic.co,cocoapods.org,code.jquery.com,codeload.github.com,conda.anaconda.org,conda.binstar.org,cpan.metacpan.org,cpan.org,crates.io,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,data.jsdelivr.com,dc.services.visualstudio.com,deb.debian.org,deb.nodesource.com,debian.map.fastlydns.net,deno.land,dist.nuget.org,dl-cdn.alpinelinux.org,dl.bintray.com,dl.fedoraproject.org,dl.google.com,dl.k8s.io,dlcdn.apache.org,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,download.eclipse.org,download.fedoraproject.org,download.java.net,download.opensuse.org,download.oracle.com,download.swift.org,downloads.gradle-dn.com,downloads.haskell.org,ela.st,elastic.co,elastic.dev,elastic.github.io,esm.sh,fastly.hex.pm,files.pythonhosted.org,fonts.googleapis.com,fonts.gstatic.com,gcr.io,ge.jetbrains.com,gems.rubyforge.org,gems.rubyonrails.org,get-ghcup.haskell.org,get.pnpm.io,getcomposer.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,gradle.org,haskell.org,hex.pm,host.docker.internal,index.crates.io,index.rubygems.org,jcenter.bintray.com,jdk.java.net,jitpack.io,json-schema.org,json.schemastore.org,jsr.io,keyring.debian.org,keyserver.ubuntu.com,kotlin.bintray.com,lfs.github.com,maven.apache.org,maven.google.com,maven.oracle.com,maven.pkg.github.com,mcr.microsoft.com,metacpan.org,mirror.archlinux.org,mirror.centos.org,mirrors.fedoraproject.org,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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.debian.org,packages.jetbrains.team,packages.microsoft.com,packagist.org,pip.pypa.io,pkg.alpinelinux.org,pkg.go.dev,pkg.machengine.org,pkgs.dev.azure.com,pkgs.k8s.io,playwright.download.prss.microsoft.com,plugins-artifacts.gradle.org,plugins.gradle.org,ppa.launchpad.net,production.cloudflare.docker.com,productionresultssa0.blob.core.windows.net,productionresultssa1.blob.core.windows.net,productionresultssa10.blob.core.windows.net,productionresultssa11.blob.core.windows.net,productionresultssa12.blob.core.windows.net,productionresultssa13.blob.core.windows.net,productionresultssa14.blob.core.windows.net,productionresultssa15.blob.core.windows.net,productionresultssa16.blob.core.windows.net,productionresultssa17.blob.core.windows.net,productionresultssa18.blob.core.windows.net,productionresultssa19.blob.core.windows.net,productionresultssa2.blob.core.windows.net,productionresultssa3.blob.core.windows.net,productionresultssa4.blob.core.windows.net,productionresultssa5.blob.core.windows.net,productionresultssa6.blob.core.windows.net,productionresultssa7.blob.core.windows.net,productionresultssa8.blob.core.windows.net,productionresultssa9.blob.core.windows.net,proxy.golang.org,pub.dartlang.org,pub.dev,public-code-search.fastmcp.app,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.clojars.org,repo.continuum.io,repo.gradle.org,repo.grails.org,repo.hex.pm,repo.maven.apache.org,repo.packagist.org,repo.scala-sbt.org,repo.spring.io,repo.typesafe.com,repo.yarnpkg.com,repo1.maven.org,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,scala-ci.typesafe.com,security.debian.org,security.ubuntu.com,services.gradle.org,sh.rustup.rs,skimdb.npmjs.com,static.crates.io,static.rust-lang.org,storage.googleapis.com,sum.golang.org,swift.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,vault.centos.org,www.cpan.org,www.elastic.co,www.java.com,www.microsoft.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com,ziglang.org" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} with: @@ -1350,8 +1459,8 @@ jobs: if: always() && steps.detection_guard.outputs.run_detection == 'true' uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: - WORKFLOW_NAME: "Internal: Downstream Users" - WORKFLOW_DESCRIPTION: "Track downstream public repo usage of elastic/ai-github-actions and update data" + WORKFLOW_NAME: "Create PR From Issue" + WORKFLOW_DESCRIPTION: "Implement an issue and open a pull request" HAS_PATCH: ${{ steps.collect_output.outputs.has_patch }} with: script: | @@ -1385,7 +1494,7 @@ jobs: env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - COPILOT_MODEL: gpt-5.3-codex + COPILOT_MODEL: ${{ inputs.model }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GITHUB_API_URL: ${{ github.api_url }} GITHUB_HEAD_REF: ${{ github.head_ref }} @@ -1441,10 +1550,11 @@ jobs: runs-on: ubuntu-slim permissions: contents: write + discussions: write issues: write pull-requests: write concurrency: - group: "gh-aw-conclusion-downstream-users" + group: "gh-aw-conclusion-gh-aw-create-pr-from-issue" cancel-in-progress: false outputs: noop_message: ${{ steps.noop.outputs.noop_message }} @@ -1474,7 +1584,7 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: "1" - GH_AW_WORKFLOW_NAME: "Internal: Downstream Users" + GH_AW_WORKFLOW_NAME: "Create PR From Issue" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1487,7 +1597,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Internal: Downstream Users" + GH_AW_WORKFLOW_NAME: "Create PR From Issue" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1500,18 +1610,18 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Internal: Downstream Users" + GH_AW_WORKFLOW_NAME: "Create PR From Issue" 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: "downstream-users" + GH_AW_WORKFLOW_ID: "gh-aw-create-pr-from-issue" 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_CODE_PUSH_FAILURE_ERRORS: ${{ needs.safe_outputs.outputs.code_push_failure_errors }} GH_AW_CODE_PUSH_FAILURE_COUNT: ${{ needs.safe_outputs.outputs.code_push_failure_count }} - GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || format('---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {0}]({{run_url}})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.', github.workflow) }}\"}" + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || format('---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {0}]({{run_url}})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.', github.workflow) }}\",\"activationComments\":\"false\"}" GH_AW_GROUP_REPORTS: "false" - GH_AW_TIMEOUT_MINUTES: "90" + GH_AW_TIMEOUT_MINUTES: "60" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1524,7 +1634,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Internal: Downstream Users" + GH_AW_WORKFLOW_NAME: "Create PR From Issue" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_NOOP_MESSAGE: ${{ steps.noop.outputs.noop_message }} @@ -1541,7 +1651,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: "Internal: Downstream Users" + GH_AW_WORKFLOW_NAME: "Create PR From Issue" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1551,6 +1661,29 @@ jobs: const { main } = require('/opt/gh-aw/actions/handle_create_pr_error.cjs'); await main(); + pre_activation: + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + matched_command: '' + steps: + - name: Setup Scripts + uses: github/gh-aw/actions/setup@956f874e40e831c08a8b01ec76f5d49ae3fe8387 # v0.53.6 + with: + destination: /opt/gh-aw/actions + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REQUIRED_ROLES: admin,maintainer,write + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/check_membership.cjs'); + await main(); + safe_outputs: needs: - activation @@ -1559,19 +1692,22 @@ jobs: runs-on: ubuntu-slim permissions: contents: write + discussions: write issues: write pull-requests: write timeout-minutes: 15 env: - GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/downstream-users" + GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/gh-aw-create-pr-from-issue" GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: "gpt-5.3-codex" - GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || format('---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {0}]({{run_url}})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.', github.workflow) }}\"}" - GH_AW_WORKFLOW_ID: "downstream-users" - GH_AW_WORKFLOW_NAME: "Internal: Downstream Users" + GH_AW_ENGINE_MODEL: "${{ inputs.model }}" + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || format('---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {0}]({{run_url}})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.', github.workflow) }}\",\"activationComments\":\"false\"}" + GH_AW_WORKFLOW_ID: "gh-aw-create-pr-from-issue" + GH_AW_WORKFLOW_NAME: "Create PR From Issue" outputs: 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 }} + comment_id: ${{ steps.process_safe_outputs.outputs.comment_id }} + comment_url: ${{ steps.process_safe_outputs.outputs.comment_url }} 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_pr_number: ${{ steps.process_safe_outputs.outputs.created_pr_number }} @@ -1629,11 +1765,11 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.jsr.io,*.pythonhosted.org,*.rvm.io,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.rubygems.org,api.snapcraft.io,archive.ubuntu.com,artifacts.elastic.co,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.jsdelivr.net,cloud.elastic.co,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,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,deb.nodesource.com,deno.land,ela.st,elastic.co,esm.sh,files.pythonhosted.org,gems.rubyforge.org,gems.rubyonrails.org,get.pnpm.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,host.docker.internal,index.crates.io,index.rubygems.org,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,lfs.github.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,public-code-search.fastmcp.app,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,sum.golang.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.elastic.co,www.npmjs.com,www.npmjs.org,yarnpkg.com" + GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.hackage.haskell.org,*.jsr.io,*.pythonhosted.org,*.rvm.io,*.vsblob.vsassets.io,adoptium.net,agents-md-generator.fastmcp.app,anaconda.org,api.adoptium.net,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.foojay.io,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.nuget.org,api.rubygems.org,api.snapcraft.io,apt.llvm.org,apt.releases.hashicorp.com,archive.apache.org,archive.ubuntu.com,archlinux.org,artifacts.elastic.co,auth.docker.io,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,binstar.org,bitbucket.org,bootstrap.pypa.io,builds.dotnet.microsoft.com,builds.hex.pm,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.azul.com,cdn.cocoapods.org,cdn.hex.pm,cdn.jsdelivr.net,cdn.playwright.dev,cdn.redhat.com,cdn.sheetjs.com,central.sonatype.com,ci.dot.net,clojars.org,cloud.elastic.co,cocoapods.org,code.jquery.com,codeload.github.com,conda.anaconda.org,conda.binstar.org,cpan.metacpan.org,cpan.org,crates.io,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,data.jsdelivr.com,dc.services.visualstudio.com,deb.debian.org,deb.nodesource.com,debian.map.fastlydns.net,deno.land,dist.nuget.org,dl-cdn.alpinelinux.org,dl.bintray.com,dl.fedoraproject.org,dl.google.com,dl.k8s.io,dlcdn.apache.org,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,download.eclipse.org,download.fedoraproject.org,download.java.net,download.opensuse.org,download.oracle.com,download.swift.org,downloads.gradle-dn.com,downloads.haskell.org,ela.st,elastic.co,elastic.dev,elastic.github.io,esm.sh,fastly.hex.pm,files.pythonhosted.org,fonts.googleapis.com,fonts.gstatic.com,gcr.io,ge.jetbrains.com,gems.rubyforge.org,gems.rubyonrails.org,get-ghcup.haskell.org,get.pnpm.io,getcomposer.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,gradle.org,haskell.org,hex.pm,host.docker.internal,index.crates.io,index.rubygems.org,jcenter.bintray.com,jdk.java.net,jitpack.io,json-schema.org,json.schemastore.org,jsr.io,keyring.debian.org,keyserver.ubuntu.com,kotlin.bintray.com,lfs.github.com,maven.apache.org,maven.google.com,maven.oracle.com,maven.pkg.github.com,mcr.microsoft.com,metacpan.org,mirror.archlinux.org,mirror.centos.org,mirrors.fedoraproject.org,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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.debian.org,packages.jetbrains.team,packages.microsoft.com,packagist.org,pip.pypa.io,pkg.alpinelinux.org,pkg.go.dev,pkg.machengine.org,pkgs.dev.azure.com,pkgs.k8s.io,playwright.download.prss.microsoft.com,plugins-artifacts.gradle.org,plugins.gradle.org,ppa.launchpad.net,production.cloudflare.docker.com,productionresultssa0.blob.core.windows.net,productionresultssa1.blob.core.windows.net,productionresultssa10.blob.core.windows.net,productionresultssa11.blob.core.windows.net,productionresultssa12.blob.core.windows.net,productionresultssa13.blob.core.windows.net,productionresultssa14.blob.core.windows.net,productionresultssa15.blob.core.windows.net,productionresultssa16.blob.core.windows.net,productionresultssa17.blob.core.windows.net,productionresultssa18.blob.core.windows.net,productionresultssa19.blob.core.windows.net,productionresultssa2.blob.core.windows.net,productionresultssa3.blob.core.windows.net,productionresultssa4.blob.core.windows.net,productionresultssa5.blob.core.windows.net,productionresultssa6.blob.core.windows.net,productionresultssa7.blob.core.windows.net,productionresultssa8.blob.core.windows.net,productionresultssa9.blob.core.windows.net,proxy.golang.org,pub.dartlang.org,pub.dev,public-code-search.fastmcp.app,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.clojars.org,repo.continuum.io,repo.gradle.org,repo.grails.org,repo.hex.pm,repo.maven.apache.org,repo.packagist.org,repo.scala-sbt.org,repo.spring.io,repo.typesafe.com,repo.yarnpkg.com,repo1.maven.org,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,scala-ci.typesafe.com,security.debian.org,security.ubuntu.com,services.gradle.org,sh.rustup.rs,skimdb.npmjs.com,static.crates.io,static.rust-lang.org,storage.googleapis.com,sum.golang.org,swift.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,vault.centos.org,www.cpan.org,www.elastic.co,www.java.com,www.microsoft.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com,ziglang.org" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"draft\":false,\"max\":1,\"max_patch_size\":10240},\"missing_data\":{},\"missing_tool\":{}}" - GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"${{ inputs.target-issue-number }}\"},\"create_pull_request\":{\"draft\":\"${{ inputs.draft-prs }}\",\"max\":1,\"max_patch_size\":10240},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.EXTRA_COMMIT_GITHUB_TOKEN }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-create-pr-from-issue.md b/.github/workflows/gh-aw-create-pr-from-issue.md new file mode 100644 index 00000000..2e8cf547 --- /dev/null +++ b/.github/workflows/gh-aw-create-pr-from-issue.md @@ -0,0 +1,116 @@ +--- +inlined-imports: true +name: "Create PR From Issue" +description: "Implement an issue and open a pull request" +imports: + - gh-aw-fragments/elastic-tools.md + - gh-aw-fragments/runtime-setup.md + - gh-aw-fragments/formatting.md + - gh-aw-fragments/rigor.md + - gh-aw-fragments/mcp-pagination.md + - gh-aw-fragments/workflow-edit-guardrails.md + - gh-aw-fragments/messages-footer.md + - gh-aw-fragments/playwright-mcp-explorer.md + - gh-aw-fragments/safe-output-add-comment-issue.md + - gh-aw-fragments/safe-output-create-pr.md + - gh-aw-fragments/network-ecosystems.md +engine: + id: copilot + model: ${{ inputs.model }} + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}-create-pr-from-issue-${{ inputs.target-issue-number }}" +on: + workflow_call: + inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" + target-issue-number: + description: "Issue number to implement" + type: string + required: true + prompt: + description: "Additional implementation instructions" + type: string + required: false + default: "" + additional-instructions: + description: "Repo-specific instructions appended to the agent prompt" + type: string + required: false + default: "" + setup-commands: + description: "Shell commands to run before the agent starts (dependency install, build, etc.)" + type: string + required: false + default: "" + messages-footer: + description: "Footer appended to all agent comments and reviews" + type: string + required: false + default: "" + draft-prs: + description: "Whether to create pull requests as drafts" + type: boolean + required: false + default: true + secrets: + COPILOT_GITHUB_TOKEN: + required: true + EXTRA_COMMIT_GITHUB_TOKEN: + required: false +concurrency: + group: ${{ github.workflow }}-create-pr-from-issue-${{ inputs.target-issue-number }} + cancel-in-progress: true +permissions: + actions: read + contents: read + issues: read + pull-requests: read +tools: + github: + toolsets: [repos, issues, pull_requests, search, actions] + bash: true + web-fetch: +strict: false +safe-outputs: + activation-comments: false + max-patch-size: 10240 + add-comment: + target: "${{ inputs.target-issue-number }}" +timeout-minutes: 60 +steps: + - name: Repo-specific setup + if: ${{ inputs.setup-commands != '' }} + env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + run: eval "$SETUP_COMMANDS" +--- + +# Create PR From Issue + +Implement issue #${{ inputs.target-issue-number }} on ${{ github.repository }} and open a pull request. + +## Context + +- **Repository**: ${{ github.repository }} +- **Issue**: #${{ inputs.target-issue-number }} +- **Additional request**: "${{ inputs.prompt }}" + +## Constraints + +- **CAN**: Read files, search code, modify files locally, run tests and commands, comment on the targeted issue, create pull requests +- **CANNOT**: Directly push or commit to the repository — use `ready_to_make_pr` then `create_pull_request` to propose changes + +## Instructions + +1. Read issue #${{ inputs.target-issue-number }} first to understand requirements and acceptance criteria. +2. Investigate the relevant code paths and implement a focused fix for the issue. +3. Run required repo checks (lint/build/test) relevant to your change. If required commands cannot run, explain why and do not open a PR. +4. Call `ready_to_make_pr` and apply its checklist. +5. Call `create_pull_request` with a clear title/body that references and closes issue #${{ inputs.target-issue-number }}. +6. If implementation is blocked or unclear, call `add_comment` on the issue with a concise status update and concrete next step. + +${{ inputs.additional-instructions }} diff --git a/.github/workflows/gh-aw-flaky-test-investigator.lock.yml b/.github/workflows/gh-aw-flaky-test-investigator.lock.yml index 4dd6ef1f..6f9d1032 100644 --- a/.github/workflows/gh-aw-flaky-test-investigator.lock.yml +++ b/.github/workflows/gh-aw-flaky-test-investigator.lock.yml @@ -38,7 +38,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"ddfeae69bd92b1952dc909a02cc03098273550767fca4f372d667ef26cd56e7d"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"65df487b67429d25ac7d30b444404b85aa016d89fcc3a48b6a09cde76c0e1bad"} name: "Flaky Test Investigator" "on": @@ -406,17 +406,30 @@ jobs: - Do not report one-off or non-reproducible failures lacking repeat evidence. - Do not include items already tracked by a current open issue/PR unless new, material evidence changes prioritization. + ### Triage Reports (When Root Cause Is Unclear) + + When a **clear repeated failure pattern** exists (3+ occurrences across different runs) but the root cause cannot be definitively identified from available CI logs alone, file a **triage report** instead of a full investigation. A triage report: + + - Documents the failure pattern (test name, frequency, error signatures) + - Lists affected runs with links + - Provides candidate hypotheses ranked by likelihood based on available evidence + - Suggests concrete investigation steps a developer could take (e.g., "add timing instrumentation to X", "check if Y resource is shared across parallel jobs") + - Does NOT recommend retries, timeouts, or quarantine as solutions + + Use the issue title format: `Flaky pattern: [test name] — triage needed` + ### Quality Gate — When to Noop Call `noop` when: - - no repeated flaky pattern is found, or + - no repeated flaky pattern is found (fewer than 3 occurrences), or - all repeated failures are already actively tracked with sufficient detail, or - - a root cause cannot be clearly identified from the available evidence, or - - the only available remediation is a workaround (retry, timeout, quarantine) rather than a true fix. + - the failure occurred only once and lacks repeat evidence. ### Issue Format - **Issue title:** Brief flaky-test investigation summary for the window + **Issue title:** + - Root cause identified: Brief flaky-test investigation summary for the window + - Root cause unclear but repeated pattern exists: `Flaky pattern: [test name] — triage needed` **Issue body:** @@ -431,11 +444,15 @@ jobs: > - Frequency: [count] > - Representative error: [short snippet] > - > **Root cause:** [specific, evidence-based — only include if truly identified; otherwise do not file an issue] - > **Recommended fix:** [concrete root-cause fix steps] + > **Root cause:** [specific, evidence-based — include only when truly identified] + > **Recommended fix:** [concrete root-cause fix steps — include only when root cause is identified] + > + > **If triage report:** + > - Candidate hypotheses: [ranked by likelihood] + > - Suggested investigation steps: [concrete next checks] > > ## Suggested Actions - > - [ ] [Concrete fix task] + > - [ ] [Concrete fix task or investigation task] > - [ ] [Validation task to confirm stability] __GH_AW_EXPR_49B959F1__ diff --git a/.github/workflows/gh-aw-flaky-test-investigator.md b/.github/workflows/gh-aw-flaky-test-investigator.md index b3db44c5..69e87c06 100644 --- a/.github/workflows/gh-aw-flaky-test-investigator.md +++ b/.github/workflows/gh-aw-flaky-test-investigator.md @@ -119,17 +119,30 @@ Detect flaky tests by combining open issues likely related to flakiness and rece - Do not report one-off or non-reproducible failures lacking repeat evidence. - Do not include items already tracked by a current open issue/PR unless new, material evidence changes prioritization. +### Triage Reports (When Root Cause Is Unclear) + +When a **clear repeated failure pattern** exists (3+ occurrences across different runs) but the root cause cannot be definitively identified from available CI logs alone, file a **triage report** instead of a full investigation. A triage report: + +- Documents the failure pattern (test name, frequency, error signatures) +- Lists affected runs with links +- Provides candidate hypotheses ranked by likelihood based on available evidence +- Suggests concrete investigation steps a developer could take (e.g., "add timing instrumentation to X", "check if Y resource is shared across parallel jobs") +- Does NOT recommend retries, timeouts, or quarantine as solutions + +Use the issue title format: `Flaky pattern: [test name] — triage needed` + ### Quality Gate — When to Noop Call `noop` when: -- no repeated flaky pattern is found, or +- no repeated flaky pattern is found (fewer than 3 occurrences), or - all repeated failures are already actively tracked with sufficient detail, or -- a root cause cannot be clearly identified from the available evidence, or -- the only available remediation is a workaround (retry, timeout, quarantine) rather than a true fix. +- the failure occurred only once and lacks repeat evidence. ### Issue Format -**Issue title:** Brief flaky-test investigation summary for the window +**Issue title:** +- Root cause identified: Brief flaky-test investigation summary for the window +- Root cause unclear but repeated pattern exists: `Flaky pattern: [test name] — triage needed` **Issue body:** @@ -144,11 +157,15 @@ Call `noop` when: > - Frequency: [count] > - Representative error: [short snippet] > -> **Root cause:** [specific, evidence-based — only include if truly identified; otherwise do not file an issue] -> **Recommended fix:** [concrete root-cause fix steps] +> **Root cause:** [specific, evidence-based — include only when truly identified] +> **Recommended fix:** [concrete root-cause fix steps — include only when root cause is identified] +> +> **If triage report:** +> - Candidate hypotheses: [ranked by likelihood] +> - Suggested investigation steps: [concrete next checks] > > ## Suggested Actions -> - [ ] [Concrete fix task] +> - [ ] [Concrete fix task or investigation task] > - [ ] [Validation task to confirm stability] ${{ inputs.additional-instructions }} diff --git a/.github/workflows/gh-aw-fragments/code-quality-audit.md b/.github/workflows/gh-aw-fragments/code-quality-audit.md new file mode 100644 index 00000000..658f7148 --- /dev/null +++ b/.github/workflows/gh-aw-fragments/code-quality-audit.md @@ -0,0 +1,46 @@ +Analyze the codebase for quality issues and file a structured report when concrete, actionable findings exist. + +**The bar is high: only report issues backed by specific code evidence.** Most runs should end with `noop` — that means the code is in good shape for the dimension being audited. Filing nothing is a success when there is nothing worth filing. + +### Severity Threshold: `${{ inputs.severity-threshold }}` + +Only include findings at or above the configured severity. Severity labels and meanings are defined by the importing workflow; this fragment uses the importing workflow's `${{ inputs.severity-threshold }}` semantics. + +### Evidence Standard + +Every finding must include **all** of the following. Findings missing any element must be dropped: + +1. **Location** — File path(s) and precise location context (line numbers when available or another unambiguous locator required by the importing workflow). +2. **Evidence** — The specific code or configuration that exhibits the issue. +3. **What is wrong** — A clear, concrete explanation of the problem. Not "this could be better" but "this does X when it should do Y" or "this violates [specific standard/guideline]." +4. **Why it matters** — Concrete impact: who is affected, what breaks, what degrades, or what standard is violated. Reference the specific standard, guideline, or documentation (e.g., WCAG 2.1 SC 4.1.2, React docs on exhaustive-deps, framework migration guide). +5. **Suggested fix** — A concrete code change or approach, not a vague recommendation. + +### Verification Pass (Required) + +After gathering findings from sub-agents, verify each one yourself: + +1. Read the file at the cited path and confirm the line numbers are accurate. +2. Confirm the code snippet matches what is actually in the file. +3. Confirm the issue is real — not a false positive from misunderstanding the code's intent. +4. Confirm the suggested fix would not break existing behavior. +5. Drop any finding where verification fails. + +### Quality Gate — When to Noop + +Call `noop` if any of these are true: +- No findings survive the verification pass. +- All findings are below the severity threshold. +- All findings are already tracked by open issues. +- All findings are subjective style preferences rather than concrete quality issues. +- You cannot provide specific file paths and line numbers for any finding. + +### Consolidation Rules + +- Group related findings (e.g., the same anti-pattern in multiple files) into a single numbered section. +- Prefer fewer, denser issues over frequent thin issues. +- If a pattern appears in many files, do a completeness pass: search the repo for all occurrences and list them, so maintainers can fix the whole family at once. + +### Output Contract + +Follow the importing workflow's issue title/body template. This shared fragment defines quality gates and evidence requirements only; per-workflow report schemas remain source-of-truth for final output format. diff --git a/.github/workflows/gh-aw-framework-best-practices.lock.yml b/.github/workflows/gh-aw-framework-best-practices.lock.yml index fef80be0..65408c3f 100644 --- a/.github/workflows/gh-aw-framework-best-practices.lock.yml +++ b/.github/workflows/gh-aw-framework-best-practices.lock.yml @@ -25,6 +25,7 @@ # # Resolved workflow manifest: # Imports: +# - gh-aw-fragments/code-quality-audit.md # - gh-aw-fragments/elastic-tools.md # - gh-aw-fragments/formatting.md # - gh-aw-fragments/mcp-pagination.md @@ -39,7 +40,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"48f7b47de6a6dacc43100a0988cb783441ec01f4fa14443520b239c22e347813"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"e6a8d8202cf666f3f1f6dbdecc02bffe040baaefce19d17428f81964f752ef00"} name: "Framework Best Practices" "on": @@ -70,6 +71,11 @@ name: "Framework Best Practices" description: Shell commands to run before the agent starts (dependency install, build, etc.) required: false type: string + severity-threshold: + default: medium + description: Minimum severity to include in the report. 'high' = only clear simplifications that reduce complexity or fix bugs. 'medium' (default) = also include missed library features that improve maintainability. 'low' = also include minor underuse patterns. + required: false + type: string title-prefix: default: "[framework-best-practices]" description: Title prefix for created issues (e.g. '[framework-best-practices]') @@ -161,6 +167,7 @@ jobs: env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_EXPR_08E89BCD: ${{ inputs.severity-threshold }} GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} GH_AW_EXPR_BF503D80: ${{ inputs.title-prefix }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} @@ -399,6 +406,55 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + Analyze the codebase for quality issues and file a structured report when concrete, actionable findings exist. + + **The bar is high: only report issues backed by specific code evidence.** Most runs should end with `noop` — that means the code is in good shape for the dimension being audited. Filing nothing is a success when there is nothing worth filing. + + ### Severity Threshold: `__GH_AW_EXPR_08E89BCD__` + + Only include findings at or above the configured severity. Severity labels and meanings are defined by the importing workflow; this fragment uses the importing workflow's `__GH_AW_EXPR_08E89BCD__` semantics. + + ### Evidence Standard + + Every finding must include **all** of the following. Findings missing any element must be dropped: + + 1. **Location** — File path(s) and precise location context (line numbers when available or another unambiguous locator required by the importing workflow). + 2. **Evidence** — The specific code or configuration that exhibits the issue. + 3. **What is wrong** — A clear, concrete explanation of the problem. Not "this could be better" but "this does X when it should do Y" or "this violates [specific standard/guideline]." + 4. **Why it matters** — Concrete impact: who is affected, what breaks, what degrades, or what standard is violated. Reference the specific standard, guideline, or documentation (e.g., WCAG 2.1 SC 4.1.2, React docs on exhaustive-deps, framework migration guide). + 5. **Suggested fix** — A concrete code change or approach, not a vague recommendation. + + ### Verification Pass (Required) + + After gathering findings from sub-agents, verify each one yourself: + + 1. Read the file at the cited path and confirm the line numbers are accurate. + 2. Confirm the code snippet matches what is actually in the file. + 3. Confirm the issue is real — not a false positive from misunderstanding the code's intent. + 4. Confirm the suggested fix would not break existing behavior. + 5. Drop any finding where verification fails. + + ### Quality Gate — When to Noop + + Call `noop` if any of these are true: + - No findings survive the verification pass. + - All findings are below the severity threshold. + - All findings are already tracked by open issues. + - All findings are subjective style preferences rather than concrete quality issues. + - You cannot provide specific file paths and line numbers for any finding. + + ### Consolidation Rules + + - Group related findings (e.g., the same anti-pattern in multiple files) into a single numbered section. + - Prefer fewer, denser issues over frequent thin issues. + - If a pattern appears in many files, do a completeness pass: search the repo for all occurrences and list them, so maintainers can fix the whole family at once. + + ### Output Contract + + Follow the importing workflow's issue title/body template. This shared fragment defines quality gates and evidence requirements only; per-workflow report schemas remain source-of-truth for final output format. + GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' You are the Framework & Library Best Practices Analyst — an expert in the libraries and frameworks used by this project who identifies opportunities to leverage built-in features instead of hand-rolled solutions. @@ -488,6 +544,7 @@ jobs: env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_INPUTS_MODEL: ${{ inputs.model }} + GH_AW_EXPR_08E89BCD: ${{ inputs.severity-threshold }} GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} GH_AW_EXPR_BF503D80: ${{ inputs.title-prefix }} with: @@ -500,6 +557,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_08E89BCD: ${{ inputs.severity-threshold }} GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} GH_AW_EXPR_BF503D80: ${{ inputs.title-prefix }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} @@ -523,6 +581,7 @@ jobs: return await substitutePlaceholders({ file: process.env.GH_AW_PROMPT, substitutions: { + GH_AW_EXPR_08E89BCD: process.env.GH_AW_EXPR_08E89BCD, GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, GH_AW_EXPR_BF503D80: process.env.GH_AW_EXPR_BF503D80, GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, diff --git a/.github/workflows/gh-aw-framework-best-practices.md b/.github/workflows/gh-aw-framework-best-practices.md index 2ad1148e..547fd50a 100644 --- a/.github/workflows/gh-aw-framework-best-practices.md +++ b/.github/workflows/gh-aw-framework-best-practices.md @@ -14,6 +14,7 @@ imports: - gh-aw-fragments/pick-three-keep-many.md - gh-aw-fragments/scheduled-audit.md - gh-aw-fragments/network-ecosystems.md + - gh-aw-fragments/code-quality-audit.md engine: id: copilot model: ${{ inputs.model }} @@ -45,6 +46,11 @@ on: type: string required: false default: "" + severity-threshold: + description: "Minimum severity to include in the report. 'high' = only clear simplifications that reduce complexity or fix bugs. 'medium' (default) = also include missed library features that improve maintainability. 'low' = also include minor underuse patterns." + type: string + required: false + default: "medium" title-prefix: description: "Title prefix for created issues (e.g. '[framework-best-practices]')" type: string diff --git a/.github/workflows/gh-aw-issue-fixer.lock.yml b/.github/workflows/gh-aw-issue-fixer.lock.yml index aa465b4e..3253cf69 100644 --- a/.github/workflows/gh-aw-issue-fixer.lock.yml +++ b/.github/workflows/gh-aw-issue-fixer.lock.yml @@ -38,7 +38,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"3f8604d2661901ac3e0c22ef174672b3855e8fb1e0e9a6be6e20a7d020005166"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"4c61ea6aae5e219787a291bb56ca9b04d74e76b426e2aed6b55134aa8b57100e"} name: "Issue Fixer" "on": @@ -409,7 +409,7 @@ jobs: ### Step 4: Post Response 1. Call `add_comment` with your triage response. - 2. If you implemented a valid fix with verification, call `create_pull_request` to open a draft PR. + 2. If you implemented a valid fix with verification, call `ready_to_make_pr` and then `create_pull_request` to open a draft PR. __GH_AW_EXPR_49B959F1__ diff --git a/.github/workflows/gh-aw-issue-fixer.md b/.github/workflows/gh-aw-issue-fixer.md index 71520bf0..2aff6a0e 100644 --- a/.github/workflows/gh-aw-issue-fixer.md +++ b/.github/workflows/gh-aw-issue-fixer.md @@ -144,6 +144,6 @@ Use `
` and `` tags for sections that would otherwise make the ### Step 4: Post Response 1. Call `add_comment` with your triage response. -2. If you implemented a valid fix with verification, call `create_pull_request` to open a draft PR. +2. If you implemented a valid fix with verification, call `ready_to_make_pr` and then `create_pull_request` to open a draft PR. ${{ inputs.additional-instructions }} diff --git a/.github/workflows/gh-aw-mention-in-issue-by-id.lock.yml b/.github/workflows/gh-aw-mention-in-issue-by-id.lock.yml index 34b78a1e..b14dd5c7 100644 --- a/.github/workflows/gh-aw-mention-in-issue-by-id.lock.yml +++ b/.github/workflows/gh-aw-mention-in-issue-by-id.lock.yml @@ -40,7 +40,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"1b43c78d22ccbf7485f143ca0ccd427535b5a047b544c900e43eb9076baef415"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"a6d4a049f8943ea3f5ec7a9f23f77eff499f206900f38e7fc00e311c9bd32395"} name: "Mention in Issue by ID" "on": @@ -376,9 +376,9 @@ jobs: ## Constraints - **CAN**: Read files, search code, modify files locally, run tests and commands, comment on the targeted issue, create pull requests, create issues - - **CANNOT**: Directly push or commit to the repository - use `create_pull_request` to propose changes + - **CANNOT**: Directly push or commit to the repository - use `ready_to_make_pr` then `create_pull_request` to propose changes - When creating pull requests, make the changes in the workspace first, then use `create_pull_request` - branches are managed automatically. + When creating pull requests, make the changes in the workspace first, call `ready_to_make_pr`, then use `create_pull_request` - branches are managed automatically. ## Instructions @@ -386,7 +386,7 @@ jobs: 2. Handle the request in `__GH_AW_INPUTS_PROMPT__` with focused investigation and evidence from the codebase. 3. Do not comment on any issue except #__GH_AW_EXPR_EA5D66D8__. 4. Use safe outputs only against issue #__GH_AW_EXPR_EA5D66D8__ when commenting. - 5. If asked to implement changes, make edits in the workspace and use `create_pull_request`. + 5. If asked to implement changes, make edits in the workspace, call `ready_to_make_pr`, then use `create_pull_request`. 6. If no code or PR action is needed, call `add_comment` with a concise, actionable response. __GH_AW_EXPR_49B959F1__ diff --git a/.github/workflows/gh-aw-mention-in-issue-by-id.md b/.github/workflows/gh-aw-mention-in-issue-by-id.md index 48450d51..cd018c61 100644 --- a/.github/workflows/gh-aw-mention-in-issue-by-id.md +++ b/.github/workflows/gh-aw-mention-in-issue-by-id.md @@ -102,9 +102,9 @@ Assist with issue #${{ inputs.target-issue-number }} on ${{ github.repository }} ## Constraints - **CAN**: Read files, search code, modify files locally, run tests and commands, comment on the targeted issue, create pull requests, create issues -- **CANNOT**: Directly push or commit to the repository - use `create_pull_request` to propose changes +- **CANNOT**: Directly push or commit to the repository - use `ready_to_make_pr` then `create_pull_request` to propose changes -When creating pull requests, make the changes in the workspace first, then use `create_pull_request` - branches are managed automatically. +When creating pull requests, make the changes in the workspace first, call `ready_to_make_pr`, then use `create_pull_request` - branches are managed automatically. ## Instructions @@ -112,7 +112,7 @@ When creating pull requests, make the changes in the workspace first, then use ` 2. Handle the request in `${{ inputs.prompt }}` with focused investigation and evidence from the codebase. 3. Do not comment on any issue except #${{ inputs.target-issue-number }}. 4. Use safe outputs only against issue #${{ inputs.target-issue-number }} when commenting. -5. If asked to implement changes, make edits in the workspace and use `create_pull_request`. +5. If asked to implement changes, make edits in the workspace, call `ready_to_make_pr`, then use `create_pull_request`. 6. If no code or PR action is needed, call `add_comment` with a concise, actionable response. ${{ inputs.additional-instructions }} diff --git a/.github/workflows/gh-aw-mention-in-issue-no-sandbox.lock.yml b/.github/workflows/gh-aw-mention-in-issue-no-sandbox.lock.yml index b3e36118..9cc5ad52 100644 --- a/.github/workflows/gh-aw-mention-in-issue-no-sandbox.lock.yml +++ b/.github/workflows/gh-aw-mention-in-issue-no-sandbox.lock.yml @@ -40,7 +40,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"14be01b9072069d5f1aade5729de2a8bf478ee6b52835f31e45644797c2c0b8d"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"5d3c3e082b16755cd90eb24df0808db7bcbe5ca30cf885c8b597ada6aec71681"} name: "Mention in Issue (no sandbox)" "on": @@ -403,9 +403,9 @@ jobs: ## Constraints - **CAN**: Read files, search code, modify files locally, run tests and commands, comment on issues, create pull requests, create issues - - **CANNOT**: Directly push or commit to the repository — use `create_pull_request` to propose changes + - **CANNOT**: Directly push or commit to the repository — use `ready_to_make_pr` then `create_pull_request` to propose changes - When creating pull requests, make the changes in the workspace first, then use `create_pull_request` — branches are managed automatically. + When creating pull requests, make the changes in the workspace first, call `ready_to_make_pr`, then use `create_pull_request` — branches are managed automatically. ## Instructions @@ -425,7 +425,7 @@ jobs: - **Debug reported problems** — reproduce locally, run required repo commands (lint/build/test) from README, CONTRIBUTING, DEVELOPING, Makefile, or CI config, and trace the code path - **Suggest solutions** — provide concrete code examples and implementation guidance - **Clarify requirements** — ask follow-up questions if the request is ambiguous - - **Create a PR** — if asked to implement something, make the changes in the workspace, then use `create_pull_request` to submit them + - **Create a PR** — if asked to implement something, make the changes in the workspace, call `ready_to_make_pr`, then use `create_pull_request` to submit them When making code changes, identify and run required repo commands (lint/build/test) from README, CONTRIBUTING, DEVELOPING, Makefile, or CI config and include results. If required commands cannot be run, explain why. @@ -434,6 +434,7 @@ jobs: Call `add_comment` with your response. Be concise and actionable — no filler or praise. If the request is unclear, ask clarifying questions rather than guessing. **Additional tools:** + - `ready_to_make_pr` — run pre-PR safety checks before opening a PR - `create_pull_request` — create a PR with your changes - `create_issue` — create a new issue (e.g. to split off sub-tasks) diff --git a/.github/workflows/gh-aw-mention-in-issue-no-sandbox.md b/.github/workflows/gh-aw-mention-in-issue-no-sandbox.md index 0f005bbf..6bf719be 100644 --- a/.github/workflows/gh-aw-mention-in-issue-no-sandbox.md +++ b/.github/workflows/gh-aw-mention-in-issue-no-sandbox.md @@ -104,9 +104,9 @@ Assist with issues on ${{ github.repository }} — answer questions, debug probl ## Constraints - **CAN**: Read files, search code, modify files locally, run tests and commands, comment on issues, create pull requests, create issues -- **CANNOT**: Directly push or commit to the repository — use `create_pull_request` to propose changes +- **CANNOT**: Directly push or commit to the repository — use `ready_to_make_pr` then `create_pull_request` to propose changes -When creating pull requests, make the changes in the workspace first, then use `create_pull_request` — branches are managed automatically. +When creating pull requests, make the changes in the workspace first, call `ready_to_make_pr`, then use `create_pull_request` — branches are managed automatically. ## Instructions @@ -126,7 +126,7 @@ Based on the request, do what's appropriate: - **Debug reported problems** — reproduce locally, run required repo commands (lint/build/test) from README, CONTRIBUTING, DEVELOPING, Makefile, or CI config, and trace the code path - **Suggest solutions** — provide concrete code examples and implementation guidance - **Clarify requirements** — ask follow-up questions if the request is ambiguous -- **Create a PR** — if asked to implement something, make the changes in the workspace, then use `create_pull_request` to submit them +- **Create a PR** — if asked to implement something, make the changes in the workspace, call `ready_to_make_pr`, then use `create_pull_request` to submit them When making code changes, identify and run required repo commands (lint/build/test) from README, CONTRIBUTING, DEVELOPING, Makefile, or CI config and include results. If required commands cannot be run, explain why. @@ -135,6 +135,7 @@ When making code changes, identify and run required repo commands (lint/build/te Call `add_comment` with your response. Be concise and actionable — no filler or praise. If the request is unclear, ask clarifying questions rather than guessing. **Additional tools:** +- `ready_to_make_pr` — run pre-PR safety checks before opening a PR - `create_pull_request` — create a PR with your changes - `create_issue` — create a new issue (e.g. to split off sub-tasks) diff --git a/.github/workflows/gh-aw-mention-in-issue.lock.yml b/.github/workflows/gh-aw-mention-in-issue.lock.yml index 328f922f..418b8331 100644 --- a/.github/workflows/gh-aw-mention-in-issue.lock.yml +++ b/.github/workflows/gh-aw-mention-in-issue.lock.yml @@ -40,7 +40,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"898e05c33b2f60cdeaebb052f6bef75fea9b8063480993cad0489673e2be51be"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"9ec1760f93b0001cac4ce1b53ebaa5fe7fd41cd668b43ed275af7007bdc2893b"} name: "Mention in Issue" "on": @@ -403,9 +403,9 @@ jobs: ## Constraints - **CAN**: Read files, search code, modify files locally, run tests and commands, comment on issues, create pull requests, create issues - - **CANNOT**: Directly push or commit to the repository — use `create_pull_request` to propose changes + - **CANNOT**: Directly push or commit to the repository — use `ready_to_make_pr` then `create_pull_request` to propose changes - When creating pull requests, make the changes in the workspace first, then use `create_pull_request` — branches are managed automatically. + When creating pull requests, make the changes in the workspace first, call `ready_to_make_pr`, then use `create_pull_request` — branches are managed automatically. ## Instructions @@ -425,7 +425,7 @@ jobs: - **Debug reported problems** — reproduce locally, run required repo commands (lint/build/test) from README, CONTRIBUTING, DEVELOPING, Makefile, or CI config, and trace the code path - **Suggest solutions** — provide concrete code examples and implementation guidance - **Clarify requirements** — ask follow-up questions if the request is ambiguous - - **Create a PR** — if asked to implement something, make the changes in the workspace, then use `create_pull_request` to submit them + - **Create a PR** — if asked to implement something, make the changes in the workspace, call `ready_to_make_pr`, then use `create_pull_request` to submit them When making code changes, identify and run required repo commands (lint/build/test) from README, CONTRIBUTING, DEVELOPING, Makefile, or CI config and include results. If required commands cannot be run, explain why. @@ -434,6 +434,7 @@ jobs: Call `add_comment` with your response. Be concise and actionable — no filler or praise. If the request is unclear, ask clarifying questions rather than guessing. **Additional tools:** + - `ready_to_make_pr` — run pre-PR safety checks before opening a PR - `create_pull_request` — create a PR with your changes - `create_issue` — create a new issue (e.g. to split off sub-tasks) diff --git a/.github/workflows/gh-aw-mention-in-issue.md b/.github/workflows/gh-aw-mention-in-issue.md index ca4dac15..11e06c5b 100644 --- a/.github/workflows/gh-aw-mention-in-issue.md +++ b/.github/workflows/gh-aw-mention-in-issue.md @@ -101,9 +101,9 @@ Assist with issues on ${{ github.repository }} — answer questions, debug probl ## Constraints - **CAN**: Read files, search code, modify files locally, run tests and commands, comment on issues, create pull requests, create issues -- **CANNOT**: Directly push or commit to the repository — use `create_pull_request` to propose changes +- **CANNOT**: Directly push or commit to the repository — use `ready_to_make_pr` then `create_pull_request` to propose changes -When creating pull requests, make the changes in the workspace first, then use `create_pull_request` — branches are managed automatically. +When creating pull requests, make the changes in the workspace first, call `ready_to_make_pr`, then use `create_pull_request` — branches are managed automatically. ## Instructions @@ -123,7 +123,7 @@ Based on the request, do what's appropriate: - **Debug reported problems** — reproduce locally, run required repo commands (lint/build/test) from README, CONTRIBUTING, DEVELOPING, Makefile, or CI config, and trace the code path - **Suggest solutions** — provide concrete code examples and implementation guidance - **Clarify requirements** — ask follow-up questions if the request is ambiguous -- **Create a PR** — if asked to implement something, make the changes in the workspace, then use `create_pull_request` to submit them +- **Create a PR** — if asked to implement something, make the changes in the workspace, call `ready_to_make_pr`, then use `create_pull_request` to submit them When making code changes, identify and run required repo commands (lint/build/test) from README, CONTRIBUTING, DEVELOPING, Makefile, or CI config and include results. If required commands cannot be run, explain why. @@ -132,6 +132,7 @@ When making code changes, identify and run required repo commands (lint/build/te Call `add_comment` with your response. Be concise and actionable — no filler or praise. If the request is unclear, ask clarifying questions rather than guessing. **Additional tools:** +- `ready_to_make_pr` — run pre-PR safety checks before opening a PR - `create_pull_request` — create a PR with your changes - `create_issue` — create a new issue (e.g. to split off sub-tasks) diff --git a/.github/workflows/gh-aw-mention-in-pr-by-id.lock.yml b/.github/workflows/gh-aw-mention-in-pr-by-id.lock.yml index 28c621fb..6c320fab 100644 --- a/.github/workflows/gh-aw-mention-in-pr-by-id.lock.yml +++ b/.github/workflows/gh-aw-mention-in-pr-by-id.lock.yml @@ -46,7 +46,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"5a85593d0161971502423e037fc9d20fe5693c8c4ef8b74ca3ba13d6a29de899"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"6a034e6e5b30edab1c44dbbf888b4e770e9a0099c3a8afd410f176deeee35193"} name: "Mention in PR by ID" "on": @@ -470,6 +470,16 @@ jobs: - Leave inline comments per the **Code Review Reference** for each finding that survives verification. Then call `submit_pull_request_review`. - **Bot-authored PRs**: If the PR author is `github-actions[bot]`, submit a `COMMENT` review only — `APPROVE` and `REQUEST_CHANGES` will fail. + **If asked to fix code or address review feedback:** + - Read `/tmp/pr-context/unresolved_threads.json` to identify open review feedback. + - Implement the requested code changes and run relevant lint/build/test commands for the modified area. + - Call `ready_to_push_to_pr` to confirm the branch is safe to push. + - Use `push_to_pull_request_branch` to push your changes once. + - Resolve every thread that is fully addressed by your changes using `resolve_pull_request_review_thread` and the thread GraphQL node ID (`id`, e.g., `PRRT_kwDO...`). + - Do **not** resolve threads you disagreed with, skipped, or only partially addressed; instead, leave a `reply_to_pull_request_review_comment` explaining status when needed. + - **Important completion step**: feedback is not fully complete until fully addressed threads are marked resolved via safe output. + - If `resolve_pull_request_review_thread` fails for fully addressed threads, call `add_comment` listing the thread IDs and failure reason. + __GH_AW_EXPR_49B959F1__ GH_AW_PROMPT_EOF diff --git a/.github/workflows/gh-aw-mention-in-pr-by-id.md b/.github/workflows/gh-aw-mention-in-pr-by-id.md index 6d832993..007c2046 100644 --- a/.github/workflows/gh-aw-mention-in-pr-by-id.md +++ b/.github/workflows/gh-aw-mention-in-pr-by-id.md @@ -157,4 +157,14 @@ Assist with pull request #${{ inputs.target-pr-number }} on ${{ github.repositor - Leave inline comments per the **Code Review Reference** for each finding that survives verification. Then call `submit_pull_request_review`. - **Bot-authored PRs**: If the PR author is `github-actions[bot]`, submit a `COMMENT` review only — `APPROVE` and `REQUEST_CHANGES` will fail. +**If asked to fix code or address review feedback:** +- Read `/tmp/pr-context/unresolved_threads.json` to identify open review feedback. +- Implement the requested code changes and run relevant lint/build/test commands for the modified area. +- Call `ready_to_push_to_pr` to confirm the branch is safe to push. +- Use `push_to_pull_request_branch` to push your changes once. +- Resolve every thread that is fully addressed by your changes using `resolve_pull_request_review_thread` and the thread GraphQL node ID (`id`, e.g., `PRRT_kwDO...`). +- Do **not** resolve threads you disagreed with, skipped, or only partially addressed; instead, leave a `reply_to_pull_request_review_comment` explaining status when needed. +- **Important completion step**: feedback is not fully complete until fully addressed threads are marked resolved via safe output. +- If `resolve_pull_request_review_thread` fails for fully addressed threads, call `add_comment` listing the thread IDs and failure reason. + ${{ inputs.additional-instructions }} diff --git a/.github/workflows/gh-aw-mention-in-pr-no-sandbox.lock.yml b/.github/workflows/gh-aw-mention-in-pr-no-sandbox.lock.yml index 9a1b63cf..6bbf6045 100644 --- a/.github/workflows/gh-aw-mention-in-pr-no-sandbox.lock.yml +++ b/.github/workflows/gh-aw-mention-in-pr-no-sandbox.lock.yml @@ -47,7 +47,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"e203d285220f3454b353b990cc63c4cdc5597116eb9e49cbd483c6118c99c295"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"78a1f3bba423f7d5f19d683f9ae0fa00a6f5d4b78e9c97a1912f5aeeda5d8c2a"} name: "Mention in PR (no sandbox)" "on": @@ -518,6 +518,7 @@ jobs: - If the fix isn't obvious from the code change alone, call `reply_to_pull_request_review_comment` with the comment's numeric ID to briefly explain what you changed. - If you disagree with feedback or it's unclear, call `reply_to_pull_request_review_comment` to explain your reasoning instead of making changes. Do NOT resolve the thread — let the reviewer decide. - Run required repo commands (lint/build/test) from README, CONTRIBUTING, DEVELOPING, Makefile, or CI config relevant to the change and include results. If required commands cannot be run, explain why and do not push changes. + - Use `ready_to_push_to_pr` to check if the changes are ready to push. - Use `push_to_pull_request_branch` to push your changes. - After pushing, resolve every review thread that your changes address by calling `resolve_pull_request_review_thread` with the thread's GraphQL node ID (the `id` field, e.g., `PRRT_kwDO...`). This includes threads left by other reviewers AND threads from your own prior reviews. Check `/tmp/pr-context/unresolved_threads.json` for all unresolved threads — also check `/tmp/pr-context/outdated_threads.json` for threads where the underlying code changed since the comment was made and verify whether your changes address them. Do NOT resolve threads you disagreed with, skipped, or only partially addressed — leave those open for the reviewer. - **Fork PRs**: Check via `pull_request_read` with method `get` whether the PR head repo differs from the base repo. If it's a fork, you cannot push — reply explaining that you do not have permission to push to fork branches and suggest that the PR author apply the changes themselves. This is a GitHub security limitation. You can still review code, make local changes, and provide suggestions. @@ -535,6 +536,7 @@ jobs: If you did not submit a PR review, call `add_comment` with your response. If you submitted a review, do NOT call `add_comment` unless explicitly requested or to report a review submission failure. **Additional tools:** + - `ready_to_push_to_pr` — run pre-push safety checks before pushing PR changes - `push_to_pull_request_branch` — push committed changes to the PR branch (same-repo PRs only) - `reply_to_pull_request_review_comment` — reply inline to a review comment thread to explain what you changed or why you disagree - `resolve_pull_request_review_thread` — resolve a review thread after addressing the feedback (pass the thread's GraphQL node ID) diff --git a/.github/workflows/gh-aw-mention-in-pr-no-sandbox.md b/.github/workflows/gh-aw-mention-in-pr-no-sandbox.md index f69a8615..cac99288 100644 --- a/.github/workflows/gh-aw-mention-in-pr-no-sandbox.md +++ b/.github/workflows/gh-aw-mention-in-pr-no-sandbox.md @@ -165,6 +165,7 @@ Based on what's asked, do the appropriate thing: - If the fix isn't obvious from the code change alone, call `reply_to_pull_request_review_comment` with the comment's numeric ID to briefly explain what you changed. - If you disagree with feedback or it's unclear, call `reply_to_pull_request_review_comment` to explain your reasoning instead of making changes. Do NOT resolve the thread — let the reviewer decide. - Run required repo commands (lint/build/test) from README, CONTRIBUTING, DEVELOPING, Makefile, or CI config relevant to the change and include results. If required commands cannot be run, explain why and do not push changes. +- Use `ready_to_push_to_pr` to check if the changes are ready to push. - Use `push_to_pull_request_branch` to push your changes. - After pushing, resolve every review thread that your changes address by calling `resolve_pull_request_review_thread` with the thread's GraphQL node ID (the `id` field, e.g., `PRRT_kwDO...`). This includes threads left by other reviewers AND threads from your own prior reviews. Check `/tmp/pr-context/unresolved_threads.json` for all unresolved threads — also check `/tmp/pr-context/outdated_threads.json` for threads where the underlying code changed since the comment was made and verify whether your changes address them. Do NOT resolve threads you disagreed with, skipped, or only partially addressed — leave those open for the reviewer. - **Fork PRs**: Check via `pull_request_read` with method `get` whether the PR head repo differs from the base repo. If it's a fork, you cannot push — reply explaining that you do not have permission to push to fork branches and suggest that the PR author apply the changes themselves. This is a GitHub security limitation. You can still review code, make local changes, and provide suggestions. @@ -182,6 +183,7 @@ Based on what's asked, do the appropriate thing: If you did not submit a PR review, call `add_comment` with your response. If you submitted a review, do NOT call `add_comment` unless explicitly requested or to report a review submission failure. **Additional tools:** +- `ready_to_push_to_pr` — run pre-push safety checks before pushing PR changes - `push_to_pull_request_branch` — push committed changes to the PR branch (same-repo PRs only) - `reply_to_pull_request_review_comment` — reply inline to a review comment thread to explain what you changed or why you disagree - `resolve_pull_request_review_thread` — resolve a review thread after addressing the feedback (pass the thread's GraphQL node ID) diff --git a/.github/workflows/gh-aw-mention-in-pr.lock.yml b/.github/workflows/gh-aw-mention-in-pr.lock.yml index ec6eb5b9..371fad7d 100644 --- a/.github/workflows/gh-aw-mention-in-pr.lock.yml +++ b/.github/workflows/gh-aw-mention-in-pr.lock.yml @@ -47,7 +47,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"4824fcfcf025e379f0e3fd91064079c49b31da3cbd9f184d559937d73412719f"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"ba2448f31f5c3194d305b4fcac41b65ca814a62b157adb330155e30cac394e0e"} name: "Mention in PR" "on": @@ -538,7 +538,9 @@ jobs: - If you disagree with feedback or it's unclear, call `reply_to_pull_request_review_comment` to explain your reasoning instead of making changes. Do NOT resolve the thread — let the reviewer decide. - Run required repo commands (lint/build/test) from README, CONTRIBUTING, DEVELOPING, Makefile, or CI config relevant to the change and include results. If required commands cannot be run, explain why and do not push changes. - Use `push_to_pull_request_branch` to push your changes. - - After pushing, resolve every review thread that your changes address by calling `resolve_pull_request_review_thread` with the thread's GraphQL node ID (the `id` field, e.g., `PRRT_kwDO...`). This includes threads left by other reviewers AND threads from your own prior reviews. Check `/tmp/pr-context/unresolved_threads.json` for all unresolved threads — also check `/tmp/pr-context/outdated_threads.json` for threads where the underlying code changed since the comment was made and verify whether your changes address them. Do NOT resolve threads you disagreed with, skipped, or only partially addressed — leave those open for the reviewer. + - After pushing, resolve every review thread that your changes fully address by calling `resolve_pull_request_review_thread` with the thread's GraphQL node ID (the `id` field, e.g., `PRRT_kwDO...`). This includes threads left by other reviewers AND threads from your own prior reviews. Check `/tmp/pr-context/unresolved_threads.json` for all unresolved threads — also check `/tmp/pr-context/outdated_threads.json` for threads where the underlying code changed since the comment was made and verify whether your changes address them. Do NOT resolve threads you disagreed with, skipped, or only partially addressed — leave those open for the reviewer. + - **Important completion step**: when feedback is completed and no further reviewer action is needed, resolving the corresponding thread is required. Do not leave fully addressed threads open. + - If `resolve_pull_request_review_thread` fails for any thread you fully addressed, call `add_comment` summarizing the specific thread IDs that could not be resolved and why. - **Fork PRs**: Check via `pull_request_read` with method `get` whether the PR head repo differs from the base repo. If it's a fork, you cannot push — reply explaining that you do not have permission to push to fork branches and suggest that the PR author apply the changes themselves. This is a GitHub security limitation. You can still review code, make local changes, and provide suggestions. **If asked to fix merge conflicts:** diff --git a/.github/workflows/gh-aw-mention-in-pr.md b/.github/workflows/gh-aw-mention-in-pr.md index 0cb816a3..04a91b6c 100644 --- a/.github/workflows/gh-aw-mention-in-pr.md +++ b/.github/workflows/gh-aw-mention-in-pr.md @@ -180,7 +180,9 @@ Based on what's asked, do the appropriate thing. - If you disagree with feedback or it's unclear, call `reply_to_pull_request_review_comment` to explain your reasoning instead of making changes. Do NOT resolve the thread — let the reviewer decide. - Run required repo commands (lint/build/test) from README, CONTRIBUTING, DEVELOPING, Makefile, or CI config relevant to the change and include results. If required commands cannot be run, explain why and do not push changes. - Use `push_to_pull_request_branch` to push your changes. -- After pushing, resolve every review thread that your changes address by calling `resolve_pull_request_review_thread` with the thread's GraphQL node ID (the `id` field, e.g., `PRRT_kwDO...`). This includes threads left by other reviewers AND threads from your own prior reviews. Check `/tmp/pr-context/unresolved_threads.json` for all unresolved threads — also check `/tmp/pr-context/outdated_threads.json` for threads where the underlying code changed since the comment was made and verify whether your changes address them. Do NOT resolve threads you disagreed with, skipped, or only partially addressed — leave those open for the reviewer. +- After pushing, resolve every review thread that your changes fully address by calling `resolve_pull_request_review_thread` with the thread's GraphQL node ID (the `id` field, e.g., `PRRT_kwDO...`). This includes threads left by other reviewers AND threads from your own prior reviews. Check `/tmp/pr-context/unresolved_threads.json` for all unresolved threads — also check `/tmp/pr-context/outdated_threads.json` for threads where the underlying code changed since the comment was made and verify whether your changes address them. Do NOT resolve threads you disagreed with, skipped, or only partially addressed — leave those open for the reviewer. +- **Important completion step**: when feedback is completed and no further reviewer action is needed, resolving the corresponding thread is required. Do not leave fully addressed threads open. +- If `resolve_pull_request_review_thread` fails for any thread you fully addressed, call `add_comment` summarizing the specific thread IDs that could not be resolved and why. - **Fork PRs**: Check via `pull_request_read` with method `get` whether the PR head repo differs from the base repo. If it's a fork, you cannot push — reply explaining that you do not have permission to push to fork branches and suggest that the PR author apply the changes themselves. This is a GitHub security limitation. You can still review code, make local changes, and provide suggestions. **If asked to fix merge conflicts:** diff --git a/.github/workflows/gh-aw-performance-profiler.lock.yml b/.github/workflows/gh-aw-performance-profiler.lock.yml index 2cfe8b11..5626f2ea 100644 --- a/.github/workflows/gh-aw-performance-profiler.lock.yml +++ b/.github/workflows/gh-aw-performance-profiler.lock.yml @@ -40,7 +40,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"e583da0f3fd61dd7db7a276354e7904815b83182a1717abdcad6e82406df2121"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"047519923812acb295057ae7e1f5c0e226bff434746b916d07219ec6aeaa0e1b"} name: "Performance Profiler" "on": @@ -449,10 +449,18 @@ jobs: 3. Re-run the same profiling or benchmark to capture **after** numbers. 4. Verify existing tests still pass — run the most relevant test command(s). + ### Data Integrity Check (Required) + + Before filing, verify the integrity of your evidence: + - The **before** and **after** benchmark outputs must be **different** — if they are identical, the optimization was not applied or the benchmark did not run correctly. Do not file. + - The benchmark command used for **before** and **after** must be the same command run against different code states. + - If you cannot confirm the benchmark actually measured the changed code path, do not file. + ### What to Report Only file an issue if **all** of these are true: - You have concrete before/after benchmark or profiling numbers. + - The before and after results are **demonstrably different** (not identical output blocks). - The improvement is **not trivial** (at least 10% improvement in time or memory for the hot path, or measurably significant for high-frequency operations). - Existing tests pass after the change. - The change is behavior-preserving — no functional regressions. diff --git a/.github/workflows/gh-aw-performance-profiler.md b/.github/workflows/gh-aw-performance-profiler.md index 5cce9770..1c59d5ba 100644 --- a/.github/workflows/gh-aw-performance-profiler.md +++ b/.github/workflows/gh-aw-performance-profiler.md @@ -134,10 +134,18 @@ Always capture **baseline numbers** before making any change. 3. Re-run the same profiling or benchmark to capture **after** numbers. 4. Verify existing tests still pass — run the most relevant test command(s). +### Data Integrity Check (Required) + +Before filing, verify the integrity of your evidence: +- The **before** and **after** benchmark outputs must be **different** — if they are identical, the optimization was not applied or the benchmark did not run correctly. Do not file. +- The benchmark command used for **before** and **after** must be the same command run against different code states. +- If you cannot confirm the benchmark actually measured the changed code path, do not file. + ### What to Report Only file an issue if **all** of these are true: - You have concrete before/after benchmark or profiling numbers. +- The before and after results are **demonstrably different** (not identical output blocks). - The improvement is **not trivial** (at least 10% improvement in time or memory for the hot path, or measurably significant for high-frequency operations). - Existing tests pass after the change. - The change is behavior-preserving — no functional regressions. diff --git a/.github/workflows/gh-aw-pr-actions-detective.lock.yml b/.github/workflows/gh-aw-pr-actions-detective.lock.yml index 62c758aa..77db30a0 100644 --- a/.github/workflows/gh-aw-pr-actions-detective.lock.yml +++ b/.github/workflows/gh-aw-pr-actions-detective.lock.yml @@ -36,7 +36,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"1a4d0a8c03c5b4362d7b7175579942bfc20d4a2099956597fb53098808a34d1c"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"a7a1c10cf00c367cf141be4fa237bed3fcd46e2442c44ff28a820fe68d81e056"} name: "PR Actions Detective" "on": @@ -337,14 +337,49 @@ jobs: - Identify the failing job/step and summarize the root cause. - Propose a concrete, minimal fix or remediation plan. - If the logs are inconclusive, state what additional data is needed. + - Before posting, check the most recent prior `PR Actions Detective` comment on the same PR (if any) and compare: + - failing workflow/job/step, + - root cause summary, and + - recommended remediation. + - If both the diagnosed issue and remediation are materially the same as the last detective report, call `noop` with a short "no meaningful change since last report" reason instead of posting another comment. ### Step 3: Respond - Call `add_comment` on the PR with: - - A concise summary of the failure and root cause - - The recommended fix or remediation plan - - Tests run and their results (if any) - - Any follow-up steps required + If you are posting a comment, call `add_comment` on the PR using this structure: + + 1. **TL;DR (required, first line)** — 1-2 sentences stating what failed and the immediate action. + 2. **Remediation (expanded, not collapsed)** — concrete fix steps and immediate next action. + 3. **All other sections inside a collapsed details block** using `
... ...
`. Put root cause evidence, failing logs context, tests run, and follow-up details inside this block. + + Use this exact shape: + + ```markdown + ### TL;DR + [short actionable summary] + + ## Remediation + - [specific fix step] + - [specific validation step] + +
+ Investigation details + + ## Root Cause + [concise explanation] + + ## Evidence + - Workflow: [name] + - Job/step: [name] + - Key log excerpt: [snippet] + + ## Validation + - [tests/commands run or "not run" with reason] + + ## Follow-up + - [optional next steps] + +
+ ``` __GH_AW_EXPR_49B959F1__ diff --git a/.github/workflows/gh-aw-pr-actions-detective.md b/.github/workflows/gh-aw-pr-actions-detective.md index f9dd06fd..59da1881 100644 --- a/.github/workflows/gh-aw-pr-actions-detective.md +++ b/.github/workflows/gh-aw-pr-actions-detective.md @@ -113,13 +113,48 @@ Assist with failed GitHub Actions checks for pull requests in ${{ github.reposit - Identify the failing job/step and summarize the root cause. - Propose a concrete, minimal fix or remediation plan. - If the logs are inconclusive, state what additional data is needed. +- Before posting, check the most recent prior `PR Actions Detective` comment on the same PR (if any) and compare: + - failing workflow/job/step, + - root cause summary, and + - recommended remediation. +- If both the diagnosed issue and remediation are materially the same as the last detective report, call `noop` with a short "no meaningful change since last report" reason instead of posting another comment. ### Step 3: Respond -Call `add_comment` on the PR with: -- A concise summary of the failure and root cause -- The recommended fix or remediation plan -- Tests run and their results (if any) -- Any follow-up steps required +If you are posting a comment, call `add_comment` on the PR using this structure: + +1. **TL;DR (required, first line)** — 1-2 sentences stating what failed and the immediate action. +2. **Remediation (expanded, not collapsed)** — concrete fix steps and immediate next action. +3. **All other sections inside a collapsed details block** using `
... ...
`. Put root cause evidence, failing logs context, tests run, and follow-up details inside this block. + +Use this exact shape: + +```markdown +### TL;DR +[short actionable summary] + +## Remediation +- [specific fix step] +- [specific validation step] + +
+Investigation details + +## Root Cause +[concise explanation] + +## Evidence +- Workflow: [name] +- Job/step: [name] +- Key log excerpt: [snippet] + +## Validation +- [tests/commands run or "not run" with reason] + +## Follow-up +- [optional next steps] + +
+``` ${{ inputs.additional-instructions }} diff --git a/.github/workflows/gh-aw-pr-actions-fixer.lock.yml b/.github/workflows/gh-aw-pr-actions-fixer.lock.yml index 62569b70..a8a37804 100644 --- a/.github/workflows/gh-aw-pr-actions-fixer.lock.yml +++ b/.github/workflows/gh-aw-pr-actions-fixer.lock.yml @@ -37,7 +37,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"e873899443c1001b07f0e00657837122b226974f03429f077f0673f7e8ae6297"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"0058ecb80ba98240972d212bff017fbf0fc7c800e7015fb41b55c20f3c136b83"} name: "PR Actions Fixer" "on": @@ -371,7 +371,7 @@ jobs: ### Step 2: Analyze and Fix - Identify the failing job/step and summarize the root cause. - - If the fix is straightforward and safe, implement it locally, run tests, and push to the PR branch. + - If the fix is straightforward and safe, implement it locally, run tests, call `ready_to_push_to_pr`, then use `push_to_pull_request_branch` to push to the PR branch. - If the fix is risky or requires broader refactoring, propose a concrete remediation plan instead of pushing. - If the PR is from a fork, do not push; provide patch guidance in the comment. @@ -384,6 +384,7 @@ jobs: - Any follow-up steps required **Additional tools:** + - `ready_to_push_to_pr` — run pre-push safety checks before pushing PR changes - `push_to_pull_request_branch` — push committed changes to the PR branch (same-repo PRs only) __GH_AW_EXPR_49B959F1__ diff --git a/.github/workflows/gh-aw-pr-actions-fixer.md b/.github/workflows/gh-aw-pr-actions-fixer.md index d9cd1f83..11984d41 100644 --- a/.github/workflows/gh-aw-pr-actions-fixer.md +++ b/.github/workflows/gh-aw-pr-actions-fixer.md @@ -122,7 +122,7 @@ Assist with failed GitHub Actions checks for pull requests in ${{ github.reposit ### Step 2: Analyze and Fix - Identify the failing job/step and summarize the root cause. -- If the fix is straightforward and safe, implement it locally, run tests, and push to the PR branch. +- If the fix is straightforward and safe, implement it locally, run tests, call `ready_to_push_to_pr`, then use `push_to_pull_request_branch` to push to the PR branch. - If the fix is risky or requires broader refactoring, propose a concrete remediation plan instead of pushing. - If the PR is from a fork, do not push; provide patch guidance in the comment. @@ -135,6 +135,7 @@ Call `add_comment` on the PR with: - Any follow-up steps required **Additional tools:** +- `ready_to_push_to_pr` — run pre-push safety checks before pushing PR changes - `push_to_pull_request_branch` — push committed changes to the PR branch (same-repo PRs only) ${{ inputs.additional-instructions }} diff --git a/.github/workflows/gh-aw-pr-ci-detective.lock.yml b/.github/workflows/gh-aw-pr-ci-detective.lock.yml index 024c3673..ee100559 100644 --- a/.github/workflows/gh-aw-pr-ci-detective.lock.yml +++ b/.github/workflows/gh-aw-pr-ci-detective.lock.yml @@ -41,7 +41,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"1a4d0a8c03c5b4362d7b7175579942bfc20d4a2099956597fb53098808a34d1c"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"a7a1c10cf00c367cf141be4fa237bed3fcd46e2442c44ff28a820fe68d81e056"} name: "PR Actions Detective" "on": @@ -342,14 +342,49 @@ jobs: - Identify the failing job/step and summarize the root cause. - Propose a concrete, minimal fix or remediation plan. - If the logs are inconclusive, state what additional data is needed. + - Before posting, check the most recent prior `PR Actions Detective` comment on the same PR (if any) and compare: + - failing workflow/job/step, + - root cause summary, and + - recommended remediation. + - If both the diagnosed issue and remediation are materially the same as the last detective report, call `noop` with a short "no meaningful change since last report" reason instead of posting another comment. ### Step 3: Respond - Call `add_comment` on the PR with: - - A concise summary of the failure and root cause - - The recommended fix or remediation plan - - Tests run and their results (if any) - - Any follow-up steps required + If you are posting a comment, call `add_comment` on the PR using this structure: + + 1. **TL;DR (required, first line)** — 1-2 sentences stating what failed and the immediate action. + 2. **Remediation (expanded, not collapsed)** — concrete fix steps and immediate next action. + 3. **All other sections inside a collapsed details block** using `
... ...
`. Put root cause evidence, failing logs context, tests run, and follow-up details inside this block. + + Use this exact shape: + + ```markdown + ### TL;DR + [short actionable summary] + + ## Remediation + - [specific fix step] + - [specific validation step] + +
+ Investigation details + + ## Root Cause + [concise explanation] + + ## Evidence + - Workflow: [name] + - Job/step: [name] + - Key log excerpt: [snippet] + + ## Validation + - [tests/commands run or "not run" with reason] + + ## Follow-up + - [optional next steps] + +
+ ``` __GH_AW_EXPR_49B959F1__ diff --git a/.github/workflows/gh-aw-pr-review-addresser.lock.yml b/.github/workflows/gh-aw-pr-review-addresser.lock.yml index 4b95c63f..0e70a791 100644 --- a/.github/workflows/gh-aw-pr-review-addresser.lock.yml +++ b/.github/workflows/gh-aw-pr-review-addresser.lock.yml @@ -40,7 +40,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"ce7ac2253e4c2d48a1e533e71bf2c87879c935b353edc7c39288f86a165a1d6c"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"47b087e1835cc62512676a12e4e670b33112ea7795f0efe87bded016d9756ba7"} name: "PR Review Addresser" "on": @@ -396,14 +396,19 @@ jobs: ### Step 3: Validate and Push 1. Run required repo commands (lint/build/test) from README, CONTRIBUTING, DEVELOPING, Makefile, or CI config relevant to the changes and include results. If required commands cannot be run, explain why and do not push changes. - 2. Use `push_to_pull_request_branch` to push your changes. - 3. **Fork PRs**: If this is a fork PR, you cannot push. Reply explaining that you do not have permission to push to fork branches and suggest that the PR author apply the changes themselves. This is a GitHub security limitation. + 2. Use `ready_to_push_to_pr` to check if the changes are ready to push. + 3. Use `push_to_pull_request_branch` to push your changes. + 4. **Fork PRs**: If this is a fork PR, you cannot push. Reply explaining that you do not have permission to push to fork branches and suggest that the PR author apply the changes themselves. This is a GitHub security limitation. ### Step 4: Resolve Addressed Threads Skip this step for fork PRs where you could not push. - After pushing, resolve every review thread that your changes address by calling `resolve_pull_request_review_thread` with the thread's GraphQL node ID (the `id` field, e.g., `PRRT_kwDO...`). This includes threads from any reviewer — external reviewers, bots, and your own prior reviews. Check `/tmp/pr-context/unresolved_threads.json` for all unresolved threads — also check `/tmp/pr-context/outdated_threads.json` for threads where the underlying code changed since the comment was made and verify whether your changes address them. Do NOT resolve threads you disagreed with, skipped, or only partially addressed — leave those open for the reviewer. Fall back to `pull_request_read` with method `get_review_comments` if the pre-fetched data is unavailable. + After pushing, resolve every review thread that your changes fully address by calling `resolve_pull_request_review_thread` with the thread's GraphQL node ID (the `id` field, e.g., `PRRT_kwDO...`). This includes threads from any reviewer — external reviewers, bots, and your own prior reviews. Check `/tmp/pr-context/unresolved_threads.json` for all unresolved threads — also check `/tmp/pr-context/outdated_threads.json` for threads where the underlying code changed since the comment was made and verify whether your changes address them. Do NOT resolve threads you disagreed with, skipped, or only partially addressed — leave those open for the reviewer. Fall back to `pull_request_read` with method `get_review_comments` if the pre-fetched data is unavailable. + + **Important completion requirement**: when feedback is completed and no further reviewer action is needed, resolving the corresponding thread is required. Do not leave fully addressed threads open. + + If `resolve_pull_request_review_thread` fails for any fully addressed thread, call `add_comment` and list the specific thread IDs that could not be resolved with the failure reason. ### Step 5: Respond diff --git a/.github/workflows/gh-aw-pr-review-addresser.md b/.github/workflows/gh-aw-pr-review-addresser.md index bc02256a..95762690 100644 --- a/.github/workflows/gh-aw-pr-review-addresser.md +++ b/.github/workflows/gh-aw-pr-review-addresser.md @@ -137,14 +137,19 @@ For each unresolved review thread: ### Step 3: Validate and Push 1. Run required repo commands (lint/build/test) from README, CONTRIBUTING, DEVELOPING, Makefile, or CI config relevant to the changes and include results. If required commands cannot be run, explain why and do not push changes. -2. Use `push_to_pull_request_branch` to push your changes. -3. **Fork PRs**: If this is a fork PR, you cannot push. Reply explaining that you do not have permission to push to fork branches and suggest that the PR author apply the changes themselves. This is a GitHub security limitation. +2. Use `ready_to_push_to_pr` to check if the changes are ready to push. +3. Use `push_to_pull_request_branch` to push your changes. +4. **Fork PRs**: If this is a fork PR, you cannot push. Reply explaining that you do not have permission to push to fork branches and suggest that the PR author apply the changes themselves. This is a GitHub security limitation. ### Step 4: Resolve Addressed Threads Skip this step for fork PRs where you could not push. -After pushing, resolve every review thread that your changes address by calling `resolve_pull_request_review_thread` with the thread's GraphQL node ID (the `id` field, e.g., `PRRT_kwDO...`). This includes threads from any reviewer — external reviewers, bots, and your own prior reviews. Check `/tmp/pr-context/unresolved_threads.json` for all unresolved threads — also check `/tmp/pr-context/outdated_threads.json` for threads where the underlying code changed since the comment was made and verify whether your changes address them. Do NOT resolve threads you disagreed with, skipped, or only partially addressed — leave those open for the reviewer. Fall back to `pull_request_read` with method `get_review_comments` if the pre-fetched data is unavailable. +After pushing, resolve every review thread that your changes fully address by calling `resolve_pull_request_review_thread` with the thread's GraphQL node ID (the `id` field, e.g., `PRRT_kwDO...`). This includes threads from any reviewer — external reviewers, bots, and your own prior reviews. Check `/tmp/pr-context/unresolved_threads.json` for all unresolved threads — also check `/tmp/pr-context/outdated_threads.json` for threads where the underlying code changed since the comment was made and verify whether your changes address them. Do NOT resolve threads you disagreed with, skipped, or only partially addressed — leave those open for the reviewer. Fall back to `pull_request_read` with method `get_review_comments` if the pre-fetched data is unavailable. + +**Important completion requirement**: when feedback is completed and no further reviewer action is needed, resolving the corresponding thread is required. Do not leave fully addressed threads open. + +If `resolve_pull_request_review_thread` fails for any fully addressed thread, call `add_comment` and list the specific thread IDs that could not be resolved with the failure reason. ### Step 5: Respond diff --git a/.github/workflows/gh-aw-project-summary.lock.yml b/.github/workflows/gh-aw-project-summary.lock.yml index e547e95b..cbc4dc00 100644 --- a/.github/workflows/gh-aw-project-summary.lock.yml +++ b/.github/workflows/gh-aw-project-summary.lock.yml @@ -39,7 +39,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"6df243851e718cb0a2ca5adadfa40fa94ec6e0467d6d220d506c35bfd33903c0"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"0b5b4e29728b3d87bf32a5b9e7ab49ca2075f06ee11504f6398e65de02dc48e0"} name: "Project Summary" "on": @@ -162,6 +162,7 @@ jobs: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_5D407588: ${{ inputs.allowed-bot-users }} GH_AW_EXPR_BF503D80: ${{ inputs.title-prefix }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} @@ -387,7 +388,9 @@ jobs: - If a previous report exists, use its `createdAt` as the start date. Otherwise, use **14 days ago**. 2. **Collect activity since the start date** + - Build one shared bot identity set once and reuse it consistently: `__GH_AW_EXPR_5D407588__` plus common bot accounts (for example `dependabot[bot]` and `renovate[bot]`). - `git log --since="" --oneline --stat` for commit count and notable changes. + - Use non-bot commit count for activity thresholding. Exclude commits authored or committed by identities in the bot set (including merge commits that only represent bot-authored PR activity). - `github-search_issues` for issues created or updated since the start date (exclude project-summary issues). - `github-search_pull_requests` for PRs created since the start date. - `github-search_pull_requests` for PRs merged since the start date. @@ -397,12 +400,12 @@ jobs: - PRs ready to merge or awaiting review. - Urgent or blocking issues (labels like `urgent`, `blocking`, `priority`, `P0`, `P1`). - Decisions needed (labels like `needs decision`, `discussion`, `question`). - - Stale items: open issues or PRs with no updates in 30+ days. + - Stale items: open issues or PRs with no updates in 30+ days, excluding items authored by identities in the shared bot set unless there is clear significant impact requiring human attention. ### Activity Threshold (Noop) Call `noop` with message **"Project summary skipped — no meaningful activity since last report"** when: - - Total activity (commits + new issues + new PRs + merged PRs) since the last report is fewer than **3**, and + - Total activity (non-bot commits + non-bot new issues + non-bot new PRs + non-bot merged PRs) since the last report is fewer than **3**, and - There are **no** urgent, decision-needed, or stale items. ### Issue Format @@ -434,8 +437,9 @@ jobs: **Guidelines:** - Include direct links to issues/PRs and a short rationale for each item. - - If a section is empty, write `None`. + - If a section is empty, **omit it entirely** rather than writing `None`. Only include sections that have meaningful content. A summary with 2 substantive sections is more useful than one with 6 sections marked `None`. - Do not repeat items already covered in the previous report unless status materially changed. + - Exclude bot-authored PRs and issues (e.g., from agentic workflows, dependabot, renovate) from activity counts, stale-item selection, and the Recent Progress section unless they represent significant changes. Bot activity should not inflate the summary or trigger a report on otherwise quiet days. __GH_AW_EXPR_49B959F1__ @@ -446,6 +450,7 @@ jobs: env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_5D407588: ${{ inputs.allowed-bot-users }} GH_AW_EXPR_BF503D80: ${{ inputs.title-prefix }} with: script: | @@ -458,6 +463,7 @@ jobs: env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} + GH_AW_EXPR_5D407588: ${{ inputs.allowed-bot-users }} GH_AW_EXPR_BF503D80: ${{ inputs.title-prefix }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} @@ -480,6 +486,7 @@ jobs: file: process.env.GH_AW_PROMPT, substitutions: { GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, + GH_AW_EXPR_5D407588: process.env.GH_AW_EXPR_5D407588, GH_AW_EXPR_BF503D80: process.env.GH_AW_EXPR_BF503D80, GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, diff --git a/.github/workflows/gh-aw-project-summary.md b/.github/workflows/gh-aw-project-summary.md index 23c4f8d5..504aa8a8 100644 --- a/.github/workflows/gh-aw-project-summary.md +++ b/.github/workflows/gh-aw-project-summary.md @@ -95,7 +95,9 @@ Create a periodic project summary with actionable highlights from recent activit - If a previous report exists, use its `createdAt` as the start date. Otherwise, use **14 days ago**. 2. **Collect activity since the start date** + - Build one shared bot identity set once and reuse it consistently: `${{ inputs.allowed-bot-users }}` plus common bot accounts (for example `dependabot[bot]` and `renovate[bot]`). - `git log --since="" --oneline --stat` for commit count and notable changes. + - Use non-bot commit count for activity thresholding. Exclude commits authored or committed by identities in the bot set (including merge commits that only represent bot-authored PR activity). - `github-search_issues` for issues created or updated since the start date (exclude project-summary issues). - `github-search_pull_requests` for PRs created since the start date. - `github-search_pull_requests` for PRs merged since the start date. @@ -105,12 +107,12 @@ Create a periodic project summary with actionable highlights from recent activit - PRs ready to merge or awaiting review. - Urgent or blocking issues (labels like `urgent`, `blocking`, `priority`, `P0`, `P1`). - Decisions needed (labels like `needs decision`, `discussion`, `question`). - - Stale items: open issues or PRs with no updates in 30+ days. + - Stale items: open issues or PRs with no updates in 30+ days, excluding items authored by identities in the shared bot set unless there is clear significant impact requiring human attention. ### Activity Threshold (Noop) Call `noop` with message **"Project summary skipped — no meaningful activity since last report"** when: -- Total activity (commits + new issues + new PRs + merged PRs) since the last report is fewer than **3**, and +- Total activity (non-bot commits + non-bot new issues + non-bot new PRs + non-bot merged PRs) since the last report is fewer than **3**, and - There are **no** urgent, decision-needed, or stale items. ### Issue Format @@ -142,7 +144,8 @@ Call `noop` with message **"Project summary skipped — no meaningful activity s **Guidelines:** - Include direct links to issues/PRs and a short rationale for each item. -- If a section is empty, write `None`. +- If a section is empty, **omit it entirely** rather than writing `None`. Only include sections that have meaningful content. A summary with 2 substantive sections is more useful than one with 6 sections marked `None`. - Do not repeat items already covered in the previous report unless status materially changed. +- Exclude bot-authored PRs and issues (e.g., from agentic workflows, dependabot, renovate) from activity counts, stale-item selection, and the Recent Progress section unless they represent significant changes. Bot activity should not inflate the summary or trigger a report on otherwise quiet days. ${{ inputs.additional-instructions }} diff --git a/.github/workflows/gh-aw-refactor-opportunist.lock.yml b/.github/workflows/gh-aw-refactor-opportunist.lock.yml index 361f3267..7c4ab686 100644 --- a/.github/workflows/gh-aw-refactor-opportunist.lock.yml +++ b/.github/workflows/gh-aw-refactor-opportunist.lock.yml @@ -40,7 +40,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"093bbafacf204a6d8c1111025cf61257dbb90b25d08e38475e3908227f2f21a3"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"db2ded522fa2647a7cbd3e225333fe706cce3c5242136e40797ad7388273e9e9"} name: "Refactor Opportunist" "on": @@ -425,6 +425,12 @@ jobs: 4. **Select one refactor target** - Choose the single highest-impact structural improvement you found. - The refactor must be decomposable — it should be possible to implement incrementally, not as one massive change. + - Use a simple prioritization score when comparing candidates: + - Impact on maintainability/changeability (0-3) + - Incremental viability and low migration risk (0-3) + - Evidence strength from code/churn/issues (0-2) + - **Extra reuse bonus (0-2):** award extra points when an existing helper or central implementation already exists and the candidate primarily consolidates usage onto it. + - Prefer the highest-scoring candidate; if scores are close, prefer the one with the stronger reuse bonus. 5. **Partially implement to prove viability** - Implement the refactor for **one representative slice** of the codebase (e.g., one module, one file pair, one abstraction boundary). diff --git a/.github/workflows/gh-aw-refactor-opportunist.md b/.github/workflows/gh-aw-refactor-opportunist.md index 1fea4553..c05dd4f8 100644 --- a/.github/workflows/gh-aw-refactor-opportunist.md +++ b/.github/workflows/gh-aw-refactor-opportunist.md @@ -110,6 +110,12 @@ You are a senior software architect reviewing this codebase with fresh eyes. You 4. **Select one refactor target** - Choose the single highest-impact structural improvement you found. - The refactor must be decomposable — it should be possible to implement incrementally, not as one massive change. + - Use a simple prioritization score when comparing candidates: + - Impact on maintainability/changeability (0-3) + - Incremental viability and low migration risk (0-3) + - Evidence strength from code/churn/issues (0-2) + - **Extra reuse bonus (0-2):** award extra points when an existing helper or central implementation already exists and the candidate primarily consolidates usage onto it. + - Prefer the highest-scoring candidate; if scores are close, prefer the one with the stronger reuse bonus. 5. **Partially implement to prove viability** - Implement the refactor for **one representative slice** of the codebase (e.g., one module, one file pair, one abstraction boundary). diff --git a/.github/workflows/gh-aw-release-update.lock.yml b/.github/workflows/gh-aw-release-update.lock.yml index e6d4fb37..f4bbcd69 100644 --- a/.github/workflows/gh-aw-release-update.lock.yml +++ b/.github/workflows/gh-aw-release-update.lock.yml @@ -36,7 +36,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"5eef6797f47cfc5795f85152396b111b7737b3c47a32a289eea4829cfbabdebb"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"708ce4bb3efec15a147635e7f347e6e895c8ffaa691e4c0fd7bfce041046ba81"} name: "Release Update Check" "on": @@ -318,7 +318,7 @@ jobs: ## Constraints - **CAN**: Read files, search code, modify files locally, run tests and commands, create a pull request. - - **CANNOT**: Push directly to the repository — use `create_pull_request`. + - **CANNOT**: Push directly to the repository — use `ready_to_make_pr` then `create_pull_request`. - **Only one PR per run.** - Only update workflow references to `elastic/ai-github-actions/.github/workflows/gh-aw-*.lock.yml@...`. - If no updates are needed, call `noop` with a brief reason. @@ -350,7 +350,7 @@ jobs: ## Step 4: Create the PR 1. Commit the changes locally. - 2. Call `create_pull_request` with: + 2. Call `ready_to_make_pr`, then call `create_pull_request` with: - **Title**: `Update ai-github-actions workflows to ` - **Body**: Summary of updated refs (old → new), release note highlights that matter, suggested workflow updates, and tests run (if none, say "Not run (workflow reference updates only)"). diff --git a/.github/workflows/gh-aw-release-update.md b/.github/workflows/gh-aw-release-update.md index 9953d968..e6392963 100644 --- a/.github/workflows/gh-aw-release-update.md +++ b/.github/workflows/gh-aw-release-update.md @@ -92,7 +92,7 @@ Check for new releases of `elastic/ai-github-actions` and open a PR that updates ## Constraints - **CAN**: Read files, search code, modify files locally, run tests and commands, create a pull request. -- **CANNOT**: Push directly to the repository — use `create_pull_request`. +- **CANNOT**: Push directly to the repository — use `ready_to_make_pr` then `create_pull_request`. - **Only one PR per run.** - Only update workflow references to `elastic/ai-github-actions/.github/workflows/gh-aw-*.lock.yml@...`. - If no updates are needed, call `noop` with a brief reason. @@ -124,7 +124,7 @@ rg -n "elastic/ai-github-actions/.github/workflows/gh-aw-.*\\.lock\\.yml@\\S+" . ## Step 4: Create the PR 1. Commit the changes locally. -2. Call `create_pull_request` with: +2. Call `ready_to_make_pr`, then call `create_pull_request` with: - **Title**: `Update ai-github-actions workflows to ` - **Body**: Summary of updated refs (old → new), release note highlights that matter, suggested workflow updates, and tests run (if none, say "Not run (workflow reference updates only)"). diff --git a/.github/workflows/gh-aw-small-problem-fixer.lock.yml b/.github/workflows/gh-aw-small-problem-fixer.lock.yml index 763b2541..633a4292 100644 --- a/.github/workflows/gh-aw-small-problem-fixer.lock.yml +++ b/.github/workflows/gh-aw-small-problem-fixer.lock.yml @@ -37,7 +37,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"29d75dc40a8462cc5c30daba01b2dba8d71dee4d78a807d0ea65594bd671e9bf"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"6e7d3cc70dcd4b3da950942a938dee92f0b80ceca361c6574996dbaae507fba7"} name: "Small Problem Fixer" "on": @@ -337,7 +337,7 @@ jobs: ## Constraints - **CAN**: Read files, search code, modify files locally, run tests and commands, create a pull request, add issue comments. - - **CANNOT**: Push directly to the repository — use `create_pull_request`. + - **CANNOT**: Push directly to the repository — use `ready_to_make_pr` then `create_pull_request`. - **Only one PR per run.** - Only combine issues if they share the same root cause and the fix is a single small change (no broad refactors). - Skip issues that need design decisions, large refactors, or ambiguous reproduction steps. @@ -394,7 +394,7 @@ jobs: ## Step 5: Create the PR - Call `create_pull_request` with: + Call `ready_to_make_pr`, then `create_pull_request` with: - **Title**: concise fix summary - **Body**: summary, linked issue(s), required commands/tests run and their results, and any follow-ups - **Labels**: include `small-problem-fixer` if the label exists (check with `github-get_label`); otherwise omit labels diff --git a/.github/workflows/gh-aw-small-problem-fixer.md b/.github/workflows/gh-aw-small-problem-fixer.md index 24ba5ca6..ec0c8f0b 100644 --- a/.github/workflows/gh-aw-small-problem-fixer.md +++ b/.github/workflows/gh-aw-small-problem-fixer.md @@ -93,7 +93,7 @@ Find a small, clearly-scoped issue (or a very small set of related issues) and o ## Constraints - **CAN**: Read files, search code, modify files locally, run tests and commands, create a pull request, add issue comments. -- **CANNOT**: Push directly to the repository — use `create_pull_request`. +- **CANNOT**: Push directly to the repository — use `ready_to_make_pr` then `create_pull_request`. - **Only one PR per run.** - Only combine issues if they share the same root cause and the fix is a single small change (no broad refactors). - Skip issues that need design decisions, large refactors, or ambiguous reproduction steps. @@ -150,7 +150,7 @@ If the fix feels uncertain, incomplete, or risky, call `noop` with a reason. A s ## Step 5: Create the PR -Call `create_pull_request` with: +Call `ready_to_make_pr`, then `create_pull_request` with: - **Title**: concise fix summary - **Body**: summary, linked issue(s), required commands/tests run and their results, and any follow-ups - **Labels**: include `small-problem-fixer` if the label exists (check with `github-get_label`); otherwise omit labels diff --git a/.github/workflows/gh-aw-test-coverage-detector.lock.yml b/.github/workflows/gh-aw-test-coverage-detector.lock.yml index 9e00c45d..30aee11c 100644 --- a/.github/workflows/gh-aw-test-coverage-detector.lock.yml +++ b/.github/workflows/gh-aw-test-coverage-detector.lock.yml @@ -25,6 +25,7 @@ # # Resolved workflow manifest: # Imports: +# - gh-aw-fragments/code-quality-audit.md # - gh-aw-fragments/elastic-tools.md # - gh-aw-fragments/formatting.md # - gh-aw-fragments/mcp-pagination.md @@ -39,7 +40,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"92c84486d3d5552f1315b28d909ceb90f47a3608ef4aafc7d3f556304a2a72b5"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"48735a22cd66d6b86333c8237876ac47fe4796f3a0fde1beae5cbe33762812f1"} name: "Test Coverage Detector" "on": @@ -70,6 +71,11 @@ name: "Test Coverage Detector" description: Shell commands to run before the agent starts (dependency install, build, etc.) required: false type: string + severity-threshold: + default: medium + description: Minimum severity to include in the report. 'high' = only untested critical paths (error handling, auth, data mutations). 'medium' (default) = also include untested public APIs and recent changes. 'low' = also include minor coverage gaps. + required: false + type: string title-prefix: default: "[test-coverage]" description: Title prefix for created issues (e.g. '[test-coverage]') @@ -161,6 +167,7 @@ jobs: env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_EXPR_08E89BCD: ${{ inputs.severity-threshold }} GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} GH_AW_EXPR_BF503D80: ${{ inputs.title-prefix }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} @@ -396,12 +403,68 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + Analyze the codebase for quality issues and file a structured report when concrete, actionable findings exist. + + **The bar is high: only report issues backed by specific code evidence.** Most runs should end with `noop` — that means the code is in good shape for the dimension being audited. Filing nothing is a success when there is nothing worth filing. + + ### Severity Threshold: `__GH_AW_EXPR_08E89BCD__` + + Only include findings at or above the configured severity. Severity labels and meanings are defined by the importing workflow; this fragment uses the importing workflow's `__GH_AW_EXPR_08E89BCD__` semantics. + + ### Evidence Standard + + Every finding must include **all** of the following. Findings missing any element must be dropped: + + 1. **Location** — File path(s) and precise location context (line numbers when available or another unambiguous locator required by the importing workflow). + 2. **Evidence** — The specific code or configuration that exhibits the issue. + 3. **What is wrong** — A clear, concrete explanation of the problem. Not "this could be better" but "this does X when it should do Y" or "this violates [specific standard/guideline]." + 4. **Why it matters** — Concrete impact: who is affected, what breaks, what degrades, or what standard is violated. Reference the specific standard, guideline, or documentation (e.g., WCAG 2.1 SC 4.1.2, React docs on exhaustive-deps, framework migration guide). + 5. **Suggested fix** — A concrete code change or approach, not a vague recommendation. + + ### Verification Pass (Required) + + After gathering findings from sub-agents, verify each one yourself: + + 1. Read the file at the cited path and confirm the line numbers are accurate. + 2. Confirm the code snippet matches what is actually in the file. + 3. Confirm the issue is real — not a false positive from misunderstanding the code's intent. + 4. Confirm the suggested fix would not break existing behavior. + 5. Drop any finding where verification fails. + + ### Quality Gate — When to Noop + + Call `noop` if any of these are true: + - No findings survive the verification pass. + - All findings are below the severity threshold. + - All findings are already tracked by open issues. + - All findings are subjective style preferences rather than concrete quality issues. + - You cannot provide specific file paths and line numbers for any finding. + + ### Consolidation Rules + + - Group related findings (e.g., the same anti-pattern in multiple files) into a single numbered section. + - Prefer fewer, denser issues over frequent thin issues. + - If a pattern appears in many files, do a completeness pass: search the repo for all occurrences and list them, so maintainers can fix the whole family at once. + + ### Output Contract + + Follow the importing workflow's issue title/body template. This shared fragment defines quality gates and evidence requirements only; per-workflow report schemas remain source-of-truth for final output format. + GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' Identify under-tested code paths that would benefit from focused tests and file a report issue with specific, actionable recommendations. **The bar is high: you must identify concrete, high-value test gaps before filing.** Most runs should end with `noop` — that means test coverage is adequate. + ### Severity Policy + + Apply `__GH_AW_EXPR_08E89BCD__` using this explicit policy: + - `high` — include only untested critical paths (error handling, authentication/authorization, data mutations, and correctness-critical business logic). + - `medium` — include everything in `high`, plus untested public APIs and recent changes that lack tests. + - `low` — include everything in `medium`, plus minor but concrete coverage gaps that still map to a real user scenario. + ### Data Gathering 1. Determine required repo commands (lint/build/test) and how to run tests: @@ -475,6 +538,7 @@ jobs: env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_INPUTS_MODEL: ${{ inputs.model }} + GH_AW_EXPR_08E89BCD: ${{ inputs.severity-threshold }} GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} GH_AW_EXPR_BF503D80: ${{ inputs.title-prefix }} with: @@ -487,6 +551,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_08E89BCD: ${{ inputs.severity-threshold }} GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} GH_AW_EXPR_BF503D80: ${{ inputs.title-prefix }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} @@ -510,6 +575,7 @@ jobs: return await substitutePlaceholders({ file: process.env.GH_AW_PROMPT, substitutions: { + GH_AW_EXPR_08E89BCD: process.env.GH_AW_EXPR_08E89BCD, GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, GH_AW_EXPR_BF503D80: process.env.GH_AW_EXPR_BF503D80, GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, @@ -637,6 +703,10 @@ jobs: TITLE_PREFIX: ${{ inputs.title-prefix }} name: List previous findings run: "set -euo pipefail\ngh issue list \\\n --repo \"$GITHUB_REPOSITORY\" \\\n --search \"in:title \\\"$TITLE_PREFIX\\\"\" \\\n --state all \\\n --limit 100 \\\n --json number,title,state \\\n > /tmp/previous-findings.json || { echo \"::warning::Failed to fetch previous findings — dedup will be skipped\"; echo \"[]\" > /tmp/previous-findings.json; }" + - env: + SEVERITY_THRESHOLD: ${{ inputs.severity-threshold }} + name: Validate severity threshold + run: "case \"$SEVERITY_THRESHOLD\" in\n high|medium|low) ;;\n *)\n echo \"Invalid severity-threshold: '$SEVERITY_THRESHOLD'. Expected one of: high, medium, low.\"\n exit 1\n ;;\nesac\n" - env: SETUP_COMMANDS: ${{ inputs.setup-commands }} if: ${{ inputs.setup-commands != '' }} diff --git a/.github/workflows/gh-aw-test-coverage-detector.md b/.github/workflows/gh-aw-test-coverage-detector.md index 813cfdff..251d0535 100644 --- a/.github/workflows/gh-aw-test-coverage-detector.md +++ b/.github/workflows/gh-aw-test-coverage-detector.md @@ -14,6 +14,7 @@ imports: - gh-aw-fragments/pick-three-keep-one.md - gh-aw-fragments/scheduled-audit.md - gh-aw-fragments/network-ecosystems.md + - gh-aw-fragments/code-quality-audit.md engine: id: copilot model: ${{ inputs.model }} @@ -45,6 +46,11 @@ on: type: string required: false default: "" + severity-threshold: + description: "Minimum severity to include in the report. 'high' = only untested critical paths (error handling, auth, data mutations). 'medium' (default) = also include untested public APIs and recent changes. 'low' = also include minor coverage gaps." + type: string + required: false + default: "medium" title-prefix: description: "Title prefix for created issues (e.g. '[test-coverage]')" type: string @@ -80,6 +86,17 @@ safe-outputs: expires: 7d timeout-minutes: 90 steps: + - name: Validate severity threshold + env: + SEVERITY_THRESHOLD: ${{ inputs.severity-threshold }} + run: | + case "$SEVERITY_THRESHOLD" in + high|medium|low) ;; + *) + echo "Invalid severity-threshold: '$SEVERITY_THRESHOLD'. Expected one of: high, medium, low." + exit 1 + ;; + esac - name: Repo-specific setup if: ${{ inputs.setup-commands != '' }} env: @@ -91,6 +108,13 @@ Identify under-tested code paths that would benefit from focused tests and file **The bar is high: you must identify concrete, high-value test gaps before filing.** Most runs should end with `noop` — that means test coverage is adequate. +### Severity Policy + +Apply `${{ inputs.severity-threshold }}` using this explicit policy: +- `high` — include only untested critical paths (error handling, authentication/authorization, data mutations, and correctness-critical business logic). +- `medium` — include everything in `high`, plus untested public APIs and recent changes that lack tests. +- `low` — include everything in `medium`, plus minor but concrete coverage gaps that still map to a real user scenario. + ### Data Gathering 1. Determine required repo commands (lint/build/test) and how to run tests: diff --git a/.github/workflows/gh-aw-test-improvement.lock.yml b/.github/workflows/gh-aw-test-improvement.lock.yml index fdf4fedf..a5b592ba 100644 --- a/.github/workflows/gh-aw-test-improvement.lock.yml +++ b/.github/workflows/gh-aw-test-improvement.lock.yml @@ -41,7 +41,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"8c1608d65330795c0baab1c5746d8d1e49fb36401e2d9264254db3563468fb29"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"055a260ce84412fca1016e88cef813f690b9512d896a7d7a0c24f8525c51ea47"} name: "Test Improver" "on": @@ -323,7 +323,7 @@ jobs: ## Constraints - **CAN**: Read files, search code, modify files locally, run tests and commands, create a pull request. - - **CANNOT**: Push directly to the repository — use `create_pull_request`. + - **CANNOT**: Push directly to the repository — use `ready_to_make_pr` then `create_pull_request`. - **Only one PR per run.** - No large refactors; prioritize targeted test additions or small cleanup of redundant tests. - If the change set is large or unsafe, call `noop` with a brief reason. @@ -387,7 +387,7 @@ jobs: ## Step 7: Create the PR 1. Commit the changes locally. - 2. Call `create_pull_request` with: + 2. Call `ready_to_make_pr`, then call `create_pull_request` with: - **Title**: concise summary of the test improvements - **Body** must include: - Summary of what changed diff --git a/.github/workflows/gh-aw-test-improver.lock.yml b/.github/workflows/gh-aw-test-improver.lock.yml index 2807c435..6877e67a 100644 --- a/.github/workflows/gh-aw-test-improver.lock.yml +++ b/.github/workflows/gh-aw-test-improver.lock.yml @@ -36,7 +36,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"8c1608d65330795c0baab1c5746d8d1e49fb36401e2d9264254db3563468fb29"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"055a260ce84412fca1016e88cef813f690b9512d896a7d7a0c24f8525c51ea47"} name: "Test Improver" "on": @@ -318,7 +318,7 @@ jobs: ## Constraints - **CAN**: Read files, search code, modify files locally, run tests and commands, create a pull request. - - **CANNOT**: Push directly to the repository — use `create_pull_request`. + - **CANNOT**: Push directly to the repository — use `ready_to_make_pr` then `create_pull_request`. - **Only one PR per run.** - No large refactors; prioritize targeted test additions or small cleanup of redundant tests. - If the change set is large or unsafe, call `noop` with a brief reason. @@ -382,7 +382,7 @@ jobs: ## Step 7: Create the PR 1. Commit the changes locally. - 2. Call `create_pull_request` with: + 2. Call `ready_to_make_pr`, then call `create_pull_request` with: - **Title**: concise summary of the test improvements - **Body** must include: - Summary of what changed diff --git a/.github/workflows/gh-aw-test-improver.md b/.github/workflows/gh-aw-test-improver.md index 27712fc5..35ada9d8 100644 --- a/.github/workflows/gh-aw-test-improver.md +++ b/.github/workflows/gh-aw-test-improver.md @@ -93,7 +93,7 @@ Identify under-tested code paths, add focused tests, and remove or consolidate d ## Constraints - **CAN**: Read files, search code, modify files locally, run tests and commands, create a pull request. -- **CANNOT**: Push directly to the repository — use `create_pull_request`. +- **CANNOT**: Push directly to the repository — use `ready_to_make_pr` then `create_pull_request`. - **Only one PR per run.** - No large refactors; prioritize targeted test additions or small cleanup of redundant tests. - If the change set is large or unsafe, call `noop` with a brief reason. @@ -157,7 +157,7 @@ If the tests don't pass this bar, call `noop`. Low-value tests are worse than no ## Step 7: Create the PR 1. Commit the changes locally. -2. Call `create_pull_request` with: +2. Call `ready_to_make_pr`, then call `create_pull_request` with: - **Title**: concise summary of the test improvements - **Body** must include: - Summary of what changed diff --git a/.github/workflows/gh-aw-text-auditor.lock.yml b/.github/workflows/gh-aw-text-auditor.lock.yml index e4c99575..35c12a90 100644 --- a/.github/workflows/gh-aw-text-auditor.lock.yml +++ b/.github/workflows/gh-aw-text-auditor.lock.yml @@ -39,7 +39,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"8a87d78e7b6d3366d5fc7a6e23a84faa147b9063f3dc429e1adf5ba5155d61b6"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"b86b0a3777025392500d164541a24989ae2572fe9df435f3bb8f8ca8fcd7dc42"} name: "Text Auditor" "on": @@ -556,6 +556,7 @@ jobs: - The problems found are in generated or vendored files - All findings are style preferences rather than clear errors - Findings require design decisions or significant rewording beyond simple corrections + - All findings are **single-instance cosmetic-only issues** — isolated casing preferences (e.g., "Node detail" vs "Node Detail"), missing articles, punctuation choices, or markdown formatting minutiae that do not cause user confusion. These are not worth a human's review time unless they are part of a broader, systematic inconsistency. Note: overlap/duplication with existing open `__GH_AW_EXPR_BF503D80__` issues and low-value micro-edits are evaluated via the rubric above. diff --git a/.github/workflows/gh-aw-text-auditor.md b/.github/workflows/gh-aw-text-auditor.md index d3568ae4..5cb63c51 100644 --- a/.github/workflows/gh-aw-text-auditor.md +++ b/.github/workflows/gh-aw-text-auditor.md @@ -236,6 +236,7 @@ Call `noop` if any of these are true: - The problems found are in generated or vendored files - All findings are style preferences rather than clear errors - Findings require design decisions or significant rewording beyond simple corrections +- All findings are **single-instance cosmetic-only issues** — isolated casing preferences (e.g., "Node detail" vs "Node Detail"), missing articles, punctuation choices, or markdown formatting minutiae that do not cause user confusion. These are not worth a human's review time unless they are part of a broader, systematic inconsistency. Note: overlap/duplication with existing open `${{ inputs.title-prefix }}` issues and low-value micro-edits are evaluated via the rubric above. diff --git a/.github/workflows/gh-aw-update-pr-body.lock.yml b/.github/workflows/gh-aw-update-pr-body.lock.yml index aec4943b..2f9e4a1f 100644 --- a/.github/workflows/gh-aw-update-pr-body.lock.yml +++ b/.github/workflows/gh-aw-update-pr-body.lock.yml @@ -35,7 +35,7 @@ # # inlined-imports: true # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"9bb4c0ab6f9ff04c347bcb52e01829775bcc2748e96578184cef91bab757efe7"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"98f4fc8ae0f9a783df21e5925a087e19f724eb3813451cc963522c4eab337379"} name: "Update PR Body" "on": @@ -170,6 +170,7 @@ jobs: GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} GH_AW_EXPR_4A6C8AF6: ${{ inputs.edit-accuracy }} GH_AW_EXPR_754DFA49: ${{ inputs.edit-format }} + GH_AW_EXPR_9B9EBBAB: ${{ inputs.messages-footer }} GH_AW_EXPR_BFC7045A: ${{ inputs.edit-style }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} @@ -316,6 +317,13 @@ jobs: - **Repository**: __GH_AW_GITHUB_REPOSITORY__ - **PR**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ — __GH_AW_GITHUB_EVENT_PULL_REQUEST_TITLE__ + - **Runtime-managed footer override input**: `__GH_AW_EXPR_9B9EBBAB__` + - **Default runtime footer text (used when no override is provided)**: + + ```text + --- + The body of this PR is automatically managed by the workflow runtime. + ``` ## Edit Level Configuration @@ -329,6 +337,7 @@ jobs: | **style** | `__GH_AW_EXPR_BFC7045A__` | How aggressively to improve writing clarity, conciseness, and tone | Level semantics: + - **`high`** — apply the agent's best judgment; proactively improve this dimension throughout the body - **`low`** — make only conservative fixes for clear problems; do not restructure or rewrite - **`none`** — do not touch this dimension at all; leave it exactly as the author wrote it @@ -387,13 +396,23 @@ jobs: Based on your analysis, compile the full list of changes warranted across all non-`none` dimensions. Group them by dimension. + Before proposing body changes, normalize footer content: + + - Identify and remove any existing footer block(s) that match either: + - the configured runtime-managed footer override input (when present), or + - the default runtime footer text above. + - If the PR body contains repeated copies of that same footer, remove all copies from the authored content you are editing. + - Treat this cleanup as mechanical deduplication, not a style/format rewrite. + Do **not** propose changes when: + - The dimension level is `none` - The level is `low` and the issue is minor (style preference, slight improvement, optional detail) - An update would erase useful context (motivation, design decisions, issue links) the author provided - The body is a reasonable high-level summary even if some details differ **Never willingly add any of the following to the PR body** (even in `high` mode): + - Commit counts, file counts, or insertion/deletion statistics (e.g., "2 commits, 143 files changed, 12,613 insertions") - Scope or size summaries — the reviewer can see these in the GitHub UI - Lists of every file changed — link to relevant code instead @@ -405,6 +424,7 @@ jobs: **If any changes are warranted:** Call `update_pull_request` **exactly once** with a `replace` operation to write a body that applies all warranted changes. You may only call this tool once per run — additional calls will be rejected by validation. The updated body must: + - Apply only the changes identified in Step 4 — do not make unplanned edits - Preserve the original structure, formatting, and wording of sections untouched by warranted changes - Preserve the original motivation and context (including issue links like `Fixes #N`) @@ -432,6 +452,7 @@ jobs: GH_AW_EXPR_235B0F42: ${{ inputs.edit-completeness }} GH_AW_EXPR_754DFA49: ${{ inputs.edit-format }} GH_AW_EXPR_BFC7045A: ${{ inputs.edit-style }} + GH_AW_EXPR_9B9EBBAB: ${{ inputs.messages-footer }} with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -446,6 +467,7 @@ jobs: GH_AW_EXPR_49B959F1: ${{ inputs.additional-instructions }} GH_AW_EXPR_4A6C8AF6: ${{ inputs.edit-accuracy }} GH_AW_EXPR_754DFA49: ${{ inputs.edit-format }} + GH_AW_EXPR_9B9EBBAB: ${{ inputs.messages-footer }} GH_AW_EXPR_BFC7045A: ${{ inputs.edit-style }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} @@ -474,6 +496,7 @@ jobs: GH_AW_EXPR_49B959F1: process.env.GH_AW_EXPR_49B959F1, GH_AW_EXPR_4A6C8AF6: process.env.GH_AW_EXPR_4A6C8AF6, GH_AW_EXPR_754DFA49: process.env.GH_AW_EXPR_754DFA49, + GH_AW_EXPR_9B9EBBAB: process.env.GH_AW_EXPR_9B9EBBAB, GH_AW_EXPR_BFC7045A: process.env.GH_AW_EXPR_BFC7045A, GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, diff --git a/.github/workflows/gh-aw-update-pr-body.md b/.github/workflows/gh-aw-update-pr-body.md index 43fd76f6..f1498a6f 100644 --- a/.github/workflows/gh-aw-update-pr-body.md +++ b/.github/workflows/gh-aw-update-pr-body.md @@ -98,6 +98,13 @@ Keep the pull request body in sync with the actual state of the code changes in - **Repository**: ${{ github.repository }} - **PR**: #${{ github.event.pull_request.number }} — ${{ github.event.pull_request.title }} +- **Runtime-managed footer override input**: `${{ inputs.messages-footer }}` +- **Default runtime footer text (used when no override is provided)**: + +```text +--- +The body of this PR is automatically managed by the workflow runtime. +``` ## Edit Level Configuration @@ -111,6 +118,7 @@ The following edit levels are configured for this run. Each dimension is indepen | **style** | `${{ inputs.edit-style }}` | How aggressively to improve writing clarity, conciseness, and tone | Level semantics: + - **`high`** — apply the agent's best judgment; proactively improve this dimension throughout the body - **`low`** — make only conservative fixes for clear problems; do not restructure or rewrite - **`none`** — do not touch this dimension at all; leave it exactly as the author wrote it @@ -169,13 +177,23 @@ Assess the PR body across each configured dimension. Use the level to determine Based on your analysis, compile the full list of changes warranted across all non-`none` dimensions. Group them by dimension. +Before proposing body changes, normalize footer content: + +- Identify and remove any existing footer block(s) that match either: + - the configured runtime-managed footer override input (when present), or + - the default runtime footer text above. +- If the PR body contains repeated copies of that same footer, remove all copies from the authored content you are editing. +- Treat this cleanup as mechanical deduplication, not a style/format rewrite. + Do **not** propose changes when: + - The dimension level is `none` - The level is `low` and the issue is minor (style preference, slight improvement, optional detail) - An update would erase useful context (motivation, design decisions, issue links) the author provided - The body is a reasonable high-level summary even if some details differ **Never willingly add any of the following to the PR body** (even in `high` mode): + - Commit counts, file counts, or insertion/deletion statistics (e.g., "2 commits, 143 files changed, 12,613 insertions") - Scope or size summaries — the reviewer can see these in the GitHub UI - Lists of every file changed — link to relevant code instead @@ -187,6 +205,7 @@ Do **not** propose changes when: **If any changes are warranted:** Call `update_pull_request` **exactly once** with a `replace` operation to write a body that applies all warranted changes. You may only call this tool once per run — additional calls will be rejected by validation. The updated body must: + - Apply only the changes identified in Step 4 — do not make unplanned edits - Preserve the original structure, formatting, and wording of sections untouched by warranted changes - Preserve the original motivation and context (including issue links like `Fixes #N`) diff --git a/.github/workflows/trigger-docs-patrol.yml b/.github/workflows/trigger-docs-patrol.yml index efd706e3..d8a4edc0 100644 --- a/.github/workflows/trigger-docs-patrol.yml +++ b/.github/workflows/trigger-docs-patrol.yml @@ -7,12 +7,23 @@ on: workflow_dispatch: permissions: - contents: read + contents: write issues: write - pull-requests: read + pull-requests: write jobs: run: uses: ./.github/workflows/gh-aw-docs-patrol.lock.yml secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + + create_pr_from_issue: + needs: run + if: ${{ needs.run.outputs.created_issue_number != '' }} + uses: ./.github/workflows/gh-aw-create-pr-from-issue.lock.yml + with: + target-issue-number: ${{ needs.run.outputs.created_issue_number }} + additional-instructions: "Create a focused pull request that resolves this issue." + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + EXTRA_COMMIT_GITHUB_TOKEN: ${{ secrets.EXTRA_COMMIT_GITHUB_TOKEN }} diff --git a/.github/workflows/trigger-framework-best-practices.yml b/.github/workflows/trigger-framework-best-practices.yml index c48df73b..40792a4f 100644 --- a/.github/workflows/trigger-framework-best-practices.yml +++ b/.github/workflows/trigger-framework-best-practices.yml @@ -7,12 +7,23 @@ on: workflow_dispatch: permissions: - contents: read + contents: write issues: write - pull-requests: read + pull-requests: write jobs: run: uses: ./.github/workflows/gh-aw-framework-best-practices.lock.yml secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + + create_pr_from_issue: + needs: run + if: ${{ needs.run.outputs.created_issue_number != '' }} + uses: ./.github/workflows/gh-aw-create-pr-from-issue.lock.yml + with: + target-issue-number: ${{ needs.run.outputs.created_issue_number }} + additional-instructions: "Create a focused pull request that resolves this issue." + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + EXTRA_COMMIT_GITHUB_TOKEN: ${{ secrets.EXTRA_COMMIT_GITHUB_TOKEN }} diff --git a/.github/workflows/trigger-text-auditor.yml b/.github/workflows/trigger-text-auditor.yml index 8dbe8aa0..f3cd874d 100644 --- a/.github/workflows/trigger-text-auditor.yml +++ b/.github/workflows/trigger-text-auditor.yml @@ -7,9 +7,9 @@ on: workflow_dispatch: permissions: - contents: read + contents: write issues: write - pull-requests: read + pull-requests: write jobs: run: @@ -22,3 +22,14 @@ jobs: edit-misleading-text: high secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + + create_pr_from_issue: + needs: run + if: ${{ needs.run.outputs.created_issue_number != '' }} + uses: ./.github/workflows/gh-aw-create-pr-from-issue.lock.yml + with: + target-issue-number: ${{ needs.run.outputs.created_issue_number }} + additional-instructions: "Create a focused pull request that resolves this issue." + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + EXTRA_COMMIT_GITHUB_TOKEN: ${{ secrets.EXTRA_COMMIT_GITHUB_TOKEN }} diff --git a/gh-agent-workflows/update-pr-body/README.md b/gh-agent-workflows/update-pr-body/README.md index 93eed0da..415f88ce 100644 --- a/gh-agent-workflows/update-pr-body/README.md +++ b/gh-agent-workflows/update-pr-body/README.md @@ -2,6 +2,8 @@ Keep pull request bodies in sync with the code changes on every commit. +The updater also deduplicates any previously appended runtime footer text in the PR body before rewriting, so repeated runs do not stack duplicate footer blocks. + ## Quick Install ```bash diff --git a/scripts/dogfood.sh b/scripts/dogfood.sh index 6847e51e..6b3bddf2 100755 --- a/scripts/dogfood.sh +++ b/scripts/dogfood.sh @@ -41,6 +41,14 @@ EXCLUDED_WORKFLOWS=( "text-beautifier" ) +# Workflows that should auto-chain issue -> remediation PR in generated dogfood triggers. +# These entries refer to gh-agent-workflows//example.yml directories. +REMEDIATION_WORKFLOWS=( + "docs-patrol" + "framework-best-practices" + "text-auditor" +) + echo "Syncing workflow files..." # Copy trigger example.yml files from gh-agent-workflows/*/ → .github/workflows/trigger-* @@ -69,10 +77,11 @@ for f in gh-agent-workflows/*/example.yml; do overrides="gh-agent-workflows/$dir/dogfood-with.yml" if [[ -f "$overrides" ]]; then awk -v of="$overrides" ' - /^ with:/ { in_with=1; next } + /^ [^ ]+:/ { current_job=$0; sub(/^ /, "", current_job); sub(/:$/, "", current_job) } + current_job=="run" && /^ with:/ { in_with=1; next } in_with && /^ [a-z]/ { in_with=0 } in_with { next } - /^ secrets:/ { + current_job=="run" && /^ secrets:/ { print " with:" while ((getline line < of) > 0) { print " " line @@ -94,6 +103,31 @@ for f in gh-agent-workflows/*/example.yml; do EXTRA_COMMIT_GITHUB_TOKEN: ${{ secrets.EXTRA_COMMIT_GITHUB_TOKEN }}' "$target" > "$target.tmp" && mv "$target.tmp" "$target" echo " + injected EXTRA_COMMIT_GITHUB_TOKEN secret" fi + + # Append automatic issue -> PR remediation chain for selected workflows. + add_remediation=false + for remediation in "${REMEDIATION_WORKFLOWS[@]}"; do + [[ "$dir" == "$remediation" ]] && add_remediation=true && break + done + if [[ "$add_remediation" == "true" ]]; then + # Ensure permissions allow downstream PR creation job. + sed -E 's/^([[:space:]]*contents: )read$/\1write/; s/^([[:space:]]*pull-requests: )read$/\1write/' "$target" > "$target.tmp" && mv "$target.tmp" "$target" + + cat >> "$target" <<'EOF' + + create_pr_from_issue: + needs: run + if: ${{ needs.run.outputs.created_issue_number != '' }} + uses: ./.github/workflows/gh-aw-create-pr-from-issue.lock.yml + with: + target-issue-number: ${{ needs.run.outputs.created_issue_number }} + additional-instructions: "Create a focused pull request that resolves this issue." + secrets: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + EXTRA_COMMIT_GITHUB_TOKEN: ${{ secrets.EXTRA_COMMIT_GITHUB_TOKEN }} +EOF + echo " + appended remediation chain jobs" + fi done echo "✓ Sync complete"