Skip to content

/explain-diff-html skill — contract

Project-local Claude Code skill at .claude/skills/explain-diff-html/. Invoked as /explain-diff-html [branch | PR number | commit range | file paths].

Three files:

File Role
SKILL.md The instructions Claude loads
validate_explanation.py Hard gate — stdlib-only checker run against the generated page
reference.html A minimal page that passes the gate cleanly; the executable version of the spec

Why this exists

Explaining a change to someone who did not write it is a recurring cost on this repo — onboarding a collaborator onto the discovery engine, handing a landscape-loop run to a reviewer, writing up why a backend swap changed the numbers. The default artifact for that is a long chat message, which is unskimmable, unlinkable, and gone by the next session.

An HTML page fixes the durability problem and introduces two new failure modes that this skill exists to prevent.

Narrating the diff instead of explaining the change. A page that walks files top to bottom leaves the reader knowing which lines moved and not what the system now does. The skill front-loads investigation — callers, tests, data models, prior behavior — and treats the diff as evidence for the explanation rather than its outline.

Shipping a quietly broken artifact. These pages fail in ways invisible to the author: a CDN font that never loads on the reader's machine, a <pre> missing white-space that collapses every code sample to one line, a quiz whose correct answer is always the longest option. Rereading your own HTML does not catch these. A validator does.

The contract

A page is deliverable only if validate_explanation.py exits 0. The checks:

Check Fails when Why it matters
document No doctype, no closing </html>, empty <title> Truncated writes are silent
offline Remote src/href asset, @import, url(https://…), fetch, XMLHttpRequest, WebSocket The page must render with the network off. Outbound <a href> links are explicitly allowed — references, not dependencies
code-blocks No CSS rule targeting pre sets white-space: pre/pre-wrap Every code sample collapses to one line, and the page still looks fine to whoever wrote it
diagrams Box-drawing characters or ASCII art inside <pre> Diagrams must be semantic HTML + CSS
structure A required section missing, or a table-of-contents link pointing at a nonexistent id Broken navigation on a long page
quiz Not exactly 5 questions, malformed entries, empty explanation, "all/none of the above" Shape the rest of the quiz checks depend on
quiz-position Correct answer in one slot 3+ times, or spread over fewer than 3 distinct slots Position becomes the answer key
quiz-length Correct option is the single longest in more than half the questions The classic tell — scoreable without reading the page
quiz-leak data-correct, a correct class, correctness in aria-label, or only the answer present in static markup Answer visible before selection

a11y and document also emit warnings (missing :focus styling, no viewport meta, inline onclick) that do not block but should normally be fixed.

The quiz-data contract

The validator can only audit the quiz because the questions live in one machine-readable block:

<script type="application/json" id="quiz-data">
[{"question": "...", "options": ["...", "..."], "answer": 2,
  "explanation": "...", "distractors": {"0": "the misreading this encodes"}}]
</script>

Two consequences worth stating explicitly:

  • answer indexes the options as emitted, and the order is final. Shuffling happens at authoring time. A runtime Math.random() shuffle would make the position-balance rule unverifiable and the page non-reproducible.
  • Option elements carry no correctness marker. The script reads answer from the JSON on click. This is what makes "do not leak the answer through markup" mechanically checkable rather than a matter of trust.

Scope

  • In scope: any code change — this repo's or another's. Nothing in the skill is OGUR-specific.
  • Out of scope: bug review (/review-engine, /code-review), API reference docs, and anything whose deliverable belongs in version control. The output is a throwaway teaching artifact written to /tmp/YYYY-MM-DD-explanation-<slug>.html, deliberately outside the repo.

How it differs from neighbouring surfaces

Surface Output Best for
git show / gh pr diff The raw change You already know the system
/code-review, /review-engine Findings about correctness Deciding whether to merge
Notion:tasks:explain-diff A Notion doc Explanations that belong in the team wiki, editable and commentable
/explain-diff-html (this skill) One offline HTML page with diagrams and a quiz Teaching the change to someone who did not write it, including your future self

The Notion sibling is the closer comparison. Reach for it when the explanation should live in the workspace alongside other docs; reach for this one when you want a self-contained file that works offline, renders diagrams, and tests comprehension.

When to invoke

  • Onboarding someone onto a subsystem they have not touched
  • After a change whose reasoning is the valuable part and would otherwise be lost — a backend swap, a gate insertion, a scoring-rule change
  • Before a design review, so attendees arrive with the mental model already loaded
  • On your own branch when it has been open long enough that you will not remember why

Rule of thumb

The reader should be able to predict what the system does in a case the page never showed them. If the page only supports recall of what it stated, it explained the diff and not the change. The quiz is the cheapest test of this: if every question is answerable by scanning back for a matching phrase, the explanation has not done its job.