From hotl
Reviews pull requests across description, code changes, scans, and unit tests using parallel subagents. Supports GitHub/gh, GitLab/glab; outputs structured reports and optional GitHub comments.
npx claudepluginhub yimwoo/hotl-plugin --plugin hotlThis skill uses the workspace's default tool permissions.
Review a pull request end-to-end across 4 dimensions (description/ticket, code changes, code scan, unit tests) using parallel subagents. Produces a structured verdict report and optionally posts line-level comments on GitHub.
Designs and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
Designs, implements, and audits WCAG 2.2 AA accessible UIs for Web (ARIA/HTML5), iOS (SwiftUI traits), and Android (Compose semantics). Audits code for compliance gaps.
Review a pull request end-to-end across 4 dimensions (description/ticket, code changes, code scan, unit tests) using parallel subagents. Produces a structured verdict report and optionally posts line-level comments on GitHub.
Announce: "Starting PR review. Detecting platform and fetching PR data..."
This skill produces a structured review report. The canonical schema is defined in
docs/contracts/pr-review-output.md. All platforms must emit every section in that
contract. Platform-specific rendering (tables, inline comments, etc.) is handled by
platform docs, not this skill.
Key rules from the contract:
gh pr view --json number,title,body,baseRefName,headRefName,url → if succeeds, use GitHub modeglab mr view → if succeeds, use GitLab mode| Platform | CLI | Mode | Capabilities |
|---|---|---|---|
| GitHub (public) | gh | full | Local report + post review comments |
| GitLab | glab | local-only | Local report only |
| Enterprise/VPN | none | local-only | Local report only (git diff fallback) |
Full mode (GitHub):
gh pr view <number> --json title,body,baseRefName,headRefName,changedFiles,additions,deletions
gh pr diff <number>
GitLab mode:
glab mr view <number>
glab mr diff <number>
Local-only fallback:
git log --oneline main..HEAD
git diff main...HEAD
git diff --name-only main...HEAD
JIRA-1234, ABC-123, #123, or full URLs (Jira, GitHub Issues, GitLab Issues, Linear)gh issue view <number> --json title,bodyWebFetch the ticket page (user must be authenticated/on VPN)glab issue view <number>WebFetch and extract textDispatch 4 subagents simultaneously using the Agent tool. Pass each subagent the PR data collected in Step 1.
Prompt template:
---
You are reviewing a PR's description and ticket alignment.
**PR Title:** {title}
**PR Description:**
{body}
**Linked Ticket (if available):**
{ticket_content or "No ticket linked/accessible"}
## Review Checklist
1. **Description quality:**
- Does it explain WHY this change is needed?
- Does it explain WHAT changed?
- Does it explain HOW it works (if non-obvious)?
- Is it clear enough for a reviewer unfamiliar with the context?
2. **Ticket alignment (if ticket available):**
- Does the PR address the ticket's requirements?
- Are all acceptance criteria covered?
- Is there scope creep (PR does more than ticket asks)?
- Is there scope gap (ticket asks for more than PR delivers)?
## Output Format
Return EXACTLY this format (two separate blocks — one for description, one for ticket):
DIMENSION: Description VERDICT: PASS | WARN | BLOCK FINDINGS:
DIMENSION: Ticket Alignment VERDICT: PASS | WARN | BLOCK | N/A FINDINGS:
---
Prompt template:
---
You are reviewing code changes in a PR.
**Changed files:** {file_list}
**Full diff:**
{diff}
## Review Checklist
1. **Correctness:** Logic errors, off-by-one, null/undefined risks, race conditions
2. **Edge cases:** Missing error handling at system boundaries, unhandled states
3. **Readability:** Unclear naming, magic numbers, overly complex logic
4. **Design:** YAGNI violations, unnecessary abstractions, code duplication. Reference `docs/checklists/architecture-and-design.md` for SOLID and architecture smell heuristics. These are review heuristics, not merge policy — use professional judgment to determine severity. If the checklist file is not available, continue with best-effort review.
5. **Security (quick scan):** Obvious injection risks, hardcoded secrets (detailed scan in separate subagent)
6. **Removal and simplification:** Reference `docs/checklists/removal-and-simplification.md`. Flag unused/redundant code introduced or left behind by this PR. Classify as safe-delete-now or defer-with-plan. If the checklist file is not available, continue with best-effort review.
## Output Format
Return EXACTLY this format:
DIMENSION: Code Changes VERDICT: PASS | WARN | BLOCK FINDINGS:
---
Prompt template:
---
You are performing a code scan on PR changes.
**Changed files:** {file_list}
**Full diff:**
{diff}
## Phase 1: Project Linters
Discover and run existing linters/scanners on changed files ONLY:
1. Check for config files: `.eslintrc*`, `pylintrc`, `.flake8`, `pyproject.toml` (ruff), `biome.json`, `.semgreprc`, `tslint.json`
2. For each found linter, run it on changed files only
3. Report findings with file:line references
If no linters are configured, note "No project linters found" and proceed to Phase 2.
## Phase 2: AI Security & Quality Scan
Reference `docs/checklists/security-and-reliability.md` for expanded coverage beyond OWASP Top 10. If the checklist file is not available, continue with best-effort review.
Analyze the diff for:
1. **OWASP Top 10:** Injection (SQL, command, XSS), broken auth, sensitive data exposure, XXE, broken access control, security misconfiguration, insecure deserialization
2. **Hardcoded secrets:** API keys, tokens, passwords, connection strings in code
3. **Unsafe patterns:** eval(), dangerouslySetInnerHTML, shell exec with user input, unparameterized queries
4. **Dependency concerns:** New dependencies added — are they well-maintained? Known vulnerabilities?
5. **Concurrency risks:** Race conditions, TOCTOU (check-then-act without locks), missing synchronization on shared state
6. **Crypto and serialization:** Unsafe deserialization of untrusted input, weak or deprecated cryptographic algorithms, insecure defaults
7. **Resource exhaustion:** Missing rate limits, unbounded loops controlled by external input, CPU/memory hotspots
## Output Format
Return EXACTLY this format:
DIMENSION: Code Scan VERDICT: PASS | WARN | BLOCK LINTER_RESULTS:
---
Prompt template:
---
You are reviewing the unit test status for a PR.
**Changed files:** {file_list}
**Full diff:**
{diff}
## Phase 1: Run Tests
1. Detect test framework from project config:
- `package.json` → look for jest/vitest/mocha scripts
- `pyproject.toml` / `setup.cfg` → pytest
- `Cargo.toml` → cargo test
- `go.mod` → go test
2. Run the test suite. Report: total tests, passed, failed, skipped.
3. If tests fail → this is a BLOCK finding.
## Phase 2: Coverage (if tooling exists)
1. Check if coverage tooling is configured (nyc, coverage.py, istanbul, c8)
2. If available, run coverage on changed files
3. Flag changed lines that are NOT covered by tests
## Phase 3: Test Quality (AI Review)
Use boundary-condition heuristics from `docs/checklists/performance-and-boundary-conditions.md` to assess whether tests cover risky input/state transitions. If the checklist file is not available, continue with best-effort review.
Review test files in the diff:
1. Are assertions meaningful (not just `expect(true).toBe(true)`)?
2. Are edge cases tested (empty input, boundaries, error paths)?
3. Are tests testing behavior, not implementation details?
4. Any redundant/duplicate tests?
5. Do tests cover risky boundary conditions (null/undefined, empty collections, numeric limits, off-by-one)?
## Output Format
Return EXACTLY this format:
DIMENSION: Unit Tests VERDICT: PASS | WARN | BLOCK TEST_RESULTS:
---
After all subagents return, the orchestrator assembles the final review artifact.
Assemble the final review artifact following docs/contracts/pr-review-output.md, and emit any platform-native inline review findings separately where supported.
Specifically:
::code-comment in Codex, line-level GitHub review comments in Claude Code full mode)Only when platform is GitHub (public) and mode is full:
gh api repos/{owner}/{repo}/pulls/{number}/reviews --method POST \
--field body="PR Review Summary: ..." \
--field event="REQUEST_CHANGES" \
--input - <<'EOF'
{
"comments": [
{"path": "src/auth.ts", "line": 42, "body": "BLOCK: SQL concatenation — use parameterized query"},
{"path": "src/auth.ts", "line": 78, "body": "WARN: Magic number 3600 — extract to named constant"}
]
}
EOF
For GitLab and enterprise platforms: Skip posting entirely. The local report is the deliverable.
| Scenario | Behavior |
|---|---|
gh not installed | Local-only mode, skip GitHub posting |
glab not installed | Local-only mode using git diff |
| Ticket URL unreachable | Skip ticket alignment, note in report |
| Linters not configured | Note "No linters found", AI scan still runs |
| Test framework not detected | Note "Could not detect test framework", skip test run, AI still reviews test files in diff |
| Coverage not configured | Note "Coverage not available", skip coverage analysis |
| GitHub API posting fails | Fall back to local report, log error |
# Review current branch's PR (auto-detect)
/hotl:pr-review
# Review a specific PR by URL
/hotl:pr-review https://github.com/org/repo/pull/123
# Review a GitLab MR
/hotl:pr-review https://gitlab.company.com/team/repo/-/merge_requests/45