← Commit history

2.6.0: a declared scroller is the pane whether or not it is overflowing - the row failed the same page when empty and passed it when populated

John Lauer ·f6c0d7f1bb ·1mo ago ·parent 876f395
3 files changed +41−4
assets/module/newbie-panel.js+10−2
@@ -450,8 +450,16 @@      * adopted the pattern I had recommended; parts-search found the documentElement one.) */     var sc = panel.parentElement;     while (sc && sc !== document.body) {+      /* A DECLARED scroller is the pane whether or not it is scrolling RIGHT NOW. Requiring+       * it to overflow was a bug with a nastier shape than the two before it: with+       * scrollbar-gutter:stable (which this pack mandates, so results arriving cause no+       * reflow) the track is reserved even when nothing overflows, so the loop walked PAST+       * the real pane, fell back to documentElement, and reported the right inset over by+       * one scrollbar width. The SAME PAGE passed when populated and failed when empty, and+       * empty is a dashboard's first-load state. Predicted from a code read by parts-search+       * and confirmed here: 16 left / 31 right, exact. */       var so = getComputedStyle(sc).overflowY;-      if ((so === 'auto' || so === 'scroll') && sc.scrollHeight > sc.clientHeight) break;+      if (so === 'auto' || so === 'scroll') break;       sc = sc.parentElement;     }     var paneLeft, paneW;@@ -477,6 +485,6 @@     return { ok: ok, rows: rows };   } -  root.AdomNewbiePanel = { mount: mount, toast: toast, selfCheck: selfCheck, version: '2.5.0',+  root.AdomNewbiePanel = { mount: mount, toast: toast, selfCheck: selfCheck, version: '2.6.0',                            TWO_COL_MIN: TWO_COL_MIN, PHRASE_BUDGET: PHRASE_BUDGET }; })(typeof window !== 'undefined' ? window : this);
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-ui-design",-  "version": "2.5.2",+  "version": "2.6.0",   "type": "skill",   "description": "The Adom UI Design System plus a bundle of focused UI skills (tooltips, floating-windows, toasts, responsive-ui, app-shell, ai-driven-apps, clickable-paths, dark-default, input-feedback, settings-layout). One install drops the whole set of skill files onto your container, plus shared icon assets (the settings cog) so every Adom app draws the same glyph.",   "dependencies": {},
skills/newbie-panel/SKILL.md+30−1
@@ -364,14 +364,33 @@ missing the previous two times, and the reason the alternation kept happening: * rows in the matrix below matter as much as the three green ones, because a check that only ever sees the case that motivated it is a check nobody has watched go red. -| page structure | verdict |+| case | verdict | |---|---| | simple page, padding on the mount div | **pass** | | app-shell, inner scroller, padding on the mount div | **pass** | | shared outer container carries the gutter, mount flush | **pass** |+| **app-shell scroller with NOTHING IN IT (does not overflow)** | **pass** | | a wrapper adding 40px on top of a correct mount div | **red** | | no gutter anywhere | **red** | +**That fourth row is the one nobody would have written**, and it was the fourth version of+this check to be wrong. The pane loop originally required an ancestor to be OVERFLOWING before+accepting it as the pane. With `scrollbar-gutter: stable`, which this pack mandates so+arriving results cause no reflow, the track is reserved whether or not the element scrolls. So+on an empty page the loop walked PAST the real pane, fell back to `documentElement`, and+reported the right inset over by exactly one scrollbar width.++**The same page passed when populated and failed when empty**, and empty is a dashboard's+first-load state. That is worse than a constant miss: an app goes green in the harness, ships,+and reds the first time anyone runs selfCheck on a fresh page, then starts adding padding to+chase it, which is the self-damage this page warns about two sections up. A declared scroller+is the pane whether or not it is scrolling; that is what the declaration means. One clause+deleted.++parts-search predicted it from a code read, labelled it explicitly as a code read rather than+a measurement, and named the exact numbers it expected. Measured: **16 left / 31 right**, to+the pixel. With the clause dropped, 16 / 16, and all five other rows unchanged.+ **THE TABLE IS THE DELIVERABLE, NOT THE FIX.** pup's point, and it is why 2.5.0 held where 2.3.0 and 2.4.0 did not: anyone can write a check that passes the case that motivated it. What makes a check trustworthy is the enumerated list of cases it was run against, including the@@ -382,6 +401,16 @@ scroller were both written down only because an app pushed back instead of compl here would have enumerated them a day earlier. A fleet that argues produces a better test suite than a fleet that obeys. +**⛔ A CHECKER TESTED AGAINST FIXTURES ITS AUTHOR WROTE INHERITS ITS AUTHOR'S ASSUMPTIONS.**+The sharpest thing anyone said in four rounds of this, from parts-search: the pattern is not+that apps are better checkers than the person who wrote the check. It is that **every one of+these bugs lived in an assumption the fixtures shared with the checker**, because the same+person authored both. The matrix above is the right instrument and it still has that property:+every row is a structure someone already knew about. **The rows that catch the next bug are+the ones nobody has thought to write**, and they come from apps testing the check against a+real page rather than against a fixture. Publish the check, invite the disagreement, and treat+a considered pushback as a test case you did not have.+ **⛔ WHEN A CHECK FAILS, ASK WHETHER IT IS FAILING THE CORRECT IMPLEMENTATIONS.** pup's framing, and it is the sharpest hazard on this page: a check that is wrong at random is noise, but a check that is systematically wrong about the WELL-BUILT cases actively teaches the fleet