- name
- pr-html-concise-public
- description
- One-page-per-question HTML explainer for a PR — classify the PR first: a new feature owes a page comparing it with the existing way, a fix owes a page showing the failure and the fix, and a PR with both owes two cross-linked pages. Leads with a diagram, plain words. Uploads to the user's own PUBLIC gh-pages-poc GitHub Pages site.
# One-Page PR Explainer (public)
Make **one page** that tells a reader everything they need to know about one PR
(or one question inside a PR). A human reads it top to bottom in two minutes and
is done. No agent has to summarize it afterward.
**Repo**: `NVIDIA-NeMo/RL` (unless the user names another).
**Upload**: the user's own copy of the `gh-pages-poc` GitHub Pages site (see
"Site setup and upload" below) — this site is **public to the internet**.
"One page" is the default *per question*, not per PR. A PR that adds a feature
**and** has a notable bug is two questions, so it is two pages — see Step 0.
---
## The bar
Three pages set the standard. Read at least one before you write:
- https://terrykong.github.io/gh-pages-poc/terryk/pr-3427-sc-ownership.html
- https://terrykong.github.io/gh-pages-poc/terryk/pr-3427-sc-samplers.html
- https://terrykong.github.io/gh-pages-poc/terryk/pr3429-cursor-advance.html
Each is one question, one great figure, one small worked example, one clear
consequence. Each is 15–25 KB of HTML. Nothing else.
**Before you upload, be your own harsh critic.** Put your page next to those
three, blind, and ask: *which one is better?* Not "is mine acceptable" — which
one would a tired engineer rather open on their phone. If yours is not the
winner, you are not done. Go back and cut, redraw, and rewrite until a critic
who has never seen your PR looks at your page and is genuinely impressed.
The critic you have to impress cares about exactly four things:
1. **Do I know whether this is broken, fixed, or only proposed?**
2. **Did the figure teach me the thing before I read any prose?**
3. **Do I understand how the fix works — could I point at the code that does it?**
4. **Could I read it without stopping to look up a word?**
Do not soften the bar. Do not ship a page you would skim past yourself.
---
## Step 0: Classify the PR, then pick the page set
**Do this before you choose a title, and before you pick a figure.** The most
common way this skill goes wrong is not a bad page — it is a good page answering
the wrong question. The pull is always toward the most *interesting* thing you
found (usually a bug), when the reader's first question is the most *important*
one: what is this change, and how does it fit next to what already exists.
Read the diff and the PR description, then classify:
| The PR is… | Tell from | Pages you owe the reader |
|---|---|---|
| **A new feature / new path / new component** | new modules, a new config block, a new dataset/worker/estimator, a new branch threaded through several layers | **(1) what it is + how it compares to the existing way** — mandatory, and it goes first. Then (2) a page per deep finding, if any. |
| **A fix** | changes an existing behavior, no new user-facing surface | one page: the failure and the fix |
| **A refactor / migration** | same behavior, new shape | one page: what moved and what stayed the same |
| **A fix inside a new feature** | both of the above in one PR | **two pages** — the feature comparison first, the bug second, cross-linked. Do not fold the bug into the feature page, and do not ship only the bug page. |
### When it is a new feature, the first page is a comparison
A reader who has never seen the feature cannot judge a bug in it. If the PR adds
a second way to do something the codebase already does, the first page must answer:
- **What is this, in one sentence?**
- **What already existed that does the same job?** Name it and link it. If nothing
did, say that — "there was no way to do X before" is a real answer.
- **Where does each one do the work?** Point at the function, in the driver, the
dataset, the worker — wherever it actually happens. A figure with both paths
stacked, packing/branching box highlighted in each, beats any prose.
- **What does the data look like at each hop, in both?** Same tiny example carried
through both paths, with real shapes. Show it *in the call-flow figure itself*, as
an abbreviated value next to every step (see "Show the data, not just the steps"
in §6), not in a separate table the reader has to line up by hand.
- **Do they converge?** Almost always yes, at some layer. Name the exact function
and line where the two become one, and say what still differs *after* that point.
"They merge at X, except for fields A and B" is the single most useful sentence
on the page.
- **Why keep both?** What each one is for, and what the new one gives up in exchange.
### Rule
**Never ship only a bug page for a PR that introduces a new feature.** A bug page
alone tells a reviewer to go fix line 291; it does not tell them whether the design
is right, which is the thing they actually have to approve. If you only have budget
for one page, write the comparison — the bug belongs in the review comments anyway.
Say your classification out loud to the user before you build, in one line:
"This is a new feature plus a possible major bug, so I'll make two pages." That
gives them a chance to redirect you before you spend the effort.
---
## Hard limits
These are limits, not targets. Breaking one means you picked too big a topic —
split it into two pages instead (that is what `pr-3427-sc-ownership` and
`pr-3427-sc-samplers` are: two pages for one PR).
| Limit | Value |
|---|---|
| Length | 1–2 screens of scrolling |
| `<h2>` sections | 3 maximum |
| Figures | 1 for the problem. A second for the fix, when a picture beats pseudocode. |
| File size | Aim under 25 KB |
| Table of contents | None. If you need one, the page is too long. |
| Lead paragraph | 5 sentences maximum |
---
## Structure
Write it in this order. Every part is required except where noted.
### 1. Title — the question, in plain words
An `<h1>` that states what the reader will learn, as a sentence a person would
say out loud:
> How the dataloader cursor advances past in-flight prompts at checkpoint save
Not "PR #3429 analysis". Not "SingleController checkpointing deep dive".
### 2. Subtitle — one line of provenance
`<p class="sub">`: link to the PR, link to any related issue, and the pinned
head SHA that all permalinks use. One line.
**If the page explains a review comment, link that comment.** This applies whether
the whole page is about one finding or the page gives each finding its own section.
The reader's next move is to go to the comment and act on it, so hand them the link
instead of making them hunt the Files tab for it. Put it at the end of the section
it belongs to, and label it with the file and line so it reads as a destination:
```html
<p class="cref">🔴 <a href="https://github.com/OWNER/REPO/pull/PRNUM#discussion_rNNNNNNNNNN">review comment — generic_sft.py:259</a></p>
```
```css
.cref{margin:6px 0 0;font-size:13px}
.cref a{display:inline-block;padding:4px 10px;border:1px solid var(--border);
border-radius:16px;background:var(--surface);font:12.5px ui-monospace,Menlo,monospace}
.cref a:hover{background:var(--surface2);text-decoration:none}
```
Read the URLs out of the API rather than assembling them by hand — every review
comment already carries the right anchor in its `url` field:
```bash
gh api graphql -f query='query { repository(owner:"OWNER", name:"REPO") {
pullRequest(number: PRNUM) { reviews(last:1) { nodes { comments(first:100) {
nodes { url path line } } } } } } }'
```
**A pending review's comments are visible only to its author.** Those anchors do
not resolve for anyone else until the review is submitted, so say that plainly when
you hand over the page — otherwise the links look broken to the first reader who
opens it.
### 3. Status — is this broken, fixed, or proposed?
**Goes directly under the subtitle, above the link bar and the lead.** This is the single most
common thing these pages leave out, and it costs the reader the whole page: they land on a
description of a problem and cannot tell whether they are reading about a bug that still exists, a
bug this PR repairs, or a fix somebody is only suggesting. Every other sentence reads differently
depending on that answer.
Three rows, in this order, one line each:
| Row | What goes in it |
|---|---|
| **Before** | What the code did before this PR — the status quo, stated as behavior, not as code. |
| **This PR** | What the change actually does. One sentence. |
| **Status** | The verdict, in bold and in words. |
The verdict is one of:
- **Fixed by this PR** — the page describes a bug the change repairs.
- **Open — not fixed in this PR** — the page describes a problem the change introduces or leaves
behind. Say where it is tracked (review comments, an issue), so the reader knows it is not lost.
- **Proposed — not implemented** — the page argues for a change nobody has made yet.
- **Pre-existing, untouched by this PR** — the page explains something the PR merely sits next to.
Rules:
- **Never make the reader infer the verdict from the tone.** A page full of red boxes reads like a
live bug even when it is describing something the PR fixes. Two pages can look almost identical
and mean opposite things; only the status box tells them apart.
- **A section that proposes a fix must say so in its heading** — "What would fix it — proposed, not
in the PR" — and open with "Nothing below is implemented." A reader who skims a code block will
otherwise take it for the diff.
- When the PR both fixes something and leaves something open, that is two questions and therefore
two pages (Step 0). Each gets its own status box, and each links to the other.
```html
<div class="status">
<dl>
<dt>Before</dt>
<dd>Setting the flag changed nothing — the code ran, cleared no cache, and reported success.</dd>
<dt>This PR</dt>
<dd>Hands the flag to the engine's own pause, which really does drop the cached state.</dd>
<dt>Status</dt>
<dd><span class="verdict good">Fixed by this PR.</span> Both modes now behave as documented.</dd>
</dl>
</div>
```
```css
.status{border:1px solid var(--border);border-radius:10px;background:var(--surface);
padding:2px 16px 10px;margin:0 0 20px}
.status dl{display:grid;grid-template-columns:max-content 1fr;gap:4px 14px;margin:12px 0 0}
.status dt{color:var(--dim);font-size:12px;text-transform:uppercase;letter-spacing:.04em;
white-space:nowrap;padding-top:2px}
.status dd{margin:0;font-size:14px}
.verdict{font-weight:700}
.verdict.good{color:var(--green)}
.verdict.open{color:var(--red)}
```
### 4. Sibling pages — the link bar
One PR often gets several pages, one question each. **Every page for a PR links
to every other page for that PR**, so a reader who lands on any one of them can
find the rest. The links go both ways: the new page lists the old ones, and you
go back and add the new page to each old one.
Put the bar right after the subtitle, whenever the PR has more than one page:
```html
<nav class="chain">
<a href="https://OWNER.github.io/gh-pages-poc/DIR/pr-3591-where-it-runs.html">where it runs</a>
<span class="here">what survives</span>
<a href="https://OWNER.github.io/gh-pages-poc/DIR/pr-3591-why-rebuild-not-shrink.html">why rebuild, not shrink</a>
</nav>
<p class="chainnote">Three pages on this PR, one question each — this one: which failures recover.</p>
```
The CSS, copied as-is into the `<style>` block:
```css
nav.chain{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 6px;padding:0}
nav.chain a,nav.chain span{display:inline-block;padding:5px 11px;border:1px solid var(--border);
border-radius:20px;background:var(--surface);text-decoration:none;color:var(--accent);
font-size:12.5px;line-height:1.3;white-space:nowrap}
nav.chain a:hover{background:var(--surface2)}
nav.chain span.here{background:var(--accent);color:var(--bg);border-color:var(--accent);font-weight:600}
p.chainnote{color:var(--dim);font-size:12px;margin:0 0 18px}
```
Rules:
- The label is 2–4 plain words naming that page's question — not its filename.
- The current page is a `<span class="here">`, not a link.
- Same order on every page. If the pages read as a sequence, number the labels
(`1 · who watches what`); if each stands alone, leave the numbers off.
- Use full site URLs, so the bar works from anywhere.
- Skip the bar entirely when this is the only page for the PR.
### 5. Lead — the mechanism, in 3–5 sentences
What the code does, enough that the figure makes sense. Every claim about the
code carries a permalink to the exact line. No history, no motivation essay, no
"this PR is part of a larger effort".
### 6. The figure — this is the page
An inline `<svg>` that carries the whole argument. A reader who looks only at
the figure should get it. Rules:
- **Colors come from CSS variables** (`fill:var(--text)`, `var(--green)`, …) via
classes, never hardcoded, so the light/dark toggle re-themes it live.
- **Every code reference in the figure is a clickable permalink**, wrapped in an
SVG `<a>` and underlined (`svg a text{text-decoration:underline}`). Assume the
reader is on a phone — there is no hover.
- **Label the states with color and a legend in the figure itself.** Green =
fine, red = the problem, gray = ignored. Put the legend inside the SVG, next
to what it labels, not in a caption below.
- **Annotate every arrow** with what call it is and which line does it.
- Draw the *specific* thing, not a generic box diagram. A grid of 30 numbered
prompts colored by fate beats three boxes labeled "loader / buffer / trainer".
- **Show the data, not just the steps.** In a call-flow or two-path figure, every
step box gets the abbreviated value that goes in and comes out, written as code:
a short JSON/dict, a struct with its key fields, or a tensor with shape and a few
values — `[{role:"user", content:"A: "}, …]` → `"A: Paris"` →
`ids [32, 25, 12095]` → `turn 2: tensor([], dtype=int64)`. Use the same tiny input
in both lanes, at the same height, so the reader can tell at a glance whether the
two sides hold the same thing at each step and spot the one step where they split.
A list of function names says what runs; the data says what it does. Abbreviate
freely (`…`, `[B=2, S=7]`, the first 3 values), but every value must come from a
real run, not be made up. Mark the step where the two lanes differ in red.
- Check the SVG tags are balanced before uploading, **and that no text runs past
the viewBox width**. SVG does not wrap and gives no warning — a long label just
vanishes off the right edge in the browser while looking fine in the source.
Estimate each label as `len(text) x font-size x 0.55` (sans) or `x 0.6` (mono),
and confirm `x + width < viewBox_width - 14`, accounting for `text-anchor`.
Long annotations belong **under** the chart, left-aligned — never in the strip
to the right of a marker line, where there is rarely room.
If the topic genuinely has no picture, use a tight aligned monospace block
instead — but try hard for the picture first.
### 7. The fix — show the mechanism, not just the outcome
On a fix PR the figure almost always shows the **problem**. That is half a page.
The reader must leave knowing *how* the code fixes it. Give the fix its own
section, in one of three forms:
- **A real diff — the default whenever the fix is a code change**, whether it
is in the PR or only proposed. Show it as a color-coded unified diff, not as
loose snippets or pseudocode: seeing which lines go and which arrive is how a
reader gets a feel for the size and shape of the change. Rules below.
- **A second figure** — an illustration of the new mechanism, held to the same
rules as §6. Use this when the fix is a new component, or a changed order of
operations. It can sit above the diff.
- **Pseudocode with a value trace** — 2–4 short blocks, one per step of the fix,
each with inline comments carrying the **actual values** at that point, and a
permalink line underneath pointing at the real code. Use this only when there
is no single code change to show (a protocol across processes, an ordering
argument). The reader should be able to follow the real Python by reading
your comments.
**Diff rules:**
- Real code, not a sketch of it: every `-` line must exist at the pinned SHA,
and every `+` line must be what you would actually commit. Keep 1–3 unchanged
context lines around each change, so the reader sees where it lands.
- One hunk per place the code changes. Head each hunk with the file, the line
numbers at the pinned SHA, and the function — `@@ single_controller.py
L4549-L4553 · _save_rollout_checkpoint_locked`. Only print line numbers you
checked; do not estimate the new-file offsets of a `@@ -a,b +c,d @@` header.
A brand-new function gets a hunk too: "new method, next to `X` (L1949)".
- Color from the theme variables — removed red, added green, hunk headers
accent — so the light/dark toggle works. Put a one-line comment inside the
`+` code wherever the new line is not obvious; the prose around the diff does
not travel with it.
- Say under the diff what each piece does, in order, with permalinks, and say
plainly if it is proposed and has not been run.
```html
<pre class="diff"><span class="hunk">@@ single_controller.py L4549-L4553 · _save_rollout_checkpoint_locked</span>
if self._optimizer_commit_in_progress:
return _RolloutCheckpointSaveResult(...)
<span class="del">- old line
</span><span class="add">+ # why this line exists
+ new line</span></pre>
```
```css
.diff{font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;background:var(--surface);
border:1px solid var(--border);border-radius:8px;padding:12px;overflow-x:auto;white-space:pre;margin:10px 0}
.diff .add{color:var(--green)}
.diff .del{color:var(--red)}
.diff .hunk{color:var(--accent)}
```
View on GitHub