From 74af1dbc1ddcf39df15033abc354538adb3845a4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 04:49:23 +0000 Subject: [PATCH 01/16] Initial plan From 07cb1a2af75b5b9bfa4fb99d21ca7224aee15ca5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 04:52:45 +0000 Subject: [PATCH 02/16] Add AI agent workflows for automatic issue and PR analysis Co-authored-by: blackboxprogramming <118287761+blackboxprogramming@users.noreply.github.com> --- .github/workflows/issue-agent.yml | 82 ++++++++++++++++++++++ .github/workflows/pr-agent.yml | 109 ++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 .github/workflows/issue-agent.yml create mode 100644 .github/workflows/pr-agent.yml diff --git a/.github/workflows/issue-agent.yml b/.github/workflows/issue-agent.yml new file mode 100644 index 0000000..d7a45ee --- /dev/null +++ b/.github/workflows/issue-agent.yml @@ -0,0 +1,82 @@ +name: Issue Agent + +on: + issues: + types: [opened, edited, reopened, labeled] + +permissions: + issues: write + models: read + +jobs: + analyze-issue: + runs-on: ubuntu-latest + steps: + - name: Analyze issue and post comment + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const issueNumber = context.issue.number; + const issueTitle = context.payload.issue.title; + const issueBody = context.payload.issue.body || '(no description provided)'; + const issueUser = context.payload.issue.user.login; + const labels = (context.payload.issue.labels || []).map(l => l.name).join(', ') || 'none'; + + // Call GitHub Models API for AI-powered analysis + const response = await fetch('https://models.inference.ai.azure.com/chat/completions', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${process.env.GITHUB_TOKEN}` + }, + body: JSON.stringify({ + model: 'gpt-4o-mini', + messages: [ + { + role: 'system', + content: `You are a rigorous technical agent reviewing GitHub issues for the "simulation-theory" repository — a research project on simulation theory, mathematics, quantum mechanics, and philosophy. Your job is to carefully read each issue and provide a thorough, structured analysis. + +For each issue produce: +1. **Summary** — a concise one-paragraph summary of what the issue is about. +2. **Key Points** — bullet list of the most important observations or questions raised. +3. **Relevance to Simulation Theory** — how this issue connects to the project's themes. +4. **Suggested Actions** — concrete next steps or questions for the author. + +Be rigorous, thoughtful, and constructive. Keep the tone academic and helpful.` + }, + { + role: 'user', + content: `Please analyze this GitHub issue:\n\n**Title:** ${issueTitle}\n**Author:** ${issueUser}\n**Labels:** ${labels}\n\n**Description:**\n${issueBody}` + } + ], + max_tokens: 1500, + temperature: 0.4 + }) + }); + + let analysisText; + if (response.ok) { + const data = await response.json(); + if (data.choices && data.choices.length > 0 && data.choices[0].message) { + analysisText = data.choices[0].message.content; + } else { + console.log('Unexpected response structure from GitHub Models API:', JSON.stringify(data)); + } + } else { + console.log(`GitHub Models API returned ${response.status}: ${await response.text()}`); + } + + // Fallback: structured analysis without AI + if (!analysisText) { + analysisText = `**Summary**\nIssue #${issueNumber} titled *"${issueTitle}"* was submitted by @${issueUser}. ${issueBody.length > 0 ? 'It contains a description that may include images or text.' : 'No description was provided.'}\n\n**Labels:** ${labels}\n\n**Suggested Actions**\n- Review the content of this issue and add appropriate labels if missing.\n- Respond to the author with any clarifying questions.\n- Link related issues or pull requests if applicable.`; + } + + const comment = `## 🤖 Agent Analysis\n\n${analysisText}\n\n---\n*This comment was generated automatically by the Issue Agent workflow.*`; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: comment + }); diff --git a/.github/workflows/pr-agent.yml b/.github/workflows/pr-agent.yml new file mode 100644 index 0000000..74ca45b --- /dev/null +++ b/.github/workflows/pr-agent.yml @@ -0,0 +1,109 @@ +name: PR Agent + +on: + pull_request: + types: [opened, edited, synchronize, reopened] + +permissions: + pull-requests: write + contents: read + models: read + +jobs: + analyze-pr: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Collect changed files + id: changed + run: | + BASE="${{ github.event.pull_request.base.sha }}" + HEAD="${{ github.event.pull_request.head.sha }}" + ALL_FILES=$(git diff --name-only "$BASE" "$HEAD" 2>/dev/null) + TOTAL=$(echo "$ALL_FILES" | grep -c . || echo 0) + FILES=$(echo "$ALL_FILES" | head -50 | tr '\n' ', ') + if [ "$TOTAL" -gt 50 ]; then + REMAINING=$(( TOTAL - 50 )) + FILES="${FILES} (and ${REMAINING} more files)" + fi + echo "files=$FILES" >> "$GITHUB_OUTPUT" + + - name: Analyze PR and post comment + uses: actions/github-script@v7 + env: + CHANGED_FILES: ${{ steps.changed.outputs.files }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const prNumber = context.payload.pull_request.number; + const prTitle = context.payload.pull_request.title; + const prBody = context.payload.pull_request.body || '(no description provided)'; + const prUser = context.payload.pull_request.user.login; + const baseBranch = context.payload.pull_request.base.ref; + const headBranch = context.payload.pull_request.head.ref; + const changedFiles = process.env.CHANGED_FILES || 'unknown'; + const additions = context.payload.pull_request.additions ?? '?'; + const deletions = context.payload.pull_request.deletions ?? '?'; + + // Call GitHub Models API for AI-powered analysis + const response = await fetch('https://models.inference.ai.azure.com/chat/completions', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${process.env.GITHUB_TOKEN}` + }, + body: JSON.stringify({ + model: 'gpt-4o-mini', + messages: [ + { + role: 'system', + content: `You are a rigorous code and content review agent for the "simulation-theory" repository — a research project on simulation theory, mathematics, quantum mechanics, and philosophy. Your job is to carefully examine each pull request and provide a thorough, structured review. + +For each PR produce: +1. **Summary** — a concise one-paragraph summary of the proposed changes. +2. **Changed Files Analysis** — observations about the files being modified and why they matter. +3. **Potential Concerns** — any risks, conflicts, or issues the reviewer should check. +4. **Relevance to Project Goals** — how these changes align with (or diverge from) simulation-theory research. +5. **Suggested Actions** — specific things the PR author or reviewers should do before merging. + +Be rigorous, constructive, and precise. Keep the tone academic and professional.` + }, + { + role: 'user', + content: `Please analyze this pull request:\n\n**Title:** ${prTitle}\n**Author:** ${prUser}\n**Base branch:** ${baseBranch} ← **Head branch:** ${headBranch}\n**Changes:** +${additions} / -${deletions} lines\n**Changed files:** ${changedFiles}\n\n**Description:**\n${prBody}` + } + ], + max_tokens: 1500, + temperature: 0.4 + }) + }); + + let analysisText; + if (response.ok) { + const data = await response.json(); + if (data.choices && data.choices.length > 0 && data.choices[0].message) { + analysisText = data.choices[0].message.content; + } else { + console.log('Unexpected response structure from GitHub Models API:', JSON.stringify(data)); + } + } else { + console.log(`GitHub Models API returned ${response.status}: ${await response.text()}`); + } + + // Fallback: structured analysis without AI + if (!analysisText) { + analysisText = `**Summary**\nPR #${prNumber} titled *"${prTitle}"* was submitted by @${prUser} merging \`${headBranch}\` into \`${baseBranch}\`.\n\n**Changed Files**\n${changedFiles || 'No files listed.'}\n\n**Stats:** +${additions} additions / -${deletions} deletions\n\n**Suggested Actions**\n- Review all changed files for correctness and consistency.\n- Ensure the description clearly explains the motivation for each change.\n- Verify no unintended files are included in this PR.`; + } + + const comment = `## 🤖 Agent Review\n\n${analysisText}\n\n---\n*This comment was generated automatically by the PR Agent workflow.*`; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: comment + }); From 4f4c9e919dcd78758280218ae1858c5fea844096 Mon Sep 17 00:00:00 2001 From: Alexa Amundson <118287761+blackboxprogramming@users.noreply.github.com> Date: Fri, 27 Feb 2026 01:43:41 -0600 Subject: [PATCH 03/16] Update issue-agent.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/issue-agent.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/issue-agent.yml b/.github/workflows/issue-agent.yml index d7a45ee..eceef72 100644 --- a/.github/workflows/issue-agent.yml +++ b/.github/workflows/issue-agent.yml @@ -6,7 +6,6 @@ on: permissions: issues: write - models: read jobs: analyze-issue: From bb7f155dade231b5e3016e0349a82d0a838f00c7 Mon Sep 17 00:00:00 2001 From: Alexa Amundson <118287761+blackboxprogramming@users.noreply.github.com> Date: Fri, 27 Feb 2026 01:44:00 -0600 Subject: [PATCH 04/16] Update issue-agent.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/issue-agent.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/issue-agent.yml b/.github/workflows/issue-agent.yml index eceef72..eec1f4f 100644 --- a/.github/workflows/issue-agent.yml +++ b/.github/workflows/issue-agent.yml @@ -56,10 +56,16 @@ Be rigorous, thoughtful, and constructive. Keep the tone academic and helpful.` let analysisText; if (response.ok) { - const data = await response.json(); - if (data.choices && data.choices.length > 0 && data.choices[0].message) { + let data; + try { + data = await response.json(); + } catch (error) { + console.log('Failed to parse JSON from GitHub Models API response:', error); + } + + if (data && data.choices && data.choices.length > 0 && data.choices[0].message) { analysisText = data.choices[0].message.content; - } else { + } else if (data) { console.log('Unexpected response structure from GitHub Models API:', JSON.stringify(data)); } } else { From 6d6bc2e962dcf053fecff8099d6cd173cf32b304 Mon Sep 17 00:00:00 2001 From: Alexa Amundson <118287761+blackboxprogramming@users.noreply.github.com> Date: Fri, 27 Feb 2026 01:44:15 -0600 Subject: [PATCH 05/16] Update issue-agent.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/issue-agent.yml | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/.github/workflows/issue-agent.yml b/.github/workflows/issue-agent.yml index eec1f4f..803d657 100644 --- a/.github/workflows/issue-agent.yml +++ b/.github/workflows/issue-agent.yml @@ -77,11 +77,36 @@ Be rigorous, thoughtful, and constructive. Keep the tone academic and helpful.` analysisText = `**Summary**\nIssue #${issueNumber} titled *"${issueTitle}"* was submitted by @${issueUser}. ${issueBody.length > 0 ? 'It contains a description that may include images or text.' : 'No description was provided.'}\n\n**Labels:** ${labels}\n\n**Suggested Actions**\n- Review the content of this issue and add appropriate labels if missing.\n- Respond to the author with any clarifying questions.\n- Link related issues or pull requests if applicable.`; } - const comment = `## 🤖 Agent Analysis\n\n${analysisText}\n\n---\n*This comment was generated automatically by the Issue Agent workflow.*`; + const marker = '*This comment was generated automatically by the Issue Agent workflow.*'; + const commentBody = `## 🤖 Agent Analysis\n\n${analysisText}\n\n---\n${marker}`; - await github.rest.issues.createComment({ + // Look for an existing Issue Agent comment and update it if found to avoid spamming + const { data: existingComments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, issue_number: issueNumber, - body: comment + per_page: 100 }); + + const existingAgentComment = existingComments.find(c => + c.user && + c.user.type === 'Bot' && + typeof c.body === 'string' && + c.body.includes(marker) + ); + + if (existingAgentComment) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existingAgentComment.id, + body: commentBody + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: commentBody + }); + } From e76d0c8ec40076dd87c307c7c487e4f0c468f09f Mon Sep 17 00:00:00 2001 From: Alexa Amundson <118287761+blackboxprogramming@users.noreply.github.com> Date: Fri, 27 Feb 2026 01:44:23 -0600 Subject: [PATCH 06/16] Update pr-agent.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/pr-agent.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-agent.yml b/.github/workflows/pr-agent.yml index 74ca45b..98a7aa0 100644 --- a/.github/workflows/pr-agent.yml +++ b/.github/workflows/pr-agent.yml @@ -1,7 +1,7 @@ name: PR Agent on: - pull_request: + pull_request_target: types: [opened, edited, synchronize, reopened] permissions: From da577bc0152e45b009c6379e45cfe6f7db88c3d9 Mon Sep 17 00:00:00 2001 From: Alexa Amundson <118287761+blackboxprogramming@users.noreply.github.com> Date: Fri, 27 Feb 2026 01:44:29 -0600 Subject: [PATCH 07/16] Update pr-agent.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/pr-agent.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-agent.yml b/.github/workflows/pr-agent.yml index 98a7aa0..9f1e55a 100644 --- a/.github/workflows/pr-agent.yml +++ b/.github/workflows/pr-agent.yml @@ -2,7 +2,7 @@ name: PR Agent on: pull_request_target: - types: [opened, edited, synchronize, reopened] + types: [opened, reopened] permissions: pull-requests: write From 601d02414c7592834f206378cd7c0a37058f3b73 Mon Sep 17 00:00:00 2001 From: Alexa Amundson <118287761+blackboxprogramming@users.noreply.github.com> Date: Fri, 27 Feb 2026 01:44:44 -0600 Subject: [PATCH 08/16] Update pr-agent.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/pr-agent.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-agent.yml b/.github/workflows/pr-agent.yml index 9f1e55a..48bddb9 100644 --- a/.github/workflows/pr-agent.yml +++ b/.github/workflows/pr-agent.yml @@ -21,10 +21,20 @@ jobs: - name: Collect changed files id: changed run: | + # Ensure the base branch ref is available locally (important for fork-based PRs) + git fetch origin "${{ github.event.pull_request.base.ref }}" --no-tags --prune --depth=1 + BASE="${{ github.event.pull_request.base.sha }}" HEAD="${{ github.event.pull_request.head.sha }}" - ALL_FILES=$(git diff --name-only "$BASE" "$HEAD" 2>/dev/null) - TOTAL=$(echo "$ALL_FILES" | grep -c . || echo 0) + + # Compute the list of changed files between base and head; fail explicitly on error + if ! ALL_FILES=$(git diff --name-only "$BASE" "$HEAD"); then + echo "Error: failed to compute git diff between $BASE and $HEAD" >&2 + exit 1 + fi + + # Count total changed files robustly, even when there are zero files + TOTAL=$(printf '%s\n' "$ALL_FILES" | sed '/^$/d' | wc -l | tr -d ' ') FILES=$(echo "$ALL_FILES" | head -50 | tr '\n' ', ') if [ "$TOTAL" -gt 50 ]; then REMAINING=$(( TOTAL - 50 )) From 80c513a5bff60ed2e296a0bd63b8728361d967ad Mon Sep 17 00:00:00 2001 From: Alexa Amundson <118287761+blackboxprogramming@users.noreply.github.com> Date: Fri, 27 Feb 2026 01:44:51 -0600 Subject: [PATCH 09/16] Update pr-agent.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/pr-agent.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pr-agent.yml b/.github/workflows/pr-agent.yml index 48bddb9..0c5825a 100644 --- a/.github/workflows/pr-agent.yml +++ b/.github/workflows/pr-agent.yml @@ -36,6 +36,7 @@ jobs: # Count total changed files robustly, even when there are zero files TOTAL=$(printf '%s\n' "$ALL_FILES" | sed '/^$/d' | wc -l | tr -d ' ') FILES=$(echo "$ALL_FILES" | head -50 | tr '\n' ', ') + FILES="${FILES%, }" if [ "$TOTAL" -gt 50 ]; then REMAINING=$(( TOTAL - 50 )) FILES="${FILES} (and ${REMAINING} more files)" From d826b372e5a730565e8752fa8144bfdef90431bc Mon Sep 17 00:00:00 2001 From: Alexa Amundson <118287761+blackboxprogramming@users.noreply.github.com> Date: Fri, 27 Feb 2026 01:45:01 -0600 Subject: [PATCH 10/16] Update pr-agent.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/pr-agent.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-agent.yml b/.github/workflows/pr-agent.yml index 0c5825a..e5f328b 100644 --- a/.github/workflows/pr-agent.yml +++ b/.github/workflows/pr-agent.yml @@ -41,7 +41,11 @@ jobs: REMAINING=$(( TOTAL - 50 )) FILES="${FILES} (and ${REMAINING} more files)" fi - echo "files=$FILES" >> "$GITHUB_OUTPUT" + { + echo 'files<> "$GITHUB_OUTPUT" - name: Analyze PR and post comment uses: actions/github-script@v7 From 4c01769a17277b97f95acb6a65f56f848624908c Mon Sep 17 00:00:00 2001 From: Alexa Amundson <118287761+blackboxprogramming@users.noreply.github.com> Date: Fri, 27 Feb 2026 01:45:25 -0600 Subject: [PATCH 11/16] Update pr-agent.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/pr-agent.yml | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/.github/workflows/pr-agent.yml b/.github/workflows/pr-agent.yml index e5f328b..cb8757f 100644 --- a/.github/workflows/pr-agent.yml +++ b/.github/workflows/pr-agent.yml @@ -65,18 +65,20 @@ jobs: const deletions = context.payload.pull_request.deletions ?? '?'; // Call GitHub Models API for AI-powered analysis - const response = await fetch('https://models.inference.ai.azure.com/chat/completions', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${process.env.GITHUB_TOKEN}` - }, - body: JSON.stringify({ - model: 'gpt-4o-mini', - messages: [ - { - role: 'system', - content: `You are a rigorous code and content review agent for the "simulation-theory" repository — a research project on simulation theory, mathematics, quantum mechanics, and philosophy. Your job is to carefully examine each pull request and provide a thorough, structured review. + let response; + try { + response = await fetch('https://models.inference.ai.azure.com/chat/completions', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${process.env.GITHUB_TOKEN}` + }, + body: JSON.stringify({ + model: 'gpt-4o-mini', + messages: [ + { + role: 'system', + content: `You are a rigorous code and content review agent for the "simulation-theory" repository — a research project on simulation theory, mathematics, quantum mechanics, and philosophy. Your job is to carefully examine each pull request and provide a thorough, structured review. For each PR produce: 1. **Summary** — a concise one-paragraph summary of the proposed changes. From 42eb3caf4602cde435ab5e9703dbfd77174450fe Mon Sep 17 00:00:00 2001 From: Alexa Amundson <118287761+blackboxprogramming@users.noreply.github.com> Date: Fri, 27 Feb 2026 01:45:45 -0600 Subject: [PATCH 12/16] Update pr-agent.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/pr-agent.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr-agent.yml b/.github/workflows/pr-agent.yml index cb8757f..82016de 100644 --- a/.github/workflows/pr-agent.yml +++ b/.github/workflows/pr-agent.yml @@ -101,11 +101,15 @@ Be rigorous, constructive, and precise. Keep the tone academic and professional. let analysisText; if (response.ok) { - const data = await response.json(); - if (data.choices && data.choices.length > 0 && data.choices[0].message) { - analysisText = data.choices[0].message.content; - } else { - console.log('Unexpected response structure from GitHub Models API:', JSON.stringify(data)); + try { + const data = await response.json(); + if (data.choices && data.choices.length > 0 && data.choices[0].message) { + analysisText = data.choices[0].message.content; + } else { + console.log('Unexpected response structure from GitHub Models API:', JSON.stringify(data)); + } + } catch (error) { + console.log('Failed to parse JSON response from GitHub Models API:', error); } } else { console.log(`GitHub Models API returned ${response.status}: ${await response.text()}`); From 08d29744cff8d1bef96d1ff2d5d60dcb2ec9c011 Mon Sep 17 00:00:00 2001 From: Alexa Amundson <118287761+blackboxprogramming@users.noreply.github.com> Date: Fri, 27 Feb 2026 01:45:54 -0600 Subject: [PATCH 13/16] Update pr-agent.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/pr-agent.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr-agent.yml b/.github/workflows/pr-agent.yml index 82016de..0b36873 100644 --- a/.github/workflows/pr-agent.yml +++ b/.github/workflows/pr-agent.yml @@ -104,15 +104,19 @@ Be rigorous, constructive, and precise. Keep the tone academic and professional. try { const data = await response.json(); if (data.choices && data.choices.length > 0 && data.choices[0].message) { + try { + if (response.ok) { + const data = await response.json(); + if (data.choices && data.choices.length > 0 && data.choices[0].message) { analysisText = data.choices[0].message.content; } else { console.log('Unexpected response structure from GitHub Models API:', JSON.stringify(data)); } - } catch (error) { - console.log('Failed to parse JSON response from GitHub Models API:', error); + } else { + console.log(`GitHub Models API returned ${response.status}: ${await response.text()}`); } - } else { - console.log(`GitHub Models API returned ${response.status}: ${await response.text()}`); + } catch (error) { + console.log('Error while calling or parsing response from GitHub Models API, falling back to templated analysis:', error); } // Fallback: structured analysis without AI From 7b8fb9a4518ddd6b52e8ef28da34a7f4daf46269 Mon Sep 17 00:00:00 2001 From: Alexa Amundson <118287761+blackboxprogramming@users.noreply.github.com> Date: Fri, 27 Feb 2026 01:46:07 -0600 Subject: [PATCH 14/16] Update pr-agent.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/pr-agent.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-agent.yml b/.github/workflows/pr-agent.yml index 0b36873..67239a5 100644 --- a/.github/workflows/pr-agent.yml +++ b/.github/workflows/pr-agent.yml @@ -121,7 +121,18 @@ Be rigorous, constructive, and precise. Keep the tone academic and professional. // Fallback: structured analysis without AI if (!analysisText) { - analysisText = `**Summary**\nPR #${prNumber} titled *"${prTitle}"* was submitted by @${prUser} merging \`${headBranch}\` into \`${baseBranch}\`.\n\n**Changed Files**\n${changedFiles || 'No files listed.'}\n\n**Stats:** +${additions} additions / -${deletions} deletions\n\n**Suggested Actions**\n- Review all changed files for correctness and consistency.\n- Ensure the description clearly explains the motivation for each change.\n- Verify no unintended files are included in this PR.`; + let changedFilesSection; + if (!changedFiles || changedFiles === 'unknown') { + changedFilesSection = 'No changed file list is available for this PR.'; + } else { + const files = changedFiles.split(',').map(f => f.trim()).filter(f => f.length > 0); + if (files.length === 0) { + changedFilesSection = 'No files listed.'; + } else { + changedFilesSection = files.map(f => `- ${f}`).join('\n'); + } + } + analysisText = `**Summary**\nPR #${prNumber} titled *"${prTitle}"* was submitted by @${prUser} merging \`${headBranch}\` into \`${baseBranch}\`.\n\n**Changed Files**\n${changedFilesSection}\n\n**Stats:** +${additions} additions / -${deletions} deletions\n\n**Suggested Actions**\n- Review all changed files for correctness and consistency.\n- Ensure the description clearly explains the motivation for each change.\n- Verify no unintended files are included in this PR.`; } const comment = `## 🤖 Agent Review\n\n${analysisText}\n\n---\n*This comment was generated automatically by the PR Agent workflow.*`; From ada719d09a5b9e5fa409aa793645c11d08fd37a3 Mon Sep 17 00:00:00 2001 From: Alexa Amundson <118287761+blackboxprogramming@users.noreply.github.com> Date: Fri, 27 Feb 2026 01:46:26 -0600 Subject: [PATCH 15/16] Update pr-agent.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/pr-agent.yml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-agent.yml b/.github/workflows/pr-agent.yml index 67239a5..ea1df68 100644 --- a/.github/workflows/pr-agent.yml +++ b/.github/workflows/pr-agent.yml @@ -135,8 +135,27 @@ Be rigorous, constructive, and precise. Keep the tone academic and professional. analysisText = `**Summary**\nPR #${prNumber} titled *"${prTitle}"* was submitted by @${prUser} merging \`${headBranch}\` into \`${baseBranch}\`.\n\n**Changed Files**\n${changedFilesSection}\n\n**Stats:** +${additions} additions / -${deletions} deletions\n\n**Suggested Actions**\n- Review all changed files for correctness and consistency.\n- Ensure the description clearly explains the motivation for each change.\n- Verify no unintended files are included in this PR.`; } - const comment = `## 🤖 Agent Review\n\n${analysisText}\n\n---\n*This comment was generated automatically by the PR Agent workflow.*`; + // Sanitize and limit the AI-generated analysis text before posting as a comment. + const MAX_COMMENT_LENGTH = 5000; + const sanitizeAnalysisText = (text) => { + if (typeof text !== 'string') { + return ''; + } + // Remove script-like tags and generic HTML tags as a defense-in-depth measure. + let cleaned = text + .replace(/<\s*\/?\s*script[^>]*>/gi, '') + .replace(/<[^>]+>/g, '') + .trim(); + if (cleaned.length > MAX_COMMENT_LENGTH) { + cleaned = cleaned.slice(0, MAX_COMMENT_LENGTH) + + '\n\n*Note: Output truncated to fit comment length limits.*'; + } + return cleaned; + }; + + const safeAnalysisText = sanitizeAnalysisText(analysisText); + const comment = `## 🤖 Agent Review\n\n${safeAnalysisText}\n\n---\n*This comment was generated automatically by the PR Agent workflow.*`; await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, From 4a41d443d8e6634cc7e3fa63d774bf41eadf6ad4 Mon Sep 17 00:00:00 2001 From: Alexa Amundson <118287761+blackboxprogramming@users.noreply.github.com> Date: Fri, 27 Feb 2026 01:46:41 -0600 Subject: [PATCH 16/16] Update pr-agent.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/pr-agent.yml | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-agent.yml b/.github/workflows/pr-agent.yml index ea1df68..42dc929 100644 --- a/.github/workflows/pr-agent.yml +++ b/.github/workflows/pr-agent.yml @@ -156,9 +156,31 @@ Be rigorous, constructive, and precise. Keep the tone academic and professional. const safeAnalysisText = sanitizeAnalysisText(analysisText); const comment = `## 🤖 Agent Review\n\n${safeAnalysisText}\n\n---\n*This comment was generated automatically by the PR Agent workflow.*`; - await github.rest.issues.createComment({ + // Try to find an existing PR Agent comment to update, to avoid spamming the thread + const { data: existingComments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, - issue_number: prNumber, - body: comment + issue_number: prNumber }); + + const existingAgentComment = existingComments.find(c => + c && + c.body && + c.body.includes('This comment was generated automatically by the PR Agent workflow.') + ); + + if (existingAgentComment) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existingAgentComment.id, + body: comment + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: comment + }); + }