skills / code

code-review-excellence

what it does

Master effective code review practices to provide constructive feedback, catch bugs early, and foster knowledge sharing while maintaining team morale. Use when reviewing pull requests, establishing review standards, or mentoring developers.

Verified Before and after: 2 models 1 try per case View source Download .zip

Compare the answers

Answers from Claude Sonnet 5.5 and GPT-6.1 Sol · try 1 of 1

Same request, same model, once with the skill and once without. Read both and judge for yourself.

“Review this before I merge please. It's the CSV contact import we talked about.”

Source material given with the request

PR #92 "Contact import from CSV" Description: Parses the uploaded CSV and inserts each row as a contact. Returns how many were imported so the UI can show "Imported N of M contacts". Tested locally with a 3-row file. --- /dev/null +++ b/src/import/importContacts.ts @@ -0,0 +1,19 @@ +import { Db } from "../db"; +import { CsvRow, toContact } from "./csv"; + +export interface ImportResult { + imported: number; + total: number; +} + +export async function importContacts(rows: CsvRow[], db: Db): Promise<ImportResult> { + let imported = 0; + + rows.forEach(async (row) => { + const contact = toContact(row);
Show the rest (7 more lines)
+ await db.contacts.insert(contact); + imported++; + }); + + return { imported, total: rows.length }; +}
with the skill
## Verdict: 🔄 Request changes The result shape fits the UI requirement, but there’s a blocking async issue. ### 🔴 Blocking — the import returns before inserts finish **`src/import/importContacts.ts`, `rows.forEach(async …)`** `forEach` doesn’t await promises returned by its callback. For any nonempty input, this function returns `{ imported: 0, total: rows.length }` before the insert continuations run—even though inserts may complete afterward. Errors from `toContact` or `insert` also won’t reject the `importContacts` promise, potentially becoming unhandled rejections. Use an awaited loop for predictable completion and error propagation: ```ts export async function importContacts( rows: CsvRow[], db: Db, ): Promise<ImportResult> { let imported = 0; for (const row of rows) { const contact = toContact(row);
Show the rest (24 more lines)
await db.contacts.insert(contact); imported++; } return { imported, total: rows.length }; } ``` ### 🟡 Important — define partial-failure behavior If row 2 fails, the loop above rejects, but row 1 may already have been saved. Before merging, clarify the intended behavior: - **All-or-nothing:** wrap the import in a database transaction. - **Best effort:** handle failures per row and return enough information for the UI to report imported versus failed rows. The loop fixes the async bug, but doesn’t by itself establish either policy. ### Tests to add The local three-row check isn’t enough to catch this reliably. Add automated tests for: - Empty input returns `{ imported: 0, total: 0 }`. - Three valid rows return `{ imported: 3, total: 3 }`. - A deliberately delayed insert keeps the import promise pending until completion. - Conversion and insert failures follow the chosen failure policy. I’d merge once the async issue is fixed and failure behavior is defined and tested.
without
**Blocker: the function returns before the inserts finish.** `forEach` ignores the promises returned by its async callback, so `importContacts()` returns `{ imported: 0, total: rows.length }` before any successful insert increments the counter. The caller cannot rely on completion, and conversion/insert failures won’t reject `importContacts()`—they can become unhandled rejections instead. If the intended behavior is to stop and reject on the first failed row, use an awaited loop: ```ts export async function importContacts( rows: CsvRow[], db: Db, ): Promise<ImportResult> { let imported = 0; for (const row of rows) { const contact = toContact(row); await db.contacts.insert(contact); imported++; } return { imported, total: rows.length };
Show the rest (13 more lines)
} ``` **Clarify failure semantics before merging.** The UI wording “Imported N of M” suggests partial success, but the fix above rejects on failure and leaves earlier inserts committed unless a surrounding transaction handles rollback. Decide whether imports should: - Be atomic: roll back all rows if any fails. - Allow partial success: handle failures per row and return counts, ideally with row-level errors. **Tests to add:** - Delayed inserts: the import promise stays pending until inserts finish and returns the correct count. - Conversion or insert failure: verify the chosen rejection/partial-success behavior. - Empty input: returns `{ imported: 0, total: 0 }`. I’d hold the merge for the async fix and an explicit failure policy.

Answers are shown exactly as the model wrote them, from the first try, and nothing is picked by hand.

The models

2 models

Claude Sonnet 5.5

made by Anthropic

claude-sonnet-5-5 · revision not reported by the provider

1 try per case · tested 3 Nov 2026

GPT-6.1 Sol

made by OpenAI

gpt-6.1-sol · revision not reported by the provider

1 try per case · tested 3 Nov 2026

The tasks

written by Carte Blanche
py-chunked-clean-diff

“Quick review before I merge? Mostly want to know if anything blocks it.”

py-search-injection-pagination

“Can you review this PR? It adds order search to our internal admin API.”

py-wallet-withdraw-race

“Please review this change to our wallet service.”

ts-async-foreach-import

“Review this before I merge please. It's the CSV contact import we talked about.”

ts-file-delete-first-pr

“This is Priya's first PR since she joined the team last week. Can you review it? I'll paste your comments into GitHub.”

Install

Download the .zip and unzip it. Put its files, in a folder named code-review-excellence, here:

Claude Code~/.claude/skills/Every project. For one project only, use .claude/skills/ inside it.
Codex~/.agents/skills/Every project. For one repository only, use .agents/skills/ inside it.
Cursor~/.cursor/skills/Cursor also reads the Claude Code and Codex folders above.

Then start a new session and ask for what the skill does. Other agents that read SKILL.md have their own skills folder; check their docs.

Coming after launch: get skills from inside your agent, no download needed.