IMPECCABLEfor PRs

Design review for every pull request.

Impeccable for PRs renders the PR, uses it the way a person would, measures the craft, and posts one critique on the pull request: what does not work, and the fix. Your agents read it like any other reviewer and keep going until it is satisfied.

Join the beta waitlist
See it on a pull request that is

ledgerline/app #418 · Add CSV and PDF export to the report toolbar · 3 files, 2 sessionscrewline/web #1287 · Invite member modal · 3 files, 3 sessionswavecast/dashboard #2210 · Add a show settings page · 4 files, 3 sessions

A sample review as it lands on a pull request. Scroll inside the review to explore.

Add CSV and PDF export to the report toolbar #418

Merged codex-agent merged 1 commit into main from report-export

  • Conversation 3
  • Commits 1
  • Checks 3
  • Files changed 3
codex-agentbotcommented

codex-agent added 1 commit 2f0a9c1

impeccablebotcommented

The Export menu answers the one question a person has at that toolbar, which file do I get, and it works from the keyboard. Nothing to fix.

5 of 5 5/5 · Ready
no blockers · nothing to fix · 2 sessions

Does it do its job?

Sessions
Nora, returning customer: 3 steps, scored 9/10. “Export sits where I expected, next to Print, and the hint under PDF said formatted report before I clicked.”
Got through
nothing to fix
Quinn, operator on a phone: 4 steps, scored 8/10. “Arrowed to CSV, Enter, done. Escape put me back on the button.”
Got through
nothing to fix
The report toolbar with the Export menu open beside Print: CSV, rows as filtered; PDF, formatted report.

The report toolbar with the Export menu open beside Print: CSV, rows as filtered; PDF, formatted report.

Measured

MeasureThis changeTotalWhere
SLOP Tells in the chrome00
DRIFT Declarations off the tokens00
CRAFT Controls without a name00
WEIGHT Page weight0 KB31 KBno images
For agents
nothing to do
About this review

Reviewed 3 files at 2f0a9c1. 2 of 2 routes rendered at 1280 and 390 px; 2 sessions. The menu opens from its button, arrows move between the two items, Escape and Tab close it and hand focus back, a click outside closes it.

Ledgerline is a sample app we keep for this. The review is written by hand in the shape the product posts, from the findings the app’s reference review names; the captures are real renders, the visitors and the counts are an example.

All checks have passed 3 successful checks

  • ci / build Successful in 2m
  • code review 2 comments
  • impeccable / design review Ready · 5/5

Pull request successfully merged and closed
The report-export branch can be safely deleted.

Invite member modal #1287

Open codex-agent wants to merge 2 commits into main from invite-modal

  • Conversation 4
  • Commits 2
  • Checks 3
  • Files changed 3
codex-agentbotcommented

codex-agent added 2 commits 8c41e0d

impeccablebotcommented

The invite is three questions on a card that looks like the app, and it works from the keyboard. One thing stops it doing its job: Send invite closes the card and says nothing, so an admin cannot tell the invitation went. And role and permissions ask the same question twice.

3 of 5 3/5 · Not yet: fixable before it ships
1 blocker · 2 on the job · 1 in the changes · 2 in the details · 3 sessions

Does it do its job?

Sessions
Nora, returning customer: 5 steps, scored 6/10. “I pressed Send invite and the card closed. Nothing said it went, and the table did not change.”
Got through, with friction
Sent the invite and could not tell.
Quinn, operator on a keyboard: 4 steps, scored 8/10. “Tab landed in the email field, Escape closed the card, and focus came back to the button.”
Got through
nothing to fix
Ravi, new visitor on a phone: 3 steps, scored 8/10. “Invite member is where I expected, and the form is three questions.”
Got through
nothing to fix
P1

Send invite ends in silence
/ · Invite member

The card closes and clears. Nothing says the invitation went, the People table gains no Invited row, and Activity, where the description says it shows up, is unchanged. An invite that vanishes without a word has not been sent as far as the admin can tell.

Fix Keep the card open until the email passes, then say what happened: an Invited row in the table, or a line in Activity. If Activity is not wired yet, say so on the card.

The foot of the dialog: Cancel and Send invite.
P2

Role and permissions ask the same question twice
/ · Invite member

The role decides what a person can do, and three checkboxes under it let the admin contradict it: a Member with the directory unchecked, a Workspace admin who cannot invite. The invite should ask who and what role, and show what the role allows as a sentence; permissions belong on the person’s page, after they exist.

Fix Drop the checkboxes from the invite. Under the role, one line: what a Member can do. Edit permissions on the member’s page.

The Invite member dialog: an email field, a role select, three permission checkboxes, Cancel and a blue Send invite.

Does each change hold up?

Invite member dialog new /

P2

Send invite is blue in a green app
styles.css:388

The button hardcodes #3b82f6. Every other primary, the Invite member trigger included, is the forest green --accent token. White on that blue is 3.7:1.

Fix Drop the colour rules and let .btn-primary style the button.

The green Invite member button on the People page.
The blue Send invite button at the foot of the dialog.

Is the craft clean?

P3

The close button has no name
index.html:184

A bare × with no aria-label: a screen reader announces “button” and nothing else.

Fix Give it aria-label="Close".

P3

The dialog is on its own spacing rhythm
styles.css:304

22 px between fields where the rest of the stylesheet moves on the 8 px scale.

Fix Replace the literal with --space-lg.

Measured

MeasureThis changeTotalWhere
SLOP Tells in the chrome00
DRIFT Declarations off the tokens33styles.css:304, :376, :383
DRIFT Shipped values against DESIGN.md11#3b82f6 where the accent is green
CRAFT Low-contrast text11Send invite, 3.7:1
CRAFT Controls without a name11the close button
CRAFT Functional text under 11px00
WEIGHT Page weight+4 KB47 KBno images
For agents
P1 · Send invite ends in silence · / · modal.js:29 · fix: keep the card open until the email passes, then an Invited row or a line in Activity.
P2 · Role and permissions ask the same question twice · / · index.html:196 · fix: drop the checkboxes; one line under the role saying what it allows.
P2 · Send invite is blue in a green app · / · styles.css:388 · fix: drop the colour rules; let .btn-primary style it.
P3 · The close button has no name · / · index.html:184 · fix: aria-label="Close".
P3 · The dialog is on its own spacing rhythm · / · styles.css:304 · fix: --space-lg.
About this review

Reviewed 3 files at 8c41e0d. 2 of 2 routes rendered at 1280 and 390 px; 3 sessions. The dialog opens with focus in the email field, traps it, closes on Escape and returns focus to the button.

Crewline is a sample app we keep for this. The review is written by hand in the shape the product posts, from the findings the app’s reference review names; the captures are real renders, the visitors and the counts are an example.

styles.cssline 388
.modal-submit {- background: #3b82f6; border-color: #3b82f6; }
impeccablebotleft a comment

Every other primary in the app takes the --accent token; this one hardcodes the blue.

Suggested change

- background: #3b82f6; border-color: #3b82f6;+ background: var(--accent); border-color: var(--accent);
Commit suggestionAdd suggestion to batch

codex-agent pushed 1 commit

All checks have passed 3 successful checks

  • ci / build Successful in 2m
  • code review 2 comments
  • impeccable / design review Ready · 5/5
Merge pull requestYou can also merge this with the command line.

Add a show settings page #2210

Open codex-agent wants to merge 3 commits into main from show-settings

  • Conversation 4
  • Commits 3
  • Checks 3
  • Files changed 4
codex-agentbotcommented

codex-agent added 3 commits 8c41e0d

impeccablebotcommented

The page is the right shape and reads in one pass: a short form that says where each thing shows up, on the app’s own ground. One thing would hurt a host: Delete show is dressed as the happy path, one click from 48 episodes gone. Two decisions go against the app: a sidebar of its own, and a section that is a heading over nothing.

3 of 5 3/5 · Not yet: fixable before it ships
1 blocker · 3 on the job · 1 in the changes · 2 in the details · 3 sessions

Does it do its job?

Sessions
Ravi, new visitor: 3 steps, scored 2/10. “Connected services is a heading over nothing. I cannot tell if I have none or it is not built yet.”
Stuck
Stuck at Connected services: nothing to connect, nothing said.
Quinn, operator on a phone: 5 steps, scored 6/10. “Two rows of links above the form on my phone, none of which did anything, so I scrolled.”
Got through, with friction
Found the setting past two rows of dead links.
Nora, returning customer: 3 steps, scored 8/10. “Category is where I expected it, and Save changes sat right under the form.”
Got through
nothing to fix
P1

Delete show is dressed as the happy path
/settings.html · Danger zone

The same fill and weight as Save changes, a few lines below it, and one click is the whole flow: no confirmation between the click and 48 episodes gone. The note above it says what deletion removes, which makes the button more dangerous, not less.

Fix Give Delete show a destructive treatment, an outlined --danger button, and a confirmation that names the show and what goes with it, with Cancel as the default.

The Danger zone card: a sentence saying deletion removes all 48 episodes, and a filled orange Delete show button.
P2

The page invents its own navigation
/settings.html · sidebar

A sidebar of four section links while every other page navigates from the masthead. Nothing updates its current state, and on a phone it wraps into two rows of links between the heading and the first field. Four sections on one short page do not need a second navigation.

Fix Cut the sidebar and its column. The section headings already do the job.

On a phone: Show details, Notifications, Connected services and Danger zone as two rows of links.
P2

Connected services is a heading over nothing
/settings.html · Connected services

An empty list under a heading. A host cannot tell whether they have no connected services or the feature is not built yet, and the PR body knows the answer.

Fix Write the empty state: one sentence saying the Spotify and Apple sync is coming and nothing needs doing now. If that cannot be written yet, leave the section out until it can.

The Connected services card: a heading and nothing under it.

Does each change hold up?

Show details form new /settings.html

P2

The title field is one line for a title that is not
settings.html:38

Show title is a single-line input, and the 105-character title runs off its right edge. The hint says apps show only the first two lines of the description; nothing says where the title is cut. The one field a host comes here to fix hides the part that matters.

Fix Make it a textarea sized to the title, with the directory’s limit beside it as a count.

The Show title field: a long title cut off at the right edge of a single-line input.

Is the craft clean?

P3

Two field names reach no control
settings.html:49

The Category label points at an id the select does not have, and Description is a heading above a textarea with no label. Both look labelled and neither is.

Fix Point the label at category, and turn the Description heading into <label for="show-description">.

The Category field: a label, a select showing Society & Culture, and a hint.
P3

Spacing in the new sections is off the app’s scale
styles.css:194

28 px gaps, 18 px section padding and a 10 px rhythm where the rest of the app moves in 12, 16 and 24.

Fix Replace the literals with the steps the stylesheet already names.

Measured

MeasureThis changeTotalWhere
SLOP Tells in the chrome00
DRIFT Declarations off the tokens99styles.css:194, :200, :226 …
DRIFT Shipped values against DESIGN.md00
CRAFT Controls without a name22Category, Description
CRAFT Low-contrast text00
CRAFT Functional text under 11px00
WEIGHT Page weight+11 KB58 KBno images
For agents
P1 · Delete show is dressed as the happy path · /settings.html · settings.html:91 · fix: destructive treatment plus a confirmation that names the show.
P2 · The page invents its own navigation · /settings.html · settings.html:23 · fix: cut the sidebar and its column.
P2 · Connected services is a heading over nothing · /settings.html · settings.html:77 · fix: write the empty state, or leave the section out.
P2 · The title field is one line for a title that is not · /settings.html · settings.html:38 · fix: a textarea sized to the title, with the limit as a count.
P3 · Two field names reach no control · /settings.html · settings.html:49 · fix: label for="category"; label the description.
P3 · Spacing off the app’s scale · /settings.html · styles.css:194 · fix: the named steps.
About this review

Reviewed 4 files at 5b2d91e. 3 of 3 routes rendered at 1280 and 390 px; 3 sessions.

Wavecast is a sample app we keep for this. The review is written by hand in the shape the product posts, from the findings the app’s reference review names; the captures are real renders, the visitors and the counts are an example.

codex-agent pushed 1 commit

All checks have passed 3 successful checks

  • ci / build Successful in 2m
  • code review 2 comments
  • impeccable / design review Ready · 5/5
Merge pull requestYou can also merge this with the command line.

Code review caught up with agentic development. Design review did not.

Teams ship many times the pull requests they used to, and the designer is out of the handoff. Slop in the code gets an AI reviewer on every PR; slop on the screen gets nobody, and it compounds into the brand, the numbers and the people who stop coming back. Impeccable for PRs is the design reviewer: one more check to gate on, one more comment to satisfy, with the fix in it.

Join the beta.

For teams with a frontend and a preview to render. Leave your email and you get one message when your seat is ready.

We keep your address and your note, plus salted hashes of your network address and browser so one machine cannot fill the list. No other mail, no sharing, no analytics on this page. The first mail carries a link that removes you.