diff --git a/.github/workflows/audit-workflows.lock.yml b/.github/workflows/audit-workflows.lock.yml index cb4fbbe3ccb..822d61e1206 100644 --- a/.github/workflows/audit-workflows.lock.yml +++ b/.github/workflows/audit-workflows.lock.yml @@ -25,11 +25,12 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/jqschema.md # - shared/reporting.md # - shared/trending-charts-simple.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"e687ed6ea9c097f90e8e0c3181f674b2bf92734fd253c3408f6775da1b76e745","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"6556f9744bd2ca5ec79310ade16237457807aaebfea54618e37fec3aa848606b","strict":true} name: "Agentic Workflow Audit Agent" "on": @@ -141,7 +142,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, upload_asset, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, upload_asset, missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). @@ -178,6 +179,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/jqschema.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -468,7 +472,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"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}]},"upload_asset":{"max":0}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"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}]},"upload_asset":{"max":0}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -508,6 +512,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Upload a file as a URL-addressable asset that can be referenced in issues, PRs, or comments. The file is stored on an orphaned git branch and returns a permanent URL. Use this for images, diagrams, or other files that need to be embedded in GitHub content. CONSTRAINTS: Maximum file size: 10240KB. Allowed file extensions: [.png .jpg .jpeg].", "inputSchema": { @@ -645,6 +691,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1479,7 +1552,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.pythonhosted.org,anaconda.org,anthropic.com,api.anthropic.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,cdn.playwright.dev,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,host.docker.internal,index.crates.io,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,playwright.download.prss.microsoft.com,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,static.crates.io,statsig.anthropic.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/audit-workflows.md b/.github/workflows/audit-workflows.md index a1fc1350491..fe062012d8b 100644 --- a/.github/workflows/audit-workflows.md +++ b/.github/workflows/audit-workflows.md @@ -22,11 +22,9 @@ safe-outputs: upload-asset: create-discussion: expires: 1d - category: "audits" - max: 1 - close-older-discussions: true timeout-minutes: 30 imports: + - shared/daily-audit-discussion.md - shared/jqschema.md - shared/reporting.md - shared/trending-charts-simple.md diff --git a/.github/workflows/auto-triage-issues.lock.yml b/.github/workflows/auto-triage-issues.lock.yml index eb54d5c99d0..9ca63125bde 100644 --- a/.github/workflows/auto-triage-issues.lock.yml +++ b/.github/workflows/auto-triage-issues.lock.yml @@ -25,9 +25,10 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"6d5ae739b2ba3b6bbba0566b0e444cf837a7639539ddad0361430acf57eee28c","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"cef1dca3145dc35ebd518ca413823f7b7ee48fc910cb75f8c9bbee7be9e4ffb2","strict":true} name: "Auto-Triage Issues" "on": @@ -148,7 +149,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, add_labels, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, add_labels, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -183,6 +184,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -346,7 +350,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"add_labels":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"add_labels":{"max":10},"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -386,6 +390,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Add labels to an existing GitHub issue or pull request for categorization and filtering. Labels must already exist in the repository. For creating new issues with labels, use create_issue with the labels property instead. CONSTRAINTS: Maximum 10 label(s) can be added.", "inputSchema": { @@ -531,6 +577,33 @@ jobs: } } }, + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1240,7 +1313,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_labels\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[Auto-Triage] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_labels\":{\"max\":10},\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[Auto-Triage] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/auto-triage-issues.md b/.github/workflows/auto-triage-issues.md index a626587605d..a9216f75be3 100644 --- a/.github/workflows/auto-triage-issues.md +++ b/.github/workflows/auto-triage-issues.md @@ -18,6 +18,7 @@ network: - defaults - github imports: + - shared/daily-audit-discussion.md - shared/reporting.md tools: github: @@ -31,9 +32,6 @@ safe-outputs: create-discussion: expires: 1d title-prefix: "[Auto-Triage] " - category: "audits" - close-older-discussions: true - max: 1 timeout-minutes: 15 features: copilot-requests: true diff --git a/.github/workflows/blog-auditor.lock.yml b/.github/workflows/blog-auditor.lock.yml index cf475fdef9b..7bfe16bc5d7 100644 --- a/.github/workflows/blog-auditor.lock.yml +++ b/.github/workflows/blog-auditor.lock.yml @@ -25,9 +25,10 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"878b2619a7ef728ee36423c6ded4bda471ba66d830dc760d5437153fdc594dc1"} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"795b50eace5751cc0141ce749040b30c1205eb91c2d4815281b762d3f2e17990"} name: "Blog Auditor" "on": @@ -138,7 +139,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -173,6 +174,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -343,7 +347,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -383,6 +387,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -480,6 +526,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1237,7 +1310,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,anthropic.com,api.anthropic.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,githubnext.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,playwright.download.prss.microsoft.com,ppa.launchpad.net,pypi.org,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,statsig.anthropic.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.githubnext.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[audit] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[audit] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/blog-auditor.md b/.github/workflows/blog-auditor.md index c893e277003..e066748d4a6 100644 --- a/.github/workflows/blog-auditor.md +++ b/.github/workflows/blog-auditor.md @@ -30,11 +30,9 @@ safe-outputs: create-discussion: expires: 1d title-prefix: "[audit] " - category: "audits" - max: 1 - close-older-discussions: true timeout-minutes: 10 imports: + - shared/daily-audit-discussion.md - shared/reporting.md --- diff --git a/.github/workflows/claude-code-user-docs-review.lock.yml b/.github/workflows/claude-code-user-docs-review.lock.yml index 265f44a2fcb..d3861b259ba 100644 --- a/.github/workflows/claude-code-user-docs-review.lock.yml +++ b/.github/workflows/claude-code-user-docs-review.lock.yml @@ -25,9 +25,10 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"5a9409064f385fdf708c176795fd7d445018ce3d6239a9e39f5de5be2aa1e20b","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"94e4dc42cfbe69fbb2dcc9bab98995ce5c31843a0e88f46620757806130a4b6f","strict":true} name: "Claude Code User Documentation Review" "on": @@ -137,7 +138,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -172,6 +173,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -358,7 +362,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -398,6 +402,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -495,6 +541,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1205,7 +1278,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,anthropic.com,api.anthropic.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,playwright.download.prss.microsoft.com,ppa.launchpad.net,pypi.org,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,statsig.anthropic.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/claude-code-user-docs-review.md b/.github/workflows/claude-code-user-docs-review.md index 5fa6ef6286d..92e2facdd7d 100644 --- a/.github/workflows/claude-code-user-docs-review.md +++ b/.github/workflows/claude-code-user-docs-review.md @@ -25,9 +25,6 @@ network: safe-outputs: create-discussion: expires: 1d - category: "audits" - max: 1 - close-older-discussions: true tools: cache-memory: true @@ -39,6 +36,7 @@ tools: timeout-minutes: 30 imports: + - shared/daily-audit-discussion.md - shared/reporting.md features: diff --git a/.github/workflows/copilot-agent-analysis.lock.yml b/.github/workflows/copilot-agent-analysis.lock.yml index 34d8a1158f8..3a0563f4f2e 100644 --- a/.github/workflows/copilot-agent-analysis.lock.yml +++ b/.github/workflows/copilot-agent-analysis.lock.yml @@ -26,11 +26,12 @@ # Resolved workflow manifest: # Imports: # - shared/copilot-pr-data-fetch.md +# - shared/daily-audit-discussion.md # - shared/jqschema.md # - shared/reporting.md # - shared/copilot-pr-analysis-base.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"8f9db38275e2f6a90812dd7c6943929ca732b8b75a0aefa841599e29f81db7c0","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"e5d40daefc477f2f0b7e972f1f8bf3524f941e41e05f221c3ecb3436c313ab69","strict":true} name: "Copilot Agent PR Analysis" "on": @@ -142,7 +143,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -177,6 +178,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/copilot-pr-analysis-base.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -399,7 +403,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"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}]}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"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}]}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -439,6 +443,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -551,6 +597,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1342,7 +1415,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,anthropic.com,api.anthropic.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,playwright.download.prss.microsoft.com,ppa.launchpad.net,pypi.org,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,statsig.anthropic.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[copilot-agent-analysis] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[copilot-agent-analysis] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/copilot-agent-analysis.md b/.github/workflows/copilot-agent-analysis.md index aa509b6f886..0c0a1a80664 100644 --- a/.github/workflows/copilot-agent-analysis.md +++ b/.github/workflows/copilot-agent-analysis.md @@ -25,11 +25,9 @@ safe-outputs: create-discussion: expires: 1d title-prefix: "[copilot-agent-analysis] " - category: "audits" - max: 1 - close-older-discussions: true imports: + - shared/daily-audit-discussion.md - shared/copilot-pr-analysis-base.md - shared/reporting.md diff --git a/.github/workflows/copilot-pr-merged-report.lock.yml b/.github/workflows/copilot-pr-merged-report.lock.yml index 2b5e4b820fc..d9eb0132340 100644 --- a/.github/workflows/copilot-pr-merged-report.lock.yml +++ b/.github/workflows/copilot-pr-merged-report.lock.yml @@ -26,12 +26,13 @@ # Resolved workflow manifest: # Imports: # - shared/copilot-pr-data-fetch.md +# - shared/daily-audit-discussion.md # - shared/gh.md # - shared/jqschema.md # - shared/reporting.md # - shared/copilot-pr-analysis-base.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"754e064128a0338fe1c412f4a91f45096dfaf541ad245d2b3d777300ca200916"} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"13fe1100a63e093494139c5f08d8b4e6b7d30797a5216b4f77f44dc25ba75d40"} name: "Daily Copilot PR Merged Report" "on": @@ -134,7 +135,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -169,6 +170,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/gh.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -372,7 +376,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -412,6 +416,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -509,6 +555,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1283,7 +1356,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[copilot-pr-merged-report] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[copilot-pr-merged-report] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/copilot-pr-merged-report.md b/.github/workflows/copilot-pr-merged-report.md index 3ad642a5585..7d31e9dfe2e 100644 --- a/.github/workflows/copilot-pr-merged-report.md +++ b/.github/workflows/copilot-pr-merged-report.md @@ -23,9 +23,6 @@ safe-outputs: create-discussion: expires: 1d title-prefix: "[copilot-pr-merged-report] " - category: "audits" - max: 1 - close-older-discussions: true network: allowed: @@ -34,6 +31,7 @@ network: - api.github.com imports: + - shared/daily-audit-discussion.md - shared/gh.md - shared/copilot-pr-analysis-base.md - shared/reporting.md diff --git a/.github/workflows/copilot-pr-nlp-analysis.lock.yml b/.github/workflows/copilot-pr-nlp-analysis.lock.yml index 4a932f8df26..1567c6c429b 100644 --- a/.github/workflows/copilot-pr-nlp-analysis.lock.yml +++ b/.github/workflows/copilot-pr-nlp-analysis.lock.yml @@ -26,12 +26,13 @@ # Resolved workflow manifest: # Imports: # - shared/copilot-pr-data-fetch.md +# - shared/daily-audit-discussion.md # - shared/jqschema.md # - shared/python-dataviz.md # - shared/reporting.md # - shared/copilot-pr-analysis-base.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"f2b6098d37f2490aa73983346ec72a1b9b929981244ae63b5af8099ce04a78b8","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"910f15ba3798b86c48633d964e46d707f94f1592df160d3031a00a5aa07c8b92","strict":true} name: "Copilot PR Conversation NLP Analysis" "on": @@ -136,7 +137,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, upload_asset, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, upload_asset, missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). @@ -173,6 +174,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/copilot-pr-analysis-base.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -427,7 +431,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"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}]},"upload_asset":{"max":0}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"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}]},"upload_asset":{"max":0}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -467,6 +471,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Upload a file as a URL-addressable asset that can be referenced in issues, PRs, or comments. The file is stored on an orphaned git branch and returns a permanent URL. Use this for images, diagrams, or other files that need to be embedded in GitHub content. CONSTRAINTS: Maximum file size: 10240KB. Allowed file extensions: [.png .jpg .jpeg].", "inputSchema": { @@ -604,6 +650,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1365,7 +1438,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.jsr.io,*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,cdn.jsdelivr.net,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,deb.nodesource.com,deno.land,esm.sh,files.pythonhosted.org,get.pnpm.io,github.com,googleapis.deno.dev,googlechromelabs.github.io,host.docker.internal,index.crates.io,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.npmjs.com,www.npmjs.org,yarnpkg.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[nlp-analysis] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[nlp-analysis] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/copilot-pr-nlp-analysis.md b/.github/workflows/copilot-pr-nlp-analysis.md index 7e9d89a3d18..5048633deb6 100644 --- a/.github/workflows/copilot-pr-nlp-analysis.md +++ b/.github/workflows/copilot-pr-nlp-analysis.md @@ -27,11 +27,9 @@ safe-outputs: create-discussion: expires: 1d title-prefix: "[nlp-analysis] " - category: "audits" - max: 1 - close-older-discussions: true imports: + - shared/daily-audit-discussion.md - shared/copilot-pr-analysis-base.md - shared/python-dataviz.md - shared/reporting.md diff --git a/.github/workflows/copilot-pr-prompt-analysis.lock.yml b/.github/workflows/copilot-pr-prompt-analysis.lock.yml index 5d9e098c9f8..650284327f6 100644 --- a/.github/workflows/copilot-pr-prompt-analysis.lock.yml +++ b/.github/workflows/copilot-pr-prompt-analysis.lock.yml @@ -26,11 +26,12 @@ # Resolved workflow manifest: # Imports: # - shared/copilot-pr-data-fetch.md +# - shared/daily-audit-discussion.md # - shared/jqschema.md # - shared/reporting.md # - shared/copilot-pr-analysis-base.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"d2adad35b52f026f410211a01c25a088c742c6aa9ac08d9f892a3edea90ab43e","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"814c8d655ba8a02be414c7dd56b04527833b74b2de5833a2a09268356d7c170c","strict":true} name: "Copilot PR Prompt Pattern Analysis" "on": @@ -136,7 +137,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -171,6 +172,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/copilot-pr-analysis-base.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -393,7 +397,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"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}]}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"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}]}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -433,6 +437,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -545,6 +591,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1281,7 +1354,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.jsr.io,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,bun.sh,cdn.jsdelivr.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,deb.nodesource.com,deno.land,esm.sh,get.pnpm.io,github.com,googleapis.deno.dev,googlechromelabs.github.io,host.docker.internal,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,storage.googleapis.com,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.npmjs.com,www.npmjs.org,yarnpkg.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[prompt-analysis] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[prompt-analysis] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/copilot-pr-prompt-analysis.md b/.github/workflows/copilot-pr-prompt-analysis.md index da092d20de7..996f4731913 100644 --- a/.github/workflows/copilot-pr-prompt-analysis.md +++ b/.github/workflows/copilot-pr-prompt-analysis.md @@ -26,11 +26,9 @@ safe-outputs: create-discussion: expires: 1d title-prefix: "[prompt-analysis] " - category: "audits" - max: 1 - close-older-discussions: true imports: + - shared/daily-audit-discussion.md - shared/copilot-pr-analysis-base.md - shared/reporting.md diff --git a/.github/workflows/copilot-session-insights.lock.yml b/.github/workflows/copilot-session-insights.lock.yml index cb30651fcaa..ae890ee772e 100644 --- a/.github/workflows/copilot-session-insights.lock.yml +++ b/.github/workflows/copilot-session-insights.lock.yml @@ -25,6 +25,7 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/jqschema.md # - shared/copilot-session-data-fetch.md # - shared/python-dataviz.md @@ -32,7 +33,7 @@ # - shared/session-analysis-charts.md # - shared/session-analysis-strategies.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"0e97b7dc1f36ccddaef55702eb1a54e51b2c23280be5b5c6c5f21199230a34b4","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"498e87b8f917c9af8994d0450c1693a6f7faffa1bd12e9037e5c01040da47984","strict":true} name: "Copilot Session Insights" "on": @@ -145,7 +146,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, upload_asset, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, upload_asset, missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). @@ -182,6 +183,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/jqschema.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -436,7 +440,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"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}]},"upload_asset":{"max":0}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"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}]},"upload_asset":{"max":0}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -476,6 +480,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Upload a file as a URL-addressable asset that can be referenced in issues, PRs, or comments. The file is stored on an orphaned git branch and returns a permanent URL. Use this for images, diagrams, or other files that need to be embedded in GitHub content. CONSTRAINTS: Maximum file size: 10240KB. Allowed file extensions: [.png .jpg .jpeg].", "inputSchema": { @@ -613,6 +659,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1429,7 +1502,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.pythonhosted.org,anaconda.org,anthropic.com,api.anthropic.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,cdn.playwright.dev,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,host.docker.internal,index.crates.io,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,playwright.download.prss.microsoft.com,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,static.crates.io,statsig.anthropic.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[copilot-session-insights] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[copilot-session-insights] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/copilot-session-insights.md b/.github/workflows/copilot-session-insights.md index 2a190088e37..2f063850a4f 100644 --- a/.github/workflows/copilot-session-insights.md +++ b/.github/workflows/copilot-session-insights.md @@ -27,9 +27,6 @@ safe-outputs: create-discussion: expires: 1d title-prefix: "[copilot-session-insights] " - category: "audits" - max: 1 - close-older-discussions: true tools: repo-memory: @@ -48,6 +45,7 @@ tools: - "date *" imports: + - shared/daily-audit-discussion.md - shared/jqschema.md # Must come before copilot-session-data-fetch.md (dependency) - shared/copilot-session-data-fetch.md - shared/session-analysis-charts.md diff --git a/.github/workflows/daily-code-metrics.lock.yml b/.github/workflows/daily-code-metrics.lock.yml index ae04ed5f80e..32695bf2a09 100644 --- a/.github/workflows/daily-code-metrics.lock.yml +++ b/.github/workflows/daily-code-metrics.lock.yml @@ -25,11 +25,12 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/python-dataviz.md # - shared/reporting.md # - shared/trends.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"b991cb66b5ef15cfab292acb7b27c302e5435b94b2aa486ca69d3954d12d84bc","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"82d7d7b8ecfa98174864b51dfd09b6702a4e13e860acf90608cecc4e8baec9ce","strict":true} name: "Daily Code Metrics and Trend Tracking Agent" "on": @@ -141,7 +142,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, upload_asset, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, upload_asset, missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). @@ -178,6 +179,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -410,7 +414,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":72,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"push_repo_memory":{"memories":[{"dir":"/tmp/gh-aw/repo-memory/default","id":"default","max_file_count":100,"max_file_size":102400,"max_patch_size":51200}]},"upload_asset":{"max":0}} + {"close_discussion":{"max":10},"create_discussion":{"expires":72,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"push_repo_memory":{"memories":[{"dir":"/tmp/gh-aw/repo-memory/default","id":"default","max_file_count":100,"max_file_size":102400,"max_patch_size":51200}]},"upload_asset":{"max":0}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -450,6 +454,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Upload a file as a URL-addressable asset that can be referenced in issues, PRs, or comments. The file is stored on an orphaned git branch and returns a permanent URL. Use this for images, diagrams, or other files that need to be embedded in GitHub content. CONSTRAINTS: Maximum file size: 10240KB. Allowed file extensions: [.png .jpg .jpeg].", "inputSchema": { @@ -587,6 +633,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1408,7 +1481,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.pythonhosted.org,anaconda.org,anthropic.com,api.anthropic.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,cdn.playwright.dev,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,host.docker.internal,index.crates.io,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,playwright.download.prss.microsoft.com,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,static.crates.io,statsig.anthropic.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":72,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":72,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/daily-code-metrics.md b/.github/workflows/daily-code-metrics.md index 37702df4c79..e80f52ab861 100644 --- a/.github/workflows/daily-code-metrics.md +++ b/.github/workflows/daily-code-metrics.md @@ -21,12 +21,10 @@ safe-outputs: upload-asset: create-discussion: expires: 3d - category: "audits" - max: 1 - close-older-discussions: true timeout-minutes: 30 strict: true imports: + - shared/daily-audit-discussion.md - shared/reporting.md - shared/python-dataviz.md - shared/trends.md diff --git a/.github/workflows/daily-compiler-quality.lock.yml b/.github/workflows/daily-compiler-quality.lock.yml index 0ea68e1933f..ca0d425eae2 100644 --- a/.github/workflows/daily-compiler-quality.lock.yml +++ b/.github/workflows/daily-compiler-quality.lock.yml @@ -25,10 +25,11 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/mcp/serena-go.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"43b61ccd4023929211202d467bd670da7af659d6869c4582f175822d3493c087","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"ead0175cdcee78574d7c36bceb9a757dd430dbdb69200dd7b7bff1fa3fe111f9","strict":true} name: "Daily Compiler Quality Check" "on": @@ -132,7 +133,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -167,6 +168,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/mcp/serena-go.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -352,7 +356,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -392,6 +396,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -489,6 +535,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1173,7 +1246,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/daily-compiler-quality.md b/.github/workflows/daily-compiler-quality.md index e785371f4e3..94ff9947235 100644 --- a/.github/workflows/daily-compiler-quality.md +++ b/.github/workflows/daily-compiler-quality.md @@ -11,6 +11,7 @@ permissions: tracker-id: daily-compiler-quality engine: copilot imports: + - shared/daily-audit-discussion.md - shared/mcp/serena-go.md - shared/reporting.md tools: @@ -28,9 +29,6 @@ tools: safe-outputs: create-discussion: expires: 1d - category: "audits" - max: 1 - close-older-discussions: true timeout-minutes: 30 strict: true features: diff --git a/.github/workflows/daily-copilot-token-report.lock.yml b/.github/workflows/daily-copilot-token-report.lock.yml index 06a5928d87b..359e7017de0 100644 --- a/.github/workflows/daily-copilot-token-report.lock.yml +++ b/.github/workflows/daily-copilot-token-report.lock.yml @@ -26,10 +26,11 @@ # Resolved workflow manifest: # Imports: # - copilot-setup-steps.yml +# - shared/daily-audit-discussion.md # - shared/python-dataviz.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"62ed9373b2a71bd045f90201268707bb8c2044f67b98fb93de8ac325d21d3613","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"ea510a5b3537f1257e8d0dc0ca844a46682b7a430459a871a47dee80b7bda189","strict":true} name: "Daily Copilot Token Consumption Report" "on": @@ -134,7 +135,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, upload_asset, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, upload_asset, missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). @@ -171,6 +172,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -435,7 +439,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":72,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"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}]},"upload_asset":{"max":0}} + {"close_discussion":{"max":10},"create_discussion":{"expires":72,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"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}]},"upload_asset":{"max":0}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -475,6 +479,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Upload a file as a URL-addressable asset that can be referenced in issues, PRs, or comments. The file is stored on an orphaned git branch and returns a permanent URL. Use this for images, diagrams, or other files that need to be embedded in GitHub content. CONSTRAINTS: Maximum file size: 10240KB. Allowed file extensions: [.png .jpg .jpeg].", "inputSchema": { @@ -612,6 +658,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1378,7 +1451,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,github.com,host.docker.internal,index.crates.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,pip.pypa.io,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,s.symcb.com,s.symcd.com,security.ubuntu.com,static.crates.io,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":72,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":72,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/daily-copilot-token-report.md b/.github/workflows/daily-copilot-token-report.md index fdaed633c0a..e3e92467692 100644 --- a/.github/workflows/daily-copilot-token-report.md +++ b/.github/workflows/daily-copilot-token-report.md @@ -39,11 +39,9 @@ safe-outputs: upload-asset: create-discussion: expires: 3d - category: "audits" - max: 1 - close-older-discussions: true timeout-minutes: 20 imports: + - shared/daily-audit-discussion.md - copilot-setup-steps.yml # Import setup steps from copilot-setup-steps.yml - shared/reporting.md - shared/python-dataviz.md diff --git a/.github/workflows/daily-firewall-report.lock.yml b/.github/workflows/daily-firewall-report.lock.yml index 67a49718c7a..46394438e46 100644 --- a/.github/workflows/daily-firewall-report.lock.yml +++ b/.github/workflows/daily-firewall-report.lock.yml @@ -25,10 +25,11 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/reporting.md # - shared/trending-charts-simple.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"575da188e33143c8c5b5e07660a4f4d3302695314638124a21ac50fec6fd4b3a","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"d8948e33ae60bbcd4c6a0b0ae488aef2eec1b8426a2c1a503435ddaed9a1300f","strict":true} name: "Daily Firewall Logs Collector and Reporter" "on": @@ -138,7 +139,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, upload_asset, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, upload_asset, missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). @@ -175,6 +176,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -437,7 +441,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":72,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"upload_asset":{"max":0}} + {"close_discussion":{"max":10},"create_discussion":{"expires":72,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"upload_asset":{"max":0}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -477,6 +481,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Upload a file as a URL-addressable asset that can be referenced in issues, PRs, or comments. The file is stored on an orphaned git branch and returns a permanent URL. Use this for images, diagrams, or other files that need to be embedded in GitHub content. CONSTRAINTS: Maximum file size: 10240KB. Allowed file extensions: [.png .jpg .jpeg].", "inputSchema": { @@ -599,6 +645,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1292,7 +1365,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,github.com,host.docker.internal,index.crates.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,pip.pypa.io,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,s.symcb.com,s.symcd.com,security.ubuntu.com,static.crates.io,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":72,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":72,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/daily-firewall-report.md b/.github/workflows/daily-firewall-report.md index b4e87394a6f..5f122d3cca8 100644 --- a/.github/workflows/daily-firewall-report.md +++ b/.github/workflows/daily-firewall-report.md @@ -21,9 +21,6 @@ safe-outputs: upload-asset: create-discussion: expires: 3d - category: "audits" - max: 1 - close-older-discussions: true tools: agentic-workflows: @@ -34,6 +31,7 @@ tools: - "*" edit: imports: + - shared/daily-audit-discussion.md - shared/reporting.md - shared/trending-charts-simple.md --- diff --git a/.github/workflows/daily-issues-report.lock.yml b/.github/workflows/daily-issues-report.lock.yml index 48a60b66fc6..6b67166c7e1 100644 --- a/.github/workflows/daily-issues-report.lock.yml +++ b/.github/workflows/daily-issues-report.lock.yml @@ -25,13 +25,14 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/issues-data-fetch.md # - shared/jqschema.md # - shared/python-dataviz.md # - shared/reporting.md # - shared/trends.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"667a196ac2033e3f747d5c0dd2d3391c9a05f01941879279691b28a1ccc5f68b","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"6818a76b8297b5268785c694a652df4dceff5ef850fe0b20c6ccc1e0317dbd96","strict":true} name: "Daily Issues Report Generator" "on": @@ -184,6 +185,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/jqschema.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' diff --git a/.github/workflows/daily-issues-report.md b/.github/workflows/daily-issues-report.md index c562df375f8..ccdaf9bb405 100644 --- a/.github/workflows/daily-issues-report.md +++ b/.github/workflows/daily-issues-report.md @@ -18,14 +18,10 @@ safe-outputs: upload-asset: create-discussion: expires: 3d - category: "audits" title-prefix: "[daily issues] " - max: 1 - close-older-discussions: true - close-discussion: - max: 10 timeout-minutes: 30 imports: + - shared/daily-audit-discussion.md - shared/jqschema.md - shared/issues-data-fetch.md - shared/python-dataviz.md diff --git a/.github/workflows/daily-observability-report.lock.yml b/.github/workflows/daily-observability-report.lock.yml index a3eafb8d47f..474faa41674 100644 --- a/.github/workflows/daily-observability-report.lock.yml +++ b/.github/workflows/daily-observability-report.lock.yml @@ -25,9 +25,10 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"1b990129663822b2a2ec35c48272d37d9b5fd2588701da99710163ff9f98f551","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"c85c1403adef70acfcdb540e5f8430968291b947f10c40c9bf7dcbb2fbad55ba","strict":true} name: "Daily Observability Report for AWF Firewall and MCP Gateway" "on": @@ -174,6 +175,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' diff --git a/.github/workflows/daily-observability-report.md b/.github/workflows/daily-observability-report.md index f206a17ff89..c8fb6699eda 100644 --- a/.github/workflows/daily-observability-report.md +++ b/.github/workflows/daily-observability-report.md @@ -17,14 +17,10 @@ tools: safe-outputs: create-discussion: expires: 1d - category: "audits" title-prefix: "[observability] " - max: 1 - close-older-discussions: true - close-discussion: - max: 10 timeout-minutes: 45 imports: + - shared/daily-audit-discussion.md - shared/reporting.md --- diff --git a/.github/workflows/daily-performance-summary.lock.yml b/.github/workflows/daily-performance-summary.lock.yml index 70f12820a06..9fd30628fb7 100644 --- a/.github/workflows/daily-performance-summary.lock.yml +++ b/.github/workflows/daily-performance-summary.lock.yml @@ -25,11 +25,12 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/github-queries-mcp-script.md # - shared/reporting.md # - shared/trending-charts-simple.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"c93c3cce9fe58a74b02303d790120c6508d3d4d0bf95bb4fc24c36df3847efd0","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"c158f00b8cac75b3378e863689927a1c3bc41e1dba1317961562b6aa95f53894","strict":true} name: "Daily Project Performance Summary Generator (Using MCP Scripts)" "on": @@ -176,6 +177,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/github-queries-mcp-script.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' diff --git a/.github/workflows/daily-performance-summary.md b/.github/workflows/daily-performance-summary.md index 8041e5df7fc..350fbe9292a 100644 --- a/.github/workflows/daily-performance-summary.md +++ b/.github/workflows/daily-performance-summary.md @@ -19,14 +19,10 @@ safe-outputs: upload-asset: create-discussion: expires: 3d - category: "audits" title-prefix: "[daily performance] " - max: 1 - close-older-discussions: true - close-discussion: - max: 10 timeout-minutes: 30 imports: + - shared/daily-audit-discussion.md - shared/github-queries-mcp-script.md - shared/trending-charts-simple.md - shared/reporting.md diff --git a/.github/workflows/daily-regulatory.lock.yml b/.github/workflows/daily-regulatory.lock.yml index ea88c62ada4..c8b7946fce1 100644 --- a/.github/workflows/daily-regulatory.lock.yml +++ b/.github/workflows/daily-regulatory.lock.yml @@ -25,10 +25,11 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/github-queries-mcp-script.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"238c3282ef64bdb6800bd48877c082702a91b29214ffb81ce63903042421d706","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"9d36c8d42bd2a9ec079b1fd41b64467d1e6403a0314d7c2677e13d89b1770a31","strict":true} name: "Daily Regulatory Report Generator" "on": @@ -172,6 +173,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/github-queries-mcp-script.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' diff --git a/.github/workflows/daily-regulatory.md b/.github/workflows/daily-regulatory.md index f1f3055de35..d22152f9b59 100644 --- a/.github/workflows/daily-regulatory.md +++ b/.github/workflows/daily-regulatory.md @@ -20,14 +20,10 @@ tools: safe-outputs: create-discussion: expires: 3d - category: "audits" title-prefix: "[daily regulatory] " - max: 1 - close-older-discussions: true - close-discussion: - max: 10 timeout-minutes: 30 imports: + - shared/daily-audit-discussion.md - shared/github-queries-mcp-script.md - shared/reporting.md --- diff --git a/.github/workflows/daily-secrets-analysis.lock.yml b/.github/workflows/daily-secrets-analysis.lock.yml index f669f909879..dd8d7f8ef64 100644 --- a/.github/workflows/daily-secrets-analysis.lock.yml +++ b/.github/workflows/daily-secrets-analysis.lock.yml @@ -25,9 +25,10 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"f2aa146eb6b0f4cbf136d67791c53ae36f856bb0e601f602bac114089b381231","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"36c9c58dd6119231334ec3acc8d46d7205e543be3b605ad0196d38bfa0931276","strict":true} name: "Daily Secrets Analysis Agent" "on": @@ -165,6 +166,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' diff --git a/.github/workflows/daily-secrets-analysis.md b/.github/workflows/daily-secrets-analysis.md index 81668166cc3..05615b1bc6c 100644 --- a/.github/workflows/daily-secrets-analysis.md +++ b/.github/workflows/daily-secrets-analysis.md @@ -18,14 +18,10 @@ tools: safe-outputs: create-discussion: expires: 3d - category: "audits" title-prefix: "[daily secrets] " - max: 1 - close-older-discussions: true - close-discussion: - max: 10 timeout-minutes: 20 imports: + - shared/daily-audit-discussion.md - shared/reporting.md features: copilot-requests: true diff --git a/.github/workflows/daily-team-evolution-insights.lock.yml b/.github/workflows/daily-team-evolution-insights.lock.yml index 1036437fb23..13817ef1a18 100644 --- a/.github/workflows/daily-team-evolution-insights.lock.yml +++ b/.github/workflows/daily-team-evolution-insights.lock.yml @@ -25,9 +25,10 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"5cd3e800be141c9f7d3c827c683abb13e8db1661f5b12e1d6af506e135cbe5a4"} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"4e0c9d08e56be835cf745bb499cd228b7716cf47e47032d72eaf29f334632174"} name: "Daily Team Evolution Insights" "on": @@ -136,7 +137,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -171,6 +172,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -340,7 +344,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -380,6 +384,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -477,6 +523,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1176,7 +1249,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,anthropic.com,api.anthropic.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,playwright.download.prss.microsoft.com,ppa.launchpad.net,pypi.org,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,statsig.anthropic.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/daily-team-evolution-insights.md b/.github/workflows/daily-team-evolution-insights.md index cc6073dc458..05cd51819ea 100644 --- a/.github/workflows/daily-team-evolution-insights.md +++ b/.github/workflows/daily-team-evolution-insights.md @@ -25,11 +25,9 @@ tools: safe-outputs: create-discussion: expires: 1d - category: "audits" - max: 1 - close-older-discussions: true timeout-minutes: 90 imports: + - shared/daily-audit-discussion.md - shared/reporting.md --- diff --git a/.github/workflows/delight.lock.yml b/.github/workflows/delight.lock.yml index f536314e9f4..a4a62d95761 100644 --- a/.github/workflows/delight.lock.yml +++ b/.github/workflows/delight.lock.yml @@ -25,10 +25,11 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/jqschema.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"e01a758d3c758d82eabd4d9eb701b44134df6d64acef6cfda2bfc18ba603d73d","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"19833761cd321432d165c5dbf8044be7159f5bbbf829d2dd5c5b082974fefd7b","strict":true} name: "Delight" "on": @@ -133,7 +134,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_issue, create_discussion, missing_tool, missing_data, noop + Tools: create_issue, create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -168,6 +169,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -363,7 +367,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":168,"max":1},"create_issue":{"expires":48,"group":true,"max":2},"missing_data":{},"missing_tool":{},"noop":{"max":1},"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}]}} + {"close_discussion":{"max":10},"create_discussion":{"expires":168,"max":1},"create_issue":{"expires":48,"group":true,"max":2},"missing_data":{},"missing_tool":{},"noop":{"max":1},"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}]}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -452,6 +456,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -564,6 +610,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1358,7 +1431,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":168,\"fallback_to_issue\":true,\"max\":1},\"create_issue\":{\"expires\":48,\"group\":true,\"labels\":[\"delight\",\"cookie\"],\"max\":2},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":168,\"fallback_to_issue\":true,\"max\":1},\"create_issue\":{\"expires\":48,\"group\":true,\"labels\":[\"delight\",\"cookie\"],\"max\":2},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/delight.md b/.github/workflows/delight.md index 3066c35c73a..10d8186f35a 100644 --- a/.github/workflows/delight.md +++ b/.github/workflows/delight.md @@ -22,10 +22,6 @@ network: - github safe-outputs: - create-discussion: - category: "audits" - max: 1 - close-older-discussions: true create-issue: expires: 2d labels: [delight, cookie] @@ -56,6 +52,7 @@ tools: timeout-minutes: 30 imports: + - shared/daily-audit-discussion.md - shared/reporting.md - shared/jqschema.md diff --git a/.github/workflows/developer-docs-consolidator.lock.yml b/.github/workflows/developer-docs-consolidator.lock.yml index afd6ddbbe4d..0cb8a1a40a7 100644 --- a/.github/workflows/developer-docs-consolidator.lock.yml +++ b/.github/workflows/developer-docs-consolidator.lock.yml @@ -25,11 +25,12 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/mcp/qmd-docs.md # - shared/mcp/serena-go.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"6062086459893e5e8da7159dd36519fd83efc186b31d4a17896352563213ccfc","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"651208a6ea832baa7dd433598465665d76876cb3e4a6f3e857823f36a32c543a","strict":true} name: "Developer Documentation Consolidator" "on": @@ -140,7 +141,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, create_pull_request, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, create_pull_request, missing_tool, missing_data, noop GH_AW_PROMPT_EOF cat "/opt/gh-aw/prompts/safe_outputs_create_pull_request.md" cat << 'GH_AW_PROMPT_EOF' @@ -178,6 +179,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -407,7 +411,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":168,"max":1},"create_pull_request":{"expires":48,"max":1,"title_prefix":"[docs] "},"missing_data":{},"missing_tool":{},"noop":{"max":1},"push_repo_memory":{"memories":[{"dir":"/tmp/gh-aw/repo-memory/default","id":"default","max_file_count":100,"max_file_size":10240,"max_patch_size":10240}]}} + {"close_discussion":{"max":10},"create_discussion":{"expires":168,"max":1},"create_pull_request":{"expires":48,"max":1,"title_prefix":"[docs] "},"missing_data":{},"missing_tool":{},"noop":{"max":1},"push_repo_memory":{"memories":[{"dir":"/tmp/gh-aw/repo-memory/default","id":"default","max_file_count":100,"max_file_size":10240,"max_patch_size":10240}]}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -447,6 +451,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Create a new GitHub pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created. Title will be prefixed with \"[docs] \". Labels [\"documentation\" \"automation\"] will be automatically added.", "inputSchema": { @@ -608,6 +654,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1646,7 +1719,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,anthropic.com,api.anthropic.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,playwright.download.prss.microsoft.com,ppa.launchpad.net,pypi.org,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,statsig.anthropic.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":168,\"fallback_to_issue\":true,\"max\":1},\"create_pull_request\":{\"draft\":false,\"expires\":48,\"labels\":[\"documentation\",\"automation\"],\"max\":1,\"max_patch_size\":1024,\"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\",\"CLAUDE.md\"],\"protected_path_prefixes\":[\".github/\",\".agents/\",\".claude/\"],\"title_prefix\":\"[docs] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":168,\"fallback_to_issue\":true,\"max\":1},\"create_pull_request\":{\"draft\":false,\"expires\":48,\"labels\":[\"documentation\",\"automation\"],\"max\":1,\"max_patch_size\":1024,\"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\",\"CLAUDE.md\"],\"protected_path_prefixes\":[\".github/\",\".agents/\",\".claude/\"],\"title_prefix\":\"[docs] \"},\"missing_data\":{},\"missing_tool\":{}}" 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/developer-docs-consolidator.md b/.github/workflows/developer-docs-consolidator.md index 309ae6ac76b..4bef4453175 100644 --- a/.github/workflows/developer-docs-consolidator.md +++ b/.github/workflows/developer-docs-consolidator.md @@ -22,10 +22,6 @@ network: - github safe-outputs: - create-discussion: - category: "audits" - max: 1 - close-older-discussions: true create-pull-request: expires: 2d title-prefix: "[docs] " @@ -52,6 +48,7 @@ tools: timeout-minutes: 30 imports: + - shared/daily-audit-discussion.md - shared/reporting.md - shared/mcp/serena-go.md - shared/mcp/qmd-docs.md diff --git a/.github/workflows/docs-noob-tester.lock.yml b/.github/workflows/docs-noob-tester.lock.yml index b3cbc60c27a..b8d3ef87f27 100644 --- a/.github/workflows/docs-noob-tester.lock.yml +++ b/.github/workflows/docs-noob-tester.lock.yml @@ -25,10 +25,11 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/docs-server-lifecycle.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"67d7121754cd87f039eff5782dd31356426aed9c72c09881a79957f3ab7b9580","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"a6cd6eb950ddf376ae429f913c30f3b7ceb1f829bbec3558a74452cf34531b08","strict":true} name: "Documentation Noob Tester" "on": @@ -132,7 +133,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, upload_asset, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, upload_asset, missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). @@ -169,6 +170,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/docs-server-lifecycle.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -338,7 +342,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"upload_asset":{"max":0}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"upload_asset":{"max":0}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -378,6 +382,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Upload a file as a URL-addressable asset that can be referenced in issues, PRs, or comments. The file is stored on an orphaned git branch and returns a permanent URL. Use this for images, diagrams, or other files that need to be embedded in GitHub content. CONSTRAINTS: Maximum file size: 10240KB. Allowed file extensions: [.png .jpg .jpeg].", "inputSchema": { @@ -500,6 +546,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1176,7 +1249,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.jsr.io,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,bun.sh,cdn.jsdelivr.net,cdn.playwright.dev,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,deb.nodesource.com,deno.land,esm.sh,get.pnpm.io,github.com,googleapis.deno.dev,googlechromelabs.github.io,host.docker.internal,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,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,playwright.download.prss.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,storage.googleapis.com,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.npmjs.com,www.npmjs.org,yarnpkg.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/docs-noob-tester.md b/.github/workflows/docs-noob-tester.md index ca9484595da..7350160254c 100644 --- a/.github/workflows/docs-noob-tester.md +++ b/.github/workflows/docs-noob-tester.md @@ -19,8 +19,6 @@ safe-outputs: upload-asset: create-discussion: expires: 1d - category: "audits" - close-older-discussions: true network: allowed: @@ -28,6 +26,7 @@ network: - node imports: + - shared/daily-audit-discussion.md - shared/docs-server-lifecycle.md - shared/reporting.md features: diff --git a/.github/workflows/example-workflow-analyzer.lock.yml b/.github/workflows/example-workflow-analyzer.lock.yml index e4770ddae6e..0fcb8548934 100644 --- a/.github/workflows/example-workflow-analyzer.lock.yml +++ b/.github/workflows/example-workflow-analyzer.lock.yml @@ -25,9 +25,10 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"b2b481f42784eb25bc36cfd587b8b96ac047f581e1d27b81d4f1563711bb420c","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"6e719f62ef8c7f3974467aa95b5893612d90f8a50eedbbd2268ee5f44c3b96bb","strict":true} name: "Weekly Workflow Analysis" "on": @@ -136,7 +137,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -171,6 +172,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -391,7 +395,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -431,6 +435,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -528,6 +574,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1234,7 +1307,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,anthropic.com,api.anthropic.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,playwright.download.prss.microsoft.com,ppa.launchpad.net,pypi.org,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,statsig.anthropic.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[workflow-analysis] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[workflow-analysis] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/example-workflow-analyzer.md b/.github/workflows/example-workflow-analyzer.md index d975ccccfd5..ccd85c4ca6e 100644 --- a/.github/workflows/example-workflow-analyzer.md +++ b/.github/workflows/example-workflow-analyzer.md @@ -17,10 +17,9 @@ safe-outputs: create-discussion: expires: 1d title-prefix: "[workflow-analysis] " - category: "audits" - close-older-discussions: true timeout-minutes: 10 imports: + - shared/daily-audit-discussion.md - shared/reporting.md --- diff --git a/.github/workflows/firewall-escape.lock.yml b/.github/workflows/firewall-escape.lock.yml index 8bea34fba32..8b6bac3eaea 100644 --- a/.github/workflows/firewall-escape.lock.yml +++ b/.github/workflows/firewall-escape.lock.yml @@ -23,7 +23,11 @@ # # Security testing to find escape paths in the AWF (Agent Workflow Firewall) # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"74e501e0d13e7e5a3b2d21418bc8460f5c0023998ac599caa303fec99234b69e","strict":true} +# Resolved workflow manifest: +# Imports: +# - shared/daily-audit-discussion.md +# +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"93dc6fdbeecb751253d74d734c95367e53805c9a60670ad8e58948331ee851a7","strict":true} name: "The Great Escapi" "on": @@ -151,7 +155,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -186,6 +190,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/firewall-escape.md}} GH_AW_PROMPT_EOF } > "$GH_AW_PROMPT" @@ -388,7 +395,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"push_repo_memory":{"memories":[{"dir":"/tmp/gh-aw/repo-memory/default","id":"default","max_file_count":50,"max_file_size":524288,"max_patch_size":10240}]}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"push_repo_memory":{"memories":[{"dir":"/tmp/gh-aw/repo-memory/default","id":"default","max_file_count":50,"max_file_size":524288,"max_patch_size":10240}]}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -428,6 +435,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -540,6 +589,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1344,7 +1420,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.jsr.io,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,bun.sh,cdn.jsdelivr.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,deb.nodesource.com,deno.land,esm.sh,get.pnpm.io,github.com,googleapis.deno.dev,googlechromelabs.github.io,host.docker.internal,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,storage.googleapis.com,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.npmjs.com,www.npmjs.org,yarnpkg.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[Firewall Escape] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[Firewall Escape] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/firewall-escape.md b/.github/workflows/firewall-escape.md index 44875827c69..39941b81017 100644 --- a/.github/workflows/firewall-escape.md +++ b/.github/workflows/firewall-escape.md @@ -35,9 +35,7 @@ sandbox: safe-outputs: create-discussion: expires: 1d - category: "audits" title-prefix: "[Firewall Escape] " - max: 1 tools: github: @@ -84,6 +82,8 @@ jobs: }); features: copilot-requests: true +imports: + - shared/daily-audit-discussion.md --- # The Great Escapi diff --git a/.github/workflows/github-mcp-structural-analysis.lock.yml b/.github/workflows/github-mcp-structural-analysis.lock.yml index a49758bcc40..04318de0971 100644 --- a/.github/workflows/github-mcp-structural-analysis.lock.yml +++ b/.github/workflows/github-mcp-structural-analysis.lock.yml @@ -25,10 +25,11 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/python-dataviz.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"bae501e108ec9d6346e7e1686373396ef4828d5e532005db44bde88081d0ea79","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"a268a6981037d56b4b3fe8f9758e76aca05f4509443196021afa7811561248d5","strict":true} name: "GitHub MCP Structural Analysis" "on": @@ -137,7 +138,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, upload_asset, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, upload_asset, missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). @@ -174,6 +175,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/python-dataviz.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -386,7 +390,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"upload_asset":{"max":0}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"upload_asset":{"max":0}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -426,6 +430,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Upload a file as a URL-addressable asset that can be referenced in issues, PRs, or comments. The file is stored on an orphaned git branch and returns a permanent URL. Use this for images, diagrams, or other files that need to be embedded in GitHub content. CONSTRAINTS: Maximum file size: 10240KB. Allowed file extensions: [.png .jpg .jpeg].", "inputSchema": { @@ -548,6 +594,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1278,7 +1351,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.pythonhosted.org,anaconda.org,anthropic.com,api.anthropic.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,cdn.playwright.dev,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,host.docker.internal,index.crates.io,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,playwright.download.prss.microsoft.com,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,static.crates.io,statsig.anthropic.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[mcp-analysis] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[mcp-analysis] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/github-mcp-structural-analysis.md b/.github/workflows/github-mcp-structural-analysis.md index 31328a90a87..778a40332de 100644 --- a/.github/workflows/github-mcp-structural-analysis.md +++ b/.github/workflows/github-mcp-structural-analysis.md @@ -24,11 +24,9 @@ tools: safe-outputs: create-discussion: expires: 1d - category: "audits" title-prefix: "[mcp-analysis] " - max: 1 - close-older-discussions: true imports: + - shared/daily-audit-discussion.md - shared/python-dataviz.md - shared/reporting.md --- diff --git a/.github/workflows/github-mcp-tools-report.lock.yml b/.github/workflows/github-mcp-tools-report.lock.yml index 1eba3bc8926..be6e9e1e3b0 100644 --- a/.github/workflows/github-mcp-tools-report.lock.yml +++ b/.github/workflows/github-mcp-tools-report.lock.yml @@ -25,9 +25,10 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"4dfbb7c20c8c63aa5741b2465985b3e579cc02728ba2187d3a28a8f548d39d2c","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"191564471b96ff9b0aae2962a207b399f2a3cc626230de18bb914d3ae61887d4","strict":true} name: "GitHub MCP Remote Server Tools Report Generator" "on": @@ -137,7 +138,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, create_pull_request, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, create_pull_request, missing_tool, missing_data, noop GH_AW_PROMPT_EOF cat "/opt/gh-aw/prompts/safe_outputs_create_pull_request.md" cat << 'GH_AW_PROMPT_EOF' @@ -175,6 +176,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -360,7 +364,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":168,"max":1},"create_pull_request":{"expires":48,"max":1,"reviewers":["copilot"],"title_prefix":"[mcp-tools] "},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":168,"max":1},"create_pull_request":{"expires":48,"max":1,"reviewers":["copilot"],"title_prefix":"[mcp-tools] "},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -400,6 +404,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Create a new GitHub pull request to propose code changes. Use this after making file edits to submit them for review and merging. The PR will be created from the current branch with your committed changes. For code review comments on an existing PR, use create_pull_request_review_comment instead. CONSTRAINTS: Maximum 1 pull request(s) can be created. Title will be prefixed with \"[mcp-tools] \". Labels [\"documentation\" \"automation\"] will be automatically added. Reviewers [\"copilot\"] will be assigned.", "inputSchema": { @@ -546,6 +592,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1338,7 +1411,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,anthropic.com,api.anthropic.com,api.github.com,api.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,playwright.download.prss.microsoft.com,ppa.launchpad.net,pypi.org,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,statsig.anthropic.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":168,\"fallback_to_issue\":true,\"max\":1},\"create_pull_request\":{\"draft\":false,\"expires\":48,\"labels\":[\"documentation\",\"automation\"],\"max\":1,\"max_patch_size\":1024,\"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\",\"CLAUDE.md\"],\"protected_path_prefixes\":[\".github/\",\".agents/\",\".claude/\"],\"reviewers\":[\"copilot\"],\"title_prefix\":\"[mcp-tools] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":168,\"fallback_to_issue\":true,\"max\":1},\"create_pull_request\":{\"draft\":false,\"expires\":48,\"labels\":[\"documentation\",\"automation\"],\"max\":1,\"max_patch_size\":1024,\"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\",\"CLAUDE.md\"],\"protected_path_prefixes\":[\".github/\",\".agents/\",\".claude/\"],\"reviewers\":[\"copilot\"],\"title_prefix\":\"[mcp-tools] \"},\"missing_data\":{},\"missing_tool\":{}}" 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/github-mcp-tools-report.md b/.github/workflows/github-mcp-tools-report.md index 14510797b0b..2f141a10bea 100644 --- a/.github/workflows/github-mcp-tools-report.md +++ b/.github/workflows/github-mcp-tools-report.md @@ -18,10 +18,6 @@ tools: cache-memory: true edit: safe-outputs: - create-discussion: - category: "audits" - max: 1 - close-older-discussions: true create-pull-request: expires: 2d title-prefix: "[mcp-tools] " @@ -30,6 +26,7 @@ safe-outputs: draft: false timeout-minutes: 15 imports: + - shared/daily-audit-discussion.md - shared/reporting.md --- diff --git a/.github/workflows/github-remote-mcp-auth-test.lock.yml b/.github/workflows/github-remote-mcp-auth-test.lock.yml index 05f761aa9ec..d3cda5ba886 100644 --- a/.github/workflows/github-remote-mcp-auth-test.lock.yml +++ b/.github/workflows/github-remote-mcp-auth-test.lock.yml @@ -23,7 +23,11 @@ # # Daily test of GitHub remote MCP authentication with GitHub Actions token # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"db9f3ebc997b550ea21426bffe49626f5370c470f814cac5e5846ac09231c0c4","strict":true} +# Resolved workflow manifest: +# Imports: +# - shared/daily-audit-discussion.md +# +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"f26eb872ab2016584fe4f0bb9d3b862c74e9c1c3ee88beed81de73f27ccc6316","strict":true} name: "GitHub Remote MCP Authentication Test" "on": @@ -133,7 +137,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -168,6 +172,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/github-remote-mcp-auth-test.md}} GH_AW_PROMPT_EOF } > "$GH_AW_PROMPT" @@ -333,7 +340,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -373,6 +380,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -470,6 +519,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1123,7 +1199,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[auth-test] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[auth-test] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/github-remote-mcp-auth-test.md b/.github/workflows/github-remote-mcp-auth-test.md index 9d28b1eb7eb..98f0024b591 100644 --- a/.github/workflows/github-remote-mcp-auth-test.md +++ b/.github/workflows/github-remote-mcp-auth-test.md @@ -19,11 +19,10 @@ safe-outputs: create-discussion: expires: 1d title-prefix: "[auth-test] " - category: "audits" - max: 1 - close-older-discussions: true timeout-minutes: 5 strict: true +imports: + - shared/daily-audit-discussion.md --- # GitHub Remote MCP Authentication Test diff --git a/.github/workflows/go-fan.lock.yml b/.github/workflows/go-fan.lock.yml index 1a448b4ee18..3d4d9a3f1b8 100644 --- a/.github/workflows/go-fan.lock.yml +++ b/.github/workflows/go-fan.lock.yml @@ -25,10 +25,11 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/mcp/serena-go.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"3ca391548ba08c8a271413f4cf5a5ec319865e7da8f0a921a2d070743534688d","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"7d60d67a3747821c28c93fc1a4fc8727b264234b3759abb0b0daccc70997f5bf","strict":true} name: "Go Fan" "on": @@ -137,7 +138,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -172,6 +173,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -360,7 +364,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -400,6 +404,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -497,6 +543,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1241,7 +1314,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,anthropic.com,api.anthropic.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,goproxy.io,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkg.go.dev,playwright.download.prss.microsoft.com,ppa.launchpad.net,proxy.golang.org,pypi.org,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,statsig.anthropic.com,storage.googleapis.com,sum.golang.org,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[go-fan] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[go-fan] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/go-fan.md b/.github/workflows/go-fan.md index f8759cce00e..8c0fb4e0fff 100644 --- a/.github/workflows/go-fan.md +++ b/.github/workflows/go-fan.md @@ -23,6 +23,7 @@ network: - go imports: + - shared/daily-audit-discussion.md - shared/reporting.md - shared/mcp/serena-go.md @@ -30,9 +31,6 @@ safe-outputs: create-discussion: expires: 1d title-prefix: "[go-fan] " - category: "audits" - max: 1 - close-older-discussions: true tools: cache-memory: true diff --git a/.github/workflows/issue-arborist.lock.yml b/.github/workflows/issue-arborist.lock.yml index e72e4cbc79f..7eb4701b7a3 100644 --- a/.github/workflows/issue-arborist.lock.yml +++ b/.github/workflows/issue-arborist.lock.yml @@ -25,10 +25,11 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/jqschema.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"62b23a3c0dede758b81863caa7459cae020a40572108751686b33bc53ff6355f","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"b8714ef4ccc5d2c100f5ee19da9c2622944dcd088d8cabf9df2a7c57ebaf09ee","strict":true} name: "Issue Arborist" "on": @@ -141,7 +142,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_issue, create_discussion, link_sub_issue, missing_tool, missing_data, noop + Tools: create_issue, create_discussion, close_discussion, link_sub_issue, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -176,6 +177,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/jqschema.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -342,7 +346,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"create_issue":{"expires":48,"group":true,"max":5},"link_sub_issue":{"max":50},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"create_issue":{"expires":48,"group":true,"max":5},"link_sub_issue":{"max":50},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -431,6 +435,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -564,6 +610,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1239,7 +1312,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,172.30.0.1,api.openai.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.githubassets.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,openai.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,s.symcb.com,s.symcd.com,security.ubuntu.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[Issue Arborist] \"},\"create_issue\":{\"expires\":48,\"group\":true,\"max\":5,\"title_prefix\":\"[Parent] \"},\"link_sub_issue\":{\"max\":50},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[Issue Arborist] \"},\"create_issue\":{\"expires\":48,\"group\":true,\"max\":5,\"title_prefix\":\"[Parent] \"},\"link_sub_issue\":{\"max\":50},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/issue-arborist.md b/.github/workflows/issue-arborist.md index 9729cce6254..ae32ab8dd23 100644 --- a/.github/workflows/issue-arborist.md +++ b/.github/workflows/issue-arborist.md @@ -14,6 +14,7 @@ network: - defaults - github imports: + - shared/daily-audit-discussion.md - shared/jqschema.md - shared/reporting.md tools: @@ -65,8 +66,6 @@ safe-outputs: create-discussion: expires: 1d title-prefix: "[Issue Arborist] " - category: "audits" - close-older-discussions: true timeout-minutes: 15 --- diff --git a/.github/workflows/lockfile-stats.lock.yml b/.github/workflows/lockfile-stats.lock.yml index d1756a8ea80..c6a5fb3281c 100644 --- a/.github/workflows/lockfile-stats.lock.yml +++ b/.github/workflows/lockfile-stats.lock.yml @@ -25,9 +25,10 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"8e7c90b156e9a9c5a415792db7e51dd31799eb95a17d36b2034ccb3ceb3d71d6","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"cb47c1df37524b9b2e754ff70942f13d6784704c82721ace21413e146324cd35","strict":true} name: "Lockfile Statistics Analysis Agent" "on": @@ -137,7 +138,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -172,6 +173,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -354,7 +358,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -394,6 +398,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -491,6 +537,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1196,7 +1269,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,anthropic.com,api.anthropic.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,playwright.download.prss.microsoft.com,ppa.launchpad.net,pypi.org,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,statsig.anthropic.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/lockfile-stats.md b/.github/workflows/lockfile-stats.md index 9fd46dc99f6..8781e3e4db2 100644 --- a/.github/workflows/lockfile-stats.md +++ b/.github/workflows/lockfile-stats.md @@ -14,12 +14,10 @@ tools: safe-outputs: create-discussion: expires: 1d - category: "audits" - max: 1 - close-older-discussions: true timeout-minutes: 15 strict: true imports: + - shared/daily-audit-discussion.md - shared/reporting.md --- diff --git a/.github/workflows/mcp-inspector.lock.yml b/.github/workflows/mcp-inspector.lock.yml index 7075c7aa195..6fef344f742 100644 --- a/.github/workflows/mcp-inspector.lock.yml +++ b/.github/workflows/mcp-inspector.lock.yml @@ -25,6 +25,7 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/mcp/arxiv.md # - shared/mcp/ast-grep.md # - shared/mcp/brave.md @@ -42,7 +43,7 @@ # - shared/mcp/tavily.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"e92fc7f19a13329f2f521f2c3ade949e9a30c1bd31c9752c012a660be935c8a8"} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"607e02c37f9b8b343118aaf03e3d520f6d5a5f64a56a7f2bad64d3637dcea585"} name: "MCP Inspector Agent" "on": @@ -152,7 +153,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -187,6 +188,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/mcp/arxiv.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -477,7 +481,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"notion-add-comment":{"description":"Add a comment to a Notion page","inputs":{"comment":{"default":null,"description":"The comment text to add","required":true,"type":"string"}},"output":"Comment added to Notion successfully!"},"post-to-slack-channel":{"description":"Post a message to a Slack channel. Message must be 200 characters or less. Supports basic Slack markdown: *bold*, _italic_, ~strike~, `code`, ```code block```, \u003equote, and links \u003curl|text\u003e. Requires GH_AW_SLACK_CHANNEL_ID environment variable to be set.","inputs":{"message":{"default":null,"description":"The message to post (max 200 characters, supports Slack markdown)","required":true,"type":"string"}},"output":"Message posted to Slack successfully!"}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"notion-add-comment":{"description":"Add a comment to a Notion page","inputs":{"comment":{"default":null,"description":"The comment text to add","required":true,"type":"string"}},"output":"Comment added to Notion successfully!"},"post-to-slack-channel":{"description":"Post a message to a Slack channel. Message must be 200 characters or less. Supports basic Slack markdown: *bold*, _italic_, ~strike~, `code`, ```code block```, \u003equote, and links \u003curl|text\u003e. Requires GH_AW_SLACK_CHANNEL_ID environment variable to be set.","inputs":{"message":{"default":null,"description":"The message to post (max 200 characters, supports Slack markdown)","required":true,"type":"string"}},"output":"Message posted to Slack successfully!"}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -517,6 +521,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -648,6 +694,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1800,7 +1873,7 @@ jobs: GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} GH_AW_SAFE_OUTPUT_JOBS: "{\"notion_add_comment\":\"\",\"post_to_slack_channel\":\"\"}" - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/mcp-inspector.md b/.github/workflows/mcp-inspector.md index 2699481d118..dd2feef42fc 100644 --- a/.github/workflows/mcp-inspector.md +++ b/.github/workflows/mcp-inspector.md @@ -21,12 +21,10 @@ sandbox: safe-outputs: create-discussion: expires: 1d - category: "audits" - max: 1 - close-older-discussions: true timeout-minutes: 20 strict: false imports: + - shared/daily-audit-discussion.md - shared/mcp/arxiv.md - shared/mcp/ast-grep.md # Note: azure.md excluded due to schema validation issue with entrypointArgs diff --git a/.github/workflows/portfolio-analyst.lock.yml b/.github/workflows/portfolio-analyst.lock.yml index 31cec5bea8f..5f857c6a92d 100644 --- a/.github/workflows/portfolio-analyst.lock.yml +++ b/.github/workflows/portfolio-analyst.lock.yml @@ -25,11 +25,12 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/jqschema.md # - shared/reporting.md # - shared/trending-charts-simple.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"e7935e168ae0e6f7257077dd33ddb274861679adccbf323280cef1efa3759fee","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"827c27451769f3cbc00cd84c01ca62bccb9d9010d0bb96fd121171b87195232b","strict":true} name: "Automated Portfolio Analyst" "on": @@ -139,7 +140,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, upload_asset, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, upload_asset, missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). @@ -176,6 +177,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -448,7 +452,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"upload_asset":{"max":0}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"upload_asset":{"max":0}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -488,6 +492,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Upload a file as a URL-addressable asset that can be referenced in issues, PRs, or comments. The file is stored on an orphaned git branch and returns a permanent URL. Use this for images, diagrams, or other files that need to be embedded in GitHub content. CONSTRAINTS: Maximum file size: 10240KB. Allowed file extensions: [.png .jpg .jpeg].", "inputSchema": { @@ -610,6 +656,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1303,7 +1376,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,github.com,host.docker.internal,index.crates.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,pip.pypa.io,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,s.symcb.com,s.symcd.com,security.ubuntu.com,static.crates.io,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[portfolio] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[portfolio] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/portfolio-analyst.md b/.github/workflows/portfolio-analyst.md index c107c7f50ef..6d7140c56f9 100644 --- a/.github/workflows/portfolio-analyst.md +++ b/.github/workflows/portfolio-analyst.md @@ -28,11 +28,10 @@ safe-outputs: create-discussion: expires: 1d title-prefix: "[portfolio] " - category: "audits" - close-older-discussions: true upload-asset: timeout-minutes: 20 imports: + - shared/daily-audit-discussion.md - shared/reporting.md - shared/jqschema.md - shared/trending-charts-simple.md diff --git a/.github/workflows/pr-nitpick-reviewer.lock.yml b/.github/workflows/pr-nitpick-reviewer.lock.yml index 4e694b100ff..6a2bc2dfc13 100644 --- a/.github/workflows/pr-nitpick-reviewer.lock.yml +++ b/.github/workflows/pr-nitpick-reviewer.lock.yml @@ -25,9 +25,10 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"02499e8cdb83ed473b50353b2f91edd95d5c962027fc11a8aaf5b11e67096427","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"1955c6bb1f6ae42bf6948755db45182aa19879c0e54df176eb5d8e8186b4d3ef","strict":true} name: "PR Nitpick Reviewer 🔍" "on": @@ -201,7 +202,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, create_pull_request_review_comment, submit_pull_request_review, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, create_pull_request_review_comment, submit_pull_request_review, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -239,6 +240,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -428,7 +432,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"create_pull_request_review_comment":{"max":10},"missing_data":{},"missing_tool":{},"noop":{"max":1},"submit_pull_request_review":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"create_pull_request_review_comment":{"max":10},"missing_data":{},"missing_tool":{},"noop":{"max":1},"submit_pull_request_review":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -468,6 +472,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Create a review comment on a specific line of code in a pull request. Use this for inline code review feedback, suggestions, or questions about specific code changes. For general PR comments not tied to specific lines, use add_comment instead. When the workflow is configured with `target: \"*\"`, you must specify `pull_request_number` to indicate which PR to target. CONSTRAINTS: Maximum 10 review comment(s) can be created. Comments will be on the RIGHT side of the diff.", "inputSchema": { @@ -660,6 +706,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1423,7 +1496,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[nitpick-report] \"},\"create_pull_request_review_comment\":{\"max\":10,\"side\":\"RIGHT\"},\"missing_data\":{},\"missing_tool\":{},\"submit_pull_request_review\":{\"max\":1}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[nitpick-report] \"},\"create_pull_request_review_comment\":{\"max\":10,\"side\":\"RIGHT\"},\"missing_data\":{},\"missing_tool\":{},\"submit_pull_request_review\":{\"max\":1}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/pr-nitpick-reviewer.md b/.github/workflows/pr-nitpick-reviewer.md index b07eed1b353..babca002809 100644 --- a/.github/workflows/pr-nitpick-reviewer.md +++ b/.github/workflows/pr-nitpick-reviewer.md @@ -15,8 +15,6 @@ safe-outputs: create-discussion: expires: 1d title-prefix: "[nitpick-report] " - category: "audits" - max: 1 create-pull-request-review-comment: max: 10 side: "RIGHT" @@ -29,6 +27,7 @@ safe-outputs: run-failure: "🔬 Lens cracked! [{workflow_name}]({run_url}) {status}. Some nitpicks remain undetected..." timeout-minutes: 15 imports: + - shared/daily-audit-discussion.md - shared/reporting.md --- diff --git a/.github/workflows/prompt-clustering-analysis.lock.yml b/.github/workflows/prompt-clustering-analysis.lock.yml index aa0092a8693..c493f1500c7 100644 --- a/.github/workflows/prompt-clustering-analysis.lock.yml +++ b/.github/workflows/prompt-clustering-analysis.lock.yml @@ -26,11 +26,12 @@ # Resolved workflow manifest: # Imports: # - shared/copilot-pr-data-fetch.md +# - shared/daily-audit-discussion.md # - shared/jqschema.md # - shared/reporting.md # - shared/trending-charts-simple.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"711d989f13320ca6c9165974764c245b845badcef5a8e6cd3b6ec8ee0373b2db","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"135fecd1b65e5779d4426d1e44fffc5aae3cb44986dc28b3136a7e5634c7908e","strict":true} name: "Copilot Agent Prompt Clustering Analysis" "on": @@ -142,7 +143,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -177,6 +178,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/jqschema.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -473,7 +477,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -513,6 +517,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -610,6 +656,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1327,7 +1400,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,*.pythonhosted.org,anaconda.org,anthropic.com,api.anthropic.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,cdn.playwright.dev,codeload.github.com,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,host.docker.internal,index.crates.io,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,playwright.download.prss.microsoft.com,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.npmjs.org,repo.anaconda.com,repo.continuum.io,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,static.crates.io,statsig.anthropic.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[prompt-clustering] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[prompt-clustering] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/prompt-clustering-analysis.md b/.github/workflows/prompt-clustering-analysis.md index e4cde4585eb..12dd609e01c 100644 --- a/.github/workflows/prompt-clustering-analysis.md +++ b/.github/workflows/prompt-clustering-analysis.md @@ -23,11 +23,9 @@ safe-outputs: create-discussion: expires: 1d title-prefix: "[prompt-clustering] " - category: "audits" - max: 1 - close-older-discussions: true imports: + - shared/daily-audit-discussion.md - shared/jqschema.md - shared/reporting.md - shared/copilot-pr-data-fetch.md diff --git a/.github/workflows/repo-audit-analyzer.lock.yml b/.github/workflows/repo-audit-analyzer.lock.yml index 91d929a6586..22fea13c5a1 100644 --- a/.github/workflows/repo-audit-analyzer.lock.yml +++ b/.github/workflows/repo-audit-analyzer.lock.yml @@ -25,9 +25,10 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"83f67c7db0b6f9679570e272c311a7239fa2f9444319c2bf3b86710a3cdaa6ec","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"4ea98cb3b241347b3e435dbda3936aded051da67245ceda7a4c29920d09d8a9a","strict":true} name: "Repository Audit & Agentic Workflow Opportunity Analyzer" "on": @@ -141,7 +142,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -176,6 +177,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -358,7 +362,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"create_missing_tool_issue":{"labels":["cookie"],"max":1,"title_prefix":"[missing tool]"},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"create_missing_tool_issue":{"labels":["cookie"],"max":1,"title_prefix":"[missing tool]"},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -398,6 +402,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -495,6 +541,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1148,7 +1221,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/repo-audit-analyzer.md b/.github/workflows/repo-audit-analyzer.md index 62417693a9d..ed2594450ce 100644 --- a/.github/workflows/repo-audit-analyzer.md +++ b/.github/workflows/repo-audit-analyzer.md @@ -24,15 +24,13 @@ tools: safe-outputs: create-discussion: expires: 1d - category: "audits" - max: 1 - close-older-discussions: true missing-tool: create-issue: true labels: [cookie] timeout-minutes: 45 strict: true imports: + - shared/daily-audit-discussion.md - shared/reporting.md --- diff --git a/.github/workflows/repository-quality-improver.lock.yml b/.github/workflows/repository-quality-improver.lock.yml index b531c2d0950..74da227d56c 100644 --- a/.github/workflows/repository-quality-improver.lock.yml +++ b/.github/workflows/repository-quality-improver.lock.yml @@ -25,10 +25,11 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/mcp/serena-go.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"6bb1a0d4a4a46eebdfbddfe915d6345a17575dd0489817be13e208c9921460da","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"c97b39f61bffe2d2d9f833d1b2c35bc0c7ba1587a697ebf14af904d398bd9e22","strict":true} name: "Repository Quality Improvement Agent" "on": @@ -137,7 +138,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -172,6 +173,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -357,7 +361,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -397,6 +401,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -494,6 +540,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1152,7 +1225,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/repository-quality-improver.md b/.github/workflows/repository-quality-improver.md index 6bae0914ea4..4d8c6eb08e7 100644 --- a/.github/workflows/repository-quality-improver.md +++ b/.github/workflows/repository-quality-improver.md @@ -11,6 +11,7 @@ permissions: pull-requests: read engine: copilot imports: + - shared/daily-audit-discussion.md - shared/reporting.md - shared/mcp/serena-go.md tools: @@ -25,9 +26,6 @@ tools: safe-outputs: create-discussion: expires: 1d - category: "audits" - max: 1 - close-older-discussions: true timeout-minutes: 20 strict: true diff --git a/.github/workflows/safe-output-health.lock.yml b/.github/workflows/safe-output-health.lock.yml index 35f9f527066..b095b9a89e5 100644 --- a/.github/workflows/safe-output-health.lock.yml +++ b/.github/workflows/safe-output-health.lock.yml @@ -25,10 +25,11 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/jqschema.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"00020e00cf1cd2251ab99ac78f281500ee26b1c69695f71ec416769285c291a9","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"a65a1bce3159397fe4905898e02b4df8413befa79bc05b1dc3384d957132310d","strict":true} name: "Safe Output Health Monitor" "on": @@ -138,7 +139,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -173,6 +174,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/jqschema.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -420,7 +424,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -460,6 +464,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -557,6 +603,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1289,7 +1362,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,anthropic.com,api.anthropic.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,playwright.download.prss.microsoft.com,ppa.launchpad.net,pypi.org,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,statsig.anthropic.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/safe-output-health.md b/.github/workflows/safe-output-health.md index 6f663abde2c..38bc3ea2864 100644 --- a/.github/workflows/safe-output-health.md +++ b/.github/workflows/safe-output-health.md @@ -21,12 +21,10 @@ steps: safe-outputs: create-discussion: expires: 1d - category: "audits" - max: 1 - close-older-discussions: true timeout-minutes: 30 strict: true imports: + - shared/daily-audit-discussion.md - shared/jqschema.md - shared/reporting.md --- diff --git a/.github/workflows/schema-consistency-checker.lock.yml b/.github/workflows/schema-consistency-checker.lock.yml index b5a9e11b9ee..1ffb237bb6a 100644 --- a/.github/workflows/schema-consistency-checker.lock.yml +++ b/.github/workflows/schema-consistency-checker.lock.yml @@ -25,9 +25,10 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"7cb844c9c9c32229b2755637af132ad41de3ddbda8eff01a2f5a5f753fb303a6","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"927d3f9868166e9bef338a1cb6610de8dff953ff5b911813f58cd731e674df3f","strict":true} name: "Schema Consistency Checker" "on": @@ -137,7 +138,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -172,6 +173,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -354,7 +358,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -394,6 +398,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -491,6 +537,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1196,7 +1269,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,anthropic.com,api.anthropic.com,api.github.com,api.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,playwright.download.prss.microsoft.com,ppa.launchpad.net,pypi.org,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,statsig.anthropic.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[Schema Consistency] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[Schema Consistency] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/schema-consistency-checker.md b/.github/workflows/schema-consistency-checker.md index 80a5e80c2c1..9961288059e 100644 --- a/.github/workflows/schema-consistency-checker.md +++ b/.github/workflows/schema-consistency-checker.md @@ -20,12 +20,10 @@ tools: safe-outputs: create-discussion: expires: 1d - category: "audits" title-prefix: "[Schema Consistency] " - max: 1 - close-older-discussions: true timeout-minutes: 30 imports: + - shared/daily-audit-discussion.md - shared/reporting.md --- diff --git a/.github/workflows/sergo.lock.yml b/.github/workflows/sergo.lock.yml index 24868a8e7ca..b4b7760e80a 100644 --- a/.github/workflows/sergo.lock.yml +++ b/.github/workflows/sergo.lock.yml @@ -25,10 +25,11 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/mcp/serena-go.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"02bf772df769e1b8dcee8170592780e7f1203860768210b7bf353632372b9d86","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"ffdf8880058e622435f10f1a41e0a416617d901e8e579cb2747ef567e63717d9","strict":true} name: "Sergo - Serena Go Expert" "on": @@ -138,7 +139,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -173,6 +174,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -360,7 +364,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -400,6 +404,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -497,6 +543,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1240,7 +1313,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,anthropic.com,api.anthropic.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,github.githubassets.com,go.dev,golang.org,goproxy.io,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pkg.go.dev,playwright.download.prss.microsoft.com,ppa.launchpad.net,proxy.golang.org,pypi.org,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,statsig.anthropic.com,storage.googleapis.com,sum.golang.org,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[sergo] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[sergo] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/sergo.md b/.github/workflows/sergo.md index edc3f9c09b4..eb79198ca5d 100644 --- a/.github/workflows/sergo.md +++ b/.github/workflows/sergo.md @@ -22,6 +22,7 @@ network: - go imports: + - shared/daily-audit-discussion.md - shared/reporting.md - shared/mcp/serena-go.md @@ -29,9 +30,6 @@ safe-outputs: create-discussion: expires: 1d title-prefix: "[sergo] " - category: "audits" - max: 1 - close-older-discussions: true tools: cache-memory: true diff --git a/.github/workflows/shared/daily-audit-discussion.md b/.github/workflows/shared/daily-audit-discussion.md new file mode 100644 index 00000000000..881d9c672ff --- /dev/null +++ b/.github/workflows/shared/daily-audit-discussion.md @@ -0,0 +1,45 @@ +--- +# Daily Audit Discussion — shared safe-output base configuration +# +# Usage: +# imports: +# - shared/daily-audit-discussion.md +# +# This component provides the standard safe-output configuration used by daily/weekly +# audit and reporting workflows that publish a discussion in the "audits" category: +# - create-discussion: category "audits", max 1, close-older-discussions +# - close-discussion: max 10 +# +# Each importing workflow keeps only its workflow-specific settings inline. +# Because create-discussion uses field-level merging, any field that is NOT set +# in the workflow's own safe-outputs block is automatically filled from this component. +# Fields typically kept per-workflow: title-prefix and expires. +# +# Example — workflow-specific block after importing: +# safe-outputs: +# create-discussion: +# title-prefix: "[my-workflow] " +# expires: 3d + +safe-outputs: + create-discussion: + category: "audits" + max: 1 + close-older-discussions: true + close-discussion: + max: 10 +--- + +## Audit Discussion Output + +Create a new discussion in the `audits` category when the analysis is complete. +Previous discussions for the same workflow are automatically closed. +Charts and artifacts can be uploaded as assets and referenced in the discussion body. + +### Discussion Format + +Follow `shared/reporting.md` guidelines: +- Use `###` (h3) for all section headers (never `#` or `##`) +- Wrap verbose details in `
` tags +- Include a summary table at the top with key metrics +- Reference the workflow run: `[${{ github.run_id }}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})` diff --git a/.github/workflows/terminal-stylist.lock.yml b/.github/workflows/terminal-stylist.lock.yml index bae77e1a0c3..e6d6042733c 100644 --- a/.github/workflows/terminal-stylist.lock.yml +++ b/.github/workflows/terminal-stylist.lock.yml @@ -25,10 +25,11 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/mcp/serena-go.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"da1780268adb86447e56695671e9c4099f9e4f3cfbba2ad1ea6299110b676880","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"0e4aae49bee0a021eeb1b73f4f536ff54121a465f241fa833bdd4c09e021ced1","strict":true} name: "Terminal Stylist" "on": @@ -137,7 +138,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -172,6 +173,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/mcp/serena-go.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -338,7 +342,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -378,6 +382,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -475,6 +521,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1126,7 +1199,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/terminal-stylist.md b/.github/workflows/terminal-stylist.md index e7bfc329a9d..8a1ae85469e 100644 --- a/.github/workflows/terminal-stylist.md +++ b/.github/workflows/terminal-stylist.md @@ -15,6 +15,7 @@ timeout-minutes: 10 strict: true imports: + - shared/daily-audit-discussion.md - shared/mcp/serena-go.md - shared/reporting.md @@ -28,9 +29,6 @@ tools: safe-outputs: create-discussion: expires: 1d - category: "audits" - max: 1 - close-older-discussions: true --- # Terminal Stylist - Console Output Analysis diff --git a/.github/workflows/typist.lock.yml b/.github/workflows/typist.lock.yml index 226934c2aff..f99f68f9318 100644 --- a/.github/workflows/typist.lock.yml +++ b/.github/workflows/typist.lock.yml @@ -25,10 +25,11 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/mcp/serena-go.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"a84f1d31ef089afc1ac4110815e97c8509584a617fb3384a318fe01d5e960c67","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"1a26a0ecb7db02014d0fe8ed4f23762446fc0b7da6c09fa521b87995592daa09","strict":true} name: "Typist - Go Type Analysis" "on": @@ -136,7 +137,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, missing_tool, missing_data, noop The following GitHub context information is available for this workflow: @@ -171,6 +172,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -341,7 +345,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -381,6 +385,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Report that a tool or capability needed to complete the task is not available, or share any information you deem important about missing functionality or limitations. Use this when you cannot accomplish what was requested because the required functionality is missing or access is restricted.", "inputSchema": { @@ -478,6 +524,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1207,7 +1280,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.githubusercontent.com,anthropic.com,api.anthropic.com,api.github.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,cdn.playwright.dev,codeload.github.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,files.pythonhosted.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,lfs.github.com,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,playwright.download.prss.microsoft.com,ppa.launchpad.net,pypi.org,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,sentry.io,statsig.anthropic.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/typist.md b/.github/workflows/typist.md index d1b0c9a4300..1108e7c0361 100644 --- a/.github/workflows/typist.md +++ b/.github/workflows/typist.md @@ -14,15 +14,13 @@ permissions: engine: claude imports: + - shared/daily-audit-discussion.md - shared/reporting.md - shared/mcp/serena-go.md safe-outputs: create-discussion: expires: 1d - category: "audits" - max: 1 - close-older-discussions: true tools: github: diff --git a/.github/workflows/weekly-issue-summary.lock.yml b/.github/workflows/weekly-issue-summary.lock.yml index e08038b5159..85271dacc34 100644 --- a/.github/workflows/weekly-issue-summary.lock.yml +++ b/.github/workflows/weekly-issue-summary.lock.yml @@ -25,11 +25,12 @@ # # Resolved workflow manifest: # Imports: +# - shared/daily-audit-discussion.md # - shared/python-dataviz.md # - shared/reporting.md # - shared/trends.md # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"ccb4a4b9b79c5fda99bccf6c37c613c84d09d13bd2d0b60ed372613aa03e78d1","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"7c27cb82ddd31ec653f571f5a98f8fc983416abf091fa858819f78732dbeea21","strict":true} name: "Weekly Issue Summary" "on": @@ -141,7 +142,7 @@ jobs: cat "/opt/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_EOF' - Tools: create_discussion, upload_asset, missing_tool, missing_data, noop + Tools: create_discussion, close_discussion, upload_asset, missing_tool, missing_data, noop upload_asset: provide a file path; returns a URL; assets are published after the workflow completes (safeoutputs). @@ -178,6 +179,9 @@ jobs: GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/shared/daily-audit-discussion.md}} + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' {{#runtime-import .github/workflows/shared/reporting.md}} GH_AW_PROMPT_EOF cat << 'GH_AW_PROMPT_EOF' @@ -361,7 +365,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' - {"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"upload_asset":{"max":0}} + {"close_discussion":{"max":10},"create_discussion":{"expires":24,"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1},"upload_asset":{"max":0}} GH_AW_SAFE_OUTPUTS_CONFIG_EOF - name: Write Safe Outputs Tools run: | @@ -401,6 +405,48 @@ jobs: }, "name": "create_discussion" }, + { + "description": "Close a GitHub discussion with a resolution comment and optional reason. You can and should always add a comment when closing a discussion to explain the action or provide context. Use this to mark discussions as resolved, answered, or no longer needed. The closing comment should explain why the discussion is being closed. If the discussion is already closed, a comment will still be posted. CONSTRAINTS: Maximum 10 discussion(s) can be closed.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Closing comment explaining why the discussion is being closed and summarizing any resolution or conclusion.", + "type": "string" + }, + "discussion_number": { + "description": "Discussion number to close. This is the numeric ID from the GitHub URL (e.g., 678 in github.com/owner/repo/discussions/678). If omitted, closes the discussion that triggered this workflow (requires a discussion event trigger).", + "type": [ + "number", + "string" + ] + }, + "integrity": { + "description": "Trustworthiness level of the message source (e.g., \"low\", \"medium\", \"high\").", + "type": "string" + }, + "reason": { + "description": "Resolution reason: RESOLVED (issue addressed), DUPLICATE (discussed elsewhere), OUTDATED (no longer relevant), or ANSWERED (question answered).", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ], + "type": "string" + }, + "secrecy": { + "description": "Confidentiality level of the message content (e.g., \"public\", \"internal\", \"private\").", + "type": "string" + } + }, + "required": [ + "body" + ], + "type": "object" + }, + "name": "close_discussion" + }, { "description": "Upload a file as a URL-addressable asset that can be referenced in issues, PRs, or comments. The file is stored on an orphaned git branch and returns a permanent URL. Use this for images, diagrams, or other files that need to be embedded in GitHub content. CONSTRAINTS: Maximum file size: 10240KB. Allowed file extensions: [.png .jpg .jpeg].", "inputSchema": { @@ -523,6 +569,33 @@ jobs: GH_AW_SAFE_OUTPUTS_TOOLS_EOF cat > /opt/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' { + "close_discussion": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "discussion_number": { + "optionalPositiveInteger": true + }, + "reason": { + "type": "string", + "enum": [ + "RESOLVED", + "DUPLICATE", + "OUTDATED", + "ANSWERED" + ] + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, "create_discussion": { "defaultMax": 1, "fields": { @@ -1201,7 +1274,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.jsr.io,*.pythonhosted.org,anaconda.org,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,binstar.org,bootstrap.pypa.io,bun.sh,cdn.jsdelivr.net,conda.anaconda.org,conda.binstar.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,deb.nodesource.com,deno.land,esm.sh,files.pythonhosted.org,get.pnpm.io,github.com,googleapis.deno.dev,googlechromelabs.github.io,host.docker.internal,index.crates.io,json-schema.org,json.schemastore.org,jsr.io,keyserver.ubuntu.com,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,pip.pypa.io,ppa.launchpad.net,pypi.org,pypi.python.org,raw.githubusercontent.com,registry.bower.io,registry.npmjs.com,registry.npmjs.org,registry.yarnpkg.com,repo.anaconda.com,repo.continuum.io,repo.yarnpkg.com,s.symcb.com,s.symcd.com,security.ubuntu.com,skimdb.npmjs.com,static.crates.io,storage.googleapis.com,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.npmjs.com,www.npmjs.org,yarnpkg.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[Weekly Summary] \"},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"close_discussion\":{\"max\":10},\"create_discussion\":{\"category\":\"audits\",\"close_older_discussions\":true,\"expires\":24,\"fallback_to_issue\":true,\"max\":1,\"title_prefix\":\"[Weekly Summary] \"},\"missing_data\":{},\"missing_tool\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/weekly-issue-summary.md b/.github/workflows/weekly-issue-summary.md index aade7184a65..571681127ab 100644 --- a/.github/workflows/weekly-issue-summary.md +++ b/.github/workflows/weekly-issue-summary.md @@ -30,9 +30,8 @@ safe-outputs: create-discussion: expires: 1d title-prefix: "[Weekly Summary] " - category: "audits" - close-older-discussions: true imports: + - shared/daily-audit-discussion.md - shared/reporting.md - shared/trends.md --- diff --git a/pkg/workflow/imports.go b/pkg/workflow/imports.go index 3a2a7c81c15..f01aed3a0f3 100644 --- a/pkg/workflow/imports.go +++ b/pkg/workflow/imports.go @@ -172,6 +172,19 @@ func getSafeOutputTypeKeys() ([]string, error) { // MergeSafeOutputs merges safe-outputs configurations from imports into the top-level safe-outputs // Returns an error if a conflict is detected (same safe-output type defined in both main and imported) +// MergeSafeOutputs merges safe-output configurations from imported workflows into the +// top-level (main workflow) configuration. For most safe-output types the main workflow +// definition takes complete precedence over any imported definition (override semantics). +// +// Exception — create-discussion: uses field-level merge semantics so that a shared +// component (e.g. shared/daily-audit-discussion.md) can provide base fields such as +// category and close-older-discussions while individual workflows override only their +// specific settings (title-prefix, expires). See mergeCreateDiscussionsFields for the +// exact fields that participate in field-level merge. +// +// Conflict detection still applies between multiple imported files: if two imported +// workflows both define the same safe-output type (including create-discussion), an +// error is returned. func (c *Compiler) MergeSafeOutputs(topSafeOutputs *SafeOutputsConfig, importedSafeOutputsJSON []string) (*SafeOutputsConfig, error) { importsLog.Print("Merging safe-outputs from imports") @@ -216,14 +229,24 @@ func (c *Compiler) MergeSafeOutputs(topSafeOutputs *SafeOutputsConfig, importedS } // Check for conflicts and remove types already defined in top-level config - // Main workflow definitions take precedence over imports (override behavior) + // Main workflow definitions take precedence over imports (override behavior). + // Exception: create-discussion supports field-level merging so shared components + // can provide base fields (category, max, close-older-discussions) while individual + // workflows override only their specific settings (title-prefix, expires). for _, key := range typeKeys { if _, exists := config[key]; exists { if topDefinedTypes[key] { - // Main workflow overrides imported definition - remove from imported config - importsLog.Printf("Main workflow overrides imported safe-output: %s", key) - delete(config, key) - continue + if key == "create-discussion" { + // Allow field-level merge: keep imported create-discussion so + // mergeSafeOutputConfig can fill in base fields that the main + // workflow has not set (e.g. category, close-older-discussions). + importsLog.Printf("Allowing field-level merge for create-discussion from import") + } else { + // Main workflow overrides imported definition - remove from imported config + importsLog.Printf("Main workflow overrides imported safe-output: %s", key) + delete(config, key) + continue + } } if importedDefinedTypes[key] { return nil, fmt.Errorf("safe-outputs conflict: '%s' is defined in multiple imported workflows. Each safe-output type can only be defined once", key) @@ -372,8 +395,14 @@ func mergeSafeOutputConfig(result *SafeOutputsConfig, config map[string]any, c * if result.CreateIssues == nil && importedConfig.CreateIssues != nil { result.CreateIssues = importedConfig.CreateIssues } - if result.CreateDiscussions == nil && importedConfig.CreateDiscussions != nil { - result.CreateDiscussions = importedConfig.CreateDiscussions + if importedConfig.CreateDiscussions != nil { + if result.CreateDiscussions == nil { + result.CreateDiscussions = importedConfig.CreateDiscussions + } else { + // Field-level merge: fill in base fields from shared component that the + // main workflow has not explicitly set (e.g. category, close-older-discussions). + mergeCreateDiscussionsFields(result.CreateDiscussions, importedConfig.CreateDiscussions) + } } if result.UpdateDiscussions == nil && importedConfig.UpdateDiscussions != nil { result.UpdateDiscussions = importedConfig.UpdateDiscussions @@ -615,6 +644,38 @@ func mergeMessagesConfig(result, imported *SafeOutputMessagesConfig) *SafeOutput return result } +// mergeCreateDiscussionsFields fills in base configuration fields from the imported (shared) +// component into the result (main workflow) config. This enables shared components to provide +// base fields such as category and close-older-discussions while individual workflows override +// only their specific settings (title-prefix, expires). +// The main workflow's non-zero/non-nil values always take precedence. +func mergeCreateDiscussionsFields(result, imported *CreateDiscussionsConfig) { + if result.Category == "" && imported.Category != "" { + result.Category = imported.Category + } + if result.CloseOlderDiscussions == nil && imported.CloseOlderDiscussions != nil { + result.CloseOlderDiscussions = imported.CloseOlderDiscussions + } + if result.RequiredCategory == "" && imported.RequiredCategory != "" { + result.RequiredCategory = imported.RequiredCategory + } + if len(result.Labels) == 0 && len(imported.Labels) > 0 { + result.Labels = imported.Labels + } + if len(result.AllowedLabels) == 0 && len(imported.AllowedLabels) > 0 { + result.AllowedLabels = imported.AllowedLabels + } + if result.Footer == nil && imported.Footer != nil { + result.Footer = imported.Footer + } + // Note: TitlePrefix, Expires, TargetRepoSlug, AllowedRepos, and CloseOlderKey are + // intentionally workflow-specific and are NOT merged from shared components. + // Max is excluded because it can be set to a non-default value per workflow (e.g. max: 2 + // for poem-bot.md) and is already defaulted to 1 by parseDiscussionsConfig, so merging + // would silently overwrite a deliberate workflow choice. + // BaseSafeOutputConfig fields (GitHubToken, Staged) are similarly excluded. +} + // MergeFeatures merges features configurations from imports with top-level features // Features from top-level take precedence over imported features func (c *Compiler) MergeFeatures(topFeatures map[string]any, importedFeatures []map[string]any) (map[string]any, error) { diff --git a/pkg/workflow/safe_outputs_import_test.go b/pkg/workflow/safe_outputs_import_test.go index a8e0b00283a..829d4f0e02f 100644 --- a/pkg/workflow/safe_outputs_import_test.go +++ b/pkg/workflow/safe_outputs_import_test.go @@ -412,6 +412,217 @@ imports: assert.Equal(t, strPtr("5"), workflowData.SafeOutputs.AddComments.Max) } +// TestCreateDiscussionFieldLevelMerge tests that when the same create-discussion type is defined +// in both main and imported workflow, base fields from the imported config fill in any unset fields +// in the main workflow's create-discussion config (field-level merge). +func TestCreateDiscussionFieldLevelMerge(t *testing.T) { + compiler := NewCompilerWithVersion("1.0.0") + + // Create a temporary directory for test files + tmpDir := t.TempDir() + workflowsDir := filepath.Join(tmpDir, ".github", "workflows") + err := os.MkdirAll(workflowsDir, 0755) + require.NoError(t, err, "Failed to create workflows directory") + + // Create a shared workflow that provides the base create-discussion config + sharedWorkflow := `--- +safe-outputs: + create-discussion: + category: "audits" + close-older-discussions: true +--- + +# Shared Audit Discussion Base Config +` + + sharedFile := filepath.Join(workflowsDir, "shared-audit-discussion.md") + err = os.WriteFile(sharedFile, []byte(sharedWorkflow), 0644) + require.NoError(t, err, "Failed to write shared file") + + // Create main workflow that only specifies workflow-specific fields + mainWorkflow := `--- +on: schedule +permissions: + contents: read + discussions: write +imports: + - ./shared-audit-discussion.md +safe-outputs: + create-discussion: + title-prefix: "[my-workflow] " + expires: 1d +--- + +# Main Workflow +` + + mainFile := filepath.Join(workflowsDir, "main.md") + err = os.WriteFile(mainFile, []byte(mainWorkflow), 0644) + require.NoError(t, err, "Failed to write main file") + + // Change to the workflows directory for relative path resolution + oldDir, err := os.Getwd() + require.NoError(t, err, "Failed to get current directory") + err = os.Chdir(workflowsDir) + require.NoError(t, err, "Failed to change directory") + defer func() { _ = os.Chdir(oldDir) }() + + // Parse the main workflow + workflowData, err := compiler.ParseWorkflowFile("main.md") + require.NoError(t, err, "Should parse workflow successfully") + require.NotNil(t, workflowData.SafeOutputs, "SafeOutputs should not be nil") + require.NotNil(t, workflowData.SafeOutputs.CreateDiscussions, "CreateDiscussions should be present") + + // Verify workflow-specific fields from main workflow are present + assert.Equal(t, "[my-workflow] ", workflowData.SafeOutputs.CreateDiscussions.TitlePrefix, "TitlePrefix should come from main workflow") + // expires: 1d is parsed as 24 hours by parseDiscussionsConfig duration parsing + assert.Equal(t, 24, workflowData.SafeOutputs.CreateDiscussions.Expires, "Expires should come from main workflow: 1d parses to 24 hours") + + // Verify base fields from shared component are filled in via field-level merge + assert.Equal(t, "audits", workflowData.SafeOutputs.CreateDiscussions.Category, "Category should come from shared component") + require.NotNil(t, workflowData.SafeOutputs.CreateDiscussions.CloseOlderDiscussions, "CloseOlderDiscussions should come from shared component") + assert.Equal(t, "true", *workflowData.SafeOutputs.CreateDiscussions.CloseOlderDiscussions, "CloseOlderDiscussions should be true from shared component") +} + +// TestCreateDiscussionFieldLevelMergeMainTakesPrecedence tests that when both main and imported +// workflow define the same create-discussion field, the main workflow's value wins. +func TestCreateDiscussionFieldLevelMergeMainTakesPrecedence(t *testing.T) { + compiler := NewCompilerWithVersion("1.0.0") + + // Create a temporary directory for test files + tmpDir := t.TempDir() + workflowsDir := filepath.Join(tmpDir, ".github", "workflows") + err := os.MkdirAll(workflowsDir, 0755) + require.NoError(t, err, "Failed to create workflows directory") + + // Create a shared workflow with base config + sharedWorkflow := `--- +safe-outputs: + create-discussion: + category: "audits" + close-older-discussions: true +--- + +# Shared Config +` + + sharedFile := filepath.Join(workflowsDir, "shared.md") + err = os.WriteFile(sharedFile, []byte(sharedWorkflow), 0644) + require.NoError(t, err, "Failed to write shared file") + + // Create main workflow that explicitly sets category (overrides shared's category) + mainWorkflow := `--- +on: schedule +permissions: + contents: read + discussions: write +imports: + - ./shared.md +safe-outputs: + create-discussion: + category: "reports" + title-prefix: "[report] " + expires: 3d +--- + +# Main Workflow +` + + mainFile := filepath.Join(workflowsDir, "main.md") + err = os.WriteFile(mainFile, []byte(mainWorkflow), 0644) + require.NoError(t, err, "Failed to write main file") + + // Change to the workflows directory for relative path resolution + oldDir, err := os.Getwd() + require.NoError(t, err, "Failed to get current directory") + err = os.Chdir(workflowsDir) + require.NoError(t, err, "Failed to change directory") + defer func() { _ = os.Chdir(oldDir) }() + + // Parse the main workflow + workflowData, err := compiler.ParseWorkflowFile("main.md") + require.NoError(t, err, "Should parse workflow successfully") + require.NotNil(t, workflowData.SafeOutputs, "SafeOutputs should not be nil") + require.NotNil(t, workflowData.SafeOutputs.CreateDiscussions, "CreateDiscussions should be present") + + // Verify main workflow's explicit category overrides shared's category + assert.Equal(t, "reports", workflowData.SafeOutputs.CreateDiscussions.Category, "Category from main workflow should take precedence over shared") + + // Verify close-older-discussions from shared fills in (not set in main) + require.NotNil(t, workflowData.SafeOutputs.CreateDiscussions.CloseOlderDiscussions, "CloseOlderDiscussions should come from shared component") + assert.Equal(t, "true", *workflowData.SafeOutputs.CreateDiscussions.CloseOlderDiscussions, "CloseOlderDiscussions should be true from shared") + + // Verify workflow-specific fields + assert.Equal(t, "[report] ", workflowData.SafeOutputs.CreateDiscussions.TitlePrefix, "TitlePrefix should come from main workflow") + assert.Equal(t, 72, workflowData.SafeOutputs.CreateDiscussions.Expires, "Expires should come from main workflow (3d = 72 hours)") +} + +// TestCreateDiscussionImportConflictBetweenSharedComponents tests that a conflict error is +// returned when create-discussion is defined in multiple imported shared workflows. +func TestCreateDiscussionImportConflictBetweenSharedComponents(t *testing.T) { + compiler := NewCompilerWithVersion("1.0.0") + + // Create a temporary directory for test files + tmpDir := t.TempDir() + workflowsDir := filepath.Join(tmpDir, ".github", "workflows") + err := os.MkdirAll(workflowsDir, 0755) + require.NoError(t, err, "Failed to create workflows directory") + + // Create two shared workflows both defining create-discussion + shared1 := `--- +safe-outputs: + create-discussion: + category: "audits" +--- + +# Shared 1 +` + shared2 := `--- +safe-outputs: + create-discussion: + category: "reports" +--- + +# Shared 2 +` + + err = os.WriteFile(filepath.Join(workflowsDir, "shared1.md"), []byte(shared1), 0644) + require.NoError(t, err, "Failed to write shared1 file") + err = os.WriteFile(filepath.Join(workflowsDir, "shared2.md"), []byte(shared2), 0644) + require.NoError(t, err, "Failed to write shared2 file") + + // Create main workflow that imports both (conflict between imports) + mainWorkflow := `--- +on: schedule +permissions: + contents: read + discussions: write +imports: + - ./shared1.md + - ./shared2.md +--- + +# Main Workflow +` + + mainFile := filepath.Join(workflowsDir, "main.md") + err = os.WriteFile(mainFile, []byte(mainWorkflow), 0644) + require.NoError(t, err, "Failed to write main file") + + // Change to the workflows directory for relative path resolution + oldDir, err := os.Getwd() + require.NoError(t, err, "Failed to get current directory") + err = os.Chdir(workflowsDir) + require.NoError(t, err, "Failed to change directory") + defer func() { _ = os.Chdir(oldDir) }() + + // Parse should fail with a conflict error + _, err = compiler.ParseWorkflowFile("main.md") + require.Error(t, err, "Should return error for create-discussion defined in multiple imports") + assert.Contains(t, err.Error(), "safe-outputs conflict", "Error should mention safe-outputs conflict") + assert.Contains(t, err.Error(), "create-discussion", "Error should mention create-discussion") +} + // TestMergeSafeOutputsUnit tests the MergeSafeOutputs function directly func TestMergeSafeOutputsUnit(t *testing.T) { compiler := NewCompilerWithVersion("1.0.0")