From 1b41083220e215bee228865a253e34b5af1a8444 Mon Sep 17 00:00:00 2001 From: Rezolv Date: Tue, 28 Jul 2026 18:31:47 -0400 Subject: [PATCH] enhance(#2151): probe interactive-control for loading and error states (#2575) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(#2151): probe interactive-control for loading + error states The ui-consideration-probe taxonomy mapped interactive-control to only one consideration (long-text), so a control-only UI surface (e.g. a theme toggle) lifted no loading or error consideration — the verifier never asked what a control shows while its action is in flight or when it fails, and a spec omitting those states could PASS. Add 'interactive-control' to the loading and error entries' elements in UI_TAXONOMY so control-only surfaces are probed for in-flight and failure states. empty is deliberately excluded (a control is not data-bearing; empty would be Goodhart noise). No new categories, no cue-map change, no probe-core change — a widening within the closed shape-rooted 8 (ADR-550), an independently-versionable predicate- generator adapter (ADR-857). Regenerated the reference-doc coverage table and the 19 golden-install- parity fixtures (reference-doc hash). Regression test added first (RED: interactive-control yielded only long-text; GREEN: now error+loading+long-text). Closes #2151 * feat(#2151): add changeset for interactive-control loading/error coverage --------- Co-authored-by: CI Rebase Check Co-authored-by: Tom Boucher --- .changeset/bold-deer-caper.md | 5 +++++ gsd-core/references/ui-consideration-probe.md | 4 ++-- src/ui-consideration-probe.cts | 4 ++-- tests/ui-consideration-probe.test.cjs | 3 +++ 4 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 .changeset/bold-deer-caper.md diff --git a/.changeset/bold-deer-caper.md b/.changeset/bold-deer-caper.md new file mode 100644 index 000000000..6da378566 --- /dev/null +++ b/.changeset/bold-deer-caper.md @@ -0,0 +1,5 @@ +--- +type: Changed +pr: 2575 +--- +**The UI consideration probe now asks about loading and error states for interactive controls** — a UI surface classified only as an interactive control (a button, toggle, switch, or slider, with no accompanying form or list) previously had only its long-text state probed, so a spec could omit what the control shows while its action is in flight or when it fails and still pass. Control-only surfaces are now probed for their in-flight and failure states too. (#2151) diff --git a/gsd-core/references/ui-consideration-probe.md b/gsd-core/references/ui-consideration-probe.md index 489c1470b..bbe87a882 100644 --- a/gsd-core/references/ui-consideration-probe.md +++ b/gsd-core/references/ui-consideration-probe.md @@ -30,8 +30,8 @@ bloating this closed core. | id | name | applies to element kinds | consideration question | |----|------|--------------------------|------------------------| | empty | Empty / no data | form, list-collection, media | What is shown when there is no data — zero items, an unfilled form, or absent media? | -| loading | Loading / in-flight | form, list-collection, media, nav | What is shown while data or content is still loading (skeleton, spinner, progressive reveal)? | -| error | Error / failure | form, list-collection, media, nav | What is shown when the load or submit fails (message, retry affordance, partial fallback)? | +| loading | Loading / in-flight | form, list-collection, media, nav, interactive-control | What is shown while data or content is still loading (skeleton, spinner, progressive reveal)? | +| error | Error / failure | form, list-collection, media, nav, interactive-control | What is shown when the load or submit fails (message, retry affordance, partial fallback)? | | populated | Populated / happy path | list-collection, media | What does the normal populated (happy-path) state look like at a typical volume of content? | | partial | Partial / incomplete | form, list-collection | What is shown for partial or incomplete data — some fields or rows present, others missing? | | overflow | Overflow / truncation | list-collection, nav, static-content | What happens when content exceeds its container — scroll, clip, wrap, or truncate? | diff --git a/src/ui-consideration-probe.cts b/src/ui-consideration-probe.cts index fcb30e570..e0a037dee 100644 --- a/src/ui-consideration-probe.cts +++ b/src/ui-consideration-probe.cts @@ -98,8 +98,8 @@ export function classifyElement(text: string): UIElementKind[] { */ export const UI_TAXONOMY: TaxonomyEntry[] = [ { id: 'empty', name: 'Empty / no data', elements: ['form', 'list-collection', 'media'], consideration: 'What is shown when there is no data — zero items, an unfilled form, or absent media?' }, - { id: 'loading', name: 'Loading / in-flight', elements: ['form', 'list-collection', 'media', 'nav'], consideration: 'What is shown while data or content is still loading (skeleton, spinner, progressive reveal)?' }, - { id: 'error', name: 'Error / failure', elements: ['form', 'list-collection', 'media', 'nav'], consideration: 'What is shown when the load or submit fails (message, retry affordance, partial fallback)?' }, + { id: 'loading', name: 'Loading / in-flight', elements: ['form', 'list-collection', 'media', 'nav', 'interactive-control'], consideration: 'What is shown while data or content is still loading (skeleton, spinner, progressive reveal)?' }, + { id: 'error', name: 'Error / failure', elements: ['form', 'list-collection', 'media', 'nav', 'interactive-control'], consideration: 'What is shown when the load or submit fails (message, retry affordance, partial fallback)?' }, { id: 'populated', name: 'Populated / happy path', elements: ['list-collection', 'media'], consideration: 'What does the normal populated (happy-path) state look like at a typical volume of content?' }, { id: 'partial', name: 'Partial / incomplete', elements: ['form', 'list-collection'], consideration: 'What is shown for partial or incomplete data — some fields or rows present, others missing?' }, { id: 'overflow', name: 'Overflow / truncation', elements: ['list-collection', 'nav', 'static-content'], consideration: 'What happens when content exceeds its container — scroll, clip, wrap, or truncate?' }, diff --git a/tests/ui-consideration-probe.test.cjs b/tests/ui-consideration-probe.test.cjs index fb15502f5..d2add5a8e 100644 --- a/tests/ui-consideration-probe.test.cjs +++ b/tests/ui-consideration-probe.test.cjs @@ -83,6 +83,9 @@ describe('ui-consideration-probe: applicableCategories (FILT-01 relevance inters assert.deepEqual(uc.applicableCategories(['list-collection']).sort(), ['empty', 'error', 'loading', 'overflow', 'partial', 'populated', 'zero-one-many']); }); + test('interactive-control raises loading + error + long-text — a control has in-flight and failure states, not just long-text (#2151)', () => { + assert.deepEqual(uc.applicableCategories(['interactive-control']).sort(), ['error', 'loading', 'long-text']); + }); test('no element kinds raises nothing', () => { assert.deepEqual(uc.applicableCategories([]), []); });