From d268428eac18fcd66ff98ca7eac50d7d1883396b Mon Sep 17 00:00:00 2001 From: meh Date: Mon, 7 Sep 2026 21:08:09 +0700 Subject: [PATCH 01/22] feat(ui): take @pathscale/ui 3.x The library moved to 3.x. Most of the 3.0 breaking changes were already satisfied here: this site was written against the 2.11 vocabulary, so it already passes `class`, `flavor` and `state` rather than `className`, `color` and the `isDisabled`/`isLoading` booleans, and it uses none of the eleven renamed components. Three things did need changing. Checkbox now reports its new value. As of 3.1 `Switch`, `Checkbox` and `Radio` hand `onChange` the checked boolean instead of the native `Event`, matching what `Slider`, `RadioGroup` and `CheckboxGroup` always did. The consent box on the study page was the only call site. It is the change worth being careful about, because a handler written for an `Event` can still compile in a loose position and then read `undefined` at run time, which for this box would silently refuse consent. The Layout compiler now runs before Babel. `@pathscale/ui` is a compiled Layout bundle, and the application compiler resolves ` - - - - + + @@ -173,11 +169,9 @@ const HomePage: Component = () => (

- - - +

@@ -258,24 +252,23 @@ const HomePage: Component = () => (
- - - - + - + Decision record +
@@ -297,11 +290,9 @@ const HomePage: Component = () => ( interface legible. Nothing more, and nothing less.

- - - +

diff --git a/tests/ps-qa/checks/chrome.ron b/tests/ps-qa/checks/chrome.ron index 7ec1ba6..9b29632 100644 --- a/tests/ps-qa/checks/chrome.ron +++ b/tests/ps-qa/checks/chrome.ron @@ -27,10 +27,8 @@ id: "the-shell-reaches-the-page", group: "chrome", what: "the built bundle mounts and the header's own name is drawn", - // The logo is a `` of text, so it has a name and, on a host with - // no fonts, no box. It still has to carry that name: it is the only - // link back to the landing page, and without one it is unreachable to - // anyone not pointing at it. + // The logo text sits inside a UI Link with its own minimum box, so the + // route home stays reachable even when the host has no fonts. open: Some("PromptSyntax"), hover: None, click: None, @@ -72,6 +70,7 @@ click: None, subject: "link:GitHub", expect: PaintsNamed, + covers: ["link:GitHub"], ), ( id: "the-header-navigation-is-a-landmark", @@ -95,6 +94,7 @@ click: None, subject: "link:Contact", expect: Present, + covers: ["link:Contact"], ), // The footer's position is not asserted, and cannot be from here: every // link in it is bare text, so on the fontless host none of them is laid diff --git a/tests/ps-qa/checks/home.ron b/tests/ps-qa/checks/home.ron index 51d1c0a..60ec21c 100644 --- a/tests/ps-qa/checks/home.ron +++ b/tests/ps-qa/checks/home.ron @@ -36,7 +36,7 @@ open: None, hover: None, click: None, - subject: "button:Read the specification", + subject: "link:Read the specification", expect: PaintsNamed, ), ( @@ -46,9 +46,10 @@ open: None, hover: None, click: None, - subject: "button:View on GitHub", + subject: "link:View on GitHub", expect: RightOf, - compare: Some("button:Read the specification"), + compare: Some("link:Read the specification"), + covers: ["link:View on GitHub"], ), // The worked example: an annotated prompt, then the receipt that says what // it did. This is the whole argument of the site in one section. @@ -122,7 +123,7 @@ open: None, hover: None, click: None, - subject: "button:Read the full specification", + subject: "link:Read the full specification", expect: PaintsNamed, ), // The TOON transport proposal. The newest section, and the one whose two @@ -138,6 +139,17 @@ subject: "heading:A TOON transport for receipts", expect: Present, ), + ( + id: "and-it-links-the-transport-format", + group: "home", + what: "the format named by the proposal has its source linked inline", + open: None, + hover: None, + click: None, + subject: "link:TOON", + expect: Present, + covers: ["link:TOON"], + ), ( id: "and-it-links-the-transport-profile", group: "home", @@ -145,8 +157,9 @@ open: None, hover: None, click: None, - subject: "button:Read the transport profile", + subject: "link:Read the transport profile", expect: PaintsNamed, + covers: ["link:Read the transport profile"], ), ( id: "and-it-links-the-decision-record", @@ -155,9 +168,10 @@ open: None, hover: None, click: None, - subject: "button:Decision record", + subject: "link:Decision record", expect: RightOf, - compare: Some("button:Read the transport profile"), + compare: Some("link:Read the transport profile"), + covers: ["link:Decision record"], ), // Scope. The section that says what the proposal does not claim, which is // the one a reader checks before taking any of the rest seriously. @@ -174,12 +188,13 @@ ( id: "and-it-invites-contribution", group: "home", - what: "the page ends on the action it wants, and the button is pressable", + what: "the page ends on the action it wants, and the link is pressable", open: None, hover: None, click: None, - subject: "button:Contribute on GitHub", + subject: "link:Contribute on GitHub", expect: PaintsNamed, + covers: ["link:Contribute on GitHub"], ), // The authored order of the page, read off the boxes the renderer produced // rather than off the source. Each pair names the control its section ends @@ -192,9 +207,9 @@ open: None, hover: None, click: None, - subject: "button:Read the specification", + subject: "link:Read the specification", expect: Above, - compare: Some("button:Read the full specification"), + compare: Some("link:Read the full specification"), ), ( id: "and-the-mechanism-comes-before-the-transport-proposal", @@ -203,9 +218,9 @@ open: None, hover: None, click: None, - subject: "button:Read the full specification", + subject: "link:Read the full specification", expect: Above, - compare: Some("button:Read the transport profile"), + compare: Some("link:Read the transport profile"), ), ( id: "and-scope-is-the-last-section", @@ -214,8 +229,8 @@ open: None, hover: None, click: None, - subject: "button:Read the transport profile", + subject: "link:Read the transport profile", expect: Above, - compare: Some("button:Contribute on GitHub"), + compare: Some("link:Contribute on GitHub"), ), ] diff --git a/tests/ps-qa/checks/navigation.ron b/tests/ps-qa/checks/navigation.ron index 0d86812..a1b5066 100644 --- a/tests/ps-qa/checks/navigation.ron +++ b/tests/ps-qa/checks/navigation.ron @@ -3,12 +3,10 @@ // This is its own group, and it sorts last on purpose. The runner buckets // checks by the surface their `open` names and walks the buckets in profile // order, so within the home bucket the files run in name order: chrome, home, -// lenses, then this one. The header logo is the only control that returns to -// the landing page and it is a `` of text, so on the fontless host CI -// builds it has no box and cannot be pressed. Home is reachable only where the -// application already is. Every other group therefore stays on the landing -// page, and this one -- running after all of them -- is the group allowed to -// leave. +// lenses, then this one. Every other home group stays on the landing page, and +// this one -- running after all of them -- is the group allowed to leave. The +// home link has a minimum box of its own, so the final check can exercise the +// route home even on the fontless host. // // The theme is also carried across a route change here, because a route change // on this site is a whole document load rather than a client-side transition. @@ -41,14 +39,18 @@ ( id: "the-hero-call-to-action-reaches-the-specification", group: "navigation", - what: "the landing page's own button goes where its label says", - // The control a visitor is most likely to press, and a Button rather - // than the header's router link. + what: "the landing page's own action goes where its label says", + // The control a visitor is most likely to press, and the prominent + // action rather than the header's router link. open: None, hover: None, click: Some("Read the specification"), subject: "link:Download PDF", expect: PaintsNamed, + // The lower call to action and footer use the same route. This driven + // outcome covers those copies without pretending that painting them + // proves navigation. + covers: ["link:Read the full specification", "link:Spec"], outcome_timeout_ms: 8000, ), ( @@ -96,16 +98,19 @@ ), // From one document to the other, and back, using the header. These // declare `open` so a single check can be re-run by id against a fresh - // host; in a whole-group run they are already where they need to be. + // host. ( id: "the-header-reaches-the-syntax-reference-from-the-specification", group: "navigation", what: "the header works from a document page, not only from home", - open: Some("Syntax reference"), + open: Some("Specification"), hover: None, - click: None, + click: Some("Syntax reference"), subject: "heading:Syntax Reference", expect: Present, + // The footer copy is the same route and label; the header copy is the + // painted representative that this check actually presses. + covers: ["#footer-syntax-reference"], outcome_timeout_ms: 8000, ), ( @@ -149,4 +154,15 @@ subject: "heading:Syntax Reference", expect: Absent, ), + ( + id: "the-site-name-returns-home-from-a-document", + group: "navigation", + what: "the persistent site name returns a document reader to the landing page", + open: Some("Specification"), + hover: None, + click: Some("#site-home"), + subject: "tablist:Choose your lens", + expect: Paints, + outcome_timeout_ms: 8000, + ), ] diff --git a/tests/ps-qa/ps-qa.ron b/tests/ps-qa/ps-qa.ron index f7e7e6f..4d47e29 100644 --- a/tests/ps-qa/ps-qa.ron +++ b/tests/ps-qa/ps-qa.ron @@ -26,18 +26,16 @@ // Sidebar entries are anchors with `padding: 3px 0`, so they measure 243x6 // with no font at all. Markers are matched case-sensitively and as substrings. // -// # Surface order is run order, and home is reachable only at the start +// # Surface order is run order // // The runner buckets every check by the surface its `open` names and walks the // buckets in the order this list gives them, so a group whose checks jump // between surfaces does not run in the order its file reads. // -// The one control that returns to the landing page is the header logo, and it -// is a `` of text: on the fontless host it has no box and cannot be -// pressed. Home is therefore reachable only where the application already is -// -- at the start of a run -- and the check files are written for that. Every -// home-surface check leaves the site on the landing page, and `navigation.ron` -// sorts last among them so the one group that leaves does so at the end. +// Every home-surface check leaves the site on the landing page, and +// `navigation.ron` sorts last among them so the one group that leaves does so +// at the end. Its final check presses the padded home link and proves a reader +// can return from a document even on the fontless host. // // # The two routes no check can reach // @@ -58,9 +56,7 @@ AppProfile( (name: "syntax", opener: "Syntax reference", marker: Some("1. At a glance")), ], navigation_controls: ["PromptSyntax", "Specification", "Syntax reference"], - // Used only to recover a sweep that has walked somewhere it cannot get - // back from, and on the fontless host it cannot: see above. Named anyway, - // because it is the control, and a sweep with a real font stack can use it. + // Used to recover a sweep that has walked away from the landing page. home_opener: Some("PromptSyntax"), // Controls that leave the site. A headless browser will follow an ordinary // anchor, and following these would make a run depend on github.com being @@ -68,7 +64,7 @@ AppProfile( // handling -- rather than on this site. // // Matched by prefix against the control's accessible name, which is why - // the three GitHub buttons are listed separately: only one of them is + // the three GitHub links are listed separately: only one of them is // named "GitHub". manual_controls: [ (label: "GitHub", command: "github.com/pathscale/promptsyntax.org"), From 046abac935dca81cb70833f1ff82d411596d8e14 Mon Sep 17 00:00:00 2001 From: meh Date: Sun, 13 Sep 2026 01:54:26 +0700 Subject: [PATCH 18/22] test(qa): reconcile document controls --- package.json | 2 +- src/components/LensTabs.tsx | 2 +- src/components/SiteNavbar.tsx | 3 +++ src/pages/DocPage.tsx | 25 +++++++++++++++++++++++++ src/pages/HomePage.tsx | 12 +++++++++--- src/pages/SpecPage.tsx | 2 +- src/pages/SyntaxPage.tsx | 2 +- tests/ps-qa/checks/docs-spec.ron | 1 + tests/ps-qa/checks/docs-syntax.ron | 1 + 9 files changed, 43 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index ed8ac8f..c3473a5 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ }, "license": "CC-BY-4.0", "dependencies": { - "@pathscale/ui": "^3.2.0", + "@pathscale/ui": "^3.2.2", "@solidjs/router": "2.0.0-next.16", "@solidjs/web": "2.0.0-rc.4", "@standard-schema/spec": "^1.0.0", diff --git a/src/components/LensTabs.tsx b/src/components/LensTabs.tsx index 37296e6..5db56ae 100644 --- a/src/components/LensTabs.tsx +++ b/src/components/LensTabs.tsx @@ -95,7 +95,7 @@ const LensTabs: Component = () => (

PromptSyntax Impact

- + {(lens) => {lens.label}} diff --git a/src/components/SiteNavbar.tsx b/src/components/SiteNavbar.tsx index 8d639ec..f5c6dcf 100644 --- a/src/components/SiteNavbar.tsx +++ b/src/components/SiteNavbar.tsx @@ -26,6 +26,7 @@ const SiteNavbar: Component = () => {
@@ -169,7 +175,7 @@ const HomePage: Component = () => (

-

diff --git a/src/pages/SpecPage.tsx b/src/pages/SpecPage.tsx index fc108f0..6f384f7 100644 --- a/src/pages/SpecPage.tsx +++ b/src/pages/SpecPage.tsx @@ -4,7 +4,7 @@ import specHtml from "~/content/spec.html?raw"; import DocPage from "~/pages/DocPage"; const SpecPage: Component = () => ( - + ); export default SpecPage; diff --git a/src/pages/SyntaxPage.tsx b/src/pages/SyntaxPage.tsx index d00212c..374b1fd 100644 --- a/src/pages/SyntaxPage.tsx +++ b/src/pages/SyntaxPage.tsx @@ -4,7 +4,7 @@ import syntaxHtml from "~/content/syntax.html?raw"; import DocPage from "~/pages/DocPage"; const SyntaxPage: Component = () => ( - + ); export default SyntaxPage; diff --git a/tests/ps-qa/checks/docs-spec.ron b/tests/ps-qa/checks/docs-spec.ron index b8d9a80..de4f2b1 100644 --- a/tests/ps-qa/checks/docs-spec.ron +++ b/tests/ps-qa/checks/docs-spec.ron @@ -422,6 +422,7 @@ open: None, hover: None, click: Some("1. Abstract"), + covers: ["@document-toc-link", "@document-content-link"], subject: "heading:1. Abstract", expect: Present, outcome_timeout_ms: 3000, diff --git a/tests/ps-qa/checks/docs-syntax.ron b/tests/ps-qa/checks/docs-syntax.ron index 3ccc7cd..80edfa5 100644 --- a/tests/ps-qa/checks/docs-syntax.ron +++ b/tests/ps-qa/checks/docs-syntax.ron @@ -281,6 +281,7 @@ open: None, hover: None, click: Some("1. At a glance"), + covers: ["@document-toc-link", "@document-content-link"], subject: "heading:1. At a glance", expect: Present, outcome_timeout_ms: 3000, From e17af346e5957cacaacc93ec262c9802ef559572 Mon Sep 17 00:00:00 2001 From: meh Date: Sun, 13 Sep 2026 02:08:10 +0700 Subject: [PATCH 19/22] test(qa): inventory full application surfaces --- src/App.tsx | 14 ++++++++++++-- src/ThemeToggle.tsx | 1 + tests/ps-qa/ps-qa.ron | 6 +++--- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index dfaaa5d..7cb2b30 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -11,7 +11,12 @@ import SyntaxPage from "~/pages/SyntaxPage"; import VignettePage from "~/pages/VignettePage"; const Shell: ParentComponent = (props) => ( -
+
{props.children}