---
name: site-critic-loop
description: "Run one BUILD → CRITIC → MEMO cycle over a public static site. Grades seven fixed areas from screenshots and measurements of the SERVED build, emits per-area deltas that each name a file or an element and carry a predicted grade move, then scores its own predictions and amends the rubric line that generated any miss. Use when asked to grade a site, run a critic pass, or continue the critic loop."
---

# The Critic Loop

One cycle = BUILD (a separate session, or skipped) → CRITIC (this skill) → MEMO
→ deltas handed to the next build.

Serve the built output locally (a static file server on a kernel-picked port,
bound to loopback) and grade the **served site**, never the source intent. A
headless browser rig for screenshots and measurement lives in the project's own
dependencies; nothing here reaches the network. The loop never deploys —
publishing belongs to a human.

## TRIGGER

Invoke when asked for a critic pass, a grade, or the next loop cycle. Do not
invoke mid-build: grade only a committed, built, clean tree, and record the
commit under test on the sheet.

## THE SEVEN AREAS, 0–5 each

1. **FIRST 30 SECONDS** — the actual first screenful, cold, at a desktop and a
   phone viewport: what is this, who made it, why keep reading.
2. **THE CLAIM** — sharp, specific, unpasteable by any other project; generic
   marketing phrasing scores 1.
3. **THE PROOF** — the site SHOWS its claims operating: inspectable receipts,
   captured refusals, reconciling numbers. A verification pitch on faith = 0.
4. **VISUAL CRAFT** — a design language executed: type scale, state-only color,
   rhythm, considered interactive states. Ruled-in design choices are critiqued
   on their execution, never on their existence.
   *(AMENDMENT A5.)* For any canvas or SVG figure, measure the effective
   ON-SCREEN px of its smallest rendered label at both viewports — drawn size ×
   (CSS width ÷ internal coordinate width). A scaled figure's type scale is not
   its source type scale, and a figure that renders smaller on desktop than on
   phone is a defect on its face.
5. **PHONE** — one-handed at a phone width: measured tap targets (44px
   guideline, 24px WCAG floor), overflow on every page, menu open/dismiss,
   open-state usability.
   *(AMENDMENT A4.)* Tap-target measurement covers EVERY route in the declared
   route list, not a sample. A delta predicted to move PHONE must state the
   measured worst target across ALL routes, not only the routes the previous
   pass happened to shoot.
6. **HONESTY** — cross-check every number that appears twice; dates vs "now";
   labels vs delivery. One confident overstatement caps the area at 2.
   Honesty-at-own-expense is signal; judge its legibility.
   *(AMENDMENT A1.)* A 5 additionally requires that every gate currently
   REFUSING is on the site's own record. Honesty is graded on the completeness
   of the record, not only the candour of what is shown; an unshown live
   refusal caps the area at 4.
7. **PERFORMANCE** — numbers only: cold bytes + requests per page, split by
   type, largest asset, total built size. Set a bar and hold it (e.g. homepage
   under 300KB and under 15 requests, fonts included).

## HARD CONDITIONS (non-negotiable)

- Findings are proven BY MUTATION: to claim an element causes a problem,
  demonstrate the delta (toggle it, measure both states) or mark the finding
  PLAUSIBLE, never CONFIRMED.
- TESTS are in scope, not just code: freshness assertions and refusal drills
  are graded surfaces — a reddened pin or a drill that no longer fires is a
  finding.
- A 5 requires naming what would have made it a 4 and why it does not apply.
- NEVER raise a grade to end a loop — an inflated 5 is the only way this job
  fails.
- Screenshots or it is theater: every visual verdict cites an image file the
  grader actually viewed, named `<dir>/area<N>-<page>-<viewport>[-state].png`.
- Every area emits a named falsifiable DELTA that names a FILE OR ELEMENT,
  never a quality. ("Recrop the portrait assets to square" is a delta; "improve
  craft" is not.) Each delta carries an owner: build-movable / content-movable /
  BLOCKED-ON-HUMAN.

## THE FOUR LOOP RULES

Three consecutive passes moved First-30s, Craft and Phone by exactly zero. The
critique was honest and the grades were probably right; the loop was
unactionable. These four rules exist to make the loop move, and they apply from
cycle one — they are not aspirations to grow into.

**A. FIRE CRITICS ONLY WHERE WORK CHANGED.** Full critique on the areas this
cycle actually touched; every other area gets the CHEAP REGRESSION CHECK
(below). Reading the diff first is part of the job — a critic who does not know
what changed cannot target anything.

**B. EVERY DELTA NAMES A FILE OR AN ELEMENT.** Not a quality, not a feeling,
not a direction. "Improve hierarchy" is not a delta. "The hero receipt on the
home page: replace the shell command with a link to the machine-readable
status file" is. A delta that cannot be written this way is not yet understood
well enough to hand to a builder, and saying so is a better outcome than
dressing it up.

*(AMENDMENT A2.)* A delta predicted to move FIRST 30 SECONDS must state the
element's expected top offset in px at both graded viewports, and must predict
NO first-30s move where that offset exceeds the fold. DOM position is not fold
position.

*(AMENDMENT A3.)* A delta that names a MEANS and a TARGET must have had the
means measured against the target before it is issued. One pass issued a delta
naming both — "cut the lede to ≤3 lines" AND "so the figure clears the fold by
≥300px" — and the two did not meet. Measured: the cut was executed exactly as
written and moved the figure 753→659px on desktop (clearing 241) and 770→638px
on phone (clearing 206). Reaching ≥300px at BOTH viewports needed the lede down
to roughly **39 characters** — one short line, which is a caption, not a lede.
The rest of the distance was not the lede's to give: 201px and 273px sat
between the lede and the figure and belonged to the figure's own preamble.
So: measure the means against the target, or issue two deltas and let the
builder report where the first one lands. A means-plus-target delta that was
never arithmetic-checked spends a full cycle to discover subtraction.

**C. THE CRITIC PREDICTS, AND IS SCORED ON IT.** Every delta is logged with a
PREDICTED move before the next build runs, and the next graded pass fills in
the ACTUAL move. Report prediction hit-rate as a NUMBER on every sheet. The
sharp end: **a delta that was executed and did NOT move its grade is a defect
in the RUBRIC, not in the builder** — the rubric asked for the wrong thing, so
amend the line that generated the failed prediction and record the amendment.
This is the only mechanism that improves the loop rather than the site.

*(AMENDMENT A6.)* Two deltas predicting a move in the SAME area in one cycle
are logged as ONE joint prediction. A delta whose prediction is "no move" must
additionally name the MECHANISM to be measured (a request list, a byte count, a
rendered box), because a null result is unfalsifiable from an area grade
another delta also moved.

*(AMENDMENT A7.)* **Before issuing a delta, NAME THE BINDING CONSTRAINT on that
area and state why this delta relieves it. A delta that fixes a real defect
which is not the binding constraint predicts NO MOVE, and says so.** One pass
is the whole argument: six deltas were executed faithfully, six fixed exactly
what they named, and six moved nothing — because each addressed a real defect
that was not the thing holding its area down. Two of them fixed one-pixel
occlusions while the figure itself rendered at 76% scale. Another fixed a
wordmark's hit box while 34 sub-WCAG targets sat on a page that pass never
opened. A delta that cannot name what is actually binding is a guess with a
file path attached, and the loop has priced that at a 44% hit-rate.

**D. CLASSIFY EVERY AREA BEFORE SPENDING A TURN ON IT.**
- *build-movable* — a build session can move it. Spend turns here.
- *content-movable* — needs writing or a decision about what to say, not code.
- *BLOCKED-ON-HUMAN* — capped until a human ruling lands.

Never spend a build turn on the last two. Say what the cap is and move on.

## FURTHER AMENDMENTS — each forced by rule C

*(These lived only in the sheets that forced them until an audit found that
several had been absent from this file for two full cycles: the loop ran its
own two-declarations defect on its own rubric, and every pass after that point
graded against a file that did not contain the rules it was applying. An
amendment that is not copied back into this file did not happen.)*

**A8 — text edits move things in quanta of line-height, or not at all.**
*(Generated by A2.)* A predicted offset following a TEXT-LENGTH change must be
derived as ⌈chars ÷ measured chars-per-line⌉ × measured line-height at each
viewport, and quoted as a LINE COUNT first, px second. A prediction not
expressible as an integer number of lines at both viewports is rejected before
the build runs. *Measured:* cutting 69 characters moved the target **0.0px** on
desktop (3 lines → 3 lines) and **23.1px** on phone (6 → 5 lines).

**A9 — measure the scale where the coordinate space changes, and name the unit
of a floor.** *(Generated by A5.)* A figure whose internal coordinate width
changes at a breakpoint must have its effective on-screen label px measured at
that breakpoint from BOTH sides and at the worst width in each layout's range —
not only at the two graded viewports — and the discontinuity reported as a
number. And: a floor expressed in DRAWN units is not a floor on rendered size.
A delta claiming a legibility floor must state the unit and the scale it
survives.

**A10 — from REFUSING to WITHHELD.** *(Generated by A1.)* A1 extends from
REFUSING to WITHHELD. Every control holding back a capability the site claims —
whether it exits nonzero, or exits clean with the capability unarmed — belongs
on the record. A block that has never fired is the class most easily left off a
record, and is worth more on it than one that has already cleared.

**A11 — a "sole blocker" is a claim about the whole area, and a multi-delta
pass grades against its combined end state.** *(Generated by A7.)* "Sole
blocker" must be backed by a re-run of that area's full cross-check list at the
graded commit, not by the absence of other findings last pass. And where a pass
ships several deltas, each area's prediction is scored against the pass's
COMBINED end state — deltas routinely create each other's blockers, and a
per-delta prediction that ignores its siblings is scoring a site that never
existed.

**A12 — a scale change must predict its containment cost, and "reusing an
idiom" must be measured on both elements.** *(Generated by A9.)* A delta that
changes a figure's rendered scale must predict and measure the CONTAINMENT
consequence at the same widths — how much of the figure leaves the box, and
what at-rest affordance signals it. A legibility gain that hides content is a
trade, and must be logged with both numbers, not one. *Corollary:* when a delta
claims to reuse an existing idiom, the reuse is verified by MEASURING the
idiom's affordance on both elements.

**A13 — the unit of record completeness is the EMITTER'S VOCABULARY.**
*(Generated by A10.)* When a delta makes a record legible, completeness is
measured against every token the WRITER can emit — grep the writer, not the
log — not against the states the delta chose to handle. State, per token, what
the reader is shown. A record renderer is complete when every emittable token
has a defined rendering, including a defined refusal to interpret an unknown
one. *Measured:* a delta gave all four tokens of one outcome family distinct
correct copy, while the writer emitted **six** outcome tokens; the three
outside that family fell into a branch asserting they had stopped at the
human-held gate, which is false for a failure logged *after* the human already
said yes.

**A14 — A2 extends to DISPLACEMENT: the fold is a fixed budget.**
*(Generated by A2.)* A delta that inserts an element into a first screenful
must state, for both viewports, every element currently above the fold that the
insertion pushes below it, and net the loss against the gain before predicting
a move. An insertion is a trade, and a first-30s prediction that names only
what arrives is scoring half the ledger. *Measured:* a 39px gloss line pushed a
footer portrait from **26.5px above** the fold on phone to **16.5px below** it —
spending a gain the previous pass had explicitly credited.

**A15 — a tap target is not a touch test.** *(Generated by A4.)* A4 made
tap-target GEOMETRY exhaustive across routes, and PHONE reached 5 on that basis
and held it for three passes, wrongly. Geometry measures whether a finger can
HIT something; it says nothing about whether the page RESPONDS to the two
gestures a phone actually has. **A PHONE grade of 4 or 5 now additionally
requires, on every route carrying a canvas, an `overflow` region, or a
non-passive listener: a synthesized VERTICAL drag whose `ΔscrollY` is compared
against an inert control element on the same page, and a synthesized HORIZONTAL
drag on every scrollable region — both deltas reported as numbers.** A region
whose at-rest affordance cannot be operated by the gesture it advertises is a
DEAD AFFORDANCE and caps PHONE at 3 regardless of tap-target geometry.
*Measured:* one page's canvas returned **0px against a control's 201px**, and
its stage panned **0 of 46px**, on a page graded 5 twice — while the fade and
the scroll cue built to survive its clip were both correct and both unreachable
by touch.
*Corollary to A12:* a containment cost measured at two wide breakpoints had its
floor then applied globally. At the phone width the same rule yielded
**0.000px** of legibility gain for **10.27%** of the composition. **A trade must
be re-measured at every width where the rule applies, not only at the width
that motivated it.**

## CYCLE CADENCE

Run cycles continuously until the human says stop. Between cycles emit a
ONE-SCREEN delta memo, nothing longer: score by area, what moved, what did not,
prediction hit-rate as a number, and the next deltas with owners.

## KEY LEARNINGS (seeded from a real record)

- The flat-pass anatomy: the total held while honesty rose +1 and performance
  fell −1 — the loss was SELF-INFLICTED collateral (an unoptimized image
  displayed at a fraction of its size), not targeted work. Totals hide trades;
  read areas, not sums.
- The private-source ceiling: 4 of 7 critics in two consecutive graded passes
  named the same blocker — every receipt bottomed out in a source only the
  operator could read. Claim and Proof plateau at 3–4 until a human rules on a
  publicly checkable anchor. Do not spend build turns there; mark
  BLOCKED-ON-HUMAN.
- Three passes stuck at 3 on First-30s, Craft, and Phone: generic "polish"
  deltas do not move them; only element-named deltas have ever moved an area.
- Cold critics find real defects the builder cannot see (an impossible weekday,
  a generation timestamp that postdates its own build) — never let the builder
  grade its own pass.
- A dead-end receipt is worse than no receipt: it converts a reader who came to
  verify into a reader who caught you bluffing. Where the evidence cannot
  travel, LABEL it — an explicitly welded pane reads as honesty rather than
  absence.
- Two declarations of one fact will drift, and the drift is invisible because
  each file reads correctly alone (a robots file versus a response header; a
  pruned title versus the commit subject it re-derives from). When a defect
  lives BETWEEN two files, the fix is a gate that refuses disagreement, not a
  careful edit.
- A GREP IS NOT A FINDING. A pattern match cannot tell a receipt invitation the
  reader cannot accept from donated source code the page exists to give away.
  One surviving hit for a shell command turned out to be a line inside a
  donated code sample — the reader's own copy-this snippet. "Converting it to
  the attestation idiom" would have broken a working sample to satisfy a
  pattern match. The structural distinction is usually already in the markup:
  exclude the donated-code figure class before scanning. Findings survive at
  the level of what a string DOES, not what it matches.

## LOOP-IMPROVE (append-only log, in this file, after every cycle)

Format: `| delta | executed? | predicted move | actual move |`

After each graded pass, append one row per prior-cycle delta and compute the
hit-rate. When prediction accuracy over the trailing five rows drops below 3/5,
amend the rubric line that generated the failed predictions and note the
amendment here. The rubric improves on measured error, never on taste.

Sheets live in a critic-sheet directory inside the site's own repo. A
prediction nobody can look up is a recollection, so the sheet has to survive the
session that wrote it — an early pass had to reconstruct its own previous-grade
column because the sheets had not been kept.

| delta | executed? | predicted move | actual move |
|---|---|---|---|
| *(start your log here — one row per delta, appended after each graded pass)* | | | |

## COST DISCIPLINE

- CHEAP REGRESSION CHECK (every untargeted area, every cycle): re-measure its
  last-pass numbers (bytes, requests, tap targets, overflow, reconciling counts)
  and re-shoot its two anchor screenshots. Nothing else. This check exists
  because one pass's Performance loss was collateral damage from untargeted
  work — it is the tripwire for exactly that.
- Cycle cap: one graded pass per invocation; at most 2 build turns between
  grades; stop and report rather than exceed the cap.
- Grading runs off the screenshot set when one is provided — re-shoot only what
  is missing or stale (commit mismatch).

## SHEET FORMAT (the memo)

Grid: seven areas × (prev, new, Δ) + the commit under test + screenshot
directory + shot count. Each area carries its owner class (rule D). The two
findings that matter most, one line each, with evidence. Deltas with owners and
PREDICTED moves (rule C). Prediction hit-rate as a number. An UNMEASURED list.
Never a verdict without its artifact.
