---
context: fork
name: code-slop-reviewer
description: "Detects AI-generated code slop patterns (defensive try/catch wrapping, premature abstractions, builtin wrappers, owner-less TODOs, over-configurable params) and scores 0-100 across five tiers. Gating input for code-reviewer agent. Use when user asks about code slop, AI 코드 검토, over-engineering 탐지, defensive code, boilerplate 코드, PR 리뷰, 코드 품질 게이트, slop detection, or LLM 코드 검증."
lang: [en, ko]
platforms: [claude-code, gemini-cli, codex-cli, cursor]
level: 3
triggers:
  - "code slop"
  - "code slop review"
  - "AI 코드 검토"
  - "slop detection"
  - "defensive code"
  - "over-engineering 검증"
  - "boilerplate code"
  - "LLM 코드 품질"
  - "PR 슬롭 검사"
  - "코드 품질 게이트"
  - "AI-generated code review"
  - "code polish review"
  - "코드 AI 티 제거"
agents:
  - "code-reviewer"
  - "refactor-cleaner"
  - "tdd-guide"
tokens: "~4K"
category: "quality"
whenNotToUse: "Do not apply to test fixtures, generated code (protobuf stubs, GraphQL codegen), or vendor files. Do not run on patches authored by humans with explicit style justifications — use code-reviewer directly instead."
---

# Code Slop Reviewer

## When This Skill Applies

- Before merging any AI-assisted pull request
- Before `code-reviewer` agent signs off on a commit
- Before `refactor-cleaner` agent plans a rewrite (baseline measurement)
- When a teammate-generated patch adds >50 lines of new code
- When a file has been regenerated by an LLM rather than edited line-by-line
- **HARD rule**: Run this skill on every patch produced by `tdd-guide`, `frontend-developer`, `backend-developer`, `refactor-cleaner` teammate sessions before the patch reaches `code-reviewer`

## Core Guidance

### 1. What Is Code Slop?

Code slop is the residue of language-model pattern-matching on training data that rewarded verbose, defensive, "safe-looking" code. The model learns that certain shapes — wrapping calls in try/catch, adding null-checks on guaranteed values, factoring single-use logic into helpers — appear near "professional code" signals in its training set. The result compiles, passes shallow review, and silently adds surface area that must be read, understood, and maintained forever.

**Three failure modes:**
- **Defensive boilerplate**: Code that guards against conditions the surrounding contract already prevents (null checks on non-null returns, try/catch around pure functions, type assertions on already-typed values)
- **Premature abstraction**: Factories, wrappers, and config objects for use cases that do not exist yet (wrapping `Array.isArray` as `isArray`, 10-param options object where 2 are ever used, strategy pattern for a single branch)
- **Narrative clutter**: Comments, TODOs, and log statements that restate the code in English instead of encoding missing context (`// increment counter` above `i++`, `TODO: fix later` without owner/date, log lines that duplicate the return value)

This skill is **not** a linter. Linters catch syntactic defects; slop is legal code that shouldn't exist.

---

### 2. Structural Slop Categories (10)

Each category has a severity weight used in scoring. Weights are an initial proposal — tune with telemetry from `plugins/_shared/rubrics/auto-flag-schema.md` flag-review logs.

| # | Category | Weight | Symptom |
|---|----------|:-----:|---------|
| 1 | Defensive try-swallow | 7 | `try { ... } catch {}` or `catch (e) { /* ignore */ }` wrapping single expressions with no recovery path |
| 2 | Premature factory | 6 | Factory function with 1-2 call sites and no polymorphism; abstraction cost exceeds benefit |
| 3 | Builtin wrapper | 5 | `function isArray(x) { return Array.isArray(x) }` style re-exports of language/stdlib primitives |
| 4 | Redundant null-check | 4 | `if (x != null) x.method()` where `x` is typed non-null or was just assigned a literal |
| 5 | Over-configurable params | 6 | Function with ≥8 optional params where callers pass 1-2; options bag inflation |
| 6 | Silent error swallow | 9 | `catch (e) {}` or logging without rethrowing/returning a failure mode; breaks observability |
| 7 | Restate-the-code comment | 3 | Comment paraphrases the next line in English (`// set user name to input`) |
| 8 | Trivial config object | 5 | `{ enabled: true, mode: "default" }` passed to a 5-line function; complexity without flexibility |
| 9 | Type-assertion chain | 6 | `value as unknown as TargetType` or `@ts-ignore` / `any` cascades to bypass type friction |
| 10 | Owner-less TODO | 5 | `// TODO: handle edge case` with no owner, no date, no issue reference |

**Additional negative signals (weight 4 each):**
- Commented-out code blocks longer than 3 lines (use VCS instead)
- Unused imports or unused function parameters beyond the first
- Functions returning only early-exits with no "happy path" work
- Repetition of the same error-handling block 3+ times when one helper would do (but see anti-pattern #1 below: do not invert into premature abstraction)

---

### 3. 5-Tier Severity Scoring

Initial proposal — tune thresholds with telemetry once enough PR samples exist.

| Score | Tier | Criteria | Gate Decision |
|------:|------|---------|---------------|
| 90-100 | Clean | 0-1 minor flags, no high-weight findings | Auto-approve path; minor polish only |
| 70-89 | Acceptable | 2-4 flags total, no critical (weight ≥7) | Merge after addressing flagged lines |
| 50-69 | Needs Work | 5-8 flags OR any critical (weight ≥7) | Block merge; request targeted rewrite |
| 30-49 | Heavy Slop | 9-15 flags OR ≥2 critical | Block merge; revise affected blocks |
| 0-29 | Reject | 16+ flags OR silent-error + type-assertion cluster | Discard patch; re-author from requirements |

**Score formula:**

```
score = max(0, 100 - sum(weight_i × count_i))
```

Cap each category's contribution at `3 × weight` so a single pattern repeated 20 times does not dominate; separate repetition flag fires instead.

**Publish gate:**
- `score ≥ 70` → may proceed to `code-reviewer` agent
- `50 ≤ score < 70` → requires human review note before `code-reviewer` runs
- `score < 50` → hard block; return patch to authoring teammate

---

### 4. Language-Specific Vocabulary

Full pattern dictionary lives in `${CLAUDE_SKILL_DIR}/references/code-slop-patterns.md`. Summary by language:

| Language | Pattern Count | Top Flags |
|----------|:-------------:|-----------|
| JavaScript / TypeScript | 17 | try-swallow, `as unknown as`, options-bag bloat, `any` cascade, `console.log` left in |
| Python | 12 | `except Exception: pass`, `lambda x: x` identity, `if x is not None and x != "":`, unused dataclass fields |
| Cross-language | 6 | commented-out blocks, owner-less TODOs, restate-the-code comments, single-use helper wrappers |

Each language section in the reference file supplies: pattern ID, weight, regex (where feasible), rationale, and before/after fix example. Regex is a screening tool only — final judgment requires reading the surrounding 20 lines.

---

### 5. Language-Idiom Allowlist (False-Positive Guard)

The following shapes look slop-like but are idiomatic in their context. Do not flag:

| Context | Idiom | Why It Is Not Slop |
|---------|-------|--------------------|
| Node.js ESM dynamic import | `try { await import(x) } catch { /* optional */ }` | Optional plugin loading is a real recovery path |
| React `useEffect` cleanup | `return () => {}` empty cleanup | Required by lifecycle contract when no teardown exists |
| Python context manager | `except Exception: raise` with finally-style logging | Legitimate re-raise for audit trail |
| Protocol / interface stubs | Empty method body with `pass` / `throw new Error("not implemented")` | Intentional placeholder bound by type contract |
| Decorator factories | Returning a wrapper function for 1-use decorators | Decorator shape requires this nesting |
| Test fixtures | Builder functions with many optional params | Test ergonomics; production weight does not apply |

When a finding falls in the allowlist, omit it from the score but note it in the report as `suppressed: idiom`.

---

### 6. Review Methodology

**Step 1 — Regex sweep (30-60 seconds)**
Run the regex table from `references/code-slop-patterns.md` across the patch diff. Record hits with file:line coordinates. Each hit is a candidate, not a confirmed flag.

**Step 2 — Context read (2-5 minutes)**
For every candidate, read the enclosing function plus 10 lines of call-site context. Promote to confirmed flag only if the surrounding code does not justify the pattern. Demote to `suppressed: idiom` when the allowlist applies.

**Step 3 — Duplication and abstraction audit**
Count structurally identical blocks (error handling, validation chains). If the same shape appears 3+ times without a helper, flag repetition. If a helper exists for a single caller, flag premature abstraction. Both are slop.

**Step 4 — TODO and comment audit**
Every `TODO`, `FIXME`, `XXX` must carry: owner (`@handle`), date (`YYYY-MM-DD`), and either an issue reference or a one-sentence description of the trigger condition. Strip or upgrade all others.

**Step 5 — Replacement suggestion**
For every confirmed flag, supply the replacement as a diff, not a description. The fix should reduce line count, reduce indentation depth, or both — never add.

---

### 7. Integration With Core Artibot

- **`code-reviewer` agent**: calls this skill before semantic review. If score < 70, reviewer returns the patch to the authoring teammate with the slop report attached.
- **`refactor-cleaner` agent**: runs this skill pre-refactor to measure slop baseline; post-refactor score must be ≥ +15 to declare the refactor net-positive.
- **`tdd-guide` agent**: runs this skill on new test files. Tests themselves may suppress categories 2, 5, 8 (fixtures and builders); other categories apply fully.
- **Parallel team context**: assign this skill's output to the `code-audit` role when teams exceed 3 parallel code-producing teammates.
- **Shared rubric link**: tier thresholds and flag schema reference `../../_shared/rubrics/severity-tiers.md` and `../../_shared/rubrics/auto-flag-schema.md` (synergy A1 output) to stay aligned with `ai-slop-reviewer` across plugins.

---

## Output Format

```
CODE SLOP REVIEW REPORT
=======================
Patch:       [file count] files, [+added / -removed] lines
Languages:   [js, ts, python, ...]
Score:       [0-100] — [tier]
Gate:        [auto-approve / proceed / review-required / block / reject]

PATTERN FLAGS
─────────────
| File:Line          | Pattern ID          | Weight | Fix Hint                   |
|--------------------|---------------------|:------:|----------------------------|
| src/api/user.ts:42 | try-swallow         |   7    | Remove try; let error bubble|
| src/api/user.ts:88 | as-unknown-as       |   6    | Narrow type or fix source  |
| src/lib/arr.js:12  | builtin-wrapper     |   5    | Use Array.isArray directly |
| scripts/run.py:31  | except-pass         |   9    | Catch specific + log + raise|
| src/ui/modal.tsx:3 | owner-less-todo     |   5    | Add owner + date + issue ref|

SUPPRESSED (idiom)
──────────────────
| File:Line               | Pattern             | Reason                       |
|-------------------------|---------------------|------------------------------|
| plugins/loader.js:12    | try-swallow         | Optional plugin import idiom |
| src/ui/Page.tsx:40      | empty-cleanup       | React useEffect contract     |

REPETITION FLAGS
────────────────
| Shape                          | Occurrences | Files            |
|--------------------------------|:-----------:|------------------|
| [error-handling block summary] |      5      | [file list]      |

REVISED EXCERPT
───────────────
[Show before/after diff for the 2 highest-weight flags]

Before:
```ts
try {
  const u = JSON.parse(raw);
  return u;
} catch {}
```

After:
```ts
return JSON.parse(raw);
```

GATE DECISION
─────────────
| Check                                    | Result     |
|------------------------------------------|------------|
| No weight-9 flag (silent-swallow)        | [Pass/Fail]|
| No type-assertion cluster (≥2 in 20 LOC) | [Pass/Fail]|
| All TODOs carry owner + date             | [Pass/Fail]|
| Score ≥ 70                               | [Pass/Fail]|

FINAL RECOMMENDATION
────────────────────
[One sentence: proceed to code-reviewer / request targeted fixes / block and reassign]
```

## Quick Reference

- **Top JS/TS flags**: try-swallow, `as unknown as`, options-bag bloat, `any` cascade, owner-less TODO
- **Top Python flags**: `except Exception: pass`, `lambda x: x`, over-broad `try/except`, unused dataclass field
- **Critical (weight ≥7)**: silent error swallow (9), defensive try-swallow (7)
- **Minimum score to proceed**: 70
- **Hard block score**: below 50

## Anti-patterns

- **Do not confuse with linters**: ESLint / Ruff / Mypy catch defects; this skill catches legal-but-unjustified code. Run both.
- **Do not inflate false positives**: always apply the idiom allowlist and read 10 lines of surrounding context before confirming.
- **Do not run without the shared rubric**: tier thresholds come from `plugins/_shared/rubrics/severity-tiers.md`. Standalone use diverges from `ai-slop-reviewer` scoring.
- **Do not invert findings into new abstractions**: flagging repetition does not automatically mean "extract a helper." Sometimes three similar lines is the correct answer.
- **Do not block on style alone**: formatting disagreements belong to prettier / black, not here.
- **Do not edit the patch**: output a report and hand back to the authoring teammate. This skill is a gate, not a rewriter.

---

## References

- `${CLAUDE_SKILL_DIR}/references/code-slop-patterns.md` — full JS/TS/Python pattern dictionary with regex, weights, and before/after examples
- `../../_shared/rubrics/severity-tiers.md` — shared tier definitions aligned with `ai-slop-reviewer`
- `../../_shared/rubrics/auto-flag-schema.md` — auto-flag YAML schema for telemetry collection
- `plugins/artibot-cowork/skills/ai-slop-reviewer/SKILL.md` — sibling skill for content slop (same scoring structure, different vocabulary)

## Common Rationalizations

| Rationalization | Why it's wrong | What to do instead |
|---|---|---|
| "The code compiles and tests pass, slop review is cosmetic" | Slop that compiles is still surface area — every unnecessary function, wrapper, or try/catch must be read, understood, and maintained by future engineers | Run slop review as a pre-merge gate separate from test passage; both must clear |
| "AI-generated code is fine if I reviewed it quickly" | Quick review catches logical errors but not structural slop — the patterns are subtle and require the specific vocabulary this skill provides | Apply the 10-category checklist and score before trusting a visual review |
| "Flagging try-swallows is too strict — defensive code is safer" | Defensive code that swallows errors destroys observability; the cost of a silent failure in production exceeds any perceived safety | Remove silent catches; propagate errors with context or handle them explicitly with a documented recovery path |
| "The score threshold of 70 is arbitrary" | The threshold is derived from observable patch quality — patches scoring below 70 consistently contain patterns that cause production issues; the number is calibrated, not arbitrary | If you believe the threshold is wrong for a specific context, document the justification and adjust in the shared rubric, not inline |
| "I'll address slop findings in a follow-up PR" | Follow-up PRs for non-functional changes are deprioritized indefinitely; slop accumulates and the codebase drifts below the threshold permanently | Fix slop in the same PR that introduced it; the diff is small by definition if the score is borderline |

## Red Flags

- Patches from `tdd-guide` or `backend-developer` teammates reaching `code-reviewer` without a slop score
- Any `catch {}` or `catch (e) { }` block without a comment explaining why the error is intentionally ignored
- Options objects with more than 6 fields where the call sites pass 2 or fewer
- The same error-handling block copy-pasted more than twice in a single file
- `TODO` comments with no owner handle, no date, and no issue reference
- A score below 50 reaching `code-reviewer` without an explicit override note from the team lead
