diff --git a/.github/docs/state-machine.md b/.github/docs/state-machine.md index 2885894bf26..c063af8148e 100644 --- a/.github/docs/state-machine.md +++ b/.github/docs/state-machine.md @@ -45,7 +45,7 @@ This document maps the 16 GitHub Actions workflows and AI agents in this reposit | 11 | `labelops-pr-security-scan.md` | ⏰ hourly, 👤 dispatch | none | add-labels, add-comment, repo-memory write | | 12 | `msbuild-quality-review.md` | ⏰ weekly, 👤 dispatch | none | create-issue, create-pull-request (draft) | | 13 | `regression-pr-shepherd.md` | ⏰ every 4h, 👤 dispatch | none | push-to-PR, add-comment, remove-labels | -| 14 | `repo-assist.md` | ⏰ every 12h, 👤 dispatch, 👤 slash_command | none | create-pull-request, add-comment, add/remove-labels, create/update-issue, push-to-PR | +| 14 | `repo-assist-scheduled.md` | ⏰ every 12h, 👤 dispatch | none | create-pull-request, add-comment, add/remove-labels, create/update-issue, push-to-PR | | 15 | `repository_lockdown_check.yml` | 👤 pull_request_target | none | PR comment (lockdown warning) | | 16 | `skill-validation.yml` | 👤 PR, ⚙️ push (main), 👤 dispatch | none | validate skills/agents | @@ -56,15 +56,15 @@ Cross-workflow interactions (producer → consumer): | Signal | Producer | Consumer | Mechanism | |--------|----------|----------|-----------| | `AI-Auto-Resolve-CI/Conflicts` labels | Human maintainer | `labelops-pr-maintenance` | Label filter on PR list | -| `AI-Issue-Regression-PR` label | `repo-assist` | `regression-pr-shepherd` | Label filter on PR list | -| `AI-thinks-issue-fixed` label | `repo-assist` | `regression-pr-shepherd` (remove) | Label on linked issue | +| `AI-Issue-Regression-PR` label | `repo-assist-scheduled` | `regression-pr-shepherd` | Label filter on PR list | +| `AI-thinks-issue-fixed` label | `repo-assist-scheduled` | `regression-pr-shepherd` (remove) | Label on linked issue | | `dispatch-workflow: labelops-flake-fix` | `labelops-pr-maintenance` | `labelops-flake-fix` | workflow_dispatch with inputs | | `Flaky` label | `labelops-flake-fix` | Human triage | always-applied on PR/issue | | `AI-needs-CI-fix-input` label | `labelops-pr-maintenance` | Human maintainer | escalation signal | | `⚠️ Affects-*` labels | `labelops-pr-security-scan` | Human reviewer | informational | | `Needs-Triage` label | `add_to_project.yml` | Human triage | imperative on new issues | | State-store `safety/scanned-PRs` | `labelops-pr-security-scan` | `labelops-pr-security-scan` | repo-memory persistence | -| State-store `memory/repo-assist` | `repo-assist` | `repo-assist` | repo-memory persistence | +| State-store `memory/repo-assist` | `repo-assist-scheduled` | `repo-assist-scheduled` | repo-memory persistence | ## Group A — LabelOps Ecosystem @@ -141,7 +141,7 @@ stateDiagram-v2 ## Group B — Regression Test Pipeline -Workflows: `repo-assist` (RA), `regression-pr-shepherd` (RPS). +Workflows: `repo-assist-scheduled` (RA), `regression-pr-shepherd` (RPS). RA creates regression test PRs and labels issues. RPS shepherds those PRs to merge. @@ -149,8 +149,8 @@ RA creates regression test PRs and labels issues. RPS shepherds those PRs to mer stateDiagram-v2 direction LR - state "repo-assist" as RA { - [*] --> RA_FetchData : ⏰ every 12h / 👤 dispatch / 👤 slash_command + state "repo-assist-scheduled" as RA { + [*] --> RA_FetchData : ⏰ every 12h / 👤 dispatch RA_FetchData --> RA_Task1 : ⚙️ task selection RA_Task1 --> RA_Task3 : ⚙️ issue investigation RA_Task3 --> RA_Task2 : ⚙️ windows-only revisit @@ -341,12 +341,12 @@ gh-aw safe-output defaults (suppressed below): `target: "*"`, `noop.report-as-is | `regression-pr-shepherd` | `push-to-pull-request-branch` | 10 | allowed-files: tests/**, vsintegration/tests/** | | `regression-pr-shepherd` | `add-comment` | 5 | hide-older-comments: true | | `regression-pr-shepherd` | `remove-labels` | 5 | allowed: AI-thinks-issue-fixed | -| `repo-assist` | `create-pull-request` | 10 | title `Add regression test: `, labels: NO_RELEASE_NOTES+AI-Issue-Regression-PR, reviewers: abonie+T-Gro, auto-merge: true | -| `repo-assist` | `add-comment` | 10 | hide-older-comments: true | -| `repo-assist` | `add-labels` | 30 | allowed: AI-thinks-issue-fixed, AI-thinks-windows-only | -| `repo-assist` | `remove-labels` | 10 | allowed: AI-thinks-issue-fixed, AI-thinks-windows-only | -| `repo-assist` | `create-issue` | 4 | title `[Repo Assist] `, labels: automation+repo-assist | -| `repo-assist` | `push-to-pull-request-branch` | 4 | title `[Repo Assist] `, protected-files: fallback-to-issue | +| `repo-assist-scheduled` | `create-pull-request` | 10 | title `Add regression test: `, labels: NO_RELEASE_NOTES+AI-Issue-Regression-PR, reviewers: abonie+T-Gro, auto-merge: true | +| `repo-assist-scheduled` | `add-comment` | 10 | hide-older-comments: true | +| `repo-assist-scheduled` | `add-labels` | 30 | allowed: AI-thinks-issue-fixed, AI-thinks-windows-only | +| `repo-assist-scheduled` | `remove-labels` | 10 | allowed: AI-thinks-issue-fixed, AI-thinks-windows-only | +| `repo-assist-scheduled` | `create-issue` | 4 | title `[Repo Assist] `, labels: automation+repo-assist | +| `repo-assist-scheduled` | `push-to-pull-request-branch` | 4 | title `[Repo Assist] `, protected-files: fallback-to-issue | ## Label Index diff --git a/.github/workflows/agentic-state-machine.md b/.github/workflows/agentic-state-machine.md index dc3b711ab12..3e4d0229127 100644 --- a/.github/workflows/agentic-state-machine.md +++ b/.github/workflows/agentic-state-machine.md @@ -309,7 +309,7 @@ You are a workflow-automation documentor. You read all workflow files in `.githu Place the glossary IMMEDIATELY after the title and intro paragraph, BEFORE the Overview table. A first-time reader rated 2/5 on a 5-point readability scale citing exactly these gaps. Missing glossary entry for a term used 3+ times = MAJOR. Missing emoji legend = MAJOR. 45. **Self-contained — never use source-file pointers as documentation.** Any phrase like `"(see file.md L100–110)"`, `"per source line N"`, `"refer to "`, or `"as defined in "` in PLACE of actual content is a documentation failure. Inline the content. Citations `(src Lnn)` are permitted ONLY as provenance markers AFTER the documented content, never AS the content. Example: - - ❌ WRONG: `RA_T2_SkipCheck --> RA_TaskFinal : ⚙️ check skip conditions (repo-assist.md L296–306)` + - ❌ WRONG: `RA_T2_SkipCheck --> RA_TaskFinal : ⚙️ check skip conditions (repo-assist-scheduled.md L296–306)` - ✅ CORRECT: `RA_T2_SkipCheck --> RA_TaskFinal : ⚙️ check 6 skip conditions` + an inline `> **Skip conditions**: 1. closed; 2. existing PR; 3. existing coverage; 4. test-link comment; 5. untestable comment; 6. human coverage comment.` callout below the diagram. Any source-pointer-as-content = MAJOR. Inlined skip conditions, taxonomy enumerations, and predicate lists belong in the doc itself. diff --git a/.github/workflows/check_release_notes.yml b/.github/workflows/check_release_notes.yml index bed91b1b52d..ae85562aa3c 100644 --- a/.github/workflows/check_release_notes.yml +++ b/.github/workflows/check_release_notes.yml @@ -23,9 +23,7 @@ jobs: PR_AUTHOR: ${{ github.event.pull_request.user.login }} PR_BASE_SHA: ${{ github.event.pull_request.base.sha }} PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} - PR_LABELS: ${{ toJSON(github.event.pull_request.labels) }} PR_NUMBER: ${{ github.event.pull_request.number }} - OPT_OUT_RELEASE_NOTES: ${{ contains(github.event.pull_request.labels.*.name, 'NO_RELEASE_NOTES') }} VNEXT: ${{ vars.VNEXT }} runs-on: ubuntu-latest steps: @@ -40,9 +38,6 @@ jobs: [[ "$PR_BASE_SHA" =~ ^[0-9a-f]{40}$ ]] || { echo "::error::Unexpected base SHA: $PR_BASE_SHA"; exit 1; } [[ "$PR_HEAD_SHA" =~ ^[0-9a-f]{40}$ ]] || { echo "::error::Unexpected head SHA: $PR_HEAD_SHA"; exit 1; } - echo "PR Tags: $PR_LABELS" - echo "Opt out of release notes: $OPT_OUT_RELEASE_NOTES" - _current_head_sha=$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" --jq '.head.sha') if [[ "$_current_head_sha" != "$PR_HEAD_SHA" ]]; then @@ -269,31 +264,46 @@ jobs: if [[ $RELEASE_NOTES_MESSAGE_DETAILS == "" ]]; then RELEASE_NOTES_MESSAGE+=$'## :white_check_mark: No release notes required\n\n' else - RELEASE_NOTES_MESSAGE+=$'## :heavy_exclamation_mark: Release notes required\n\n' - RELEASE_NOTES_MESSAGE+=$"**You can open this PR in browser to add release notes: [open in github.dev](https://github.dev/dotnet/fsharp/pull/${PR_NUMBER})**" - RELEASE_NOTES_MESSAGE+=$'\n\n' + if [[ $RELEASE_NOTES_NOT_FOUND != "" ]]; then + RELEASE_NOTES_MESSAGE+=$'## :heavy_exclamation_mark: Release notes required\n\n' + RELEASE_NOTES_MESSAGE+=$"**You can open this PR in browser to add release notes: [open in github.dev](https://github.dev/dotnet/fsharp/pull/${PR_NUMBER})**" + RELEASE_NOTES_MESSAGE+=$'\n\n' + else + RELEASE_NOTES_MESSAGE+=$'## :white_check_mark: Release notes checked\n\n' + fi RELEASE_NOTES_MESSAGE+=$RELEASE_NOTES_MESSAGE_DETAILS fi - _current_head_sha=$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" --jq '.head.sha') + _current_pr=$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}") + _current_head_sha=$(jq -r '.head.sha' <<< "$_current_pr") if [[ "$_current_head_sha" != "$PR_HEAD_SHA" ]]; then echo "::notice::Discarding stale release-note result for ${PR_HEAD_SHA}; current head is ${_current_head_sha}." exit 0 fi + OPT_OUT_RELEASE_NOTES=$(jq -r 'any(.labels[]; .name == "NO_RELEASE_NOTES")' <<< "$_current_pr") + echo "Opt out of release notes: $OPT_OUT_RELEASE_NOTES" + RELEASE_NOTES_REQUIRED=false + if [[ $RELEASE_NOTES_NOT_FOUND != "" && "$OPT_OUT_RELEASE_NOTES" != true ]]; then + RELEASE_NOTES_REQUIRED=true + fi + RELEASE_NOTES_COMMENT_NEEDED=$RELEASE_NOTES_REQUIRED + if [[ "$PULL_REQUEST_FOUND" = false && "$OPT_OUT_RELEASE_NOTES" != true ]]; then + RELEASE_NOTES_COMMENT_NEEDED=true + fi + { + echo "release-notes-comment-needed=$RELEASE_NOTES_COMMENT_NEEDED" + echo "release-notes-exempt=$OPT_OUT_RELEASE_NOTES" echo "release-notes-check-message<<$EOF" if [[ "$OPT_OUT_RELEASE_NOTES" = true ]]; then echo "" echo "" - echo "## :warning: Release notes required, but author opted out" - echo "" + echo "## :white_check_mark: Release-note check exempted" echo "" - echo "> [!WARNING]" - echo "> **Author opted out of release notes, check is disabled for this pull request.**" - echo "> cc @dotnet/fsharp-team-msft" + echo "The NO_RELEASE_NOTES label exempts this pull request." else echo "${RELEASE_NOTES_MESSAGE}" fi @@ -301,7 +311,7 @@ jobs: echo "$EOF" } >> "$GITHUB_OUTPUT" - if [[ $RELEASE_NOTES_NOT_FOUND != "" && ${OPT_OUT_RELEASE_NOTES} != true ]]; then + if [[ "$RELEASE_NOTES_REQUIRED" = true ]]; then exit 1 fi # Keep one bot comment current without evaluating pull request content as JavaScript. @@ -316,6 +326,8 @@ jobs: uses: actions/github-script@v9 env: COMMENT_BODY: ${{ steps.release_notes_changes.outputs.release-notes-check-message }} + COMMENT_NEEDED: ${{ steps.release_notes_changes.outputs.release-notes-comment-needed }} + RELEASE_NOTES_EXEMPT: ${{ steps.release_notes_changes.outputs.release-notes-exempt }} with: github-token: ${{ github.token }} script: | @@ -330,6 +342,24 @@ jobs: const existing = comments.find(comment => comment.user?.login === 'github-actions[bot]' && comment.body?.includes(marker)); + if (existing?.body === process.env.COMMENT_BODY) { + return existing.id; + } + if (!existing && process.env.COMMENT_NEEDED !== 'true') { + return; + } + + const { data: current } = await github.rest.pulls.get({ + ...context.repo, + pull_number: context.issue.number + }); + const exempt = current.labels.some(label => label.name === 'NO_RELEASE_NOTES'); + if (current.head.sha !== process.env.PR_HEAD_SHA || + String(exempt) !== process.env.RELEASE_NOTES_EXEMPT) { + core.info('Skipping outdated release-note comment.'); + return; + } + if (existing) { const comment = await github.rest.issues.updateComment({ owner: context.repo.owner, diff --git a/.github/workflows/labelops-pr-maintenance.lock.yml b/.github/workflows/labelops-pr-maintenance.lock.yml index 4e70e742b1c..b8f7445ddfc 100644 --- a/.github/workflows/labelops-pr-maintenance.lock.yml +++ b/.github/workflows/labelops-pr-maintenance.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"0e7a666f84b8d4dbfc831f492c9f3240fc61b5ce5da3ed7f7cc56eb5fa161d93","compiler_version":"v0.76.1","strict":true,"agent_id":"copilot","agent_model":"${{ (github.job == 'detection' \u0026\u0026 vars.GH_AW_MODEL_DETECTION_COPILOT) || vars.GH_AW_MODEL_AGENT_COPILOT || 'gpt-5.6-sol' }}"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"b464954323d42269c9cff6b6be3f6edbcb647616e623b953a59c2252446e7786","compiler_version":"v0.76.1","strict":true,"agent_id":"copilot","agent_model":"${{ (github.job == 'detection' \u0026\u0026 vars.GH_AW_MODEL_DETECTION_COPILOT) || vars.GH_AW_MODEL_AGENT_COPILOT || 'gpt-5.6-sol' }}"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"46d564922b082d0db93244972e8005ea6904ee5f","version":"v0.76.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.55"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.55"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.55"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.19"},{"image":"ghcr.io/github/github-mcp-server:v1.0.4","digest":"sha256:e3816a476a977cfb836e7d221510011436c654d11861db66ecfd826601aba6a4","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.4@sha256:e3816a476a977cfb836e7d221510011436c654d11861db66ecfd826601aba6a4"},{"image":"node:lts-alpine","digest":"sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14","pinned_image":"node:lts-alpine@sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14"}]} # ___ _ _ # / _ \ | | (_) @@ -198,23 +198,23 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_39b30d1552c4e8b2_EOF' + cat << 'GH_AW_PROMPT_2c0d106342c787c4_EOF' - GH_AW_PROMPT_39b30d1552c4e8b2_EOF + GH_AW_PROMPT_2c0d106342c787c4_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_39b30d1552c4e8b2_EOF' + cat << 'GH_AW_PROMPT_2c0d106342c787c4_EOF' Tools: add_comment(max:5), add_labels(max:3), push_to_pull_request_branch(max:5), dispatch_workflow(max:3), missing_tool, missing_data, noop - GH_AW_PROMPT_39b30d1552c4e8b2_EOF + GH_AW_PROMPT_2c0d106342c787c4_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_push_to_pr_branch.md" - cat << 'GH_AW_PROMPT_39b30d1552c4e8b2_EOF' + cat << 'GH_AW_PROMPT_2c0d106342c787c4_EOF' - GH_AW_PROMPT_39b30d1552c4e8b2_EOF + GH_AW_PROMPT_2c0d106342c787c4_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_39b30d1552c4e8b2_EOF' + cat << 'GH_AW_PROMPT_2c0d106342c787c4_EOF' The following GitHub context information is available for this workflow: {{#if github.actor}} @@ -246,13 +246,13 @@ jobs: - **Note**: If a branch you need is not in the list above and is not listed as an additional fetched ref, it has NOT been checked out. For private repositories you cannot fetch it without proper authentication. If the branch is required and not available, exit with an error and ask the user to add it to the `fetch:` option of the `checkout:` configuration (e.g., `fetch: ["refs/pulls/open/*"]` for all open PR refs, or `fetch: ["main", "feature/my-branch"]` for specific branches). - GH_AW_PROMPT_39b30d1552c4e8b2_EOF + GH_AW_PROMPT_2c0d106342c787c4_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_39b30d1552c4e8b2_EOF' + cat << 'GH_AW_PROMPT_2c0d106342c787c4_EOF' {{#runtime-import .github/workflows/shared/model-defaults.md}} {{#runtime-import .github/workflows/labelops-pr-maintenance.md}} - GH_AW_PROMPT_39b30d1552c4e8b2_EOF + GH_AW_PROMPT_2c0d106342c787c4_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -463,9 +463,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_56152362d0c281b2_EOF' - {"add_comment":{"hide_older_comments":true,"max":5,"target":"*"},"add_labels":{"allowed":["AI-needs-CI-fix-input"],"max":3,"target":"*"},"create_report_incomplete_issue":{},"dispatch_workflow":{"aw_context_workflows":["labelops-flake-fix"],"max":3,"workflow_files":{"labelops-flake-fix":".lock.yml"},"workflows":["labelops-flake-fix"]},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"false"},"push_to_pull_request_branch":{"if_no_changes":"warn","max":5,"max_patch_size":10240,"protect_top_level_dot_folders":true,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS","DESIGN.md","README.md","CONTRIBUTING.md","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","AGENTS.md","CLAUDE.md","GEMINI.md"],"protected_files_policy":"allowed","target":"*"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_56152362d0c281b2_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_ddcf455414ad4a1a_EOF' + {"add_comment":{"hide_older_comments":true,"max":5,"target":"*"},"add_labels":{"allowed":["AI-needs-CI-fix-input"],"max":3,"target":"*"},"create_report_incomplete_issue":{},"dispatch_workflow":{"aw_context_workflows":["labelops-flake-fix"],"max":3,"workflow_files":{"labelops-flake-fix":".lock.yml"},"workflows":["labelops-flake-fix"]},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"false"},"push_to_pull_request_branch":{"if_no_changes":"warn","max":5,"max_patch_size":10240,"protect_top_level_dot_folders":true,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS","DESIGN.md","README.md","CONTRIBUTING.md","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","AGENTS.md","CLAUDE.md","GEMINI.md"],"protected_files_policy":"allowed","signed_commits":false,"target":"*"},"report_incomplete":{}} + GH_AW_SAFE_OUTPUTS_CONFIG_ddcf455414ad4a1a_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -732,7 +732,7 @@ jobs: mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_9d4e88feb921faab_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_537f5480798bcfaa_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -776,7 +776,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_9d4e88feb921faab_EOF + GH_AW_MCP_CONFIG_537f5480798bcfaa_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true @@ -1151,6 +1151,7 @@ jobs: GH_AW_CODE_PUSH_FAILURE_COUNT: ${{ needs.safe_outputs.outputs.code_push_failure_count }} GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"activationComments\":\"false\"}" GH_AW_GROUP_REPORTS: "false" GH_AW_FAILURE_REPORT_AS_ISSUE: "false" GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true" @@ -1390,6 +1391,7 @@ jobs: GH_AW_ENGINE_ID: "copilot" GH_AW_ENGINE_MODEL: "${{ (github.job == 'detection' && vars.GH_AW_MODEL_DETECTION_COPILOT) || vars.GH_AW_MODEL_AGENT_COPILOT || 'gpt-5.6-sol' }}" GH_AW_ENGINE_VERSION: "1.0.52" + GH_AW_SAFE_OUTPUT_MESSAGES: "{\"activationComments\":\"false\"}" GH_AW_WORKFLOW_ID: "labelops-pr-maintenance" GH_AW_WORKFLOW_NAME: "LabelOps — PR Maintenance" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/labelops-pr-maintenance.md" @@ -1510,7 +1512,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.vsblob.vsassets.io,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.nuget.org,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,builds.dotnet.microsoft.com,ci.dot.net,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,dc.services.visualstudio.com,dev.azure.com,dist.nuget.org,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkgs.dev.azure.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com,www.microsoft.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":5,\"target\":\"*\"},\"add_labels\":{\"allowed\":[\"AI-needs-CI-fix-input\"],\"max\":3,\"target\":\"*\"},\"create_report_incomplete_issue\":{},\"dispatch_workflow\":{\"aw_context_workflows\":[\"labelops-flake-fix\"],\"max\":3,\"workflow_files\":{\"labelops-flake-fix\":\".lock.yml\"},\"workflows\":[\"labelops-flake-fix\"]},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"false\"},\"push_to_pull_request_branch\":{\"if_no_changes\":\"warn\",\"max\":5,\"max_patch_size\":10240,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"CHANGELOG.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\",\"CLAUDE.md\",\"GEMINI.md\"],\"protected_files_policy\":\"allowed\",\"target\":\"*\"},\"report_incomplete\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":5,\"target\":\"*\"},\"add_labels\":{\"allowed\":[\"AI-needs-CI-fix-input\"],\"max\":3,\"target\":\"*\"},\"create_report_incomplete_issue\":{},\"dispatch_workflow\":{\"aw_context_workflows\":[\"labelops-flake-fix\"],\"max\":3,\"workflow_files\":{\"labelops-flake-fix\":\".lock.yml\"},\"workflows\":[\"labelops-flake-fix\"]},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"false\"},\"push_to_pull_request_branch\":{\"if_no_changes\":\"warn\",\"max\":5,\"max_patch_size\":10240,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"CHANGELOG.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\",\"CLAUDE.md\",\"GEMINI.md\"],\"protected_files_policy\":\"allowed\",\"signed_commits\":false,\"target\":\"*\"},\"report_incomplete\":{}}" GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/labelops-pr-maintenance.md b/.github/workflows/labelops-pr-maintenance.md index 96fd3aba90e..cb71600760c 100644 --- a/.github/workflows/labelops-pr-maintenance.md +++ b/.github/workflows/labelops-pr-maintenance.md @@ -39,6 +39,7 @@ tools: bash: true safe-outputs: + activation-comments: false # Transient gh-aw infra crashes (e.g. unhealthy firewall container) and engine # hiccups must not open tracking issues — real problems surface as PR labels/comments. report-failure-as-issue: false @@ -53,6 +54,7 @@ safe-outputs: target: "*" max: 5 protected-files: allowed + signed-commits: false add-labels: allowed: ["AI-needs-CI-fix-input"] max: 3 @@ -113,7 +115,7 @@ Use the **`pr-build-status`** skill. Collect ALL errors from ALL platforms first 3. **Proven flake** — invoke `flaky-test-detector`. Needs ≥3 distinct unrelated PRs. If insufficient evidence, `noop`. If proven and test not introduced by this PR → check for existing `[LabelOps Flake]` PR, then dispatch `labelops-flake-fix`. -4. **Can't fix** → reproduce locally, add `AI-needs-CI-fix-input` label, post escalation with what's failing, minimal repro, and options. End comment with ``. +4. **Can't fix** → reproduce locally, add `AI-needs-CI-fix-input` label, post escalation with what's failing, minimal repro, and options. End comment with `` as inline code, including literal backticks in the posted body. **If Step 3 pushed → stop this PR for this run.** CI restarts; next run sees fresh status. @@ -131,6 +133,14 @@ Can't resolve → `git merge --abort`, comment explaining which files and why. N ## Hygiene -- At most one comment per PR per run. +- At most one explicit comment per PR per run. Automatic push confirmations are disabled. +- Do not post routine healthy or no-op reports. +- Before posting, read all existing workflow-authored comments, including minimized comments. +- End each report with `` as inline code, including literal backticks in the posted body. + Use the PR head and `origin/main` SHA examined for this attempt. Use `ci` or `conflicts` for the subtopic. + Use `fix-submitted`, `needs-input`, or `unresolved` for the outcome. +- If the same marker and substantive outcome already exist, omit the duplicate comment. Continue any eligible repair attempt. + A failed-push warning is not a successful repair. Do not claim a submitted push has already been applied. +- Keep the CI escalation marker from Step 3 in addition to the report marker. - `hide-older-comments: true` collapses previous LabelOps comments. - `regression-pr-shepherd` owns `AI-Issue-Regression-PR` PRs — don't touch those. diff --git a/.github/workflows/repo-assist.lock.yml b/.github/workflows/repo-assist-scheduled.lock.yml similarity index 98% rename from .github/workflows/repo-assist.lock.yml rename to .github/workflows/repo-assist-scheduled.lock.yml index c39409eb723..3081fc277e7 100644 --- a/.github/workflows/repo-assist.lock.yml +++ b/.github/workflows/repo-assist-scheduled.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"ac95ba22cbeb6c74fd6563cace0a94828953bbd7a10301a0456e2629f1c7d3fa","compiler_version":"v0.76.1","strict":true,"agent_id":"copilot","agent_model":"${{ (github.job == 'detection' \u0026\u0026 vars.GH_AW_MODEL_DETECTION_COPILOT) || vars.GH_AW_MODEL_AGENT_COPILOT || 'gpt-5.6-sol' }}"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"2cda5c54f3db4eabe7be97fbe7e708fb5006d97ef1edcc47193893ceb82c5f84","compiler_version":"v0.76.1","strict":true,"agent_id":"copilot","agent_model":"${{ (github.job == 'detection' \u0026\u0026 vars.GH_AW_MODEL_DETECTION_COPILOT) || vars.GH_AW_MODEL_AGENT_COPILOT || 'gpt-5.6-sol' }}"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"46d564922b082d0db93244972e8005ea6904ee5f","version":"v0.76.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.55"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.55"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.55"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.19"},{"image":"ghcr.io/github/github-mcp-server:v1.0.4","digest":"sha256:e3816a476a977cfb836e7d221510011436c654d11861db66ecfd826601aba6a4","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.4@sha256:e3816a476a977cfb836e7d221510011436c654d11861db66ecfd826601aba6a4"},{"image":"node:lts-alpine","digest":"sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14","pinned_image":"node:lts-alpine@sha256:2bdb65ed1dab192432bc31c95f94155ca5ad7fc1392fb7eb7526ab682fa5bf14"}]} # ___ _ _ # / _ \ | | (_) @@ -23,7 +23,7 @@ # For more information: https://github.github.com/gh-aw/introduction/overview/ # # A friendly repository assistant that runs 2 times a day to support contributors and maintainers. -# Can also be triggered on-demand via '/repo-assist ' to perform specific tasks. +# Can also be started manually with workflow_dispatch. # - Labels and triages open issues # - Comments helpfully on open issues to unblock contributors and onboard newcomers # - Identifies issues that can be fixed and creates draft pull requests with fixes @@ -68,7 +68,6 @@ name: "Repo Assist" on: schedule: - cron: "30 */12 * * *" - # Friendly format: every 12h (scattered) workflow_dispatch: inputs: aw_context: @@ -113,7 +112,7 @@ jobs: job-name: ${{ github.job }} env: GH_AW_SETUP_WORKFLOW_NAME: "Repo Assist" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist.lock.yml@${{ github.ref }} + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist-scheduled.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.52" GH_AW_INFO_AWF_VERSION: "v0.25.55" GH_AW_INFO_BODY_MODIFIED: "false" @@ -177,7 +176,7 @@ jobs: id: check-lock-file uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_WORKFLOW_FILE: "repo-assist.lock.yml" + GH_AW_WORKFLOW_FILE: "repo-assist-scheduled.lock.yml" GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" with: script: | @@ -225,25 +224,25 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_0dab8234e3870e10_EOF' + cat << 'GH_AW_PROMPT_9e60879157e084db_EOF' - GH_AW_PROMPT_0dab8234e3870e10_EOF + GH_AW_PROMPT_9e60879157e084db_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/repo_memory_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_0dab8234e3870e10_EOF' + cat << 'GH_AW_PROMPT_9e60879157e084db_EOF' Tools: add_comment(max:10), create_issue(max:4), update_issue, create_pull_request(max:10), add_labels(max:30), remove_labels(max:10), push_to_pull_request_branch(max:4), missing_tool, missing_data, noop - GH_AW_PROMPT_0dab8234e3870e10_EOF + GH_AW_PROMPT_9e60879157e084db_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_push_to_pr_branch.md" - cat << 'GH_AW_PROMPT_0dab8234e3870e10_EOF' + cat << 'GH_AW_PROMPT_9e60879157e084db_EOF' - GH_AW_PROMPT_0dab8234e3870e10_EOF + GH_AW_PROMPT_9e60879157e084db_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_0dab8234e3870e10_EOF' + cat << 'GH_AW_PROMPT_9e60879157e084db_EOF' The following GitHub context information is available for this workflow: {{#if github.actor}} @@ -275,13 +274,13 @@ jobs: - **Note**: If a branch you need is not in the list above and is not listed as an additional fetched ref, it has NOT been checked out. For private repositories you cannot fetch it without proper authentication. If the branch is required and not available, exit with an error and ask the user to add it to the `fetch:` option of the `checkout:` configuration (e.g., `fetch: ["refs/pulls/open/*"]` for all open PR refs, or `fetch: ["main", "feature/my-branch"]` for specific branches). - GH_AW_PROMPT_0dab8234e3870e10_EOF + GH_AW_PROMPT_9e60879157e084db_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_0dab8234e3870e10_EOF' + cat << 'GH_AW_PROMPT_9e60879157e084db_EOF' {{#runtime-import .github/workflows/shared/model-defaults.md}} - {{#runtime-import .github/workflows/repo-assist.md}} - GH_AW_PROMPT_0dab8234e3870e10_EOF + {{#runtime-import .github/workflows/repo-assist-scheduled.md}} + GH_AW_PROMPT_9e60879157e084db_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -389,7 +388,7 @@ jobs: GH_AW_ASSETS_BRANCH: "" GH_AW_ASSETS_MAX_SIZE_KB: 0 GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs - GH_AW_WORKFLOW_ID_SANITIZED: repoassist + GH_AW_WORKFLOW_ID_SANITIZED: repoassistscheduled outputs: agentic_engine_timeout: ${{ steps.detect-agent-errors.outputs.agentic_engine_timeout || 'false' }} checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} @@ -416,7 +415,7 @@ jobs: parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: GH_AW_SETUP_WORKFLOW_NAME: "Repo Assist" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist.lock.yml@${{ github.ref }} + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist-scheduled.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.52" GH_AW_INFO_AWF_VERSION: "v0.25.55" GH_AW_INFO_BODY_MODIFIED: "false" @@ -631,9 +630,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_57dc159c74571308_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_bc3aaba2f698ab85_EOF' {"add_comment":{"hide_older_comments":true,"max":10,"target":"*"},"add_labels":{"allowed":["AI-thinks-issue-fixed","AI-thinks-windows-only"],"max":30,"target":"*"},"create_issue":{"labels":["automation","repo-assist"],"max":4,"title_prefix":"[Repo Assist] "},"create_pull_request":{"allowed_files":["tests/**","vsintegration/tests/**"],"auto_merge":true,"draft":false,"labels":["NO_RELEASE_NOTES","AI-Issue-Regression-PR"],"max":10,"max_patch_files":100,"max_patch_size":1024,"protect_top_level_dot_folders":true,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS","DESIGN.md","README.md","CONTRIBUTING.md","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","AGENTS.md","CLAUDE.md","GEMINI.md"],"protected_files_policy":"request_review","reviewers":["abonie","T-Gro"],"title_prefix":"Add regression test: "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"false"},"push_repo_memory":{"memories":[{"dir":"/tmp/gh-aw/repo-memory/default","id":"default","max_file_count":100,"max_file_size":102400,"max_patch_size":10240}]},"push_to_pull_request_branch":{"if_no_changes":"warn","max":4,"max_patch_size":1024,"protect_top_level_dot_folders":true,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS","DESIGN.md","README.md","CONTRIBUTING.md","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","AGENTS.md","CLAUDE.md","GEMINI.md"],"protected_files_policy":"fallback-to-issue","target":"*","title_prefix":"[Repo Assist] "},"remove_labels":{"allowed":["AI-thinks-issue-fixed","AI-thinks-windows-only"],"max":10,"target":"*"},"report_incomplete":{},"update_issue":{"allow_body":true,"max":1,"target":"*","title_prefix":"[Repo Assist] "}} - GH_AW_SAFE_OUTPUTS_CONFIG_57dc159c74571308_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_bc3aaba2f698ab85_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -1020,7 +1019,7 @@ jobs: mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_100a6a34878b7f3a_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_75d2569b1d43dd42_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -1064,7 +1063,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_100a6a34878b7f3a_EOF + GH_AW_MCP_CONFIG_75d2569b1d43dd42_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true @@ -1326,7 +1325,7 @@ jobs: issues: write pull-requests: write concurrency: - group: "gh-aw-conclusion-repo-assist" + group: "gh-aw-conclusion-repo-assist-scheduled" cancel-in-progress: false queue: max outputs: @@ -1345,7 +1344,7 @@ jobs: parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: GH_AW_SETUP_WORKFLOW_NAME: "Repo Assist" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist.lock.yml@${{ github.ref }} + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist-scheduled.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.52" GH_AW_INFO_AWF_VERSION: "v0.25.55" GH_AW_INFO_BODY_MODIFIED: "false" @@ -1444,7 +1443,7 @@ jobs: GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/blob/7c7feb61a52b662eb2089aa2945588b7a200d404/workflows/repo-assist.md" 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: "repo-assist" + GH_AW_WORKFLOW_ID: "repo-assist-scheduled" GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168" GH_AW_ENGINE_ID: "copilot" GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }} @@ -1503,7 +1502,7 @@ jobs: parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: GH_AW_SETUP_WORKFLOW_NAME: "Repo Assist" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist.lock.yml@${{ github.ref }} + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist-scheduled.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.52" GH_AW_INFO_AWF_VERSION: "v0.25.55" GH_AW_INFO_BODY_MODIFIED: "false" @@ -1573,7 +1572,7 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: WORKFLOW_NAME: "Repo Assist" - WORKFLOW_DESCRIPTION: "A friendly repository assistant that runs 2 times a day to support contributors and maintainers.\nCan also be triggered on-demand via '/repo-assist ' to perform specific tasks.\n- Labels and triages open issues\n- Comments helpfully on open issues to unblock contributors and onboard newcomers\n- Identifies issues that can be fixed and creates draft pull requests with fixes\n- Improves performance, testing, and code quality via PRs\n- Makes engineering investments: dependency updates, CI improvements, tooling\n- Updates its own PRs when CI fails or merge conflicts arise\n- Nudges stale PRs waiting for author response\n- Takes the repository forward with proactive improvements\n- Maintains a persistent memory of work done and what remains\nAlways polite, constructive, and mindful of the project's goals." + WORKFLOW_DESCRIPTION: "A friendly repository assistant that runs 2 times a day to support contributors and maintainers.\nCan also be started manually with workflow_dispatch.\n- Labels and triages open issues\n- Comments helpfully on open issues to unblock contributors and onboard newcomers\n- Identifies issues that can be fixed and creates draft pull requests with fixes\n- Improves performance, testing, and code quality via PRs\n- Makes engineering investments: dependency updates, CI improvements, tooling\n- Updates its own PRs when CI fails or merge conflicts arise\n- Nudges stale PRs waiting for author response\n- Takes the repository forward with proactive improvements\n- Maintains a persistent memory of work done and what remains\nAlways polite, constructive, and mindful of the project's goals." HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: script: | @@ -1712,7 +1711,7 @@ jobs: parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: GH_AW_SETUP_WORKFLOW_NAME: "Repo Assist" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist.lock.yml@${{ github.ref }} + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist-scheduled.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.52" GH_AW_INFO_AWF_VERSION: "v0.25.55" GH_AW_INFO_BODY_MODIFIED: "false" @@ -1778,7 +1777,7 @@ jobs: pull-requests: write timeout-minutes: 15 env: - GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/repo-assist" + GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/repo-assist-scheduled" GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} @@ -1786,7 +1785,7 @@ jobs: GH_AW_ENGINE_MODEL: "${{ (github.job == 'detection' && vars.GH_AW_MODEL_DETECTION_COPILOT) || vars.GH_AW_MODEL_AGENT_COPILOT || 'gpt-5.6-sol' }}" GH_AW_ENGINE_VERSION: "1.0.52" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e Generated by 🌈 {workflow_name}, see [workflow run]({run_url}). [Learn more](https://github.com/githubnext/agentics/blob/main/docs/repo-assist.md).\",\"runStarted\":\"{workflow_name} is processing {event_type}, see [workflow run]({run_url})...\",\"runSuccess\":\"✓ {workflow_name} completed successfully, see [workflow run]({run_url}).\",\"runFailure\":\"✗ {workflow_name} encountered {status}, see [workflow run]({run_url}).\"}" - GH_AW_WORKFLOW_ID: "repo-assist" + GH_AW_WORKFLOW_ID: "repo-assist-scheduled" GH_AW_WORKFLOW_NAME: "Repo Assist" GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/repo-assist.md@7c7feb61a52b662eb2089aa2945588b7a200d404" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/blob/7c7feb61a52b662eb2089aa2945588b7a200d404/workflows/repo-assist.md" @@ -1816,7 +1815,7 @@ jobs: parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: GH_AW_SETUP_WORKFLOW_NAME: "Repo Assist" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist.lock.yml@${{ github.ref }} + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/repo-assist-scheduled.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.52" GH_AW_INFO_AWF_VERSION: "v0.25.55" GH_AW_INFO_BODY_MODIFIED: "false" diff --git a/.github/workflows/repo-assist.md b/.github/workflows/repo-assist-scheduled.md similarity index 97% rename from .github/workflows/repo-assist.md rename to .github/workflows/repo-assist-scheduled.md index b4c9e7b85f9..6679cf44a63 100644 --- a/.github/workflows/repo-assist.md +++ b/.github/workflows/repo-assist-scheduled.md @@ -1,7 +1,8 @@ --- +name: Repo Assist description: | A friendly repository assistant that runs 2 times a day to support contributors and maintainers. - Can also be triggered on-demand via '/repo-assist ' to perform specific tasks. + Can also be started manually with workflow_dispatch. - Labels and triages open issues - Comments helpfully on open issues to unblock contributors and onboard newcomers - Identifies issues that can be fixed and creates draft pull requests with fixes @@ -17,7 +18,8 @@ imports: - shared/model-defaults.md on: - schedule: every 12h + schedule: + - cron: "30 */12 * * *" workflow_dispatch: timeout-minutes: 60 @@ -40,7 +42,8 @@ tools: toolsets: [all] min-integrity: none # This workflow is allowed to examine and comment on any issues or PRs bash: true - repo-memory: true + repo-memory: + branch-name: memory/repo-assist safe-outputs: noop: @@ -182,17 +185,17 @@ source: githubnext/agentics/workflows/repo-assist.md@7c7feb61a52b662eb2089aa2945 # Repo Assist -## Command Mode +## Manual instructions Take heed of **instructions**: "${{ steps.sanitized.outputs.text }}" -If these are non-empty (not ""), then you have been triggered via `/repo-assist `. Follow the user's instructions instead of the normal scheduled workflow. Focus exclusively on those instructions. Apply all the same guidelines (read AGENTS.md, run formatters/linters/tests, be polite, use AI disclosure). Skip the normal task sequence and the monthly activity summary update, and instead directly do what the user requested. If no specific instructions were provided (empty or blank), proceed with the normal scheduled workflow below. +If these are non-empty (not ""), follow the supplied instructions instead of the normal scheduled workflow. Focus exclusively on those instructions. Apply all the same guidelines (read AGENTS.md, run formatters/linters/tests, be polite, use AI disclosure). Skip the normal task sequence and the monthly activity summary update, and instead directly do what the user requested. If no specific instructions were provided (empty or blank), proceed with the normal scheduled workflow below. If the instructions don't result in any actionable work, call `noop` with a brief explanation before exiting. Then exit - do not run the normal workflow after completing the instructions. -## Non-Command Mode +## Scheduled or default run You are Repo Assist for `${{ github.repository }}`. Your job is to support human contributors, help onboard newcomers, identify improvements, and fix bugs by creating pull requests. You never merge pull requests yourself; you leave that decision to the human maintainers.