You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Clear both red audits, unify the re-send label, fix two bugs in the selector
icon-audit 2 findings -> 0, row-actions-audit 1 -> 0. Both exit 0 now.
The row actions fix is the one its sibling already made. design.md settles that
a row reaching three actions gets the menu, and /admin/barcode_items carried
View, Edit and Delete -- but /barcode_items had the identical shape and resolved
it the cheaper way, with the reasoning recorded in the partial: the View goes
because the record's name in the first cell links to it, leaving a settled pair
that is always both present, so they stay inline. Two clicks saved over a menu,
and a column that cannot move because nothing in it is conditional. Collapsing
to a menu would have satisfied the rule and left two parallel tables looking
different for no reason. design.md now records dropping to two as an accepted
resolution beside "gets the menu", since the rule is about reaching three and
not about the menu being the only cure.
The two icon findings were unregistered rather than wrong. The lexicon is a
meaning->glyph registry whose own note says adding one has to be a decision
rather than a reflex, so `bi-key` = reset a password and `bi-arrow-left-right`
= compare with another period are now in it.
And the lexicon had already drifted from design.md in exactly the way its note
warns against -- "change both together" -- with six entries in the JSON and
absent from the prose table: bi-people, bi-person-gear, bi-filetype-csv,
bi-sliders, bi-clipboard, bi-calculator. All eight are in both now, checked in
both directions.
The label is "Re-send invitation" in all three places. Chosen because the code
and the user-facing noun already say invitation everywhere -- invitation_status,
reinvitable?, resend_user_invitation_path -- so consistency with the domain beats
a two-to-one majority for "invite". The dated mockup keeps the old wording as a
record.
which-audits.rb selected all 30 and all 30 were run, which is the point. All
clean: axe 0 violations over 160 pages, keyboard no findings, responsive no
findings, page-audit 0 defects, template-compile all compile, dead-code at its
documented 147. form-validation names /partners/family_requests/new under "7
forms an empty submit does not exercise" -- informational, not a finding.
Using the tool found two defects in the tool:
* it printed `ruby bin/design/dead-code.rb`, which fails. Three Ruby audits
need the app booted and they are exactly the three that mention `Rails.`, so
the runner is inferred now and a new Rails-using audit gets it for free.
* the pasteable command reported only each audit's last four lines, so it
prints `exit=` too -- several of these say something reassuring in prose
while exiting non-zero, and dead-code exits 1 by design.
81 examples 0 failures; erb_lint and rubocop clean; state.rb --check up to date.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/changelog.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -353,6 +353,7 @@ zero across these commits; several were pre-existing bugs the old markup had bee
353
353
| `daba48850` | **`responsive-audit` reports zero across the whole app, and the last two findings were the same class of false positive as the flicker.** Both remaining findings were "fixed/sticky chrome covers 186px of a 360px viewport", on `/admin/base_items` and `/admin/partners`. The check sums the vertical bands of everything `fixed` or `sticky`; **a `sticky` element with `top` and `bottom` both `auto` is pinned to a horizontal edge**, and its band scrolls away with the content rather than occluding a fixed strip. The frozen actions column is precisely that — measured on `/admin/partners` at 740×360, eight `td.cell-actions` at `top: auto, bottom: auto, right: 0px` in consecutive bands (216..269, 269..322, 322..375), unioned to 186 of 360 and over the 50% threshold, for a column that eats **no height at all**. Same family as the ancestor bug fixed an hour earlier: a geometric rule reading an element whose geometry does not mean what the rule assumes. **Five controls, all correct**: a right-pinned column over eight rows scores 0, a sticky topbar 64, a fixed bottom bar 56, both together 120 (unioned, not summed), and a topbar beside a pinned column scores only the topbar's 64. Three full runs byte-identical, **0 findings across 155 routes**. **Then the interesting part, which is a correction of my own.** Having removed the column, a four-page spot check showed nothing pinned and I concluded — and wrote into the code and the to-do — that the check had gone inert on this app. So the run now prints what it considered, per the suite's own "count what you examined" rule, and that line **falsified me in one run**: it considers **30 elements across 146 page visits**, identical on three runs, every one of them `.table-rail`, the fixed 24px scroll rail on a wide table, at 24px of 360 — about 7%. Live input, negative verdict. Both claims corrected in place. What is genuinely unexercised is the *reporting* path above 50%, which no real screen reaches; the five controls live nowhere yet because the check is inline rather than exported, and `docs/todo.md` names the extraction. **Two doc corrections in the same commit.** `design-decisions.md` still said `/broadcast_announcements/1/edit` and `/partners/children/new` "still 404 and are still skipped by every audit" — fixed the next day by `3403c72b7`; marked superseded rather than rewritten, because a dated entry is a record and not a status page, and re-verified at 155 routes with an empty not-reached list. And `todo.md`'s skills figures said 17 files/1,383 lines against an actual **18/1,599**. The other two numbers in that file were re-measured and both still hold: 11 of `UiHelper`'s 27 methods live, and 9 users whose `display_name` is the placeholder. |
354
354
| `3c4812e72` | **The skills-symlink premise, verified — it holds, and symlinks are followed.** The standing item to make `.claude/skills/` available outside this repo rested on a claim nobody had tested here: that Claude also reads `~/.claude/skills/`. It had never been tested because that directory has never existed on this machine, so the plan's foundation was an assumption. **Asking a model whether it can see a file is the weakest available evidence**, so it was checked with a canary: a skill at `/tmp/canary-skill/SKILL.md` carrying **two different random tokens**, one in the frontmatter `description` and one in the body, installed exactly as the plan proposes — as a symlink, `~/.claude/skills/canary-probe -> /tmp/canary-skill`. `claude -p` run from `/tmp`, a directory with no `.claude/skills` of its own, returned **both**. Two tokens because they answer different questions: the description token proves *registration*, the body token proves the file was *read*. **The negative control is what makes it evidence** — the symlink was removed while the file was left on disk inside the working directory, and the same prompt returned `NO-CANARY-SKILL`, excluding the confound that a positive result alone leaves open (the file simply being near the session's cwd). Corroborating but insufficient on its own, and ranked as such: the client binary carries **14** references to `~/.claude/skills/`, including a `synced` subdirectory named in help text — string evidence shows the path is *known*, only the canary shows it is *loaded*. Both artefacts were removed and `~/.claude/skills/` left absent, so `todo.md` still describes the machine as it stands. **The symlink itself is still not done** and still needs a decision: it writes outside the repo, and the one real tradeoff is unchanged — a symlink points at a path, so if this repo moves the skills stop working silently, while a copy trades that for two versions that drift. Generalised into `evidence-discipline` as "verify a mechanism with a canary, not with a self-report". |
355
355
| `718e5cbaf` | **Ran the seven audits I had skipped, and built the thing that stops the skipping.** Yesterday's changes removed **fifty keyboard tab stops** and altered two control sizes, and the audits re-run afterwards were chosen from memory — so `keyboard-audit`, `wcag22-audit`, `row-actions-audit`, `tooltip-audit`, `wcag-audit`, `icon-audit` and `table-audit` were all skipped, every one of them a check measuring exactly what had changed. **Run now, and the tab-stop removal broke nothing**: keyboard-audit 146 screens at 1280 and again at 375, no findings; axe 160 pages 0 violations; wcag22 no failures with its examined counts printed; tooltip 653 icon-only controls 0 defects; table-audit 155 tables, 0 mixed weights, 0 filled buttons in a row. **Two audits exit non-zero and neither is from yesterday**, which is worth stating rather than implying: `icon-audit` reports `bi-arrow-left-right` ("Compare with the previous period") and `bi-key` ("Reset password") as glyphs absent from the lexicon, and `row-actions-audit` reports `/admin/barcode_items` carrying 3 inline actions with no menu, plus advisories on nine tables that need a human. **One genuine inconsistency surfaced**: `bi-envelope` now carries three labels — "Re-send invitation" on `/organization` against "Re-send invite" in `admin/users/_list` and `partners/_partner_row` — for the same action. Pre-existing (the old `title` said "Re-send invitation" too), but it took a proper `aria-label` for the audit to see it. **The fix for the skipping is `bin/design/which-audits.rb`.** Not a checklist, deliberately: a checklist is memory written down, correct the day it is written and silently wrong the day an audit is added. Instead omission is impossible by construction — each audit declares its inputs in its own header (`AUDIT-READS: RENDER`), the script **enumerates `bin/design/` itself** rather than carrying a list, and **a file that neither declares nor is named a non-audit fails the run**, so a new audit cannot drop silently out of every future selection. Six non-audits are excused with a reason each, because an unexplained absence reads identically to an oversight. Bundles are coarse on purpose: a browser audit drives real pages, so for a render-path change the honest answer is *most of them* — asked by hand about one view and one controller I picked six and the truthful number was twenty-eight. **Three controls, in the three directions the failure can hide**: a view change selects the render audits; a **docs-only change selects zero browser audits** (otherwise it is not selecting, it is saying "everything"); and a planted undeclared file fails with exit 2, proven both with the file present and after removing it. It also prints what it considered and did *not* select, and a pasteable command for the selected set. Fixed on the way: the `state.rb` paragraph in `onboarding.md` was **inside** a ```bash fence and rendering as shell. Generalised into `audit-suite` as "after a change, do not choose the audits from memory". |
356
+
| `TBD` | **Both red audits cleared, the label unified, and the new selector earned its keep by finding two bugs in itself.** `icon-audit` **2 findings → 0** and `row-actions-audit` **1 → 0**, both now exit 0. **The row actions fix is the one its sibling already made.** design.md settles that a row reaching three actions gets the menu, and `/admin/barcode_items` carried View, Edit and Delete — but `/barcode_items` had the identical shape and resolved it the cheaper way, with the reasoning recorded in the partial: the View goes because the record's name in the first cell links to it, leaving a settled pair that is always both present, so they stay inline. Two clicks saved over a menu and a column that cannot move, because nothing in it is conditional. Collapsing to a menu would have satisfied the rule and left two parallel tables looking different for no reason. design.md now records **dropping to two** as an accepted resolution beside "gets the menu", since the rule is about reaching three and not about the menu being the only cure. **The two icon findings were unregistered, not wrong**: the lexicon is a meaning→glyph registry whose own note says a new glyph must be a decision rather than a reflex, so `bi-key` = *reset a password* and `bi-arrow-left-right` = *compare with another period* are now in it. **And the lexicon had already drifted from design.md** in the way its note warns against — "change both together" — with **6 entries** (`bi-people`, `bi-person-gear`, `bi-filetype-csv`, `bi-sliders`, `bi-clipboard`, `bi-calculator`) in the JSON and absent from the prose table. All 8 are in both now, checked both directions. **The label is "Re-send invitation" in all three places**, chosen because the code and the user-facing noun already say *invitation* everywhere (`invitation_status`, `reinvitable?`, `resend_user_invitation_path`) — the two `Re-send invite` call sites changed, the dated mockup left as a record. **`which-audits.rb` selected all 30 and they were all run, which is the point**: 30 clean, including axe 0 violations over 160 pages, keyboard no findings, responsive no findings, page-audit 0 defects, template-compile all compile, `dead-code` at its documented 147. `form-validation` names `/partners/family_requests/new` under "7 forms an empty submit does not exercise" — informational, not a finding, and the right discipline. **Using the tool found two defects in the tool.** It printed `ruby bin/design/dead-code.rb`, which fails: three Ruby audits need the app booted, and they are exactly the three that mention `Rails.`, so the runner is now inferred rather than listed and a new Rails-using audit gets it for free. And the pasteable command reported only each audit's last four lines — so it now prints **`exit=`** too, because several of these say something reassuring in prose while exiting non-zero and `dead-code` exits 1 by design. 81 examples 0 failures. |
0 commit comments