SlopBlock
Diff-grounded PR gatekeeping

Make authors prove they understand their pull request.

SlopBlock is a GitHub App that blocks merges behind a short quiz built from the diff. It skips obvious changes, asks focused questions for risky ones, and keeps the status check tied to actual code comprehension instead of vibes.

GitHub App
PR author only
Required status check
Status check Awaiting author quiz

Instead of approving a merge because the author opened the PR, SlopBlock asks them to explain the changed code in context.

01 Reads the diff
02 Generates targeted questions
03 Passes only on fully correct answers
How it works

One short flow from PR open to merge

01

SlopBlock watches a pull request when it opens, updates, or becomes ready for review.

02

It decides whether the diff is trivial enough to skip or worth turning into a quiz.

03

The PR author answers multiple-choice questions tied directly to the changed code.

04

Passing the quiz updates the required status check so the PR can merge.

Public Example Quiz

A real sample, grounded in a visible diff

This is the kind of quiz SlopBlock would generate for an actual pull request. The changed lines are shown first, then the questions test whether the author understands what the diff really did.

sampnorris/slopblock-quiz

PR #184: Make quiz submission reject missing answers

This example is based on a realistic server change: the answer endpoint now validates the submitted answer map and returns a 400 when a question is missing instead of silently accepting incomplete submissions.

3 questions
Changed lines
diff --git a/src/routes/api/session/[token]/answer/+server.ts b/src/routes/api/session/[token]/answer/+server.ts
@@
 if (action === "pass") {
   const answers = body?.answers;
   if (!answers || typeof answers !== "object" || Array.isArray(answers)) {
     return json({ ok: false, message: "Answers are required." }, { status: 400 });
   }

   try {
     const result = await markQuizPassed({ octokit, session, answers });
     return json(result);
   } catch (error) {
     return json({ ok: false, message: error instanceof Error ? error.message : "Failed to grade quiz." }, { status: 400 });
   }
 }
Question 1 Multiple choice

What new request shape is required before the endpoint will grade the quiz?

A An `answers` object keyed by question ID must be present in the request body.
B A `score` number must already be calculated on the client.
C A `passed: true` flag must be sent with the answers.
Correct answer: the route now rejects requests that do not include an `answers` object for grading.
Question 2 Multiple choice

Why does the handler wrap `markQuizPassed(...)` in a `try/catch`?

A So grading errors can be turned into a `400` JSON response instead of crashing the request.
B So the server can retry grading up to three times.
C So the handler can swallow failures and still return `ok: true`.
Correct answer: validation and grading failures are returned as explicit client-visible errors with status `400`.
Question 3 Multiple choice

What behavior changed for incomplete quiz submissions after this diff?

A They now fail fast with an error message instead of slipping through to grading.
B They automatically generate default answers for the missing questions.
C They are accepted, but the score is capped at 50 percent.
Correct answer: the new guard stops incomplete payloads before grading and reports the problem clearly.
Why teams use it

Catch cargo-culted changes before they merge

SlopBlock gives maintainers a lightweight gate when they want authors to demonstrate real understanding of risky diffs, generated code, or LLM-assisted changes.