@tamsensedev/runner 0.13.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +5 -5
- package/README.md +61 -57
- package/dist/cli.js +646 -315
- package/dist/cli.js.map +1 -1
- package/dist/recorder.cjs.map +1 -1
- package/library/.claude-plugin/plugin.json +5 -5
- package/library/THIRD_PARTY_NOTICES.md +123 -123
- package/library/agents/code-architect.md +67 -67
- package/library/agents/code-explorer.md +61 -61
- package/library/agents/code-reviewer.md +73 -73
- package/library/agents/code-simplifier.md +62 -62
- package/library/agents/design-critic.md +52 -52
- package/library/agents/second-opinion.md +64 -64
- package/library/agents/security-auditor.md +86 -86
- package/library/agents/silent-failure-hunter.md +70 -70
- package/library/agents/test-coverage-analyzer.md +78 -78
- package/library/agents/test-runner.md +48 -48
- package/library/agents/ui-tester.md +50 -50
- package/library/licenses/Apache-2.0.txt +202 -202
- package/library/skills/accessibility/SKILL.md +144 -144
- package/library/skills/accessibility/references/wcag-checks.md +168 -168
- package/library/skills/addressing-review-feedback/SKILL.md +109 -109
- package/library/skills/app-screens/SKILL.md +96 -96
- package/library/skills/app-screens/references/shell-kpis-charts.md +108 -108
- package/library/skills/app-screens/references/states-density-phone.md +54 -54
- package/library/skills/app-screens/references/tables-forms-settings.md +104 -104
- package/library/skills/avoiding-generic-ai-design/SKILL.md +92 -92
- package/library/skills/avoiding-generic-ai-design/references/tells.md +112 -112
- package/library/skills/clean-commits/SKILL.md +85 -85
- package/library/skills/design-review/SKILL.md +107 -107
- package/library/skills/design-review/references/critique-passes.md +101 -101
- package/library/skills/design-review/references/screenshot-procedure.md +121 -121
- package/library/skills/differential-security-review/LICENSE +427 -427
- package/library/skills/differential-security-review/SKILL.md +105 -105
- package/library/skills/differential-security-review/references/adversarial.md +115 -115
- package/library/skills/differential-security-review/references/methodology.md +145 -145
- package/library/skills/differential-security-review/references/patterns.md +108 -108
- package/library/skills/false-positive-check/LICENSE +427 -427
- package/library/skills/false-positive-check/SKILL.md +95 -95
- package/library/skills/false-positive-check/references/bug-class-verification.md +128 -128
- package/library/skills/false-positive-check/references/deep-verification.md +113 -113
- package/library/skills/false-positive-check/references/evidence-templates.md +93 -93
- package/library/skills/false-positive-check/references/false-positive-patterns.md +122 -122
- package/library/skills/false-positive-check/references/gate-reviews.md +36 -36
- package/library/skills/false-positive-check/references/standard-verification.md +80 -80
- package/library/skills/focused-implementation/SKILL.md +104 -104
- package/library/skills/implementation-plan/SKILL.md +66 -66
- package/library/skills/interface-design/SKILL.md +144 -144
- package/library/skills/interface-design/references/craft-defaults.md +130 -130
- package/library/skills/interface-design/references/new-direction.md +62 -62
- package/library/skills/interface-design/references/writing.md +52 -52
- package/library/skills/interface-polish/SKILL.md +103 -103
- package/library/skills/interface-polish/references/detail-rules.md +154 -154
- package/library/skills/interface-polish/references/worst-case-data.md +158 -158
- package/library/skills/motion-design/SKILL.md +106 -106
- package/library/skills/motion-design/references/recipes.md +243 -243
- package/library/skills/postgres-performance/SKILL.md +97 -97
- package/library/skills/postgres-performance/references/rules.md +265 -265
- package/library/skills/project-orientation/SKILL.md +77 -77
- package/library/skills/reviewing-changes/SKILL.md +183 -183
- package/library/skills/safe-database-changes/SKILL.md +111 -111
- package/library/skills/safe-database-changes/references/backfills.md +75 -75
- package/library/skills/safe-database-changes/references/migration-tools.md +69 -69
- package/library/skills/safe-database-changes/references/postgres-ddl.md +199 -199
- package/library/skills/security-review/SKILL.md +132 -132
- package/library/skills/security-review/references/checks-by-area.md +107 -107
- package/library/skills/security-review/references/do-not-report.md +86 -86
- package/library/skills/spec-writing/SKILL.md +144 -144
- package/library/skills/systematic-debugging/SKILL.md +130 -130
- package/library/skills/systematic-debugging/references/flaky-tests.md +51 -51
- package/library/skills/systematic-debugging/references/root-cause-tracing.md +55 -55
- package/library/skills/task-interview/SKILL.md +84 -84
- package/library/skills/test-driven-development/SKILL.md +116 -116
- package/library/skills/test-driven-development/references/writing-good-tests.md +85 -85
- package/library/skills/ui-testing/SKILL.md +102 -102
- package/library/skills/ui-testing/references/headless-check.md +295 -295
- package/library/skills/ui-testing/references/local-stand.md +51 -51
- package/library/skills/ui-testing/references/playwright-patterns.md +134 -134
- package/library/skills/ui-testing/references/recording.md +61 -61
- package/library/skills/verification-before-completion/SKILL.md +113 -113
- package/library/skills/web-interface-guidelines/SKILL.md +202 -202
- package/package.json +46 -46
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
# Critique passes
|
|
2
|
-
|
|
3
|
-
Read this when judging screenshots. Make each pass on its own; do not blend them. Write the answers down: a critique you only think through drifts toward approving your own work.
|
|
4
|
-
|
|
5
|
-
Judge the pictures. If a problem shows in a screenshot, it is real, whatever the code says. Judge against the product's own design language (step 2 of the main skill), not a generic ideal.
|
|
6
|
-
|
|
7
|
-
## The whole screen first
|
|
8
|
-
|
|
9
|
-
Open the desktop first screen, then the full page, then the phone.
|
|
10
|
-
|
|
11
|
-
1. **One second, then five.** Glance and look away: what did you see? There should be one answer (a word, a number, an object). If the answer is "a screen", there is no focal point. Then give it five seconds as a stranger: can you say what this is, who it is for and what to do next?
|
|
12
|
-
2. **Squint.** Blur your attention until text becomes grey bars. The screen should reduce to two or three masses with clear size differences, in the right order. Many similar masses mean everything is medium and nothing leads.
|
|
13
|
-
3. **Cover the name.** Could this screen belong to a competitor or another industry? If swapping the product name and one noun gives an equally valid screen, the free choices were defaulted.
|
|
14
|
-
4. **Edges.** Follow the left edge of every text block down the screen. Count the distinct x positions: two or three, reused on purpose, is composed; six means things were placed one at a time. Check right edges of rows of cards too.
|
|
15
|
-
5. **Space and frame.** Related things close, unrelated far. Gaps between sections clearly larger than gaps inside them. Any hole (empty by accident, beside a short column or under a removed element) rather than a rest (empty by decision)? Equal outer margins? A section using half the width with the other half empty?
|
|
16
|
-
6. **Type.** Is the jump from body to title decisive? More than five or six sizes? Weights doing hierarchy work, or size alone? A heading with one orphan word on its last line? Paragraphs wider than about 75 characters? Text in a grey too light to read?
|
|
17
|
-
7. **Colour.** Name the proportions: what holds most of the surface, what supports, where the accent is. An accent in ten places means nothing; on the one action and one detail it means "here". Is colour carrying meaning (status, selection, data) or decorating?
|
|
18
|
-
8. **Sameness.** Write one word for each block's layout (split, list, table, grid, statement). The same word three times in a row is the template showing, unless the blocks really are peers.
|
|
19
|
-
9. **Phone.** Is the phone layout a composition of its own (navigation folded, its own line breaks, the first screen still one clear thing), or the desktop squeezed? Anything running off the edge, a row scrolling sideways, a tap target smaller than 44px?
|
|
20
|
-
10. **Collisions.** Anything overlapping a heading, a label or a button at any width? Text clipped by its container? A sticky header covering focused content?
|
|
21
|
-
11. **Substance.** Does every block deliver its information completely and at a readable size? Is the primary action a real button on the first screen? Is any content invented (metrics, customers, quotes) or placeholder text left in?
|
|
22
|
-
|
|
23
|
-
## The lenses
|
|
24
|
-
|
|
25
|
-
Then one lens at a time, asking each time: was this decided, or defaulted?
|
|
26
|
-
|
|
27
|
-
- **Hierarchy.** Name the focal element. Does it win through size, weight, contrast or space? Is everything else demoted (secondary actions quieter, metadata muted)? Can you tell primary, secondary and metadata apart without reading?
|
|
28
|
-
- **Typography and colour.** A real scale or near-equal sizes? A text-colour ramp (primary, secondary, muted) or just "text" and "grey text"? Tabular figures on numbers that update or align? One accent with a job?
|
|
29
|
-
- **Surfaces and depth.** One depth strategy (borders, tone steps or shadows), held everywhere? Borders findable but not loud? Nested radii concentric? Shadows only on floating layers?
|
|
30
|
-
- **Layout and rhythm.** Tight inside groups, generous between them? Shared edges? A grid that fits the item count, no orphan cells, no stretched cards with blank bands?
|
|
31
|
-
- **States and polish.** Hover, focus, active, disabled on every control? Loading, empty, error, long content on every data block? Hit areas? Press feedback? Motion short and purposeful?
|
|
32
|
-
- **Content and honesty.** Every visible string read as a user would: do the title, body and numbers tell one coherent story? Do numbers add up and agree where shown twice? Copy in the product's voice, sentence case unless the product does otherwise?
|
|
33
|
-
- **System fit.** Uses the project's components, tokens and patterns? Looks like it shipped with its sibling screens? No hand-rolled control where the project has one?
|
|
34
|
-
|
|
35
|
-
## Extra questions for app screens
|
|
36
|
-
|
|
37
|
-
From `app-screens`:
|
|
38
|
-
|
|
39
|
-
1. Is the screen's one question answered by the biggest thing on it, and is that read first?
|
|
40
|
-
2. Do all blocks share the screen's edges, with no dead strip, orphan cell or stretched card?
|
|
41
|
-
3. Is colour only on data, status and the one primary action?
|
|
42
|
-
4. Do numbers add up, line up digit for digit, and name their baseline?
|
|
43
|
-
5. Is every zero a zero and every missing value a dash?
|
|
44
|
-
6. Does every legend swatch match its mark, with no colliding labels?
|
|
45
|
-
7. On the phone, is navigation folded and does each block still answer its question?
|
|
46
|
-
8. Is the most frequent job one click from the first screen?
|
|
47
|
-
|
|
48
|
-
## Extra questions for marketing pages
|
|
49
|
-
|
|
50
|
-
- Does the first screen carry a clear title in the page's `h1`, a sentence saying what this is, and one primary action?
|
|
51
|
-
- Does every section have a heading that names it, and a composition different from its neighbours?
|
|
52
|
-
- Is each screen of the desktop page full (one dominant thing and its content), not a narrow column of small text with dead ground either side?
|
|
53
|
-
- Is every image doing a job (showing the product, proving a claim), with consistent crops? Any grey boxes or fake dashboards?
|
|
54
|
-
- Does the idea carry past the first screen into pricing, FAQ and footer, or do they become stock blocks?
|
|
55
|
-
|
|
56
|
-
## Cognitive load
|
|
57
|
-
|
|
58
|
-
Count the failures; two or three mean the screen needs simplifying, four or more is a blocker for a task screen:
|
|
59
|
-
|
|
60
|
-
- **Single focus**: the main task can be done without competing elements pulling attention.
|
|
61
|
-
- **Chunking**: information comes in groups of about four or fewer.
|
|
62
|
-
- **Grouping**: related items are visibly together.
|
|
63
|
-
- **Visible priority**: it is immediately clear what matters most.
|
|
64
|
-
- **One decision at a time**: the person is not asked to read, decide and navigate at once.
|
|
65
|
-
- **Few choices**: about four or fewer options at a decision point (one primary action, one or two secondary, the rest in a menu).
|
|
66
|
-
- **No memory bridge**: nothing from a previous screen has to be remembered to act here.
|
|
67
|
-
- **Progressive disclosure**: rare detail is revealed when needed, not shown upfront.
|
|
68
|
-
|
|
69
|
-
## Writing it down
|
|
70
|
-
|
|
71
|
-
```
|
|
72
|
-
Round n
|
|
73
|
-
Seen in one second: ...
|
|
74
|
-
Focal element: ... (wins / does not win, because ...)
|
|
75
|
-
Layout words by block: header=... / list=... / ...
|
|
76
|
-
Problems (most visible first), each with screenshot and fix:
|
|
77
|
-
1. ...
|
|
78
|
-
2. ...
|
|
79
|
-
3. ...
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
Name problems the way a designer would to a colleague: "the supporting text starts 24px left of the title's edge", "the empty state is the third bordered box in a row", "on the phone the Save button sits under the fold". "Could be more polished" is not a finding.
|
|
83
|
-
|
|
84
|
-
## What to fix first
|
|
85
|
-
|
|
86
|
-
Later items cannot rescue earlier ones:
|
|
87
|
-
|
|
88
|
-
1. The focal point and hierarchy: make the big thing bigger and the small things fewer.
|
|
89
|
-
2. Layout: shared edges, spacing between and within groups, holes, grid fit.
|
|
90
|
-
3. Typography: scale contrast, line breaks, measure.
|
|
91
|
-
4. Colour: proportions and accent discipline.
|
|
92
|
-
5. States and details: focus, hover, empty, error, small alignments, phone refinements.
|
|
93
|
-
6. Motion, last.
|
|
94
|
-
|
|
95
|
-
When removing something leaves a gap, close the gap or enlarge what remains; do not refill it with an ornament.
|
|
96
|
-
|
|
97
|
-
## When to stop
|
|
98
|
-
|
|
99
|
-
At most three rounds of critique, fix the top three, re-render, critique. Stop early when a round finds nothing a stranger would notice. If problems remain after round three, list them plainly in the report; do not round up.
|
|
100
|
-
|
|
101
|
-
Sources: adapted from Leonxlnx/taste-skill references/critique.md and app-screens.md (MIT, changed: scoring and caps tied to its inspector removed, product-screen questions added), Dammyjay93/interface-design design-review lenses (MIT) and the cognitive load checklist in pbakaus/impeccable critique reference (Apache-2.0, changed: rewritten).
|
|
1
|
+
# Critique passes
|
|
2
|
+
|
|
3
|
+
Read this when judging screenshots. Make each pass on its own; do not blend them. Write the answers down: a critique you only think through drifts toward approving your own work.
|
|
4
|
+
|
|
5
|
+
Judge the pictures. If a problem shows in a screenshot, it is real, whatever the code says. Judge against the product's own design language (step 2 of the main skill), not a generic ideal.
|
|
6
|
+
|
|
7
|
+
## The whole screen first
|
|
8
|
+
|
|
9
|
+
Open the desktop first screen, then the full page, then the phone.
|
|
10
|
+
|
|
11
|
+
1. **One second, then five.** Glance and look away: what did you see? There should be one answer (a word, a number, an object). If the answer is "a screen", there is no focal point. Then give it five seconds as a stranger: can you say what this is, who it is for and what to do next?
|
|
12
|
+
2. **Squint.** Blur your attention until text becomes grey bars. The screen should reduce to two or three masses with clear size differences, in the right order. Many similar masses mean everything is medium and nothing leads.
|
|
13
|
+
3. **Cover the name.** Could this screen belong to a competitor or another industry? If swapping the product name and one noun gives an equally valid screen, the free choices were defaulted.
|
|
14
|
+
4. **Edges.** Follow the left edge of every text block down the screen. Count the distinct x positions: two or three, reused on purpose, is composed; six means things were placed one at a time. Check right edges of rows of cards too.
|
|
15
|
+
5. **Space and frame.** Related things close, unrelated far. Gaps between sections clearly larger than gaps inside them. Any hole (empty by accident, beside a short column or under a removed element) rather than a rest (empty by decision)? Equal outer margins? A section using half the width with the other half empty?
|
|
16
|
+
6. **Type.** Is the jump from body to title decisive? More than five or six sizes? Weights doing hierarchy work, or size alone? A heading with one orphan word on its last line? Paragraphs wider than about 75 characters? Text in a grey too light to read?
|
|
17
|
+
7. **Colour.** Name the proportions: what holds most of the surface, what supports, where the accent is. An accent in ten places means nothing; on the one action and one detail it means "here". Is colour carrying meaning (status, selection, data) or decorating?
|
|
18
|
+
8. **Sameness.** Write one word for each block's layout (split, list, table, grid, statement). The same word three times in a row is the template showing, unless the blocks really are peers.
|
|
19
|
+
9. **Phone.** Is the phone layout a composition of its own (navigation folded, its own line breaks, the first screen still one clear thing), or the desktop squeezed? Anything running off the edge, a row scrolling sideways, a tap target smaller than 44px?
|
|
20
|
+
10. **Collisions.** Anything overlapping a heading, a label or a button at any width? Text clipped by its container? A sticky header covering focused content?
|
|
21
|
+
11. **Substance.** Does every block deliver its information completely and at a readable size? Is the primary action a real button on the first screen? Is any content invented (metrics, customers, quotes) or placeholder text left in?
|
|
22
|
+
|
|
23
|
+
## The lenses
|
|
24
|
+
|
|
25
|
+
Then one lens at a time, asking each time: was this decided, or defaulted?
|
|
26
|
+
|
|
27
|
+
- **Hierarchy.** Name the focal element. Does it win through size, weight, contrast or space? Is everything else demoted (secondary actions quieter, metadata muted)? Can you tell primary, secondary and metadata apart without reading?
|
|
28
|
+
- **Typography and colour.** A real scale or near-equal sizes? A text-colour ramp (primary, secondary, muted) or just "text" and "grey text"? Tabular figures on numbers that update or align? One accent with a job?
|
|
29
|
+
- **Surfaces and depth.** One depth strategy (borders, tone steps or shadows), held everywhere? Borders findable but not loud? Nested radii concentric? Shadows only on floating layers?
|
|
30
|
+
- **Layout and rhythm.** Tight inside groups, generous between them? Shared edges? A grid that fits the item count, no orphan cells, no stretched cards with blank bands?
|
|
31
|
+
- **States and polish.** Hover, focus, active, disabled on every control? Loading, empty, error, long content on every data block? Hit areas? Press feedback? Motion short and purposeful?
|
|
32
|
+
- **Content and honesty.** Every visible string read as a user would: do the title, body and numbers tell one coherent story? Do numbers add up and agree where shown twice? Copy in the product's voice, sentence case unless the product does otherwise?
|
|
33
|
+
- **System fit.** Uses the project's components, tokens and patterns? Looks like it shipped with its sibling screens? No hand-rolled control where the project has one?
|
|
34
|
+
|
|
35
|
+
## Extra questions for app screens
|
|
36
|
+
|
|
37
|
+
From `app-screens`:
|
|
38
|
+
|
|
39
|
+
1. Is the screen's one question answered by the biggest thing on it, and is that read first?
|
|
40
|
+
2. Do all blocks share the screen's edges, with no dead strip, orphan cell or stretched card?
|
|
41
|
+
3. Is colour only on data, status and the one primary action?
|
|
42
|
+
4. Do numbers add up, line up digit for digit, and name their baseline?
|
|
43
|
+
5. Is every zero a zero and every missing value a dash?
|
|
44
|
+
6. Does every legend swatch match its mark, with no colliding labels?
|
|
45
|
+
7. On the phone, is navigation folded and does each block still answer its question?
|
|
46
|
+
8. Is the most frequent job one click from the first screen?
|
|
47
|
+
|
|
48
|
+
## Extra questions for marketing pages
|
|
49
|
+
|
|
50
|
+
- Does the first screen carry a clear title in the page's `h1`, a sentence saying what this is, and one primary action?
|
|
51
|
+
- Does every section have a heading that names it, and a composition different from its neighbours?
|
|
52
|
+
- Is each screen of the desktop page full (one dominant thing and its content), not a narrow column of small text with dead ground either side?
|
|
53
|
+
- Is every image doing a job (showing the product, proving a claim), with consistent crops? Any grey boxes or fake dashboards?
|
|
54
|
+
- Does the idea carry past the first screen into pricing, FAQ and footer, or do they become stock blocks?
|
|
55
|
+
|
|
56
|
+
## Cognitive load
|
|
57
|
+
|
|
58
|
+
Count the failures; two or three mean the screen needs simplifying, four or more is a blocker for a task screen:
|
|
59
|
+
|
|
60
|
+
- **Single focus**: the main task can be done without competing elements pulling attention.
|
|
61
|
+
- **Chunking**: information comes in groups of about four or fewer.
|
|
62
|
+
- **Grouping**: related items are visibly together.
|
|
63
|
+
- **Visible priority**: it is immediately clear what matters most.
|
|
64
|
+
- **One decision at a time**: the person is not asked to read, decide and navigate at once.
|
|
65
|
+
- **Few choices**: about four or fewer options at a decision point (one primary action, one or two secondary, the rest in a menu).
|
|
66
|
+
- **No memory bridge**: nothing from a previous screen has to be remembered to act here.
|
|
67
|
+
- **Progressive disclosure**: rare detail is revealed when needed, not shown upfront.
|
|
68
|
+
|
|
69
|
+
## Writing it down
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
Round n
|
|
73
|
+
Seen in one second: ...
|
|
74
|
+
Focal element: ... (wins / does not win, because ...)
|
|
75
|
+
Layout words by block: header=... / list=... / ...
|
|
76
|
+
Problems (most visible first), each with screenshot and fix:
|
|
77
|
+
1. ...
|
|
78
|
+
2. ...
|
|
79
|
+
3. ...
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Name problems the way a designer would to a colleague: "the supporting text starts 24px left of the title's edge", "the empty state is the third bordered box in a row", "on the phone the Save button sits under the fold". "Could be more polished" is not a finding.
|
|
83
|
+
|
|
84
|
+
## What to fix first
|
|
85
|
+
|
|
86
|
+
Later items cannot rescue earlier ones:
|
|
87
|
+
|
|
88
|
+
1. The focal point and hierarchy: make the big thing bigger and the small things fewer.
|
|
89
|
+
2. Layout: shared edges, spacing between and within groups, holes, grid fit.
|
|
90
|
+
3. Typography: scale contrast, line breaks, measure.
|
|
91
|
+
4. Colour: proportions and accent discipline.
|
|
92
|
+
5. States and details: focus, hover, empty, error, small alignments, phone refinements.
|
|
93
|
+
6. Motion, last.
|
|
94
|
+
|
|
95
|
+
When removing something leaves a gap, close the gap or enlarge what remains; do not refill it with an ornament.
|
|
96
|
+
|
|
97
|
+
## When to stop
|
|
98
|
+
|
|
99
|
+
At most three rounds of critique, fix the top three, re-render, critique. Stop early when a round finds nothing a stranger would notice. If problems remain after round three, list them plainly in the report; do not round up.
|
|
100
|
+
|
|
101
|
+
Sources: adapted from Leonxlnx/taste-skill references/critique.md and app-screens.md (MIT, changed: scoring and caps tied to its inspector removed, product-screen questions added), Dammyjay93/interface-design design-review lenses (MIT) and the cognitive load checklist in pbakaus/impeccable critique reference (Apache-2.0, changed: rewritten).
|
|
@@ -1,121 +1,121 @@
|
|
|
1
|
-
# Rendering screens for a design check
|
|
2
|
-
|
|
3
|
-
Read this when you need screenshots of changed screens at desktop, tablet and phone widths, and their key states. The output is pictures you open with the Read tool and judge.
|
|
4
|
-
|
|
5
|
-
## Ground rules
|
|
6
|
-
|
|
7
|
-
Everything about running the app comes from the `ui-testing` skill and holds here too: headless only, the project's own start command on a free port, no new dependencies or browser downloads (if the project has no Playwright but `TAMSENSE_PLAYWRIGHT` is set, the headless check uses the `playwright-core` and browser the TAMsense runner installed outside the project), outputs only in a new folder under the OS temp directory, nothing written to shared systems, the server stopped at the end by its process id (never kill processes by name: other programs on the computer may be using the same runtime), `git status` clean. In a review step, also change nothing in the repository (no fixtures, seed edits or config): states come from intercepting responses in the browser.
|
|
8
|
-
|
|
9
|
-
If the project uses Storybook for the changed components, story URLs (`/iframe.html?id=<story-id>`) are often the quickest way to see each state; render them the same way.
|
|
10
|
-
|
|
11
|
-
In a TAMsense run the browser is recorded for the task too: open contexts through the recorder with a title and a purpose, as [the ui-testing recording reference](../../ui-testing/references/recording.md) shows. For a design check the title names the variant and the purpose names the question, for example "Design option 2" and "Denser table for the invoices list, compared with option 1". Mark each state as you reach it (`mark('Empty state')`, `mark('Error state')`), and add `video: true` when the screen draws on a canvas, shows a map or a video, or embeds another site.
|
|
12
|
-
|
|
13
|
-
## What to capture
|
|
14
|
-
|
|
15
|
-
For each changed screen:
|
|
16
|
-
|
|
17
|
-
| Width | Name |
|
|
18
|
-
|---|---|
|
|
19
|
-
| 1440 | desktop |
|
|
20
|
-
| 768 | tablet |
|
|
21
|
-
| 390 | phone |
|
|
22
|
-
|
|
23
|
-
At each width: the first screen (what is visible without scrolling) and the full page. For pages taller than about four screens, also capture screen-height slices, because one very tall image is hard to judge.
|
|
24
|
-
|
|
25
|
-
Then the states the change affects, at desktop and phone at least:
|
|
26
|
-
|
|
27
|
-
- **Empty**: the endpoint returns no items.
|
|
28
|
-
- **Loading**: the endpoint does not answer while the screenshot is taken.
|
|
29
|
-
- **Error**: the endpoint returns a 500 (and a 403 if permissions matter).
|
|
30
|
-
- **Long content**: the real response with worst-case values swapped in (long names, unbreakable emails, big numbers, missing optional fields; see `interface-polish`).
|
|
31
|
-
- **Interaction**: hover on the primary action, keyboard focus on the first controls (press Tab), an open menu or dialog if the change adds one.
|
|
32
|
-
- **Theme**: dark mode if the product supports it; reduced motion if the change adds motion.
|
|
33
|
-
|
|
34
|
-
## Using the ui-testing headless check
|
|
35
|
-
|
|
36
|
-
Use the script in the `ui-testing` skill's `references/headless-check.md`, written to your temp folder, with these settings:
|
|
37
|
-
|
|
38
|
-
- `CONFIG.widths`: `[1440, 768, 390]`.
|
|
39
|
-
- `CONFIG.paths`: the routes of the changed screens.
|
|
40
|
-
- `CONFIG.title` and `CONFIG.purpose`: the variant and the question this render answers ("Design option 1", "Checking the billing page after the redesign").
|
|
41
|
-
- If the screens need a signed-in user, follow the auth section of `ui-testing` (a storage state saved in the temp folder, passed to `browser.newContext`).
|
|
42
|
-
- If `CHROME_PATH` is set, add `executablePath: process.env.CHROME_PATH` to the launch options.
|
|
43
|
-
- For dark mode, add `colorScheme: 'dark'` to `browser.newContext`; for reduced motion, `reducedMotion: 'reduce'`.
|
|
44
|
-
|
|
45
|
-
Its own screenshot is the full page in the final state of `steps`. Capture the first screen and the states inside `steps`, and leave the page in its normal state at the end:
|
|
46
|
-
|
|
47
|
-
```js
|
|
48
|
-
async function steps(page, { path, width, mark }) {
|
|
49
|
-
const slug = path.replace(/[^a-z0-9]+/gi, '-').replace(/^-+|-+$/g, '') || 'home'
|
|
50
|
-
const shot = async (state) => {
|
|
51
|
-
await mark(`${state} state`)
|
|
52
|
-
await page.screenshot({
|
|
53
|
-
path: join(CONFIG.outDir, `${slug}-${width}-${state}.png`),
|
|
54
|
-
animations: 'disabled',
|
|
55
|
-
})
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
await page.evaluate(async () => { await document.fonts.ready })
|
|
59
|
-
await shot('fold')
|
|
60
|
-
if (path !== '/billing') return
|
|
61
|
-
|
|
62
|
-
await page.getByRole('button', { name: 'Create invoice' }).hover()
|
|
63
|
-
await shot('hover')
|
|
64
|
-
await page.keyboard.press('Tab')
|
|
65
|
-
await page.keyboard.press('Tab')
|
|
66
|
-
await shot('focus')
|
|
67
|
-
|
|
68
|
-
const api = '**/api/invoices**'
|
|
69
|
-
|
|
70
|
-
await page.route(api, (route) => route.fulfill({ json: { items: [], total: 0 } }))
|
|
71
|
-
await page.reload()
|
|
72
|
-
await page.getByText('No invoices').waitFor()
|
|
73
|
-
await shot('empty')
|
|
74
|
-
await page.unroute(api)
|
|
75
|
-
|
|
76
|
-
await page.route(api, (route) => route.fulfill({
|
|
77
|
-
status: 500, contentType: 'application/json', body: '{"error":"Internal error"}',
|
|
78
|
-
}))
|
|
79
|
-
await page.reload()
|
|
80
|
-
await page.getByRole('button', { name: 'Try again' }).waitFor()
|
|
81
|
-
await shot('error')
|
|
82
|
-
await page.unroute(api)
|
|
83
|
-
|
|
84
|
-
await page.route(api, () => {})
|
|
85
|
-
await page.reload({ waitUntil: 'domcontentloaded' })
|
|
86
|
-
await page.locator('[aria-busy="true"]').first().waitFor()
|
|
87
|
-
await shot('loading')
|
|
88
|
-
await page.unroute(api)
|
|
89
|
-
|
|
90
|
-
await page.route(api, async (route) => {
|
|
91
|
-
const response = await route.fetch()
|
|
92
|
-
const json = await response.json()
|
|
93
|
-
json.items[0].customer = 'Aleksandra Wiśniewska-Kowalczyk Consulting GmbH'
|
|
94
|
-
json.items[1].email = 'bartholomew.fitzgerald@northwind-industries-holdings.example.com'
|
|
95
|
-
json.items[2].amount = 12345678.9
|
|
96
|
-
await route.fulfill({ response, json })
|
|
97
|
-
})
|
|
98
|
-
await page.reload()
|
|
99
|
-
await page.getByText('Aleksandra').waitFor()
|
|
100
|
-
await shot('long')
|
|
101
|
-
await page.unroute(api)
|
|
102
|
-
|
|
103
|
-
await page.reload()
|
|
104
|
-
}
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
Adapt the endpoint pattern, the response shape and the readiness checks (`waitFor` on the element that proves each state) to the real screen; find the endpoint in the code or the failed-request list of a first run. The loading route never answers on purpose, so the following `reload` discards it.
|
|
108
|
-
|
|
109
|
-
If the data is rendered on the server and cannot be intercepted in the browser, use the states the project's stories, fixtures or seed data already provide. In a code step you may add a fixture where the project keeps fixtures; in a review step, list the states you could not render.
|
|
110
|
-
|
|
111
|
-
## Naming and reporting
|
|
112
|
-
|
|
113
|
-
Files are named `<screen>-<width>-<state>.png` (for example `billing-390-error.png`) so findings can cite them. Put the temp folder path in the report, describe what each cited screenshot shows, and delete the folder when the step ends unless the task asks to keep artifacts.
|
|
114
|
-
|
|
115
|
-
When you attach screenshots to the task with `attach_screenshot`, give each a title and a purpose that say what it shows and why: "Design option 1" with "Billing page at 1440, the denser table", not "billing-1440-fold". The replays of the render are attached by themselves.
|
|
116
|
-
|
|
117
|
-
## When rendering is impossible
|
|
118
|
-
|
|
119
|
-
If the app needs services that are not available, the build fails, Playwright is not installed (neither in the project nor through `TAMSENSE_PLAYWRIGHT`), or no browser can run: say exactly that in the report, review from the code, and mark every visual finding as inferred rather than seen.
|
|
120
|
-
|
|
121
|
-
Sources: written for this library on top of the `ui-testing` headless check; the three widths and the screenshot-first critique follow Leonxlnx/taste-skill (MIT) inspect and critique references, described in words instead of shipping its inspector.
|
|
1
|
+
# Rendering screens for a design check
|
|
2
|
+
|
|
3
|
+
Read this when you need screenshots of changed screens at desktop, tablet and phone widths, and their key states. The output is pictures you open with the Read tool and judge.
|
|
4
|
+
|
|
5
|
+
## Ground rules
|
|
6
|
+
|
|
7
|
+
Everything about running the app comes from the `ui-testing` skill and holds here too: headless only, the project's own start command on a free port, no new dependencies or browser downloads (if the project has no Playwright but `TAMSENSE_PLAYWRIGHT` is set, the headless check uses the `playwright-core` and browser the TAMsense runner installed outside the project), outputs only in a new folder under the OS temp directory, nothing written to shared systems, the server stopped at the end by its process id (never kill processes by name: other programs on the computer may be using the same runtime), `git status` clean. In a review step, also change nothing in the repository (no fixtures, seed edits or config): states come from intercepting responses in the browser.
|
|
8
|
+
|
|
9
|
+
If the project uses Storybook for the changed components, story URLs (`/iframe.html?id=<story-id>`) are often the quickest way to see each state; render them the same way.
|
|
10
|
+
|
|
11
|
+
In a TAMsense run the browser is recorded for the task too: open contexts through the recorder with a title and a purpose, as [the ui-testing recording reference](../../ui-testing/references/recording.md) shows. For a design check the title names the variant and the purpose names the question, for example "Design option 2" and "Denser table for the invoices list, compared with option 1". Mark each state as you reach it (`mark('Empty state')`, `mark('Error state')`), and add `video: true` when the screen draws on a canvas, shows a map or a video, or embeds another site.
|
|
12
|
+
|
|
13
|
+
## What to capture
|
|
14
|
+
|
|
15
|
+
For each changed screen:
|
|
16
|
+
|
|
17
|
+
| Width | Name |
|
|
18
|
+
|---|---|
|
|
19
|
+
| 1440 | desktop |
|
|
20
|
+
| 768 | tablet |
|
|
21
|
+
| 390 | phone |
|
|
22
|
+
|
|
23
|
+
At each width: the first screen (what is visible without scrolling) and the full page. For pages taller than about four screens, also capture screen-height slices, because one very tall image is hard to judge.
|
|
24
|
+
|
|
25
|
+
Then the states the change affects, at desktop and phone at least:
|
|
26
|
+
|
|
27
|
+
- **Empty**: the endpoint returns no items.
|
|
28
|
+
- **Loading**: the endpoint does not answer while the screenshot is taken.
|
|
29
|
+
- **Error**: the endpoint returns a 500 (and a 403 if permissions matter).
|
|
30
|
+
- **Long content**: the real response with worst-case values swapped in (long names, unbreakable emails, big numbers, missing optional fields; see `interface-polish`).
|
|
31
|
+
- **Interaction**: hover on the primary action, keyboard focus on the first controls (press Tab), an open menu or dialog if the change adds one.
|
|
32
|
+
- **Theme**: dark mode if the product supports it; reduced motion if the change adds motion.
|
|
33
|
+
|
|
34
|
+
## Using the ui-testing headless check
|
|
35
|
+
|
|
36
|
+
Use the script in the `ui-testing` skill's `references/headless-check.md`, written to your temp folder, with these settings:
|
|
37
|
+
|
|
38
|
+
- `CONFIG.widths`: `[1440, 768, 390]`.
|
|
39
|
+
- `CONFIG.paths`: the routes of the changed screens.
|
|
40
|
+
- `CONFIG.title` and `CONFIG.purpose`: the variant and the question this render answers ("Design option 1", "Checking the billing page after the redesign").
|
|
41
|
+
- If the screens need a signed-in user, follow the auth section of `ui-testing` (a storage state saved in the temp folder, passed to `browser.newContext`).
|
|
42
|
+
- If `CHROME_PATH` is set, add `executablePath: process.env.CHROME_PATH` to the launch options.
|
|
43
|
+
- For dark mode, add `colorScheme: 'dark'` to `browser.newContext`; for reduced motion, `reducedMotion: 'reduce'`.
|
|
44
|
+
|
|
45
|
+
Its own screenshot is the full page in the final state of `steps`. Capture the first screen and the states inside `steps`, and leave the page in its normal state at the end:
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
async function steps(page, { path, width, mark }) {
|
|
49
|
+
const slug = path.replace(/[^a-z0-9]+/gi, '-').replace(/^-+|-+$/g, '') || 'home'
|
|
50
|
+
const shot = async (state) => {
|
|
51
|
+
await mark(`${state} state`)
|
|
52
|
+
await page.screenshot({
|
|
53
|
+
path: join(CONFIG.outDir, `${slug}-${width}-${state}.png`),
|
|
54
|
+
animations: 'disabled',
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
await page.evaluate(async () => { await document.fonts.ready })
|
|
59
|
+
await shot('fold')
|
|
60
|
+
if (path !== '/billing') return
|
|
61
|
+
|
|
62
|
+
await page.getByRole('button', { name: 'Create invoice' }).hover()
|
|
63
|
+
await shot('hover')
|
|
64
|
+
await page.keyboard.press('Tab')
|
|
65
|
+
await page.keyboard.press('Tab')
|
|
66
|
+
await shot('focus')
|
|
67
|
+
|
|
68
|
+
const api = '**/api/invoices**'
|
|
69
|
+
|
|
70
|
+
await page.route(api, (route) => route.fulfill({ json: { items: [], total: 0 } }))
|
|
71
|
+
await page.reload()
|
|
72
|
+
await page.getByText('No invoices').waitFor()
|
|
73
|
+
await shot('empty')
|
|
74
|
+
await page.unroute(api)
|
|
75
|
+
|
|
76
|
+
await page.route(api, (route) => route.fulfill({
|
|
77
|
+
status: 500, contentType: 'application/json', body: '{"error":"Internal error"}',
|
|
78
|
+
}))
|
|
79
|
+
await page.reload()
|
|
80
|
+
await page.getByRole('button', { name: 'Try again' }).waitFor()
|
|
81
|
+
await shot('error')
|
|
82
|
+
await page.unroute(api)
|
|
83
|
+
|
|
84
|
+
await page.route(api, () => {})
|
|
85
|
+
await page.reload({ waitUntil: 'domcontentloaded' })
|
|
86
|
+
await page.locator('[aria-busy="true"]').first().waitFor()
|
|
87
|
+
await shot('loading')
|
|
88
|
+
await page.unroute(api)
|
|
89
|
+
|
|
90
|
+
await page.route(api, async (route) => {
|
|
91
|
+
const response = await route.fetch()
|
|
92
|
+
const json = await response.json()
|
|
93
|
+
json.items[0].customer = 'Aleksandra Wiśniewska-Kowalczyk Consulting GmbH'
|
|
94
|
+
json.items[1].email = 'bartholomew.fitzgerald@northwind-industries-holdings.example.com'
|
|
95
|
+
json.items[2].amount = 12345678.9
|
|
96
|
+
await route.fulfill({ response, json })
|
|
97
|
+
})
|
|
98
|
+
await page.reload()
|
|
99
|
+
await page.getByText('Aleksandra').waitFor()
|
|
100
|
+
await shot('long')
|
|
101
|
+
await page.unroute(api)
|
|
102
|
+
|
|
103
|
+
await page.reload()
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Adapt the endpoint pattern, the response shape and the readiness checks (`waitFor` on the element that proves each state) to the real screen; find the endpoint in the code or the failed-request list of a first run. The loading route never answers on purpose, so the following `reload` discards it.
|
|
108
|
+
|
|
109
|
+
If the data is rendered on the server and cannot be intercepted in the browser, use the states the project's stories, fixtures or seed data already provide. In a code step you may add a fixture where the project keeps fixtures; in a review step, list the states you could not render.
|
|
110
|
+
|
|
111
|
+
## Naming and reporting
|
|
112
|
+
|
|
113
|
+
Files are named `<screen>-<width>-<state>.png` (for example `billing-390-error.png`) so findings can cite them. Put the temp folder path in the report, describe what each cited screenshot shows, and delete the folder when the step ends unless the task asks to keep artifacts.
|
|
114
|
+
|
|
115
|
+
When you attach screenshots to the task with `attach_screenshot`, give each a title and a purpose that say what it shows and why: "Design option 1" with "Billing page at 1440, the denser table", not "billing-1440-fold". The replays of the render are attached by themselves.
|
|
116
|
+
|
|
117
|
+
## When rendering is impossible
|
|
118
|
+
|
|
119
|
+
If the app needs services that are not available, the build fails, Playwright is not installed (neither in the project nor through `TAMSENSE_PLAYWRIGHT`), or no browser can run: say exactly that in the report, review from the code, and mark every visual finding as inferred rather than seen.
|
|
120
|
+
|
|
121
|
+
Sources: written for this library on top of the `ui-testing` headless check; the three widths and the screenshot-first critique follow Leonxlnx/taste-skill (MIT) inspect and critique references, described in words instead of shipping its inspector.
|