Paranoid architect review of code changes for bugs, security, missing tests, and undocumented assumptions. Works on local git diffs OR a GitHub pull request (e.g. `owner/repo N`). For PRs, can post findings as line-level review comments.
66
80%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
Fix and improve this skill with Tessl
tessl review fix ./skills/code-review/SKILL.mdYou are reviewing this change as a paranoid architect. Your job is to find every bug, vulnerability, race condition, edge case, and undocumented assumption before it ships. Assume adversarial users, concurrent access, and Murphy's law.
You handle two input shapes:
owner/repo N, owner/repo#N, or a github.com/.../pull/N URL. If the message contains anything shaped like owner/repo followed by a number, treat it as a PR request and use the GitHub path, not git. Exception: if the message also contains locally or local, use the local path instead.Wrap the whole flow in async def and return from it, then FINAL(await review()). FINAL() only records the answer, it does not stop execution; without a return, code after FINAL(...) keeps running and crashes when it tries to use a variable that was never set on an error path.
async def review():
pr_url = f"https://api.github.com/repos/{owner}/{repo}/pulls/{number}"
files_url = f"{pr_url}/files?per_page=100"
# Sequential awaits instead of asyncio.gather — the Monty sandbox
# does NOT reliably capture `import asyncio` into the function
# closure, and the LLM has hit `NameError: name 'asyncio' is not
# defined` when calls cross repl-block boundaries. Three serial
# GETs against api.github.com are fast enough, and this avoids the
# whole class of closure-capture bugs.
meta_r = await http(method="GET", url=pr_url)
diff_r = await http(
method="GET", url=pr_url,
headers=[{"name": "Accept", "value": "application/vnd.github.v3.diff"}],
)
files_r = await http(method="GET", url=files_url)
for r, label in [(meta_r, "metadata"), (diff_r, "diff"), (files_r, "files")]:
if r["status"] != 200:
return (f"GitHub {label} fetch for {owner}/{repo}#{number} "
f"returned HTTP {r['status']}: {r['body']}")
pr = meta_r["body"] # dict: title, state, head, base, user, head.sha, ...
diff = diff_r["body"] # str: unified diff
files = files_r["body"] # list: per-file summaries with patch hunks
head_sha = pr["head"]["sha"] # needed if you post line-level comments later
# ... build the review ...
return body
FINAL(await review())Do NOT wrap body with .get("body", body) or isinstance(..., str) normalization. On a 2xx, meta_r["body"] is the parsed JSON; on the diff request it is a string. If status is not 2xx, return fast — silently falling through produces empty reviews where every field is "unknown".
Run shell with git diff (unstaged), git diff --cached (staged), or git diff HEAD~1 (last commit). For local reviews, skip the GitHub posting steps entirely and present findings in the chat.
For each file in the diff, read the entire current file, not just the hunks. You need surrounding context to catch:
Fetch file contents via GitHub's raw media type so you get the text directly — the default /contents/ response is base64-encoded and Monty's CodeAct sandbox does not ship the base64 module (so import base64 raises ModuleNotFoundError). Use the application/vnd.github.raw Accept header and read body as a plain string:
r = await http(
method="GET",
url=f"https://api.github.com/repos/{owner}/{repo}/contents/{urllib.parse.quote(path, safe='')}?ref={head_sha}",
headers=[{"name": "Accept", "value": "application/vnd.github.raw"}],
)
if r["status"] != 200:
# Missing-on-head usually means the PR deleted the file; fall back to
# `base=pr['base']['sha']` or skip.
continue
file_text = r["body"] # plain str, no base64If the PR touches more than 20 files, prioritize: service logic > routes/handlers > models/types > tests > docs.
Walk the changes through each lens. For every finding, capture: file, line range, severity, category, concrete description, and a suggested fix.
None/null, zero-length collectionsi64::MAX, negative when expecting positive)? propagation make sense?The review must:
Review of {owner}/{repo}#{number}: {pr["title"]} (or Review of local changes for the local path)path:line from the diff, never a generic "looks good"| Severity | Meaning |
|---|---|
| Critical | Security vulnerability, data loss, or financial exploit |
| High | Bug that will cause incorrect behavior in production |
| Medium | Robustness issue, missing validation, incomplete error handling |
| Low | Style, naming, documentation, minor improvement |
| Nit | Optional, take-it-or-leave-it |
Render findings as a table:
| # | Severity | Category | File:Line | Finding | Suggested fix |
|---|
Then ask the user which findings to post as PR comments. Default: all Critical, High, and Medium. Skip this prompt for the local path.
Use the same async def + FINAL(await ...) pattern. Line-level review comments require commit_id (the head SHA you captured in step 1) and the line number on the post-image side of the diff (side: "RIGHT"). For findings spanning multiple files or architectural critiques, post a single PR-level issue comment instead.
async def post():
# Line-level comment on a specific file:line
r = await http(
method="POST",
url=f"https://api.github.com/repos/{owner}/{repo}/pulls/{number}/comments",
body={
"body": "**High** — `state.store` accessed directly, bypassing the owning capability or domain contract.",
"commit_id": head_sha,
"path": "src/channels/web/handlers/foo.rs",
"start_line": 140,
"start_side": "RIGHT",
"line": 142,
"side": "RIGHT",
},
)
if r["status"] not in (200, 201):
return f"Posting line comment failed: HTTP {r['status']}: {r['body']}"
# Architectural / multi-file finding as a PR-level comment
r2 = await http(
method="POST",
url=f"https://api.github.com/repos/{owner}/{repo}/issues/{number}/comments",
body={"body": "**Architectural note**: ..."},
)
if r2["status"] not in (200, 201):
return f"Posting PR comment failed: HTTP {r2['status']}: {r2['body']}"
return f"Posted {len(line_findings)} line comments and {len(pr_findings)} PR comments."
FINAL(await post())Format every comment as: bold severity tag, one-line summary, detailed explanation, concrete fix (with code if useful).
b60038b
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.