review-labels #14

Merged
ztimson merged 5 commits from review-labels into master 2026-01-14 14:06:21 -05:00
Owner

Description

  • Only use AI review bot on PRs with the "LABEL_ENABLED" env var (defauled to "Review/AI")
  • Improved the system prompt to provide shorter summaries
  • Provide the AI with the PR title & description for more context

Checklist

]
  • Reviewed changes
  • Updated comments/documentation
## Description <!-- Addition information & context --> - Only use AI review bot on PRs with the "LABEL_ENABLED" env var (defauled to "Review/AI") - Improved the system prompt to provide shorter summaries - Provide the AI with the PR title & description for more context ## Checklist <!-- Complete after creating PR -->] - [ ] Reviewed changes - [ ] Updated comments/documentation
ztimson added 3 commits 2026-01-14 13:47:00 -05:00
Added label to enable review bot on PRs
All checks were successful
Publish Library / Build NPM Project (push) Successful in 3s
Publish Library / Tag Version (push) Successful in 5s
677f84c97a
Merge branch 'master' of git.zakscode.com:ztimson/ai-agents into review-labels
All checks were successful
Publish Library / Build NPM Project (push) Successful in 3s
Publish Library / Tag Version (push) Successful in 5s
ebc3da8605
Added PR info as context to AI
All checks were successful
Publish Library / Build NPM Project (push) Successful in 3s
Publish Library / Tag Version (push) Successful in 5s
Code review / review (pull_request) Successful in 46s
1460c3a0ae
assistant reviewed 2026-01-14 13:47:40 -05:00
assistant left a comment
First-time contributor

Summary

The changes introduce label-based triggering for code reviews and improve duplicate detection logic. However, there are some critical issues that need attention:

Critical Issues:

  1. Logic error in src/review.mjs line 30: The boolean condition will cause the review to skip incorrectly when labels are present. The || operator should be && or the condition should be restructured.
  2. Missing error handling: The fetch call for PR info lacks proper error handling, which could cause crashes.

Code Quality Issues:
3. Type coercion: The duplicate detection uses loose equality (==) which may cause bugs if IDs are inconsistently typed.
4. Complex condition: The duplicate detection logic is difficult to read and maintain.

Minor Issues:
5. Informal language: The word "sitrep" in the system prompt is military jargon that may be unclear.

The version bump and workflow changes look appropriate. The PR template simplification is good. Overall, the changes add useful functionality but need fixes to the conditional logic before merging.

## Summary The changes introduce label-based triggering for code reviews and improve duplicate detection logic. However, there are some critical issues that need attention: **Critical Issues:** 1. **Logic error in `src/review.mjs` line 30**: The boolean condition will cause the review to skip incorrectly when labels are present. The `||` operator should be `&&` or the condition should be restructured. 2. **Missing error handling**: The fetch call for PR info lacks proper error handling, which could cause crashes. **Code Quality Issues:** 3. **Type coercion**: The duplicate detection uses loose equality (`==`) which may cause bugs if IDs are inconsistently typed. 4. **Complex condition**: The duplicate detection logic is difficult to read and maintain. **Minor Issues:** 5. **Informal language**: The word "sitrep" in the system prompt is military jargon that may be unclear. The version bump and workflow changes look appropriate. The PR template simplification is good. Overall, the changes add useful functionality but need fixes to the conditional logic before merging.
@@ -184,2 +184,3 @@
// Handle duplicates
if(hasDuplicates && hasDuplicates !== 'NONE' && (dupeId = dupeIds.find(id => id == hasDuplicates.trim()))) {
if(hasDuplicates && !hasDuplicates.toUpperCase().includes('NONE') && (dupeId = dupeIds.find(id => id == hasDuplicates.trim())) != null && dupeId != issueData.id) {
First-time contributor

Improved duplicate detection logic, but the condition is overly complex. Consider simplifying: dupeId = dupeIds.find(id => id == hasDuplicates.trim()); if(hasDuplicates && !hasDuplicates.toUpperCase().includes('NONE') && dupeId != null && dupeId != issueData.id) could be clearer with early returns or better variable naming.

Improved duplicate detection logic, but the condition is overly complex. Consider simplifying: `dupeId = dupeIds.find(id => id == hasDuplicates.trim()); if(hasDuplicates && !hasDuplicates.toUpperCase().includes('NONE') && dupeId != null && dupeId != issueData.id)` could be clearer with early returns or better variable naming.
First-time contributor

Potential type coercion bug: Using == instead of === in dupeIds.find(id => id == hasDuplicates.trim()) and dupeId != issueData.id may cause unexpected behavior if IDs are sometimes strings and sometimes numbers. Use strict equality (=== and !==) for more predictable comparisons.

Potential type coercion bug: Using `==` instead of `===` in `dupeIds.find(id => id == hasDuplicates.trim())` and `dupeId != issueData.id` may cause unexpected behavior if IDs are sometimes strings and sometimes numbers. Use strict equality (`===` and `!==`) for more predictable comparisons.
ztimson marked this conversation as resolved
@@ -25,3 +26,4 @@
token = process.env['AI_TOKEN'];
console.log(`Reviewing: ${root}\n`);
const info = await fetch(`${git}/api/v1/repos/${owner}/${repo}/pulls/${pr}`)
First-time contributor

Missing error handling: The fetch call should handle errors. If the API call fails, info will be undefined and line 30 will throw an error when trying to access info.labels.

Missing error handling: The fetch call should handle errors. If the API call fails, `info` will be undefined and line 30 will throw an error when trying to access `info.labels`.
ztimson marked this conversation as resolved
src/review.mjs Outdated
@@ -26,2 +27,4 @@
console.log(`Reviewing: ${root}\n`);
const info = await fetch(`${git}/api/v1/repos/${owner}/${repo}/pulls/${pr}`)
.then(async resp => { return resp.ok ? resp.json() : throw new Error(`${resp.status} ${await resp.text()}`); });
First-time contributor

Logic error: The condition info.labels?.length > 0 || !info.labels.some(l => l.name === labelEnabled) will always be true when labels exist. This should use && instead of ||. Currently, if labels.length > 0, it skips even if the enabled label is present. The correct logic should be: !info.labels?.some(l => l.name === labelEnabled) or info.labels?.length === 0 || !info.labels.some(l => l.name === labelEnabled)

Logic error: The condition `info.labels?.length > 0 || !info.labels.some(l => l.name === labelEnabled)` will always be true when labels exist. This should use `&&` instead of `||`. Currently, if labels.length > 0, it skips even if the enabled label is present. The correct logic should be: `!info.labels?.some(l => l.name === labelEnabled)` or `info.labels?.length === 0 || !info.labels.some(l => l.name === labelEnabled)`
ztimson marked this conversation as resolved
src/review.mjs Outdated
@@ -54,3 +62,3 @@
model: [host, model],
path: process.env['path'] || os.tmpdir(),
system: `You are a code reviewer. Analyze the git diff and use the \`recommend\` tool for EACH issue you find. You must call \`recommend\` exactly once for every bug or improvement opportunity directly related to changes. Ignore formatting recommendations. After making all recommendations, provide some concluding remarks about the overall state of the changes.${existingComments}`,
system: `You are a code reviewer. Analyze the git diff and use the \`recommend\` tool for EACH issue you find. You must call \`recommend\` exactly once for every bug or improvement opportunity directly related to changes. Ignore formatting recommendations. After making all recommendations, provide a quick 75 words or less sitrep.${existingComments}`,
First-time contributor

Typo in system prompt: 'sitrep' is informal military jargon. Consider using more professional language like 'summary' or 'overview' for better clarity in a code review context.

Typo in system prompt: 'sitrep' is informal military jargon. Consider using more professional language like 'summary' or 'overview' for better clarity in a code review context.
ztimson marked this conversation as resolved
ztimson added 1 commit 2026-01-14 13:51:44 -05:00
Fixed label condition check 💀
All checks were successful
Publish Library / Build NPM Project (push) Successful in 9s
Publish Library / Tag Version (push) Successful in 23s
Code review / review (pull_request) Successful in 49s
3b01e1bfc1
assistant reviewed 2026-01-14 13:52:35 -05:00
assistant left a comment
First-time contributor

Review Summary

This PR introduces label-based triggering for AI code reviews and refines the duplicate detection logic. However, there are critical bugs that will prevent the code from running:

Critical Issues:

  1. Syntax error in review.mjs line 30 - The throw statement cannot be used directly in a ternary expression, causing a parse error
  2. Logic error in review.mjs line 31 - The label checking condition appears inverted, likely causing reviews to skip when they should run

Moderate Issues:
3. Missing error handling for network failures on the fetch call
4. Type coercion bugs in refine.mjs using == instead of ===
5. Potential null/undefined errors when PR title/body are missing

Minor Issues:
6. Informal language ("sitrep") in system prompt
7. Redundant check in duplicate detection

The workflow configuration changes and version bump look good. The PR template simplification is appropriate. Please address the critical syntax and logic errors before merging, as they will cause runtime failures.

## Review Summary This PR introduces label-based triggering for AI code reviews and refines the duplicate detection logic. However, there are **critical bugs** that will prevent the code from running: **Critical Issues:** 1. **Syntax error in review.mjs line 30** - The `throw` statement cannot be used directly in a ternary expression, causing a parse error 2. **Logic error in review.mjs line 31** - The label checking condition appears inverted, likely causing reviews to skip when they should run **Moderate Issues:** 3. Missing error handling for network failures on the fetch call 4. Type coercion bugs in refine.mjs using `==` instead of `===` 5. Potential null/undefined errors when PR title/body are missing **Minor Issues:** 6. Informal language ("sitrep") in system prompt 7. Redundant check in duplicate detection The workflow configuration changes and version bump look good. The PR template simplification is appropriate. Please address the critical syntax and logic errors before merging, as they will cause runtime failures.
@@ -184,2 +184,3 @@
// Handle duplicates
if(hasDuplicates && hasDuplicates !== 'NONE' && (dupeId = dupeIds.find(id => id == hasDuplicates.trim()))) {
if(hasDuplicates && !hasDuplicates.toUpperCase().includes('NONE') && (dupeId = dupeIds.find(id => id == hasDuplicates.trim())) != null && dupeId != issueData.id) {
First-time contributor

Potential type coercion bug: Using == instead of === in dupeIds.find(id => id == hasDuplicates.trim()) may cause unexpected behavior if IDs are sometimes strings and sometimes numbers. Use strict equality (===) for more predictable comparisons.

Potential type coercion bug: Using `==` instead of `===` in `dupeIds.find(id => id == hasDuplicates.trim())` may cause unexpected behavior if IDs are sometimes strings and sometimes numbers. Use strict equality (`===`) for more predictable comparisons.
First-time contributor

Redundant check: The condition dupeId != issueData.id is unnecessary since the search is limited to 3 results and unlikely to return the current issue. However, if kept, use strict inequality (!==) instead of != for consistency.

Redundant check: The condition `dupeId != issueData.id` is unnecessary since the search is limited to 3 results and unlikely to return the current issue. However, if kept, use strict inequality (`!==`) instead of `!=` for consistency.
ztimson marked this conversation as resolved
@@ -25,3 +26,4 @@
token = process.env['AI_TOKEN'];
console.log(`Reviewing: ${root}\n`);
const info = await fetch(`${git}/api/v1/repos/${owner}/${repo}/pulls/${pr}`)
First-time contributor

Missing error handling: The fetch call should handle network errors with a .catch() handler. If the API call fails due to network issues, the promise will reject and crash the script before reaching line 30.

Missing error handling: The fetch call should handle network errors with a .catch() handler. If the API call fails due to network issues, the promise will reject and crash the script before reaching line 30.
ztimson marked this conversation as resolved
src/review.mjs Outdated
@@ -26,2 +27,4 @@
console.log(`Reviewing: ${root}\n`);
const info = await fetch(`${git}/api/v1/repos/${owner}/${repo}/pulls/${pr}`)
.then(async resp => { return resp.ok ? resp.json() : throw new Error(`${resp.status} ${await resp.text()}`); });
First-time contributor

Syntax error: throw new Error(...) cannot be used directly in a ternary expression. This should be wrapped in a block: resp.ok ? resp.json() : (() => { throw new Error(...); })() or use an if-else statement instead.

Syntax error: `throw new Error(...)` cannot be used directly in a ternary expression. This should be wrapped in a block: `resp.ok ? resp.json() : (() => { throw new Error(...); })()` or use an if-else statement instead.
ztimson marked this conversation as resolved
src/review.mjs Outdated
@@ -27,1 +28,4 @@
console.log(`Reviewing: ${root}\n`);
const info = await fetch(`${git}/api/v1/repos/${owner}/${repo}/pulls/${pr}`)
.then(async resp => { return resp.ok ? resp.json() : throw new Error(`${resp.status} ${await resp.text()}`); });
if(info.labels?.length > 0 && !info.labels.some(l => l.name === labelEnabled)) {
First-time contributor

Logic error: The condition info.labels?.length > 0 && !info.labels.some(l => l.name === labelEnabled) will skip the review when labels exist but the enabled label is NOT present. This appears backwards - it should run when the label IS present. Consider: if(!info.labels?.some(l => l.name === labelEnabled)) to skip when the label is missing.

Logic error: The condition `info.labels?.length > 0 && !info.labels.some(l => l.name === labelEnabled)` will skip the review when labels exist but the enabled label is NOT present. This appears backwards - it should run when the label IS present. Consider: `if(!info.labels?.some(l => l.name === labelEnabled))` to skip when the label is missing.
ztimson marked this conversation as resolved
src/review.mjs Outdated
@@ -54,3 +62,3 @@
model: [host, model],
path: process.env['path'] || os.tmpdir(),
system: `You are a code reviewer. Analyze the git diff and use the \`recommend\` tool for EACH issue you find. You must call \`recommend\` exactly once for every bug or improvement opportunity directly related to changes. Ignore formatting recommendations. After making all recommendations, provide some concluding remarks about the overall state of the changes.${existingComments}`,
system: `You are a code reviewer. Analyze the git diff and use the \`recommend\` tool for EACH issue you find. You must call \`recommend\` exactly once for every bug or improvement opportunity directly related to changes. Ignore formatting recommendations. After making all recommendations, provide a quick 75 words or less sitrep.${existingComments}`,
First-time contributor

Typo in system prompt: 'sitrep' is informal military jargon. Consider using more professional language like 'summary' or 'overview' for better clarity in a code review context.

Typo in system prompt: 'sitrep' is informal military jargon. Consider using more professional language like 'summary' or 'overview' for better clarity in a code review context.
ztimson marked this conversation as resolved
src/review.mjs Outdated
@@ -88,3 +96,3 @@
});
const messages = await ai.language.ask(gitDiff);
const messages = await ai.language.ask(`Title: ${info.title}
First-time contributor

Potential null/undefined error: If info.title or info.body is null/undefined, this will insert "null" or "undefined" as text in the prompt. Add fallback values: Title: ${info.title || 'No title'} and ${info.body || 'No description'}.

Potential null/undefined error: If `info.title` or `info.body` is null/undefined, this will insert "null" or "undefined" as text in the prompt. Add fallback values: `Title: ${info.title || 'No title'}` and `${info.body || 'No description'}`.
ztimson marked this conversation as resolved
ztimson added 1 commit 2026-01-14 14:05:45 -05:00
Fixed more logic checks
Some checks failed
Publish Library / Build NPM Project (push) Successful in 4s
Code review / review (pull_request) Has been cancelled
Publish Library / Tag Version (push) Successful in 6s
7447204351
ztimson merged commit 1ab97c2676 into master 2026-01-14 14:06:21 -05:00
ztimson deleted branch review-labels 2026-01-14 14:06:22 -05:00
Sign in to join this conversation.