Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ Review Buddy automates the boring parts of Code Review:
* **PR Title**: Renames your PR to follow Conventional Commits (e.g., `fix: login bug` instead of `update`).
* **Description**: Writes a full, formatted description (Summary, Changes, Testing Guide) if you didn't provides one.
* **Labels**: Automatically adds relevant labels based on change type, quality score, and detected issues.
3. **Engaging Feedback**: comments on your PR in your chosen tone (Professional or Roast).
4. **Final Recommendation**: Provides a clear recommendation (Approve/Request Changes/Reject) with actionable next steps for reviewers.
5. **Interactive Chat**: Reply to any comment with `/Buddy` (e.g., "Why is this wrong? /Buddy") and Review Buddy will explain!
3. **Best Practices Suggestions**: Identifies code patterns that can be improved with modern best practices (e.g., `if (a == undefined)` → `if (!a)`, using `const/let` instead of `var`, arrow functions, template literals, etc.) with before/after examples.
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README’s new best-practices example suggests if (a == undefined)if (!a), but those are not equivalent in JS (it will also treat 0, '', and false as “undefined”). Consider adjusting the documentation examples to semantics-preserving patterns (e.g., a == null for null/undefined) to avoid encouraging incorrect refactors.

Suggested change
3. **Best Practices Suggestions**: Identifies code patterns that can be improved with modern best practices (e.g., `if (a == undefined)``if (!a)`, using `const/let` instead of `var`, arrow functions, template literals, etc.) with before/after examples.
3. **Best Practices Suggestions**: Identifies code patterns that can be improved with modern best practices (e.g., `if (a == undefined)``if (a == null)`, using `const/let` instead of `var`, arrow functions, template literals, etc.) with before/after examples.

Copilot uses AI. Check for mistakes.
4. **Engaging Feedback**: comments on your PR in your chosen tone (Professional or Roast).
5. **Final Recommendation**: Provides a clear recommendation (Approve/Request Changes/Reject) with actionable next steps for reviewers.
6. **Interactive Chat**: Reply to any comment with `/Buddy` (e.g., "Why is this wrong? /Buddy") and Review Buddy will explain!

---

Expand Down Expand Up @@ -68,6 +69,15 @@ I built **Review Buddy** to solve this:
- **Quality Score**: `good first review` (90+), `needs work` (<50)
- **Security Concerns**: `security` (if Critical/High issues detected)
- **Performance Issues**: `performance` (if optimization opportunities found)
- **💡 Best Practices Suggestions**: Identifies code patterns that can be improved:
- Loose equality checks (`==`) → Strict equality (`===`)
- `if (a == undefined)` → `if (!a)` or `if (a === undefined)`
- `var` declarations → `const` or `let`
Comment on lines +73 to +75
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section repeats the if (a == undefined)if (!a) suggestion, which can change runtime behavior for falsy non-nullish values. Consider replacing it with a semantics-preserving example (e.g., a == null or typeof a === 'undefined' depending on intent) and calling out when if (a) is appropriate (boolean variables only).

Copilot uses AI. Check for mistakes.
- Traditional functions → Arrow functions (where appropriate)
- Manual string concatenation → Template literals
- Callback hell → `async/await` or Promises
- For loops → Modern array methods (`map`, `filter`, `reduce`)
- Each suggestion includes before/after code examples with explanations
- **🎯 Smart PR Recommendations**: Posts a final recommendation comment with:
- **✅ APPROVE**: High quality code (80+), no critical issues - ready to merge
- **⚠️ REQUEST CHANGES**: Medium quality (40-79) or some concerns - needs improvements
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v4.17
v5.18
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bumping VERSION from v4.17 to v5.18 will trigger the auto-release workflow and is a large jump in major version. If this isn’t an intentional major release, consider incrementing according to the project’s versioning policy (e.g., v4.18).

Copilot uses AI. Check for mistakes.
24 changes: 19 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ async function handlePullRequest(env, adapter, apiKey, model) {

// Debug: Log the parsed structure
logInfo(`🔍 Parsed Keys: ${Object.keys(analysisResults).join(', ')}`);
logInfo(`🔍 Field Types: review=${typeof analysisResults.review_comment}, perf=${typeof analysisResults.performance_analysis}, sec=${typeof analysisResults.security_analysis}, qual=${typeof analysisResults.quality_analysis}`);
logInfo(`🔍 Field Types: review=${typeof analysisResults.review_comment}, perf=${typeof analysisResults.performance_analysis}, sec=${typeof analysisResults.security_analysis}, qual=${typeof analysisResults.quality_analysis}, best=${typeof analysisResults.best_practices}`);
logInfo(`📝 Title Type/Value: ${typeof analysisResults.new_title} = ${analysisResults.new_title === null ? 'null' : analysisResults.new_title === undefined ? 'undefined' : `"${analysisResults.new_title}"`}`);
logInfo(`📝 Description Type: ${typeof analysisResults.new_description} = ${analysisResults.new_description === null ? 'null' : analysisResults.new_description === undefined ? 'undefined' : `${String(analysisResults.new_description).substring(0, 100)}...`}`);

Expand All @@ -172,6 +172,7 @@ async function handlePullRequest(env, adapter, apiKey, model) {
performance_analysis,
security_analysis,
quality_analysis,
best_practices,
new_title,
new_description,
quality_score,
Expand Down Expand Up @@ -203,6 +204,7 @@ async function handlePullRequest(env, adapter, apiKey, model) {
const cleanedPerformance = cleanField(performance_analysis, 'performance_analysis');
const cleanedSecurity = cleanField(security_analysis, 'security_analysis');
const cleanedQuality = cleanField(quality_analysis, 'quality_analysis');
const cleanedBestPractices = cleanField(best_practices, 'best_practices');

const score = quality_score || 0;
const mScore = maintainability_score || 0;
Expand Down Expand Up @@ -305,8 +307,20 @@ ${footer}`;
await postComment(GITHUB_REPOSITORY, prNumber, comment, GITHUB_TOKEN);
}

// Step 6: Smart Labels
logInfo("Step 6: Adding smart labels...");
// Step 6: Best Practices
logInfo("Step 6: Posting best practices suggestions...");
if (cleanedBestPractices) {
const comment = `<!-- Review Buddy Best Practices -->
## 💡 Review Buddy - Best Practices & Alternative Suggestions
> 👥 **Attention:** ${commonMentions}

${cleanedBestPractices}
${footer}`;
await postComment(GITHUB_REPOSITORY, prNumber, comment, GITHUB_TOKEN);
}

// Step 7: Smart Labels
logInfo("Step 7: Adding smart labels...");
const finalTitle = (updatePayload.title) || currentTitle;
const labelsToAdd = determineLabels(finalTitle, mScore, security_analysis, performance_analysis);
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

determineLabels() expects string inputs (uses .includes() and .toLowerCase()), but this call passes the raw security_analysis / performance_analysis fields, even though the code now has cleanedSecurity / cleanedPerformance to handle broken model outputs (arrays/objects). This can throw at runtime if the model returns non-strings. Use the cleaned fields when determining labels.

Suggested change
const labelsToAdd = determineLabels(finalTitle, mScore, security_analysis, performance_analysis);
const labelsToAdd = determineLabels(finalTitle, mScore, cleanedSecurity, cleanedPerformance);

Copilot uses AI. Check for mistakes.

Expand All @@ -316,8 +330,8 @@ ${footer}`;
logInfo("No labels to add.");
}

// Step 7: Final Recommendation
logInfo("Step 7: Posting final recommendation...");
// Step 8: Final Recommendation
logInfo("Step 8: Posting final recommendation...");
const recData = determineRecommendation(mScore, score, cleanedSecurity, cleanedPerformance, tone, language, verdict);

let recComment = `<!-- Review Buddy Recommendation -->
Expand Down
30 changes: 27 additions & 3 deletions src/prompts/reviewPrompt.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,42 @@ Tasks:
- Be EXTREMELY detailed (100+ lines)
- MUST be a string, NOT an array

5. **PR Metadata**:
5. **Best Practices & Alternative Suggestions** (MUST BE A MARKDOWN STRING):
- Use the EXACT Tone (${tone}) and Language (${lang}) specified above
- Identify code patterns that can be written better using modern best practices
Comment on lines +73 to +75
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The prompt intro still says “provide FOUR comprehensive analyses”, but the task list now includes an additional “Best Practices & Alternative Suggestions” section. Consider updating the intro / enumerated instructions so the model isn’t given contradictory guidance (which can reduce output quality).

Copilot uses AI. Check for mistakes.
- Examples to look for:
* if (a == undefined) → Suggest: if (!a) or if (a === undefined)
* if (x == null || x == undefined) → Suggest: if (x == null)
* array.length > 0 → Suggest: array.length
* for loops → Suggest: forEach, map, filter, reduce
* var → Suggest: const/let
* function() → Suggest: arrow functions where appropriate
* callback hell → Suggest: async/await or Promises
* repetitive code → Suggest: extract to function/utility
* manual string concatenation → Suggest: template literals
* == → Suggest: ===
* object[key] === undefined → Suggest: optional chaining (?.)
Comment on lines +76 to +87
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The best-practices examples include suggestions that are not semantics-preserving in JavaScript. In particular, if (a == undefined) → if (!a) changes behavior for falsy values like 0, '', and false, and array.length > 0 → array.length is only valid in a boolean context (e.g., inside an if). Consider rewriting these examples to only propose behavior-equivalent alternatives (e.g., a == null for null/undefined checks, or if (arr.length) inside conditionals) and explicitly require preserving semantics in the generated suggestions.

Suggested change
- Examples to look for:
* if (a == undefined) Suggest: if (!a) or if (a === undefined)
* if (x == null || x == undefined) Suggest: if (x == null)
* array.length > 0 Suggest: array.length
* for loops Suggest: forEach, map, filter, reduce
* var Suggest: const/let
* function() Suggest: arrow functions where appropriate
* callback hell Suggest: async/await or Promises
* repetitive code Suggest: extract to function/utility
* manual string concatenation Suggest: template literals
* == Suggest: ===
* object[key] === undefined Suggest: optional chaining (?.)
- ALL SUGGESTIONS MUST PRESERVE THE ORIGINAL RUNTIME BEHAVIOR unless the PR explicitly intends a behavior change (in which case, explain the change clearly).
- Examples to look for:
* if (a == undefined) Suggest: if (a == null) (to check specifically for null or undefined)
* if (x == null || x == undefined) Suggest: if (x == null)
* if (array.length > 0) Suggest: if (array.length) (only inside boolean conditions)
* for loops Suggest: forEach, map, filter, reduce where this does not change behavior (no reliance on indices, early breaks, or specific loop ordering side effects)
* var Suggest: const/let
* function() Suggest: arrow functions where appropriate
* callback hell Suggest: async/await or Promises
* repetitive code Suggest: extract to function/utility
* manual string concatenation Suggest: template literals
* == Suggest: ===
* verbose/null-checking property access (for example, object && object.prop && object.prop.subProp) Suggest: optional chaining (?.) where it preserves the existing behavior

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example object[key] === undefined → optional chaining (?.) is incorrect: optional chaining prevents throws on nullish receivers but does not replace an undefined comparison. This guidance is likely to produce wrong refactors (e.g., obj?.[key] changes behavior only when obj can be nullish). Consider updating the example to the actual intent (safe access vs existence check) and require the model to explain semantic differences when suggesting optional chaining.

Suggested change
* object[key] === undefined Suggest: optional chaining (?.)
* accessing nested properties with && guards (e.g., obj && obj[key]) Suggest: safe access using optional chaining (e.g., obj?.[key]) and EXPLAIN how this differs from equality checks like obj[key] === undefined (optional chaining only prevents errors on null/undefined receivers)

Copilot uses AI. Check for mistakes.
- For EACH suggestion provide:
* Current code snippet from the PR
* Better alternative with explanation
* Why it's better (readability, performance, safety)
- Format as markdown with code blocks showing before/after
- If no improvements found, say "Code follows best practices" in the specified tone
- MUST be a string, NOT an array

6. **PR Metadata**:
- Check if current title follows Conventional Commits
- If title is GOOD, return null for new_title
- ONLY suggest new_title if it's vague or violates conventions
- Generate comprehensive PR description (Markdown) with Summary, Changes, Verification
- If needsDesc is "true", provide new_description. If "false", return null

6. **Overall Benchmark Score (0-100)**:
7. **Overall Benchmark Score (0-100)**:
- Calculate comprehensive maintainability score
- Weigh: Code Quality (30%), Security (25%), Performance (25%), Maintainability (20%)
- Scoring: 90-100 Excellent, 70-89 Good, 50-69 Needs Improvement, 0-49 Poor

7. **Verdict**:
8. **Verdict**:
- Consider PERSPECTIVE and PURPOSE of changes
- Evaluate ACTUAL impact and risk
- Verdict: "APPROVE", "REQUEST_CHANGES", or "REJECT"
Expand All @@ -99,6 +122,7 @@ Output JSON with this EXACT structure:
"performance_analysis": "<markdown string - 100+ lines>",
"security_analysis": "<markdown string - comprehensive>",
"quality_analysis": "<markdown string - 100+ lines>",
"best_practices": "<markdown string with before/after code examples>",
"new_title": "<string or null>",
"new_description": "<markdown string or null>",
"quality_score": <number 1-10>,
Expand Down
Loading