diff --git a/.github/workflows/dotnet-code-portability-nightly.md b/.github/workflows/dotnet-code-portability-nightly.md deleted file mode 100644 index be9c39df..00000000 --- a/.github/workflows/dotnet-code-portability-nightly.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -description: Nightly agent that randomly inspects the .NET codebase for small Go portability improvements without public API or behavior changes -tracker-id: dotnet-code-portability-nightly -model: "gpt-5.5" -engine: - id: copilot -network: - allowed: - - defaults - - go -on: - schedule: - - cron: "19 22 * * 1-5" - workflow_dispatch: -checkout: - fetch-depth: 0 -permissions: - contents: read - pull-requests: read - issues: read - copilot-requests: write -tools: - edit: - bash: - - "git:*" - - "go:*" - - gofmt - - rg - - find - - sed - - awk - - jq - - grep - - cat - - ls - - pwd - - date - - head - - tail - - sort - - uniq - - wc - github: - toolsets: [context, repos, issues, pull_requests] -safe-outputs: - max-patch-size: 4096 - noop: - report-as-issue: false - create-pull-request: - title-prefix: "[dotnet-code] " - draft: true - base-branch: main - auto-close-issue: true - if-no-changes: ignore - protected-files: allowed -timeout-minutes: 90 ---- - -# .NET-to-Go Code Portability Refactoring Agent - -You are a nightly refactoring agent for `microsoft/agent-framework-go`. - -Your job is to open one small PR that makes future .NET-to-Go ports easier by making existing Go internals more structurally similar to the corresponding .NET code. This is code portability work only. - -## Hard Rules - -- Do not change public Go APIs. -- Do not intentionally change behavior. -- Do not add missing .NET features, placeholders, examples, or feature docs. -- Do not edit `.github/`, governance files, or agent workflow files. -- Prefer one small production-code cleanup. If that is too risky, add or improve a narrow test that locks existing behavior. -- `noop` only after checking at least three candidate Go areas and finding no safe code or test improvement. - -## Setup - -- Go SDK checkout: `${{ github.workspace }}` - -Work from the Go SDK checkout: - -```bash -cd ${{ github.workspace }} -``` - -Fetch the upstream .NET repository before choosing work: - -```bash -git remote get-url upstream-agent-framework || git remote add upstream-agent-framework https://github.com/microsoft/agent-framework.git -git fetch --prune upstream-agent-framework +refs/heads/main:refs/remotes/upstream-agent-framework/main -``` - -Use `upstream-agent-framework/main` as the current .NET reference. List candidate files with `git ls-tree -r --name-only upstream-agent-framework/main dotnet | sort -R | head -40` and inspect files with `git show upstream-agent-framework/main:dotnet/`. - -## Work Loop - -1. Randomly sample the current .NET codebase without using workflow inputs or prior run state. Inspect at least three candidates from the sample, preferably across different areas such as workflow, agents, skills, messages, tools, providers, or compaction. -2. Check for open `[dotnet-code]` PRs before editing a sampled candidate. If one already covers that candidate, reject the candidate with the PR link and choose another. -3. Compare the sampled .NET code with the corresponding Go implementation and make one tiny internal change that helps future .NET-to-Go ports. Good changes include extracting an unexported helper, consolidating duplicate internal logic, simplifying control flow, table-driving repeated cases, clarifying an unexported name, or adding a preservation test. -4. Run `gofmt` and targeted `go test` packages. Use broader `go test ./...` for shared runtime changes. -5. Inspect the diff. If it changes public API, intentionally changes behavior, adds a feature, or creates churn, revert that candidate and choose another. -6. Open exactly one draft PR with `create_pull_request`, or call `noop` after three rejected areas. - -## PR Body - -Use this shape: - -```markdown -## Summary - -Describe the internal cleanup and why it helps future .NET-to-Go ports. - -## .NET Reference - -- `dotnet/path/to/file.cs` - short description - -Write `None` only if the improvement was based on Go code shape without a useful .NET file reference. - -## Public API and Behavior - -No public Go API changed. No intentional behavior change was made. - -## Tests - -List tests run and any preservation tests added or updated. - -## Notes - -Mention rejected candidates, uncertainty, or follow-ups. -``` - -Titles should be short and concrete, for example: - -- `[dotnet-code] Simplify workflow edge dispatch internals` -- `[dotnet-code] Consolidate skill resource lookup helpers` -- `[dotnet-code] Clarify agent response assembly internals` - -## No-Change Requirement - -Call `noop` with a concise message explaining: - -- The random .NET sample inspected -- The three .NET and Go areas checked -- Why each candidate was rejected \ No newline at end of file diff --git a/.github/workflows/dotnet-code-portability-nightly.lock.yml b/.github/workflows/dotnet-code-portability-weekly.lock.yml similarity index 89% rename from .github/workflows/dotnet-code-portability-nightly.lock.yml rename to .github/workflows/dotnet-code-portability-weekly.lock.yml index 4f2b2b81..1e9b4477 100644 --- a/.github/workflows/dotnet-code-portability-nightly.lock.yml +++ b/.github/workflows/dotnet-code-portability-weekly.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"488e108f067166a05d72b05bc8e9c525519792134c8ab0d9d66431df5c5c1d38","body_hash":"8f0faf2dd2003fadb83b0810dd3ddf174b09f35eb7defcbefb19a8995e24f111","compiler_version":"v0.88.7","strict":true,"agent_id":"copilot","agent_model":"gpt-5.5","engine_versions":{"copilot":"1.0.80"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"df3fede783e11b3b01a27e0ff3207b7a7474a6a6575ccb5029682a9537afae18","body_hash":"7839d45263cd2c13751947bde03107cc65cf0279d33f957d2dac7137b6e1dbe1","compiler_version":"v0.88.7","strict":true,"agent_id":"copilot","agent_model":"gpt-5.5","engine_versions":{"copilot":"1.0.80"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_DEFAULT_OTLP_HEADERS","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/cache/save","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5e508589e03a7757a7e05b26e834292f5445bfb6","version":"v0.88.7"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.28.14","digest":"sha256:f7df036c86575527b61f3f7df91c4412349a12b2a74988d929eafa2999230c98","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.28.14@sha256:f7df036c86575527b61f3f7df91c4412349a12b2a74988d929eafa2999230c98"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.28.14","digest":"sha256:6f95e2234dd9bd6333a8ff28ccea7ecf0204acd4a09108723844dbd2bf6268c5","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.28.14@sha256:6f95e2234dd9bd6333a8ff28ccea7ecf0204acd4a09108723844dbd2bf6268c5"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.28.14","digest":"sha256:2ce8df3abf3e9b76e9c0cf5863da41f1ab3f89b20ad14b988806ab89e7bf2cd5","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.28.14@sha256:2ce8df3abf3e9b76e9c0cf5863da41f1ab3f89b20ad14b988806ab89e7bf2cd5"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.18","digest":"sha256:85b940556a8faa4e1fdbef124bfd75f2c4ebd855a10b88a1c3b6f3e97f6f1a53","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.18@sha256:85b940556a8faa4e1fdbef124bfd75f2c4ebd855a10b88a1c3b6f3e97f6f1a53"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:a8082161d7dceda14b68f32eb39d0eaa96b825d07f5895b096afab9d9e0c7748","pinned_image":"ghcr.io/github/gh-aw-node@sha256:a8082161d7dceda14b68f32eb39d0eaa96b825d07f5895b096afab9d9e0c7748"},{"image":"ghcr.io/github/github-mcp-server:v1.11.0","digest":"sha256:fbec75de11c255213fa08d80fb166abe73d851fff631c51c0079872967720699","pinned_image":"ghcr.io/github/github-mcp-server:v1.11.0@sha256:fbec75de11c255213fa08d80fb166abe73d851fff631c51c0079872967720699"}],"mcp_servers":[{"name":"github","tools":["get_commit","get_file_contents","get_latest_release","get_me","get_pull_request","get_pull_request_comments","get_pull_request_diff","get_pull_request_files","get_pull_request_review_comments","get_pull_request_reviews","get_pull_request_status","get_release_by_tag","get_tag","issue_read","list_branches","list_commits","list_issue_types","list_issues","list_pull_requests","list_releases","list_starred_repositories","list_tags","pull_request_read","search_code","search_issues","search_pull_requests","search_repositories"]},{"name":"safeoutputs","tools":["create_pull_request","missing_data","missing_tool","noop"]}]} # This file was automatically generated by gh-aw (v0.88.7). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # @@ -23,7 +23,9 @@ # # For more information: https://github.github.com/gh-aw/introduction/overview/ # -# Nightly agent that randomly inspects the .NET codebase for small Go portability improvements without public API or behavior changes +# Weekly audit for evidence-backed .NET-to-Go portability improvements without public API or behavior changes +# +# Intent: Reduce maintainer effort when porting .NET changes to Go without cosmetic churn or duplicate work. # # Secrets used: # - GH_AW_CI_TRIGGER_TOKEN @@ -52,10 +54,10 @@ # - ghcr.io/github/gh-aw-node@sha256:a8082161d7dceda14b68f32eb39d0eaa96b825d07f5895b096afab9d9e0c7748 # - ghcr.io/github/github-mcp-server:v1.11.0@sha256:fbec75de11c255213fa08d80fb166abe73d851fff631c51c0079872967720699 -name: ".NET-to-Go Code Portability Refactoring Agent" +name: ".NET-to-Go Weekly Portability Audit" on: schedule: - - cron: "19 22 * * 1-5" + - cron: "19 22 * * 1" workflow_dispatch: inputs: aw_context: @@ -70,12 +72,12 @@ concurrency: group: "gh-aw-${{ github.workflow }}" queue: max -run-name: ".NET-to-Go Code Portability Refactoring Agent" +run-name: ".NET-to-Go Weekly Portability Audit" env: OTEL_EXPORTER_OTLP_ENDPOINT: ${{ vars.GH_AW_DEFAULT_OTLP_ENDPOINT }} - OTEL_SERVICE_NAME: gh-aw.dotnet-code-portability-nightly - OTEL_RESOURCE_ATTRIBUTES: 'gh-aw.workflow.name=.NET-to-Go%20Code%20Portability%20Refactoring%20Agent,gh-aw.repository=${{ github.repository }},gh-aw.run.id=${{ github.run_id }},github.run_id=${{ github.run_id }},gh-aw.engine.id=copilot' + OTEL_SERVICE_NAME: gh-aw.dotnet-code-portability-weekly + OTEL_RESOURCE_ATTRIBUTES: 'gh-aw.workflow.name=.NET-to-Go%20Weekly%20Portability%20Audit,gh-aw.repository=${{ github.repository }},gh-aw.run.id=${{ github.run_id }},github.run_id=${{ github.run_id }},gh-aw.engine.id=copilot' OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.GH_AW_DEFAULT_OTLP_HEADERS }} GH_AW_OTLP_ENDPOINTS: '[{"url":"${{ vars.GH_AW_DEFAULT_OTLP_ENDPOINT }}","headers":"${{ secrets.GH_AW_DEFAULT_OTLP_HEADERS }}"}]' GH_AW_OTLP_IF_MISSING: ignore @@ -113,8 +115,8 @@ jobs: job-name: ${{ github.job }} safe-output-artifact-client: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} env: - GH_AW_SETUP_WORKFLOW_NAME: ".NET-to-Go Code Portability Refactoring Agent" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/dotnet-code-portability-nightly.lock.yml@${{ github.ref }} + GH_AW_SETUP_WORKFLOW_NAME: ".NET-to-Go Weekly Portability Audit" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/dotnet-code-portability-weekly.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.80" GH_AW_INFO_AWF_VERSION: "v0.28.14" GH_AW_INFO_ENGINE_ID: "copilot" @@ -129,7 +131,7 @@ jobs: GH_AW_INFO_VERSION: "1.0.80" GH_AW_INFO_AGENT_VERSION: "1.0.80" GH_AW_INFO_CLI_VERSION: "v0.88.7" - GH_AW_INFO_WORKFLOW_NAME: ".NET-to-Go Code Portability Refactoring Agent" + GH_AW_INFO_WORKFLOW_NAME: ".NET-to-Go Weekly Portability Audit" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" @@ -139,6 +141,7 @@ jobs: GH_AW_INFO_AWMG_VERSION: "" GH_AW_INFO_FIREWALL_TYPE: "squid" GH_AW_INFO_AGENT_RUNTIME: "" + GH_AW_INFO_CACHE_MEMORY: "true" GH_AW_COMPILED_STRICT: "true" uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: @@ -155,8 +158,8 @@ jobs: continue-on-error: true uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: - key: agentic-workflow-usage-dotnetcodeportabilitynightly-${{ github.run_id }} - restore-keys: agentic-workflow-usage-dotnetcodeportabilitynightly- + key: agentic-workflow-usage-dotnetcodeportabilityweekly-${{ github.run_id }} + restore-keys: agentic-workflow-usage-dotnetcodeportabilityweekly- path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl - name: Restore daily AIC usage cache (artifact fallback) id: restore-daily-aic-cache-fallback @@ -180,8 +183,8 @@ jobs: if: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_WORKFLOW_NAME: ".NET-to-Go Code Portability Refactoring Agent" - GH_AW_WORKFLOW_ID: "dotnet-code-portability-nightly" + GH_AW_WORKFLOW_NAME: ".NET-to-Go Weekly Portability Audit" + GH_AW_WORKFLOW_ID: "dotnet-code-portability-weekly" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_WORKFLOW_DISPATCH_AW_CONTEXT: ${{ github.event.inputs.aw_context || '' }} GH_AW_HAS_SLASH_COMMAND: "false" @@ -226,7 +229,7 @@ jobs: id: check-lock-file uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_WORKFLOW_FILE: "dotnet-code-portability-nightly.lock.yml" + GH_AW_WORKFLOW_FILE: "dotnet-code-portability-weekly.lock.yml" GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" with: script: | @@ -257,7 +260,7 @@ jobs: GH_AW_ACTIONS_DIR: ${{ runner.temp }}/gh-aw/actions GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl - GH_AW_PROMPT_CONFIG: "{\"items\":[{\"content_env\":\"GH_AW_PROMPT_CONTENT_0000\"},{\"file\":\"xpia.md\"},{\"file\":\"temp_folder_prompt.md\"},{\"file\":\"markdown.md\"},{\"file\":\"safe_outputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0001\"},{\"file\":\"safe_outputs_create_pull_request.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0002\"},{\"file\":\"mcp_cli_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0003\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"}]}" + GH_AW_PROMPT_CONFIG: "{\"items\":[{\"content_env\":\"GH_AW_PROMPT_CONTENT_0000\"},{\"file\":\"xpia.md\"},{\"file\":\"temp_folder_prompt.md\"},{\"file\":\"markdown.md\"},{\"file\":\"cache_memory_prompt.md\"},{\"file\":\"safe_outputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0001\"},{\"file\":\"safe_outputs_create_pull_request.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0002\"},{\"file\":\"mcp_cli_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0003\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"}]}" GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} @@ -271,7 +274,7 @@ jobs: GH_AW_PROMPT_CONTENT_0002: "\n" GH_AW_PROMPT_CONTENT_0003: "\nThe following GitHub context information is available for this workflow:\n{{#if github.actor}}\n- **actor**: __GH_AW_GITHUB_ACTOR__\n{{/if}}\n{{#if github.repository}}\n- **repository**: __GH_AW_GITHUB_REPOSITORY__\n{{/if}}\n{{#if github.workspace}}\n- **workspace**: __GH_AW_GITHUB_WORKSPACE__\n{{/if}}\n{{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}\n- **issue-number**: #__GH_AW_EXPR_802A9F6A__\n{{/if}}\n{{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}\n- **discussion-number**: #__GH_AW_EXPR_1A3A194A__\n{{/if}}\n{{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}\n- **pull-request-number**: #__GH_AW_EXPR_463A214A__\n{{/if}}\n{{#if github.event.comment.id || github.aw.context.comment_id}}\n- **comment-id**: __GH_AW_EXPR_FF1D34CE__\n{{/if}}\n{{#if github.run_id}}\n- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__\n{{/if}}\n- **checkouts**: The following repositories have been checked out and are available in the workspace:\n - repo `__GH_AW_GITHUB_REPOSITORY__` → `$GITHUB_WORKSPACE` (cwd) [full history, all branches available as remote-tracking refs]\n - **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. 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).\n - **Warning: No git credentials are available to the agent.** Credentials are\n intentionally removed after the checkout step for security. This means any git\n operation that needs to authenticate to the remote will fail. In private repositories, that includes:\n - `git fetch`, `git pull`, `git clone`, and `git push` (direct push, not via safe-output tools)\n - Checking out or switching to a remote branch that is not already fetched\n - Deepening a shallow clone (`git fetch --unshallow`)\n - On-demand blob fetches in partial/blobless clones (operations on files not in the initial checkout)\n Do NOT attempt to configure credentials, run `git credential fill`, or modify `.gitconfig` —\n authentication will not succeed. If you encounter credential prompts or authentication errors,\n stop immediately and report the limitation rather than spending turns trying to work around it.\n\n\n" GH_AW_PROMPT_CONTENT_0004: "\n" - GH_AW_PROMPT_CONTENT_0005: "{{#runtime-import .github/workflows/dotnet-code-portability-nightly.md}}\n" + GH_AW_PROMPT_CONTENT_0005: "{{#runtime-import .github/workflows/dotnet-code-portability-weekly.md}}\n" with: script: | const { setupGlobals } = require(process.env.GH_AW_ACTIONS_DIR + '/setup_globals.cjs'); @@ -296,6 +299,9 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt + GH_AW_ALLOWED_EXTENSIONS: "\nAllowed file extensions: .json." + GH_AW_CACHE_DESCRIPTION: '' + GH_AW_CACHE_DIR: '/tmp/gh-aw/cache-memory/' GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} @@ -318,6 +324,9 @@ jobs: return await substitutePlaceholders({ file: process.env.GH_AW_PROMPT, substitutions: { + GH_AW_ALLOWED_EXTENSIONS: process.env.GH_AW_ALLOWED_EXTENSIONS, + GH_AW_CACHE_DESCRIPTION: process.env.GH_AW_CACHE_DESCRIPTION, + GH_AW_CACHE_DIR: process.env.GH_AW_CACHE_DIR, GH_AW_EXPR_1A3A194A: process.env.GH_AW_EXPR_1A3A194A, GH_AW_EXPR_463A214A: process.env.GH_AW_EXPR_463A214A, GH_AW_EXPR_802A9F6A: process.env.GH_AW_EXPR_802A9F6A, @@ -388,12 +397,14 @@ jobs: GH_AW_PR_HEAD_BASE_SHA: "" GH_AW_PR_HEAD_REPO: "" GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} - GH_AW_WORKFLOW_ID_SANITIZED: dotnetcodeportabilitynightly + GH_AW_WORKFLOW_ID_SANITIZED: dotnetcodeportabilityweekly outputs: agentic_engine_timeout: ${{ steps.detect-agent-errors.outputs.agentic_engine_timeout || 'false' }} ai_credits_rate_limit_error: ${{ steps.parse-mcp-gateway.outputs.ai_credits_rate_limit_error || 'false' }} aic: ${{ steps.parse-mcp-gateway.outputs.aic }} ambient_context: ${{ steps.parse-mcp-gateway.outputs.ambient_context }} + cache_memory_restore_0_cache_hit: ${{ steps.restore_cache_memory_0.outputs.cache-hit || 'false' }} + cache_memory_restore_0_matched_key: ${{ steps.restore_cache_memory_0.outputs.cache-matched-key || '' }} checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} has_patch: ${{ steps.collect_output.outputs.has_patch }} @@ -423,8 +434,8 @@ jobs: trace-id: ${{ needs.activation.outputs.setup-trace-id }} parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: - GH_AW_SETUP_WORKFLOW_NAME: ".NET-to-Go Code Portability Refactoring Agent" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/dotnet-code-portability-nightly.lock.yml@${{ github.ref }} + GH_AW_SETUP_WORKFLOW_NAME: ".NET-to-Go Weekly Portability Audit" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/dotnet-code-portability-weekly.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.80" GH_AW_INFO_AWF_VERSION: "v0.28.14" GH_AW_INFO_ENGINE_ID: "copilot" @@ -461,6 +472,34 @@ jobs: with: name: activation path: /tmp/gh-aw + # Cache memory file share configuration from frontmatter processed below + - name: Create cache-memory directory + run: bash "${RUNNER_TEMP}/gh-aw/actions/create_cache_memory_dir.sh" + - name: Restore cache-memory file share data + id: restore_cache_memory_0 + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + key: memory-none-nopolicy-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }} + path: /tmp/gh-aw/cache-memory + restore-keys: | + memory-none-nopolicy-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}- + - name: Setup cache-memory git repository + env: + GH_AW_CACHE_DIR: /tmp/gh-aw/cache-memory + GH_AW_MIN_INTEGRITY: none + GH_AW_ALLOWED_EXTENSIONS: '.json' + run: bash "${RUNNER_TEMP}/gh-aw/actions/setup_cache_memory_git.sh" + - name: Fetch upstream .NET reference + run: | + set -euo pipefail + git fetch --no-tags https://github.com/microsoft/agent-framework.git +refs/heads/main:refs/remotes/upstream-agent-framework/main + upstream_sha="$(git rev-parse --verify 'refs/remotes/upstream-agent-framework/main^{commit}')" + git cat-file -e "${upstream_sha}:dotnet/src" + git cat-file -e "${upstream_sha}:dotnet/tests" + echo "DOTNET_UPSTREAM_SHA=$upstream_sha" >> "$GITHUB_ENV" + shell: bash + working-directory: ${{ github.workspace }} + - name: Configure Git credentials env: GITHUB_REPOSITORY: ${{ github.repository }} @@ -529,7 +568,7 @@ jobs: env: GH_AW_FILE_ROOT: "${{ runner.temp }}/gh-aw" GH_AW_FILE_CONFIG: "{\"files\":[{\"path\":\"safeoutputs/config.json\",\"content_env\":\"GH_AW_SAFE_OUTPUTS_CONFIG\"}]}" - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_pull_request\":{\"auto_close_issue\":true,\"base_branch\":\"main\",\"draft\":true,\"if_no_changes\":\"ignore\",\"max\":1,\"max_patch_files\":100,\"max_patch_size\":4096,\"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\"],\"protected_files_policy\":\"allowed\",\"title_prefix\":\"[dotnet-code] \"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"false\"},\"report_incomplete\":{}}" + GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_pull_request\":{\"allowed_files\":[\"agent/**\",\"internal/**\",\"message/**\",\"provider/**\",\"tool/**\",\"workflow/**\"],\"auto_close_issue\":true,\"base_branch\":\"main\",\"draft\":true,\"if_no_changes\":\"ignore\",\"max\":1,\"max_patch_files\":100,\"max_patch_size\":4096,\"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\"],\"protected_files_policy\":\"allowed\",\"title_prefix\":\"[dotnet-code] \"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"false\"},\"report_incomplete\":{}}" with: script: | const path = require('path'); @@ -930,7 +969,7 @@ jobs: GH_AW_AWF_ATTEMPT_LOG_NAME=copilot \ bash "${RUNNER_TEMP}/gh-aw/actions/run_awf_with_startup_retries.sh" -- \ awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_AGENT_ID --mount /tmp/gh-aw:/tmp/gh-aw:rw --log-level info --skip-pull \ - -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" "${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs" "${RUNNER_TEMP}/gh-aw/bin/copilot" --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --allow-tool '\''shell(awk)'\'' --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(find)'\'' --allow-tool '\''shell(git add:*)'\'' --allow-tool '\''shell(git branch:*)'\'' --allow-tool '\''shell(git checkout:*)'\'' --allow-tool '\''shell(git commit:*)'\'' --allow-tool '\''shell(git merge:*)'\'' --allow-tool '\''shell(git rm:*)'\'' --allow-tool '\''shell(git status)'\'' --allow-tool '\''shell(git switch:*)'\'' --allow-tool '\''shell(git:*)'\'' --allow-tool '\''shell(github:*)'\'' --allow-tool '\''shell(go:*)'\'' --allow-tool '\''shell(gofmt)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(printf)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(rg)'\'' --allow-tool '\''shell(safeoutputs:*)'\'' --allow-tool '\''shell(sed)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" "${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs" "${RUNNER_TEMP}/gh-aw/bin/copilot" --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --allow-tool '\''shell(awk)'\'' --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(date)'\'' --allow-tool '\''shell(echo)'\'' --allow-tool '\''shell(find)'\'' --allow-tool '\''shell(git add:*)'\'' --allow-tool '\''shell(git branch:*)'\'' --allow-tool '\''shell(git checkout:*)'\'' --allow-tool '\''shell(git commit:*)'\'' --allow-tool '\''shell(git merge:*)'\'' --allow-tool '\''shell(git rm:*)'\'' --allow-tool '\''shell(git status)'\'' --allow-tool '\''shell(git switch:*)'\'' --allow-tool '\''shell(git:*)'\'' --allow-tool '\''shell(github:*)'\'' --allow-tool '\''shell(go:*)'\'' --allow-tool '\''shell(gofmt)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(printf)'\'' --allow-tool '\''shell(pwd)'\'' --allow-tool '\''shell(rg)'\'' --allow-tool '\''shell(safeoutputs:*)'\'' --allow-tool '\''shell(sed)'\'' --allow-tool '\''shell(sort)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(uniq)'\'' --allow-tool '\''shell(wc)'\'' --allow-tool '\''shell(yq)'\'' --allow-tool write --add-dir /tmp/gh-aw/cache-memory/ --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' env: AWF_REFLECT_ENABLED: 1 COPILOT_AGENT_RUNNER_TYPE: STANDALONE @@ -1112,6 +1151,41 @@ jobs: if [ ! -f /tmp/gh-aw/agent_output.json ]; then echo '{"items":[]}' > /tmp/gh-aw/agent_output.json fi + - name: Commit cache-memory changes + if: always() + env: + GH_AW_CACHE_DIR: /tmp/gh-aw/cache-memory + run: bash "${RUNNER_TEMP}/gh-aw/actions/commit_cache_memory_git.sh" + - name: Validate cache-memory file types + id: validate_cache_memory_64656661756c74 + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + MEMORY_DIR: /tmp/gh-aw/cache-memory + MEMORY_ID: default + ALLOWED_EXTENSIONS: '[".json"]' + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { validateMemoryStep } = require(path.join(actionsDir, 'validate_memory_step.cjs')); + validateMemoryStep(core, { kind: 'cache', writeMarker: true }); + - name: Check cache-memory git integrity + if: always() + continue-on-error: true + env: + GH_AW_CACHE_DIR: /tmp/gh-aw/cache-memory + run: bash "${RUNNER_TEMP}/gh-aw/actions/check_cache_memory_git_integrity.sh" + - name: Upload cache-memory data as artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + if: always() && steps.validate_cache_memory_64656661756c74.outcome == 'success' + with: + name: cache-memory + include-hidden-files: true + path: /tmp/gh-aw/cache-memory + retention-days: 30 # Small dedicated copy of the agent output so safe-output processing # survives a failed or timed-out upload of the larger agent artifact - name: Upload agent output fallback artifact @@ -1157,6 +1231,7 @@ jobs: - agent - detection - safe_outputs + - update_cache_memory if: > always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' || needs.activation.outputs.oauth_token_check_failed == 'true' || needs.activation.outputs.stale_lock_file_failed == 'true' || @@ -1168,7 +1243,7 @@ jobs: issues: write pull-requests: write concurrency: - group: "gh-aw-conclusion-dotnet-code-portability-nightly" + group: "gh-aw-conclusion-dotnet-code-portability-weekly" cancel-in-progress: false queue: max env: @@ -1188,8 +1263,8 @@ jobs: trace-id: ${{ needs.activation.outputs.setup-trace-id }} parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: - GH_AW_SETUP_WORKFLOW_NAME: ".NET-to-Go Code Portability Refactoring Agent" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/dotnet-code-portability-nightly.lock.yml@${{ github.ref }} + GH_AW_SETUP_WORKFLOW_NAME: ".NET-to-Go Weekly Portability Audit" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/dotnet-code-portability-weekly.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.80" GH_AW_INFO_AWF_VERSION: "v0.28.14" GH_AW_INFO_ENGINE_ID: "copilot" @@ -1256,8 +1331,8 @@ jobs: continue-on-error: true uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: - key: agentic-workflow-usage-dotnetcodeportabilitynightly-${{ github.run_id }} - restore-keys: agentic-workflow-usage-dotnetcodeportabilitynightly- + key: agentic-workflow-usage-dotnetcodeportabilityweekly-${{ github.run_id }} + restore-keys: agentic-workflow-usage-dotnetcodeportabilityweekly- path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl - name: Write daily AIC usage cache entry id: write-daily-aic-cache @@ -1279,7 +1354,7 @@ jobs: continue-on-error: true uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: - key: agentic-workflow-usage-dotnetcodeportabilitynightly-${{ github.run_id }} + key: agentic-workflow-usage-dotnetcodeportabilityweekly-${{ github.run_id }} path: /tmp/gh-aw/agentic-workflow-usage-cache.jsonl - name: Upload daily AIC usage cache artifact id: upload-daily-aic-cache @@ -1297,16 +1372,16 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_NOOP_MAX: "1" - GH_AW_WORKFLOW_NAME: ".NET-to-Go Code Portability Refactoring Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/dotnet-code-portability-nightly.md" - GH_AW_TRACKER_ID: "dotnet-code-portability-nightly" + GH_AW_WORKFLOW_NAME: ".NET-to-Go Weekly Portability Audit" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/dotnet-code-portability-weekly.md" + GH_AW_TRACKER_ID: "dotnet-code-portability-weekly" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_NOOP_REPORT_AS_ISSUE: "false" GH_AW_AIC: ${{ needs.agent.outputs.aic }} GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }} GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} - GH_AW_WORKFLOW_ID: "dotnet-code-portability-nightly" + GH_AW_WORKFLOW_ID: "dotnet-code-portability-weekly" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1321,9 +1396,9 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: ".NET-to-Go Code Portability Refactoring Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/dotnet-code-portability-nightly.md" - GH_AW_TRACKER_ID: "dotnet-code-portability-nightly" + GH_AW_WORKFLOW_NAME: ".NET-to-Go Weekly Portability Audit" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/dotnet-code-portability-weekly.md" + GH_AW_TRACKER_ID: "dotnet-code-portability-weekly" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} @@ -1342,9 +1417,9 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_MISSING_TOOL_CREATE_ISSUE: "true" - GH_AW_WORKFLOW_NAME: ".NET-to-Go Code Portability Refactoring Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/dotnet-code-portability-nightly.md" - GH_AW_TRACKER_ID: "dotnet-code-portability-nightly" + GH_AW_WORKFLOW_NAME: ".NET-to-Go Weekly Portability Audit" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/dotnet-code-portability-weekly.md" + GH_AW_TRACKER_ID: "dotnet-code-portability-weekly" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1360,9 +1435,9 @@ jobs: env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true" - GH_AW_WORKFLOW_NAME: ".NET-to-Go Code Portability Refactoring Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/dotnet-code-portability-nightly.md" - GH_AW_TRACKER_ID: "dotnet-code-portability-nightly" + GH_AW_WORKFLOW_NAME: ".NET-to-Go Weekly Portability Audit" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/dotnet-code-portability-weekly.md" + GH_AW_TRACKER_ID: "dotnet-code-portability-weekly" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1378,12 +1453,12 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: ".NET-to-Go Code Portability Refactoring Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/dotnet-code-portability-nightly.md" - GH_AW_TRACKER_ID: "dotnet-code-portability-nightly" + GH_AW_WORKFLOW_NAME: ".NET-to-Go Weekly Portability Audit" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/dotnet-code-portability-weekly.md" + GH_AW_TRACKER_ID: "dotnet-code-portability-weekly" 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: "dotnet-code-portability-nightly" + GH_AW_WORKFLOW_ID: "dotnet-code-portability-weekly" GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "0" GH_AW_ENGINE_ID: "copilot" GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} @@ -1416,6 +1491,9 @@ jobs: GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true" GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true" GH_AW_TIMEOUT_MINUTES: "90" + GH_AW_CACHE_MEMORY_ENABLED: "true" + GH_AW_CACHE_MEMORY_RESTORE_0_MATCHED_KEY: ${{ needs.agent.outputs.cache_memory_restore_0_matched_key || '' }} + GH_AW_CACHE_MEMORY_RESTORE_0_CACHE_HIT: ${{ needs.agent.outputs.cache_memory_restore_0_cache_hit || 'false' }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1431,9 +1509,9 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} - GH_AW_WORKFLOW_NAME: ".NET-to-Go Code Portability Refactoring Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/dotnet-code-portability-nightly.md" - GH_AW_TRACKER_ID: "dotnet-code-portability-nightly" + GH_AW_WORKFLOW_NAME: ".NET-to-Go Weekly Portability Audit" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/dotnet-code-portability-weekly.md" + GH_AW_TRACKER_ID: "dotnet-code-portability-weekly" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_REPORT_FAILED_JOBS: "true" with: @@ -1473,8 +1551,8 @@ jobs: trace-id: ${{ needs.activation.outputs.setup-trace-id }} parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: - GH_AW_SETUP_WORKFLOW_NAME: ".NET-to-Go Code Portability Refactoring Agent" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/dotnet-code-portability-nightly.lock.yml@${{ github.ref }} + GH_AW_SETUP_WORKFLOW_NAME: ".NET-to-Go Weekly Portability Audit" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/dotnet-code-portability-weekly.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.80" GH_AW_INFO_AWF_VERSION: "v0.28.14" GH_AW_INFO_ENGINE_ID: "copilot" @@ -1541,8 +1619,8 @@ jobs: if: always() && steps.detection_guard.outputs.run_detection == 'true' uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - WORKFLOW_NAME: ".NET-to-Go Code Portability Refactoring Agent" - WORKFLOW_DESCRIPTION: "Nightly agent that randomly inspects the .NET codebase for small Go portability improvements without public API or behavior changes" + WORKFLOW_NAME: ".NET-to-Go Weekly Portability Audit" + WORKFLOW_DESCRIPTION: "Weekly audit for evidence-backed .NET-to-Go portability improvements without public API or behavior changes" HAS_PATCH: ${{ needs.agent.outputs.has_patch }} GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" GH_AW_DETECTION_SKIP_PROMPT_SUMMARY: "true" @@ -1610,8 +1688,8 @@ jobs: RUNNER_TEMP: ${{ runner.temp }} S2STOKENS: true TRACEPARENT: ${{ env.GITHUB_AW_OTEL_TRACE_ID != '' && env.GITHUB_AW_OTEL_PARENT_SPAN_ID != '' && format('00-{0}-{1}-01', env.GITHUB_AW_OTEL_TRACE_ID, env.GITHUB_AW_OTEL_PARENT_SPAN_ID) || '' }} - WORKFLOW_NAME: ".NET-to-Go Code Portability Refactoring Agent" - WORKFLOW_DESCRIPTION: "Nightly agent that randomly inspects the .NET codebase for small Go portability improvements without public API or behavior changes" + WORKFLOW_NAME: ".NET-to-Go Weekly Portability Audit" + WORKFLOW_DESCRIPTION: "Weekly audit for evidence-backed .NET-to-Go portability improvements without public API or behavior changes" HAS_PATCH: ${{ needs.agent.outputs.has_patch }} GH_AW_DETECTION_CONTINUE_ON_ERROR: "true" run: | @@ -1726,7 +1804,7 @@ jobs: GH_AW_AGENT_AIC: ${{ needs.agent.outputs.aic }} GH_AW_AIC: ${{ needs.agent.outputs.aic }} GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} - GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/dotnet-code-portability-nightly" + GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/dotnet-code-portability-weekly" 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 }} @@ -1734,10 +1812,10 @@ jobs: GH_AW_ENGINE_MODEL: "gpt-5.5" GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }} - GH_AW_TRACKER_ID: "dotnet-code-portability-nightly" - GH_AW_WORKFLOW_ID: "dotnet-code-portability-nightly" - GH_AW_WORKFLOW_NAME: ".NET-to-Go Code Portability Refactoring Agent" - GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/dotnet-code-portability-nightly.md" + GH_AW_TRACKER_ID: "dotnet-code-portability-weekly" + GH_AW_WORKFLOW_ID: "dotnet-code-portability-weekly" + GH_AW_WORKFLOW_NAME: ".NET-to-Go Weekly Portability Audit" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/dotnet-code-portability-weekly.md" 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 }} @@ -1765,8 +1843,8 @@ jobs: trace-id: ${{ needs.activation.outputs.setup-trace-id }} parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} env: - GH_AW_SETUP_WORKFLOW_NAME: ".NET-to-Go Code Portability Refactoring Agent" - GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/dotnet-code-portability-nightly.lock.yml@${{ github.ref }} + GH_AW_SETUP_WORKFLOW_NAME: ".NET-to-Go Weekly Portability Audit" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/dotnet-code-portability-weekly.lock.yml@${{ github.ref }} GH_AW_INFO_VERSION: "1.0.80" GH_AW_INFO_AWF_VERSION: "v0.28.14" GH_AW_INFO_ENGINE_ID: "copilot" @@ -1827,7 +1905,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,go.dev,golang.org,goproxy.io,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkg.go.dev,ppa.launchpad.net,proxy.golang.org,s.symcb.com,s.symcd.com,security.ubuntu.com,storage.googleapis.com,sum.golang.org,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"auto_close_issue\":true,\"base_branch\":\"main\",\"draft\":true,\"if_no_changes\":\"ignore\",\"max\":1,\"max_patch_files\":100,\"max_patch_size\":4096,\"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\"],\"protected_files_policy\":\"allowed\",\"title_prefix\":\"[dotnet-code] \"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"false\"},\"report_incomplete\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"allowed_files\":[\"agent/**\",\"internal/**\",\"message/**\",\"provider/**\",\"tool/**\",\"workflow/**\"],\"auto_close_issue\":true,\"base_branch\":\"main\",\"draft\":true,\"if_no_changes\":\"ignore\",\"max\":1,\"max_patch_files\":100,\"max_patch_size\":4096,\"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\"],\"protected_files_policy\":\"allowed\",\"title_prefix\":\"[dotnet-code] \"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"false\"},\"report_incomplete\":{}}" GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1848,3 +1926,69 @@ jobs: /tmp/gh-aw/temporary-id-map.json /tmp/gh-aw/safe-output-errors.json if-no-files-found: ignore + + update_cache_memory: + needs: + - activation + - agent + - detection + if: always() && needs.detection.result == 'success' && needs.agent.result == 'success' + runs-on: ubuntu-slim + permissions: + actions: write + env: + GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} + GH_AW_WORKFLOW_ID_SANITIZED: dotnetcodeportabilityweekly + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@5e508589e03a7757a7e05b26e834292f5445bfb6 # v0.88.7 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: ".NET-to-Go Weekly Portability Audit" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/dotnet-code-portability-weekly.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.80" + GH_AW_INFO_AWF_VERSION: "v0.28.14" + GH_AW_INFO_ENGINE_ID: "copilot" + - name: Download cache-memory artifact (default) + id: download_cache_default + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + continue-on-error: true + with: + name: cache-memory + path: /tmp/gh-aw/cache-memory + - name: Check if cache-memory folder has content (default) + id: check_cache_default + shell: bash + run: | + if [ -d "/tmp/gh-aw/cache-memory" ] && [ "$(ls -A /tmp/gh-aw/cache-memory 2>/dev/null)" ]; then + echo "has_content=true" >> "$GITHUB_OUTPUT" + else + echo "has_content=false" >> "$GITHUB_OUTPUT" + fi + - name: Validate cache-memory before save (default) + id: validate_cache_memory_64656661756c74 + if: steps.check_cache_default.outputs.has_content == 'true' + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + MEMORY_DIR: /tmp/gh-aw/cache-memory + MEMORY_ID: default + ALLOWED_EXTENSIONS: '[".json"]' + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { validateMemoryStep } = require(path.join(actionsDir, 'validate_memory_step.cjs')); + validateMemoryStep(core, { kind: 'cache' }); + - name: Save cache-memory to cache (default) + if: steps.check_cache_default.outputs.has_content == 'true' && steps.validate_cache_memory_64656661756c74.outcome == 'success' + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + key: memory-none-nopolicy-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }} + path: /tmp/gh-aw/cache-memory diff --git a/.github/workflows/dotnet-code-portability-weekly.md b/.github/workflows/dotnet-code-portability-weekly.md new file mode 100644 index 00000000..4c6ac7f1 --- /dev/null +++ b/.github/workflows/dotnet-code-portability-weekly.md @@ -0,0 +1,178 @@ +--- +description: Weekly audit for evidence-backed .NET-to-Go portability improvements without public API or behavior changes +intent: Reduce maintainer effort when porting .NET changes to Go without cosmetic churn or duplicate work. +tracker-id: dotnet-code-portability-weekly +model: "gpt-5.5" +engine: + id: copilot +network: + allowed: + - defaults + - go +on: + schedule: + - cron: "19 22 * * 1" + workflow_dispatch: +checkout: + fetch-depth: 0 +steps: + - name: Fetch upstream .NET reference + shell: bash + working-directory: ${{ github.workspace }} + run: | + set -euo pipefail + git fetch --no-tags https://github.com/microsoft/agent-framework.git +refs/heads/main:refs/remotes/upstream-agent-framework/main + upstream_sha="$(git rev-parse --verify 'refs/remotes/upstream-agent-framework/main^{commit}')" + git cat-file -e "${upstream_sha}:dotnet/src" + git cat-file -e "${upstream_sha}:dotnet/tests" + echo "DOTNET_UPSTREAM_SHA=$upstream_sha" >> "$GITHUB_ENV" +permissions: + contents: read + pull-requests: read + issues: read + copilot-requests: write +tools: + edit: + cache-memory: + retention-days: 30 + allowed-extensions: [".json"] + bash: + - "git:*" + - "go:*" + - gofmt + - rg + - find + - sed + - awk + - jq + - grep + - cat + - ls + - pwd + - date + - head + - tail + - sort + - uniq + - wc + github: + toolsets: [context, repos, issues, pull_requests] +safe-outputs: + max-patch-size: 4096 + noop: + report-as-issue: false + create-pull-request: + max: 1 + title-prefix: "[dotnet-code] " + draft: true + base-branch: main + auto-close-issue: true + if-no-changes: ignore + allowed-files: ["agent/**", "internal/**", "message/**", "provider/**", "tool/**", "workflow/**"] + protected-files: allowed +timeout-minutes: 90 +--- + +# .NET-to-Go Weekly Portability Audit + +You are a weekly portability auditor for `microsoft/agent-framework-go`. + +Find concrete obstacles to maintaining or porting the corresponding .NET behavior in Go. Propose at most one small, evidence-backed code or test improvement. Structural resemblance alone is not a benefit, and producing a PR is not a success criterion. A useful audit that ends in `noop` is a successful run. + +## Hard Rules + +- Do not change public Go APIs. +- Do not intentionally change behavior. +- Do not add missing .NET features, placeholders, examples, or feature docs. +- Do not edit `.github/`, governance files, or agent workflow files. +- Follow idiomatic Go rather than reproducing .NET implementation details. +- Bug fixes and feature ports belong to `[dotnet-port-fixes]` and `[dotnet-port-api]`, respectively. If a candidate needs a behavior or public API change, defer it rather than extracting a cosmetic subset. +- Do not port experimental upstream behavior, even as a test-only change. +- Prefer `noop` to speculative cleanup, insufficient evidence, or duplicate work. There is no minimum number of candidates to reject and no requirement to change code. + +## Setup + +- Go SDK checkout: `${{ github.workspace }}` +- The deterministic setup step fetches upstream before the sandboxed agent starts, verifies the .NET source and test trees, and sets `DOTNET_UPSTREAM_SHA` to the fetched commit. A failed fetch must fail setup, not silently reduce the evidence requirement. + +Work from the Go SDK checkout: + +```bash +cd ${{ github.workspace }} +``` + +Use the pinned `DOTNET_UPSTREAM_SHA` for all upstream inspection, including `git log`, `git show`, and source/test links. For example: + +```bash +git log -20 --oneline "$DOTNET_UPSTREAM_SHA" -- dotnet/src dotnet/tests +git ls-tree -r --name-only "$DOTNET_UPSTREAM_SHA" dotnet/src dotnet/tests +``` + +Do not fetch upstream again inside the sandbox or replace source inspection with search snippets, directory metadata, or file names. If the pinned reference or required evidence is unavailable, call `noop` explaining the blocker; do not claim the area is aligned. + +## History and Feedback + +- Before selecting work, read recent tracking issues and PRs with the `[dotnet-code]`, `[dotnet-port-fixes]`, and `[dotnet-port-api]` prefixes, including open items and items updated in the last 30 days. Read relevant maintainer comments and linked PR outcomes, not just titles. +- This repository can report a proposed PR as an issue containing a branch link because automatic PR creation is disabled. Treat that issue as pending work, not as permission to produce another proposal. For each shortlisted candidate, search both issues and PRs in all states for the same upstream change, Go behavior, or algorithm, including older matches. +- Skip work already pending or merged. Do not resubmit rejected proposals unless relevant source/tests or explicit maintainer feedback changed; explain that new evidence. If relevant history is filtered or unreadable, skip the uncertain candidate rather than assuming no duplicate exists. +- Use `/tmp/gh-aw/cache-memory/portability-audit.json` as an optional rolling record of the last 20 inspected candidates: upstream and Go commit SHAs, relevant paths, decision, reason, and issue/PR links. Read it before selecting work and update it before the terminal safe-output call, including on `noop`. Recheck live GitHub outcomes; cached proposals are not evidence of acceptance. Only revisit a rejected candidate when its relevant evidence changed. A cache miss or save failure must not prevent the audit or replace the GitHub history checks. + +## Acceptance Threshold + +Before editing, establish all of the following: + +1. **Concrete benefit:** identify a specific porting obstacle, materially duplicated algorithm, or missing behavioral test for an existing Go capability. Explain which maintenance work the proposal eliminates or which uncovered contract it protects; "closer to .NET" or "easier future ports" is not enough. +2. **Verified evidence:** inspect the corresponding source and relevant tests at the pinned upstream commit and the Go implementation/callers. Cite the exact files, symbols, upstream commit or PR when applicable, and behavioral scenario. A matching name or path is not evidence. +3. **Simpler Go or useful coverage:** consolidate meaningful duplicated logic, remove a demonstrated obstacle to applying an upstream change, or adapt a missing upstream behavioral test that the current Go implementation already passes. Check existing helpers and tests first. +4. **Preserved contracts:** identify how tests cover affected behavior, including ownership, ordering, error, or lifecycle paths when relevant. Unexported code and passing unrelated tests do not prove behavior preservation. + +Reject single-use helper extraction, renaming, moving short blocks, or adding intermediate slices, passes, or abstractions solely to imitate .NET layout. Do not manufacture duplicate tests to justify such a refactor. Do not turn a test that exposes a Go bug into a behavior-changing fix in this workflow; defer it to the appropriate porting workflow. + +## Work Loop + +1. Check history and feedback, then inspect at most three promising candidates. Prefer recent upstream changes, concrete difficulties documented in prior ports, and uncovered upstream test scenarios over random files. Stop early when evidence is missing or candidates are already covered; do not expand the search merely to produce a patch. +2. Apply the acceptance threshold before editing. If no candidate qualifies, record the audit outcome and call `noop`. +3. Implement only the strongest qualifying candidate. For production edits, add or identify focused preservation tests and run them before and after the refactor. For test-only work, confirm the new scenario passes against unchanged production code. Adapt upstream behavioral test intent rather than asserting private Go implementation details. +4. Run `gofmt` and targeted unit tests. Use broader unit tests for shared runtime changes, excluding E2E and replay-harness tests. Investigate failures; do not weaken assertions or change behavior to make the candidate pass. +5. Inspect the diff against the stated benefit and contracts. If it changes public API or behavior, adds a feature, or only creates churn, discard the candidate and call `noop`; do not search for replacement busywork. +6. Update the audit record. Call `create_pull_request` at most once for a qualifying, validated change; otherwise call `noop`. Do not claim that a PR exists merely because a write intent was submitted. + +## PR Body + +Use this shape: + +```markdown +## Summary + +Describe the scoped code or test change, the concrete porting obstacle or coverage gap, and the maintenance work eliminated or contract protected. Explain why leaving the current Go implementation unchanged is worse. + +## .NET Reference + +- Upstream commit SHA and immutable source/test links +- Relevant symbols and behavioral scenarios, plus the upstream PR when applicable +- Corresponding Go implementation and existing coverage inspected + +## Public API and Behavior + +No public Go API changed. No intentional behavior change was made. + +## Tests + +List the specific behavior covered, tests added or reused, and actual before/after test results. For test-only changes, explain the previously uncovered upstream scenario and confirm production code is unchanged. + +## Notes + +Link related tracking issues/PRs and relevant prior feedback. Mention skipped candidates, deferred bug/feature ports, and remaining uncertainty. +``` + +Titles should name the specific behavior or duplicated algorithm, not generic cleanup or alignment. + +## No-Change Requirement + +Call `noop` without creating an issue when there is no qualifying change. Give a concise audit summary: + +- The pinned upstream SHA and inspected commit range or areas, if available +- History/feedback checked, with links to existing work when relevant +- Why inspected candidates did not meet the threshold, including evidence blockers or deferred behavior changes + +Do not describe missing evidence as proof that no portability problem exists. \ No newline at end of file