Skip to content

feat(ci): add non-blocking "slop cop" PR analyzer - #5552

Merged
adrians5j merged 2 commits into
nextfrom
feat/slop-cop-pr-agent
Aug 4, 2026
Merged

feat(ci): add non-blocking "slop cop" PR analyzer#5552
adrians5j merged 2 commits into
nextfrom
feat/slop-cop-pr-agent

Conversation

@adrians5j

@adrians5j adrians5j commented Aug 4, 2026

Copy link
Copy Markdown
Member

What

A new Slop Cop workflow that runs on every PR, asks Claude to sanity-check the diff, and posts a single sticky comment with two kinds of feedback:

  1. Integrity — does anything look like it shouldn't be in the PR? (accidental content, wiped commits, leaked secrets, …)
  2. Code style — do the diff's added/changed lines break any project code-style rule?

Motivating case for (1): #5496 was titled feat(admin): breadcrumbs but deleted 3508 lines across 245 files — the signature of a bad rebase/merge that wiped commits. A heads-up comment before merge would have caught it.

How

pull_request (opened/reopened/synchronize) → one job:

  1. gh pr view --json gathers intent (title/body/commits) + footprint (per-file +/-); gh pr diff grabs a capped raw patch.
  2. slopCop.js (Node 24 global fetch, zero new deps) calls the Anthropic Messages API (claude-sonnet-5) and returns JSON findings, each tagged category: integrity | style.
  3. A sticky comment (hidden marker) is posted/updated in place — no spam per push. The report splits findings into a 🚨 Should this be in the PR? section and a 📏 Code-style rule checks section, each severity-sorted.

Integrity checks (job A)

Footprint-vs-intent mismatch (highest priority), leaked secrets, committed artifacts (node_modules/build output), leftover debug code / focused tests, unresolved conflict markers, commit-history smells.

Code-style checks (job B)

Every rule under ai-context/code-style/ (one-import-per-line, no-console-in-backend, es-modules, one-class-per-file, …) is loaded from the PR's checkout and fed to the model. It flags violations only on lines the diff adds or changes — never pre-existing or removed code — respects each rule's scope (e.g. no-console-in-backend applies only to api-*), cites the offending rule file, and is capped to the ~15 most important. Wired via CODE_STYLE_DIR; point it elsewhere without touching the script. Because rules come from the PR branch, a PR that adds/edits a rule is checked against its own new rules.

Safety (phase 1 = advisory)

  • Never blocks. The job always exits 0. A missing key or API error is non-fatal and leaves the check green.
  • Fork PRs skipped (!head.repo.fork) — no secrets on pull_request, so no pull_request_target pwn-request risk.
  • Diff capped at 200 KB; the per-file footprint (the key integrity signal) is always complete. Rules block capped at 60 KB.

Setup

Reads ANTHROPIC_API_KEY from repo secrets (already configured).

Notes

  • Source of truth is slopCop.wac.ts; slopCop.yml is generated via ghawac build.
  • Also regenerates assignMilestone.yml, which had drifted from its wac source (missing the createJob permissions baseline).
  • Tested end-to-end with a mocked API: feat(admin): breadcrumbs #5496's real numbers flag a high-severity footprint mismatch; the style path correctly flags one-import-per-line + no-console-in-backend on added lines.

Future phases

  • Inline review comments instead of (or alongside) the single sticky comment.
  • Tune the model/prompt once we trust the signal; revisit the ~15-finding cap.
  • Optional blocking / required status check. Deliberately not done here — phase 1 is advisory, so the job always exits 0 and would gate on nothing if marked required. Making it a real merge gate is a separate change with real trade-offs:
    • The job must be able to fail — and only on high-severity integrity findings, never on style (too noisy) and never on API/parse errors (non-blocking → stays green), or flaky API/rate-limits would block all merges.
    • It must always report a status even when skipped (e.g. fork PRs, which are skipped today) — a required check that never reports leaves the PR stuck "Expected — waiting for status" and unmergeable forever.
    • LLM output is non-deterministic; false positives would wedge unrelated PRs. Let advisory comments build trust first.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NFTbnZYKArMQiiCyUKuP6G

adrians5j and others added 2 commits August 4, 2026 17:24
Adds a new "Slop Cop" workflow that runs on every PR and posts a single
sticky comment flagging content that likely should not be in the PR -
most importantly a footprint mismatch (narrow title, mass deletions),
the signature of a bad rebase/merge that silently wiped commits.

- New workflow slopCop.wac.ts (+ generated slopCop.yml).
- Analysis script slopCop.js: reads PR intent + footprint + capped diff,
  calls the Anthropic Messages API (claude-sonnet-5) via Node 24 global
  fetch (zero new deps), returns JSON findings, renders a Markdown report.
- Sticky comment via gh (marker-based), updated in place per push.

Phase 1 is advisory only: the job always succeeds and never blocks a
merge. Fork PRs are skipped (no secrets on pull_request); a missing key
or API error is non-fatal and leaves the check green.

Reads ANTHROPIC_API_KEY from repo secrets.

Also regenerates assignMilestone.yml, which had drifted from its wac
source (missing the createJob permissions baseline).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NFTbnZYKArMQiiCyUKuP6G
Extends the slop cop analysis with a second dimension: when CODE_STYLE_DIR
is set (wired to ai-context/code-style), it checks the diff's added/changed
lines against every code-style rule and reports violations in a separate
"Code-style rule checks" section, citing the rule file.

- Findings now carry a category ("integrity" | "style"); the report splits
  them into two sections.
- Style check is only over added lines, capped, conservative, and still
  fully non-blocking. Disabled cleanly when no rules dir is provided.
- Bumped max_tokens to 4000 to fit the extra findings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NFTbnZYKArMQiiCyUKuP6G
@adrians5j
adrians5j merged commit 06dcdb9 into next Aug 4, 2026
4 checks passed
@adrians5j
adrians5j deleted the feat/slop-cop-pr-agent branch August 4, 2026 15:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant