@clipboard-health/ai-rules 2.24.4 → 2.25.1
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/package.json +1 -1
- package/skills/babysit-pr/SKILL.md +4 -4
- package/skills/babysit-pr/scripts/_sentinel.sh +1 -1
- package/skills/clipboard-design-engineering/SKILL.md +113 -0
- package/skills/commit-push-pr/SKILL.md +2 -2
- package/skills/frontend-ui-verification/SKILL.md +121 -0
- package/skills/frontend-ui-verification/references/admin-app.md +119 -0
- package/skills/frontend-ui-verification/references/mobile-app.md +129 -0
- package/skills/frontend-ui-verification/references/tooling.md +128 -0
- package/skills/frontend-ui-verification/scripts/inspect-ui-verification-surface.sh +274 -0
package/package.json
CHANGED
|
@@ -27,9 +27,9 @@ This skill always runs exactly one pass. It never waits or repeats internally. F
|
|
|
27
27
|
|
|
28
28
|
The skill uses two sentinels. Each is a visible footer line wrapped in `<sub>` (a 🤖 mark plus the token in `<code>`).
|
|
29
29
|
|
|
30
|
-
**Addressed sentinel**: `<sub>🤖 <code>babysit-pr:addressed v1 core@3.
|
|
30
|
+
**Addressed sentinel**: `<sub>🤖 <code>babysit-pr:addressed v1 core@3.8.0</code></sub>`. Appended on its own line at the end of every reply the skill posts (both thread replies and the review-body summary); this is how re-runs know which threads and review-body comments are already handled. Dedupe matches the version-agnostic substring `babysit-pr:addressed v1` followed by a space (also matches legacy `<!-- babysit-pr:addressed v1 ... -->` sentinels). Grep `babysit-pr:addressed v1` for any version; add `core@3.8.0` for a specific one.
|
|
31
31
|
|
|
32
|
-
**Follow-up sentinel**: `<sub>🤖 <code>babysit-pr:followup v1 core@3.
|
|
32
|
+
**Follow-up sentinel**: `<sub>🤖 <code>babysit-pr:followup v1 core@3.8.0</code></sub>`. Attached to replies that defer an out-of-scope comment as a tracked follow-up (see the Scope subsection and the Defer verdict in step 6). Grep `babysit-pr:followup` across PR conversation JSON to enumerate deferred items. This sentinel is additive — the post-reply scripts still append the `addressed` sentinel at the end, so a deferred thread is correctly machine-classified as addressed (the skill _has_ handled it — by deferring). Human reviewers and future sweeps distinguish deferred from resolved by looking for the follow-up sentinel.
|
|
33
33
|
|
|
34
34
|
**Sentinel recency rules.** The script emits a per-thread `activityState` with three values:
|
|
35
35
|
|
|
@@ -280,7 +280,7 @@ Body templates (the script appends the `addressed` sentinel if missing):
|
|
|
280
280
|
- **Agree**: `Addressed in <commit-url>. <one-line what-changed>.`
|
|
281
281
|
- **Disagree**: `Leaving current behavior. <reasoning>.`
|
|
282
282
|
- **Already fixed**: `Already handled by <commit-url-or-file:line>. <brief pointer>.`
|
|
283
|
-
- **Defer**: `Out of scope for this PR; this looks like follow-up work rather than something introduced or required by this change. <one-line rationale or pointer if useful>.\n\n<sub>🤖 <code>babysit-pr:followup v1 core@3.
|
|
283
|
+
- **Defer**: `Out of scope for this PR; this looks like follow-up work rather than something introduced or required by this change. <one-line rationale or pointer if useful>.\n\n<sub>🤖 <code>babysit-pr:followup v1 core@3.8.0</code></sub>`
|
|
284
284
|
|
|
285
285
|
For Defer replies, include the follow-up sentinel on its own line as shown. The script will append the `addressed` sentinel after it on its own line, so the final body ends with the follow-up sentinel followed by a blank line followed by the `addressed` sentinel — `grep babysit-pr:followup` finds the deferral and `grep babysit-pr:addressed` still marks the thread handled for dedupe.
|
|
286
286
|
|
|
@@ -296,7 +296,7 @@ The PR-level summary should:
|
|
|
296
296
|
|
|
297
297
|
- Group by source. Use `## Review-body findings` for step-7 work and `## Conversation-tab comments` for step-6b work. Omit a section if its list is empty.
|
|
298
298
|
- Inside each section, group verdicts under **Agree / Disagree / Already fixed / Deferred (out of scope)** subheadings. Omit a subheading if its list is empty.
|
|
299
|
-
- Under **Deferred (out of scope)**, list each deferred item as a bullet, followed on its own line by `<sub>🤖 <code>babysit-pr:followup v1 core@3.
|
|
299
|
+
- Under **Deferred (out of scope)**, list each deferred item as a bullet, followed on its own line by `<sub>🤖 <code>babysit-pr:followup v1 core@3.8.0</code></sub>` so grep catches them individually.
|
|
300
300
|
- Include the commit URL for fixes.
|
|
301
301
|
- End with a fenced fingerprint block listing every current fingerprint — addressed and deferred — one per line. Include both `reviewBodyComments[].fingerprint` (whole-body, one per automated review) and `activeIssueComments[].fingerprint` (per Conversation-tab comment). Future runs dedupe by matching these against `priorBabysitSentinels`.
|
|
302
302
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
# substituted at build time by embedPluginVersion.mts.
|
|
10
10
|
|
|
11
11
|
SENTINEL_PREFIX='babysit-pr:addressed v1 '
|
|
12
|
-
SENTINEL='<sub>🤖 <code>babysit-pr:addressed v1 core@3.
|
|
12
|
+
SENTINEL='<sub>🤖 <code>babysit-pr:addressed v1 core@3.8.0</code></sub>'
|
|
13
13
|
|
|
14
14
|
# Bot author allowlist (JSON array literal). Used by unresolvedPrComments.sh
|
|
15
15
|
# as a fallback when GraphQL's `author.__typename == "Bot"` misses a GitHub
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: clipboard-design-engineering
|
|
3
|
+
description: Use when a Clipboard frontend task involves UI polish, motion or animation decisions, interaction feel, small interaction details, visual hierarchy, component craft, or reviewing whether admin/mobile UI feels consistent with Clipboard's product and design-system standards.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Clipboard Design Engineering
|
|
7
|
+
|
|
8
|
+
Use this skill when the UI already works functionally but still needs taste: spacing that holds up under dense data, motion that feels intentional, interaction states that respond immediately, and components that belong inside Clipboard's admin and mobile products.
|
|
9
|
+
|
|
10
|
+
Clipboard UI is operational software. People use it to scan, compare, decide, and repeat. The best visual work here is quiet. It makes state obvious, removes doubt, and keeps the user moving. Decoration that does not improve comprehension is noise.
|
|
11
|
+
|
|
12
|
+
## Core Philosophy
|
|
13
|
+
|
|
14
|
+
- **System first**: existing Clipboard components, stories, and theme tokens are the starting point. New visual patterns need a reason.
|
|
15
|
+
- **Evidence over vibes**: Figma and screenshots define intent. Storybook screenshots prove the implementation.
|
|
16
|
+
- **Density is a design constraint**: admin tables, cards, drawers, shift details, and mobile sheets must survive long names, translated copy, dense rows, empty states, and loading states.
|
|
17
|
+
- **Motion must earn its cost**: motion should explain state, preserve spatial continuity, show progress, or confirm input.
|
|
18
|
+
- **Frequent actions should feel instant**: if the user hits it all day, keep it crisp and almost invisible.
|
|
19
|
+
- **Rare moments can carry more feeling**: completion, education, and onboarding can be warmer, but never sloppy.
|
|
20
|
+
|
|
21
|
+
## Before Changing UI
|
|
22
|
+
|
|
23
|
+
1. Search existing components, stories, and theme tokens before creating a new visual pattern.
|
|
24
|
+
2. Prefer repo-owned design-system components over bespoke markup.
|
|
25
|
+
3. In admin redesign work, use Berlin/MUI `sx` with theme tokens.
|
|
26
|
+
4. In mobile redesign work, use the existing app V2 redesign components, Storybook decorators, and mobile viewport presets.
|
|
27
|
+
5. Add or update a Storybook story for any non-trivial visual, interaction, or animation change.
|
|
28
|
+
|
|
29
|
+
## Motion Decision Framework
|
|
30
|
+
|
|
31
|
+
Before adding animation, answer these in order:
|
|
32
|
+
|
|
33
|
+
1. **How often will this run?**
|
|
34
|
+
- Keyboard-heavy or repeated actions: no motion, or near-instant feedback only.
|
|
35
|
+
- Occasional actions such as drawers, dialogs, filters, and toasts: restrained motion.
|
|
36
|
+
- Rare education or completion moments: more expressive motion is allowed.
|
|
37
|
+
2. **What does it explain?**
|
|
38
|
+
- Good reasons: state change, spatial relationship, input feedback, progress, continuity.
|
|
39
|
+
- Bad reason: it makes the mock feel more alive.
|
|
40
|
+
3. **What should the user feel?**
|
|
41
|
+
- Admin surfaces should feel fast, stable, and trustworthy.
|
|
42
|
+
- Mobile surfaces should feel responsive, thumb-friendly, and native enough.
|
|
43
|
+
- Anything that delays decision-making is a regression.
|
|
44
|
+
|
|
45
|
+
## Motion Rules That Matter
|
|
46
|
+
|
|
47
|
+
- Do not animate keyboard-heavy or very frequent actions unless the motion is nearly instant and clearly improves feedback.
|
|
48
|
+
- Prefer no animation over slow animation.
|
|
49
|
+
- Keep most UI motion under 300ms. Longer motion needs a reason such as education, progress, or a rare completion moment.
|
|
50
|
+
- Use explicit transition properties. Do not use `transition: all`.
|
|
51
|
+
- Prefer `transform` and `opacity` for movement. Avoid animating layout properties such as width, height, top, and left unless the component has a measured reason.
|
|
52
|
+
- Entering UI should respond immediately. Slow starts make the product feel delayed.
|
|
53
|
+
- Moving UI should handle rapid user input. Prefer CSS transitions for state changes that can be redirected and reserve keyframes for predetermined loops or decorative sequences.
|
|
54
|
+
- Respect `prefers-reduced-motion`. Reduced motion can keep opacity/color transitions, but should remove or reduce position and transform movement.
|
|
55
|
+
- Gate hover-only motion behind real hover capability on touch-sensitive UI.
|
|
56
|
+
- Loading skeletons should match the final content shape and not resize the layout.
|
|
57
|
+
- Pressed states should acknowledge input immediately with a subtle visual response when the component style supports it.
|
|
58
|
+
- Popovers, menus, and anchored overlays should visually originate from the trigger. Dialogs and centered modals should stay centered.
|
|
59
|
+
- For stacked overlays such as drawers, side panels, dialogs, or bottom sheets over an existing surface, preserve spatial continuity: the parent layer should remain stable, the child layer should have a clear origin, and backdrop, focus, dismiss, and rapid re-open behavior should be inspectable.
|
|
60
|
+
- Loops and pulses need a stop condition or a strong reason. Persistent pulsing is usually visual debt.
|
|
61
|
+
|
|
62
|
+
## Component Feel Checklist
|
|
63
|
+
|
|
64
|
+
Check these before calling a UI polished:
|
|
65
|
+
|
|
66
|
+
- Text hierarchy scans correctly in the target viewport.
|
|
67
|
+
- Spacing uses theme tokens and matches nearby local patterns.
|
|
68
|
+
- Interactive elements have hover, active/pressed, focus-visible, disabled, and loading states where applicable.
|
|
69
|
+
- Touch targets are at least 44px on mobile.
|
|
70
|
+
- Long names, translated copy, dense data, and empty/error states do not break layout.
|
|
71
|
+
- Iconography, radius, borders, shadows, and colors match the local design-system usage.
|
|
72
|
+
- Loading, success, and error states are specific enough that the user knows what happened and what to do next.
|
|
73
|
+
- Motion communicates a state change, not just style.
|
|
74
|
+
|
|
75
|
+
## Anti-Slop Checks
|
|
76
|
+
|
|
77
|
+
Reject these patterns unless there is a very specific local reason:
|
|
78
|
+
|
|
79
|
+
- A new wrapper `Box` layer that only exists to make spacing guesses easier.
|
|
80
|
+
- A color copied from Figma instead of mapped to a theme token or named as a design-system gap.
|
|
81
|
+
- A story that only renders the happy path.
|
|
82
|
+
- A loading state whose skeleton does not match the final content footprint.
|
|
83
|
+
- A mobile sheet that looks fine at `390x844` but clips at `375x667`.
|
|
84
|
+
- A hover effect that fires on touch devices.
|
|
85
|
+
- An animation that cannot be replayed or inspected in Storybook.
|
|
86
|
+
- A "polished" component with no focus-visible state.
|
|
87
|
+
- Text that only works for the sample name or English copy.
|
|
88
|
+
|
|
89
|
+
## Storybook Evidence
|
|
90
|
+
|
|
91
|
+
For visual or motion claims, the Storybook story should make the claim inspectable:
|
|
92
|
+
|
|
93
|
+
- Include default, loading, empty, error, disabled, long-text, and dense-data states when relevant.
|
|
94
|
+
- Include mobile and desktop stories when the layout differs.
|
|
95
|
+
- For animation, include a replay control, deterministic key, or explicit in-flight state.
|
|
96
|
+
- For stacked overlay motion, include opened, child-opened, dismissed, and rapid re-open states so layering and focus handoff are visible before product integration.
|
|
97
|
+
- For Figma work, attach the Figma URL with `parameters.design` when the repo supports `@storybook/addon-designs`.
|
|
98
|
+
- Verify the story in a browser-controlled surface and report the story URL, viewport, state, and any console errors.
|
|
99
|
+
|
|
100
|
+
## Review Output
|
|
101
|
+
|
|
102
|
+
When reviewing UI polish, use this table format. Keep the rows concrete enough that another agent can patch the code without guessing.
|
|
103
|
+
|
|
104
|
+
| Before | After | Why |
|
|
105
|
+
| ------------------------------------------------ | -------------------------------------------------------------------------------- | --------------------------------------------------------------- |
|
|
106
|
+
| `transition: all 300ms` | `transition: transform 180ms ease-out, opacity 180ms ease-out` | The moving properties are explicit and easier to verify. |
|
|
107
|
+
| A bottom sheet that only exists in the app route | A Storybook story with default, loading, long-copy, and repeatable motion states | Visual feedback stays cheap before integration work. |
|
|
108
|
+
| A custom color copied from Figma | The closest repo theme token or a named design-system gap | Clipboard UI should stay tied to the shared system. |
|
|
109
|
+
| One beautiful happy-path card | Stories for default, dense data, long text, empty, error, and loading | Product UI breaks first at the edges. |
|
|
110
|
+
| Hover-only affordance on mobile | Press/focus/tap states that work without hover | Most mobile users never get a real hover state. |
|
|
111
|
+
| Animation judged from code | Storybook replay plus screenshot or short video evidence | Motion quality is a rendered behavior, not a code-style belief. |
|
|
112
|
+
|
|
113
|
+
If the right answer depends on taste or a missing design-system token, stop and ask for human confirmation with the Storybook URL and the exact ambiguity.
|
|
@@ -47,7 +47,7 @@ Script paths in this procedure are written as `scripts/...`, relative to this SK
|
|
|
47
47
|
6. Check for an existing PR with `gh pr view`.
|
|
48
48
|
|
|
49
49
|
PR title format: conventional-commit type + description, with no scope, plus the Linear ticket in parentheses at the end when one applies (e.g., `feat: add resume command (STAFF-123)`). This differs from the commit subject, which keeps its scope. Derive the ticket from the branch name, commit body, or session context; omit the parenthetical when no ticket applies.
|
|
50
|
-
- No PR: create with `gh pr create` using the PR title format above. Description = the PR body shape above, followed by the session footer line if known and the agent footer `<sub>🤖 <code>commit-push-pr:created v1 core@3.
|
|
51
|
-
- PR exists: if the title doesn't match the format above, correct it with `gh pr edit --title`. Refresh the body via `gh pr edit --body` so (a) the new commit's changes are reflected in the prose while existing `## Summary`, `## Validation`, and `## Notes` sections are preserved unless clearly stale, (b) any known session footer line is appended if missing, never removing or rewriting existing `Agent session: ...` or `Agent session ID: ...` lines, and (c) any existing footer carrying the substring `commit-push-pr:created v1` is preserved verbatim, appending `<sub>🤖 <code>commit-push-pr:created v1 core@3.
|
|
50
|
+
- No PR: create with `gh pr create` using the PR title format above. Description = the PR body shape above, followed by the session footer line if known and the agent footer `<sub>🤖 <code>commit-push-pr:created v1 core@3.8.0</code></sub>` on its own line.
|
|
51
|
+
- PR exists: if the title doesn't match the format above, correct it with `gh pr edit --title`. Refresh the body via `gh pr edit --body` so (a) the new commit's changes are reflected in the prose while existing `## Summary`, `## Validation`, and `## Notes` sections are preserved unless clearly stale, (b) any known session footer line is appended if missing, never removing or rewriting existing `Agent session: ...` or `Agent session ID: ...` lines, and (c) any existing footer carrying the substring `commit-push-pr:created v1` is preserved verbatim, appending `<sub>🤖 <code>commit-push-pr:created v1 core@3.8.0</code></sub>` only if absent. Then report the URL.
|
|
52
52
|
|
|
53
53
|
7. End with one short text response: branch name and the full PR URL (e.g., `https://github.com/clipboardhealth/core-utils/pull/123`). Never use shorthand like `repo#123` — always output the complete URL.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-ui-verification
|
|
3
|
+
description: Use when a Clipboard frontend task involves a new UI idea, Figma/design URL, screenshot, redesign UI, design-to-code implementation, Storybook visual validation, Playwright/browser screenshot, animation/motion visual proof, or preventing design-system and visual-fidelity drift in admin or mobile UI work.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Frontend UI Verification
|
|
7
|
+
|
|
8
|
+
Use this skill for UI work where visual fidelity, design-system reuse, responsive behavior, or human review matters. The goal is to make frontend visual changes cheap to inspect before real integration makes feedback slow and expensive.
|
|
9
|
+
|
|
10
|
+
## Core Rule
|
|
11
|
+
|
|
12
|
+
Code is the source of truth for available components, story patterns, and design-system usage. Design references are the source of truth for intended appearance and behavior. Do not invent components, wrappers, or design tokens until you have searched the repo and checked the relevant design/reference source.
|
|
13
|
+
|
|
14
|
+
Keep this as a cheap visual layer. Use repo rules and agent judgment for routine React implementation details. Be prescriptive only where agents commonly drift: choosing the reference source, finding existing components, creating an isolated Storybook surface, managing the Storybook server lifecycle, opening the exact canvas URL, capturing browser evidence, classifying console findings, and deleting temporary checkpoint stories.
|
|
15
|
+
|
|
16
|
+
## Required Workflow
|
|
17
|
+
|
|
18
|
+
1. **Identify the surface**
|
|
19
|
+
- Determine repo and surface: admin web, mobile web/app, shared package, or another frontend.
|
|
20
|
+
- Identify the strongest available reference source:
|
|
21
|
+
- Figma/design URL: fetch screenshot, design context, variables/tokens, metadata, and design-system/Code Connect mappings when available. If the URL is inaccessible, falls behind login, or returns an error, ask for an export/screenshot or treat the work as screenshot/written-idea based; do not claim exact Figma fidelity without design evidence.
|
|
22
|
+
- Screenshot/image: use it as the visual reference, and call out missing states, viewport, or interaction details.
|
|
23
|
+
- Written idea only: do not block. Search existing components and stories, choose the closest Clipboard pattern, build a Storybook checkpoint, and ask for confirmation before deeper integration if the visual interpretation is subjective.
|
|
24
|
+
- No visual reference: derive from nearby product patterns and design-system components, then verify the proposed interpretation in Storybook before product integration.
|
|
25
|
+
- Classify visible UI work as design-first: implement the smallest inspectable surface, verify it visually, then move to product integration.
|
|
26
|
+
|
|
27
|
+
2. **Find the existing pattern first**
|
|
28
|
+
- Search for existing components, stories, hooks, fixtures, and nearby feature folders before creating anything.
|
|
29
|
+
- In `cbh-admin-frontend`, prefer `src/appV2/redesign/**` and Berlin components from `src/appV2/redesign/components/**`.
|
|
30
|
+
- Reuse existing Clipboard components, tokens, layouts, decorators, and story patterns whenever they satisfy the job.
|
|
31
|
+
- Add a new component only when existing components cannot express the needed UI without awkward composition.
|
|
32
|
+
- Create a generic shared component only when it is reusable across multiple surfaces and matches the established component API style. Otherwise keep it feature-local.
|
|
33
|
+
- Keep reusable components loosely coupled: pass primitive/domain props, not raw API response objects.
|
|
34
|
+
|
|
35
|
+
3. **Build an isolated verification surface**
|
|
36
|
+
- For meaningful visual work, build or update the visual slice in Storybook before product integration.
|
|
37
|
+
- Use a temporary story when the goal is to validate a design slice before wiring backend/auth/routing. It is acceptable for this story to contain the full proposed UI composition with fixtures while the real product code is still being shaped.
|
|
38
|
+
- Iterate inside Storybook: apply visual feedback, retake screenshots, and keep refining until the Storybook surface matches the reference or the human confirms the interpretation.
|
|
39
|
+
- After the UI is integrated, delete temporary checkpoint stories. Keep only stories that are useful permanent documentation: generic components, reusable compositions, or important product states.
|
|
40
|
+
- Cover the states the user would naturally inspect: default, loading, empty, error, disabled, long text, dense data, permission/flag variants, and desktop/mobile variants when the design differs.
|
|
41
|
+
- For drawers, menus, popovers, steppers, tabs, forms, and animated UI, make the story render deterministic pre-action states such as closed, opened, selected, invalid, in-flight, and settled.
|
|
42
|
+
- Mock data at the story boundary. Do not force live API, auth, or route setup just to inspect visual composition.
|
|
43
|
+
|
|
44
|
+
4. **Verify with browser evidence**
|
|
45
|
+
- Run the repo Storybook server as the primary visual verification surface.
|
|
46
|
+
- Start long-running Storybook servers in a process you can stop. In CLI or prompt-command validation, redirect logs to `/tmp`, record the server PID, and stop it before the final report. Do not leave a foreground dev server blocking screenshot capture, cleanup, or the final response.
|
|
47
|
+
- Open the exact story in a browser-controlled surface. Prefer the active Browser/Chrome tool when available; otherwise use Playwright against the Storybook URL.
|
|
48
|
+
- If the Storybook UI shell is noisy, open the canvas URL directly with `iframe.html?viewMode=story&id=<story-id>`.
|
|
49
|
+
- Use native Storybook test/a11y or component-level Playwright scripts only when the repo already exposes them. Do not invent a new harness for this layer.
|
|
50
|
+
- Check console errors, layout overflow, text clipping, loading/empty states, keyboard/interaction cues, and desktop/mobile viewport sizes.
|
|
51
|
+
- Classify console findings as story-introduced, provider/decorator gaps, or pre-existing/global Storybook warnings. Fix story-introduced errors before proceeding; report global warnings separately instead of hiding them.
|
|
52
|
+
- If motion or animation is part of the change, verify the motion in Storybook with a repeatable or controllable story, then capture evidence after the animation starts and after it settles.
|
|
53
|
+
- Capture screenshots when visual fidelity is part of the claim. For Figma work, compare the Storybook screenshot against the Figma screenshot element by element.
|
|
54
|
+
- If the design is non-trivial or the user needs sign-off, share the Storybook URL and screenshot summary, then wait for confirmation before deeper integration.
|
|
55
|
+
|
|
56
|
+
5. **Do not give up on visual access early**
|
|
57
|
+
- Run the helper's `inspect` command first when the repo command, build command, or story URL shape is unclear.
|
|
58
|
+
- If the Storybook dev server fails, try the repo's Storybook build command and inspect the built Storybook when practical.
|
|
59
|
+
- If port `6006` is busy, use the alternate port Storybook prints and report that exact URL.
|
|
60
|
+
- If the story fails because of providers, routing, API data, or feature context, fix the story with decorators or fixture props instead of switching to product integration.
|
|
61
|
+
- If one browser tool fails, try another available browser path: Browser plugin, Chrome, Playwright CLI/script, or the agent's equivalent.
|
|
62
|
+
- Stop only after at least two reasonable Storybook access paths fail, and report the exact command, URL, error, and what evidence is missing.
|
|
63
|
+
|
|
64
|
+
6. **Ask for human confirmation at the right time**
|
|
65
|
+
- Ask before choosing between multiple plausible visual interpretations.
|
|
66
|
+
- Ask after a temporary Storybook checkpoint when the user requested exact visual match, when the reference is subjective, or when the design changes layout density/hierarchy.
|
|
67
|
+
- Ask before adding a new generic component unless there are at least two concrete reuse sites or an existing design-system gap.
|
|
68
|
+
- Do not ask for routine wiring details once the Storybook surface clearly matches existing patterns.
|
|
69
|
+
|
|
70
|
+
7. **Hand off after the visual surface is sound**
|
|
71
|
+
- If the UI is simple and maps directly to existing components, proceed to integration after visual inspection.
|
|
72
|
+
- Treat full product workflow checks as a separate post-verification layer.
|
|
73
|
+
- Do not expand this skill into full-flow Playwright or product-environment work.
|
|
74
|
+
|
|
75
|
+
8. **Final verification report**
|
|
76
|
+
- List the reference source used: Figma/Notion/screenshot/written idea/story/code path.
|
|
77
|
+
- List the Storybook URL checked.
|
|
78
|
+
- List viewport sizes and states verified.
|
|
79
|
+
- State any unresolved visual ambiguity, missing source reference, or verification gap.
|
|
80
|
+
|
|
81
|
+
## When to Stop and Ask
|
|
82
|
+
|
|
83
|
+
Stop before continuing if:
|
|
84
|
+
|
|
85
|
+
- Figma/design docs conflict with current code patterns.
|
|
86
|
+
- A new generic component seems necessary but reuse is not proven.
|
|
87
|
+
- The visual match depends on a subjective choice the reference does not answer.
|
|
88
|
+
- A Figma URL is provided but no Figma screenshot, metadata, or design context can be fetched.
|
|
89
|
+
- You cannot render the Storybook story or capture useful evidence.
|
|
90
|
+
- User approval is needed after a temporary Storybook checkpoint.
|
|
91
|
+
|
|
92
|
+
## Reference Files
|
|
93
|
+
|
|
94
|
+
- Admin app details: read [`references/admin-app.md`](./references/admin-app.md) when working in `cbh-admin-frontend`.
|
|
95
|
+
- Mobile app details: read [`references/mobile-app.md`](./references/mobile-app.md) when working in `cbh-mobile-app`.
|
|
96
|
+
- Tooling details: read [`references/tooling.md`](./references/tooling.md) when using Figma, Notion, Linear, Storybook, browser screenshots, or another agent environment.
|
|
97
|
+
- For motion-heavy UI, also apply the `clipboard-design-engineering` skill if it is available.
|
|
98
|
+
|
|
99
|
+
## Helper Script
|
|
100
|
+
|
|
101
|
+
Script paths below are written as `scripts/...`, relative to this `SKILL.md`, matching the other core skills such as `babysit-pr`.
|
|
102
|
+
|
|
103
|
+
Use the helper before visual work to make the verification surface deterministic:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
bash scripts/inspect-ui-verification-surface.sh inspect
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Use these subcommands when an agent needs exact values instead of prose:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
bash scripts/inspect-ui-verification-surface.sh storybook-command
|
|
113
|
+
bash scripts/inspect-ui-verification-surface.sh storybook-build-command
|
|
114
|
+
bash scripts/inspect-ui-verification-surface.sh storybook-test-command
|
|
115
|
+
bash scripts/inspect-ui-verification-surface.sh component-test-command
|
|
116
|
+
bash scripts/inspect-ui-verification-surface.sh storybook-url <story-id>
|
|
117
|
+
bash scripts/inspect-ui-verification-surface.sh storybook-iframe-url <story-id>
|
|
118
|
+
bash scripts/inspect-ui-verification-surface.sh figma-story-files
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
When running manually from a frontend repo instead of through host skill resolution, use the installed skill path, for example `.agents/skills/frontend-ui-verification/scripts/inspect-ui-verification-surface.sh`.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Admin App Verification Notes
|
|
2
|
+
|
|
3
|
+
Use this reference for `cbh-admin-frontend`.
|
|
4
|
+
|
|
5
|
+
## Source Locations
|
|
6
|
+
|
|
7
|
+
- Redesign features live under `src/appV2/redesign/**`.
|
|
8
|
+
- Shared Berlin components live under `src/appV2/redesign/components/**`.
|
|
9
|
+
- Storybook config lives in `.storybook/`.
|
|
10
|
+
- Stories are discovered from `src/**/*.stories.@(js|jsx|ts|tsx)` and `src/**/*.stories.mdx`.
|
|
11
|
+
- Existing app rules require user-facing copy in redesign code to use `useTu(namespace).tu(...)`.
|
|
12
|
+
- PHI shown in UI must be masked with `data-dd-privacy="mask"`.
|
|
13
|
+
- Feature folders usually follow `api/`, `components/`, `hooks/`, `utils/`, plus container/view files, `types.ts`, `constants.ts`, and `paths.ts`.
|
|
14
|
+
|
|
15
|
+
## Existing Storybook Setup
|
|
16
|
+
|
|
17
|
+
The admin Storybook is React Vite based. `.storybook/main.ts` discovers all `src/**/*.stories.*`, serves `public`, uses `@storybook/addon-essentials`, `@storybook/addon-a11y`, and `@storybook/addon-links`, supports SVG imports, and mocks `@src/mobile/utils/openUrl` with `.storybook/mocks/openUrl.ts`.
|
|
18
|
+
|
|
19
|
+
The global preview already wraps stories with:
|
|
20
|
+
|
|
21
|
+
- `MemoryRouter`
|
|
22
|
+
- `QueryClientProvider`
|
|
23
|
+
- `BerlinThemeProvider`
|
|
24
|
+
|
|
25
|
+
That means most visual stories should use the existing Storybook instead of a custom preview app. Add local decorators only for extra providers such as MUI date pickers, feature-specific contexts, or fixed-width containers.
|
|
26
|
+
|
|
27
|
+
Common commands:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm run storybook
|
|
31
|
+
npm run build-storybook
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
As of the repo audit, these are the only native visual-layer scripts detected for admin. Use the app server only after the Storybook surface is visually sound and the work moves into product integration.
|
|
35
|
+
|
|
36
|
+
Use this as the primary visual verification server:
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
http://localhost:6006/
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Story URLs usually follow this shape:
|
|
43
|
+
|
|
44
|
+
```text
|
|
45
|
+
http://localhost:6006/?path=/story/<story-id>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Direct canvas URLs are useful for screenshots:
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
http://localhost:6006/iframe.html?viewMode=story&id=<story-id>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
If port `6006` is busy, use the alternate port Storybook prints and report that exact URL in the handoff.
|
|
55
|
+
|
|
56
|
+
## Story Requirements
|
|
57
|
+
|
|
58
|
+
For visual feature work, prefer one of these story shapes:
|
|
59
|
+
|
|
60
|
+
- Component primitive story: all variants, sizes, disabled/loading/error states.
|
|
61
|
+
- Feature composition story: realistic fixture data showing the component in its card, drawer, modal, page section, or mobile shell.
|
|
62
|
+
- Temporary design checkpoint story: a focused story that renders the full proposed UI before app wiring. Use it to iterate, capture screenshots, and get user sign-off. After integration, delete it unless it has become a useful permanent generic/component/state story.
|
|
63
|
+
|
|
64
|
+
Stories should avoid live network/auth dependencies. If the real component requires API context, compose lower-level presentational pieces with realistic fixture data, as existing `DailyView`, `Calendar`, `Chat`, and `WorkerDocuments` stories do.
|
|
65
|
+
|
|
66
|
+
Good local patterns:
|
|
67
|
+
|
|
68
|
+
- `src/appV2/redesign/Calendar/Daily/Mobile/Layout.stories.tsx`: fullscreen mobile layout, fixed story date, realistic panes, local full-height decorator.
|
|
69
|
+
- `src/appV2/redesign/DailyView/components/ShiftPostingForm/ShiftPostingForm.stories.tsx`: visual composition story for an API-bound form, using lower-level pieces and a Figma reference comment.
|
|
70
|
+
- `src/appV2/redesign/DailyView/components/ValidationModals/RushFeeDialog.stories.tsx`: modal state coverage with mobile viewport parameters.
|
|
71
|
+
|
|
72
|
+
## Design-System Checks
|
|
73
|
+
|
|
74
|
+
Before creating new UI, search for:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
rg "export function .*" src/appV2/redesign/components
|
|
78
|
+
find src/appV2/redesign -name '*.stories.tsx'
|
|
79
|
+
rg "title: .*<feature-or-component>" src/appV2/redesign -g '*.stories.tsx'
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Check whether existing components already cover the need:
|
|
83
|
+
|
|
84
|
+
- `Button`, `IconButton`, `Text`, `TextInput`, `SearchInput`
|
|
85
|
+
- `Chip`, `Tag`, `Badge`, `Pill`, `StatusDot`
|
|
86
|
+
- `Dialog`, `ResponsiveDialog`, `Drawer`, `SidePanel`, `BottomSheet`
|
|
87
|
+
- `Tabs`, `SegmentedControl`, `DataGrid`, `PageLayout`
|
|
88
|
+
- `InfoBanner`, `AcknowledgementBanner`, `NotificationCard`
|
|
89
|
+
|
|
90
|
+
Use MUI `sx` with theme tokens. Avoid ad hoc CSS files, hardcoded colors, raw pixel spacing when a theme token exists, and wrapper `Box` layers that do not add layout value.
|
|
91
|
+
|
|
92
|
+
Admin styling and component rules to preserve:
|
|
93
|
+
|
|
94
|
+
- Use `BerlinThemeProvider`, not legacy theme providers, for new redesign surfaces.
|
|
95
|
+
- Use `sx` with theme tokens and full property names such as `padding`, `paddingX`, `marginY`.
|
|
96
|
+
- Keep presentational components API-light: pass primitives or domain props, not raw API response objects.
|
|
97
|
+
- Register every new or updated shared UI component in Storybook with a `Default` story first and useful controls.
|
|
98
|
+
|
|
99
|
+
## Storybook Browser Verification
|
|
100
|
+
|
|
101
|
+
For non-trivial visual changes, inspect at least:
|
|
102
|
+
|
|
103
|
+
- Mobile: `375x812`
|
|
104
|
+
- Tablet or narrow desktop when relevant: `768x1024`
|
|
105
|
+
- Desktop: `1440x900`
|
|
106
|
+
|
|
107
|
+
Check:
|
|
108
|
+
|
|
109
|
+
- No clipped text or horizontal overflow.
|
|
110
|
+
- Loading, empty, disabled, error, and dense-data states.
|
|
111
|
+
- Long names, long labels, and translated-copy expansion.
|
|
112
|
+
- Keyboard and pointer cues for interactive elements.
|
|
113
|
+
- Console errors and missing assets.
|
|
114
|
+
- Motion and animation states when present: initial, active/in-flight, settled, and reduced-motion behavior when practical.
|
|
115
|
+
- Feature flag and route behavior only after Storybook looks correct.
|
|
116
|
+
|
|
117
|
+
## Out of Scope
|
|
118
|
+
|
|
119
|
+
Do not use this skill to solve full workflow E2E coverage or product-environment setup. Those belong to the later post-verification layer after the Storybook visual surface has been reviewed.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Mobile App Verification Notes
|
|
2
|
+
|
|
3
|
+
Use this reference for `cbh-mobile-app`.
|
|
4
|
+
|
|
5
|
+
## Source Locations
|
|
6
|
+
|
|
7
|
+
- App V2 code lives under `src/appV2/**`.
|
|
8
|
+
- Redesign mobile surfaces live under `src/appV2/redesign/**`.
|
|
9
|
+
- Shared redesign components live under `src/appV2/redesign/components/**`.
|
|
10
|
+
- Storybook config lives in `.storybook/`, with extra decorators under `src/appV2/.storybook/decorators/**`.
|
|
11
|
+
- Stories are discovered from `src/**/*.stories.@(js|jsx|ts|tsx)` and `src/**/*.mdx`.
|
|
12
|
+
- Many redesign stories live under `src/appV2/redesign/stories/**`; component-specific stories may also be colocated near the component.
|
|
13
|
+
|
|
14
|
+
## Existing Storybook Setup
|
|
15
|
+
|
|
16
|
+
The mobile Storybook is React Vite based and includes:
|
|
17
|
+
|
|
18
|
+
- `@storybook/addon-designs` for attaching Figma/design references.
|
|
19
|
+
- `@storybook/addon-interactions` for interaction stories.
|
|
20
|
+
- A `design-system` Storybook ref named `CBH Core Design System` at `https://cbh-core.cbh.rocks/`.
|
|
21
|
+
- Static assets from `public` and `src/assets`.
|
|
22
|
+
- Vite TypeScript path support, SVG support, and node polyfills.
|
|
23
|
+
|
|
24
|
+
Common commands:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm run storybook
|
|
28
|
+
npm run storybook:build
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
As of the repo audit, these are the native visual-layer scripts detected for mobile. Use the app server or device runtime only after the Storybook surface is visually sound and the work moves into product integration.
|
|
32
|
+
|
|
33
|
+
Use this as the primary visual verification server:
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
http://localhost:6006/
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Story URLs usually follow this shape:
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
http://localhost:6006/?path=/story/<story-id>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Direct canvas URLs are useful for screenshots:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
http://localhost:6006/iframe.html?viewMode=story&id=<story-id>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
If port `6006` is busy, use the alternate port Storybook prints and report that exact URL in the handoff.
|
|
52
|
+
|
|
53
|
+
The global preview wraps stories with:
|
|
54
|
+
|
|
55
|
+
- `SnackbarProviderDecorator`
|
|
56
|
+
- `ReactQueryDecorator`
|
|
57
|
+
- `MuiThemeDecorator`
|
|
58
|
+
- `RouterDecorator`
|
|
59
|
+
- `SegmentPluginDecorator`
|
|
60
|
+
|
|
61
|
+
Use local story decorators when a redesign surface needs a different provider. Existing examples use:
|
|
62
|
+
|
|
63
|
+
- `RedesignMuiThemeDecorator` from `src/appV2/.storybook/decorators/ShiftDiscoveryMuiTheme` for redesign UI.
|
|
64
|
+
- `MockWorkerDecorator` for stories that need worker query data.
|
|
65
|
+
- `CustomRouteDecorator` for route-dependent components.
|
|
66
|
+
- `GoogleMapsDecorator` for Google Places autocomplete behavior.
|
|
67
|
+
- `KnockGuideProviderDecorator` for Knock guides.
|
|
68
|
+
|
|
69
|
+
## Mobile Screen Sizes
|
|
70
|
+
|
|
71
|
+
The Storybook preview already defines these useful screen sizes:
|
|
72
|
+
|
|
73
|
+
- `iPhoneSE`: `375x667`
|
|
74
|
+
- `iPhone12`: `390x844`
|
|
75
|
+
- `pixel6`: `412x915`
|
|
76
|
+
- `iPadMini`: `768x1024`
|
|
77
|
+
- `smallScreen`: `420x300`
|
|
78
|
+
|
|
79
|
+
Default visual inspection should include the default `iPhone12`, the smallest relevant phone viewport, and `iPadMini` when layout may stretch.
|
|
80
|
+
|
|
81
|
+
## Story Requirements
|
|
82
|
+
|
|
83
|
+
Prefer stories that render the real mobile shell or bottom-sheet/card/list composition with realistic fixture data. Good local patterns include:
|
|
84
|
+
|
|
85
|
+
- `src/appV2/Connectivity/OfflineIndicator.stories.tsx`
|
|
86
|
+
- `src/appV2/PostShiftReview/PostShiftReviewFlowContent.stories.tsx`
|
|
87
|
+
- `src/appV2/redesign/stories/**`
|
|
88
|
+
- `src/appV2/redesign/Placements/components/PlacementCard/PlacementCardV2.stories.tsx`
|
|
89
|
+
- `src/appV2/redesign/EmergencyCredits/components/CreditProgressBar.stories.tsx`
|
|
90
|
+
|
|
91
|
+
Temporary design checkpoint stories may render the full proposed UI before app wiring. Use them to iterate, capture screenshots, and get user sign-off. After integration, delete them unless they have become useful permanent generic/component/state stories.
|
|
92
|
+
|
|
93
|
+
When a story maps to a Figma node, attach the design reference in Storybook:
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
parameters: {
|
|
97
|
+
design: {
|
|
98
|
+
type: "figma",
|
|
99
|
+
url: "https://www.figma.com/design/...",
|
|
100
|
+
},
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
For mobile redesign work, verify:
|
|
105
|
+
|
|
106
|
+
- Bottom sheets, dialogs, sticky footers, safe-area spacing, and keyboard overlap.
|
|
107
|
+
- Long workplace names, worker names, addresses, rates, dates, and translated-copy expansion.
|
|
108
|
+
- Loading, empty, offline, retry, permission-denied, disabled, and submitted states.
|
|
109
|
+
- Tap target size, focus order, scroll boundaries, and hidden overflow.
|
|
110
|
+
- Whether a component should be mobile-specific or shared content inside a mobile shell.
|
|
111
|
+
- If animation is part of the UI, provide a story control to replay it or render the in-flight state. `CreditProgressBar.stories.tsx` is a good local pattern.
|
|
112
|
+
|
|
113
|
+
Avoid live network/auth dependencies in stories. Mock query data or pass fixture props at the story boundary.
|
|
114
|
+
|
|
115
|
+
Mobile redesign lint/style constraints to preserve:
|
|
116
|
+
|
|
117
|
+
- Use design-system or MUI components instead of raw `div` and `span` in redesign code.
|
|
118
|
+
- Avoid raw hex colors; use theme variables.
|
|
119
|
+
- Use `getStoryBackgrounds()` when a story needs the standard light/dark background set.
|
|
120
|
+
- Keep mobile app verification in Storybook for visual work. Capacitor-only behavior, native permissions, push, deep links, and true device APIs are post-verification concerns.
|
|
121
|
+
|
|
122
|
+
## Out of Scope
|
|
123
|
+
|
|
124
|
+
Do not use this skill to solve full workflow E2E coverage, product-environment setup, or Capacitor device behavior. Those belong to the later post-verification layer after the Storybook visual surface has been reviewed.
|
|
125
|
+
|
|
126
|
+
Report separately:
|
|
127
|
+
|
|
128
|
+
- Storybook visual evidence.
|
|
129
|
+
- Any device capability gap, such as camera, location access, push, deep links, or Capacitor-only behavior.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Verification Tooling Notes
|
|
2
|
+
|
|
3
|
+
Use this reference when the task depends on external design/project sources or shared agent workflows.
|
|
4
|
+
|
|
5
|
+
## Source References
|
|
6
|
+
|
|
7
|
+
- **Figma**: Use the Figma MCP/plugin when available. For Figma URLs, explicitly fetch screenshot plus structured design context before implementation. Prefer `get_design_context`, `get_screenshot`, `get_metadata`, `get_variable_defs`, `search_design_system`, and Code Connect results over visual guessing. If the MCP is unavailable or the link is blocked by login/permissions, ask for a Figma screenshot/export or link-specific notes before claiming exact fidelity.
|
|
8
|
+
- **Notion**: Use Notion MCP for project docs, design process notes, and rollout context. Summarize only the UI requirements that affect the implementation or verification plan.
|
|
9
|
+
- **Linear**: Use Linear MCP for project and ticket traceability. Keep tracking minimal: one project and only the few tickets needed to map back to source work.
|
|
10
|
+
- **Screenshots**: Treat screenshots as design evidence, but call out missing dimensions, states, or interaction details when they are not visible.
|
|
11
|
+
- **Written ideas**: Treat the user's text as product intent, not a complete visual spec. Search existing Clipboard components and stories first, compose the closest pattern, and create a Storybook checkpoint for human confirmation when the idea leaves room for visual interpretation.
|
|
12
|
+
- **No reference**: Do not invent a new visual language. Derive from nearby feature patterns, shared design-system components, and existing Storybook stories, then verify the proposed UI in Storybook before product integration.
|
|
13
|
+
|
|
14
|
+
## Figma Workflow
|
|
15
|
+
|
|
16
|
+
When a Figma URL is present:
|
|
17
|
+
|
|
18
|
+
1. Use the installed Figma skill/plugin or MCP first. If the environment exposes a named Figma or design tool, use that before coding from memory.
|
|
19
|
+
2. Parse the URL before calling tools:
|
|
20
|
+
- For `figma.com/design/:fileKey/...?...node-id=1-2`, use the `/design/` segment as `fileKey` and convert `node-id` hyphens to colons, such as `1-2` to `1:2`, when the tool schema expects a node ID.
|
|
21
|
+
- For branch links, use the branch file key when the Figma server requires it.
|
|
22
|
+
- For desktop selection-based flows, follow the local Figma server's parameter requirements; the file key may be implicit.
|
|
23
|
+
3. If the agent does not automatically choose the right Figma tool, request it by name:
|
|
24
|
+
- `get_design_context` for structured design context.
|
|
25
|
+
- `get_screenshot` for visual fidelity.
|
|
26
|
+
- `get_variable_defs` for variables, styles, colors, spacing, and typography.
|
|
27
|
+
- `get_metadata` to map pages/layers or recover from large-context designs.
|
|
28
|
+
- `search_design_system` when looking for reusable components, variables, or styles.
|
|
29
|
+
- `get_code_connect_map` or Code Connect mappings when the design system has mappings to repo components.
|
|
30
|
+
- `get_libraries` when the remote Figma MCP exposes library metadata and the task needs design-system source discovery.
|
|
31
|
+
4. Treat Figma MCP output as design context, not production-ready code. Translate it into the repo's components, theme tokens, Storybook patterns, and TypeScript rules.
|
|
32
|
+
5. Fetch screenshot, metadata, design context, variables/tokens, and design-system matches for the target node. If `get_design_context` is too large or truncated, call `get_metadata`, select smaller child nodes, and re-run `get_design_context` on the relevant subtree.
|
|
33
|
+
6. Map Figma components to repo components before coding. If Code Connect mappings exist, use them; otherwise search the repo and Storybook for closest components.
|
|
34
|
+
7. Implement the smallest isolated Storybook surface that can be compared to the Figma screenshot.
|
|
35
|
+
8. If the repo supports `@storybook/addon-designs`, attach the Figma URL with `parameters.design` in the story when the story is expected to remain useful.
|
|
36
|
+
9. Capture a Storybook screenshot at the matching viewport and compare layout, spacing, typography, color, border radius, iconography, density, and state text.
|
|
37
|
+
10. If the Figma URL returns a login screen, permission error, network error, or non-design page, fall back to a provided screenshot/export. If no visual export is available, proceed as a written idea/no-reference task and label exact Figma fidelity as unverified.
|
|
38
|
+
11. Ask the human to confirm when the match depends on taste, when a design token is missing, or when the Figma node appears stale compared with current code.
|
|
39
|
+
|
|
40
|
+
## Browser Verification
|
|
41
|
+
|
|
42
|
+
Use the repo's native Storybook server first. Then use whichever browser-controlled surface is available in the current agent: Browser plugin, Chrome, Playwright CLI/script, Playwright MCP, or the agent's built-in browser automation.
|
|
43
|
+
|
|
44
|
+
For CLI agents, manage Storybook as a background process with explicit cleanup. A foreground dev server can block the agent before it captures screenshots, deletes temporary stories, or reports results.
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
storybook_command="$(bash scripts/inspect-ui-verification-surface.sh storybook-command)"
|
|
48
|
+
storybook_log="${TMPDIR:-/tmp}/frontend-ui-verification-storybook.log"
|
|
49
|
+
|
|
50
|
+
bash -lc "$storybook_command" >"$storybook_log" 2>&1 &
|
|
51
|
+
storybook_pid="$!"
|
|
52
|
+
|
|
53
|
+
# Run browser verification here, then always stop the server.
|
|
54
|
+
kill "$storybook_pid" 2>/dev/null || true
|
|
55
|
+
wait "$storybook_pid" 2>/dev/null || true
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Prefer the helper for deterministic commands and URLs:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
bash scripts/inspect-ui-verification-surface.sh storybook-command
|
|
62
|
+
bash scripts/inspect-ui-verification-surface.sh storybook-build-command
|
|
63
|
+
bash scripts/inspect-ui-verification-surface.sh storybook-test-command
|
|
64
|
+
bash scripts/inspect-ui-verification-surface.sh component-test-command
|
|
65
|
+
bash scripts/inspect-ui-verification-surface.sh storybook-url <story-id>
|
|
66
|
+
bash scripts/inspect-ui-verification-surface.sh storybook-iframe-url <story-id>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Access ladder:
|
|
70
|
+
|
|
71
|
+
1. Start Storybook with the exact command returned by `storybook-command`, then open the story URL returned by `storybook-url <story-id>`.
|
|
72
|
+
2. If the Storybook shell interferes with inspection, open the canvas URL returned by `storybook-iframe-url <story-id>`.
|
|
73
|
+
3. If no browser plugin is available, use Playwright to navigate to the Storybook URL, set the viewport, wait for the story root, collect console errors, and capture a screenshot.
|
|
74
|
+
4. Classify console output as story-introduced, provider/decorator gaps, or pre-existing/global Storybook warnings. Fix story-introduced rendering errors before claiming the story is verified.
|
|
75
|
+
5. If the helper returns a native Storybook test/a11y command, use it for isolated accessibility or interaction checks after the story renders.
|
|
76
|
+
6. If the helper returns a native component browser-test command, use it only for focused component-level checks that can mount with stable providers and mocks.
|
|
77
|
+
7. If the dev server fails, run the exact command returned by `storybook-build-command` and inspect the built Storybook when practical.
|
|
78
|
+
8. If provider/context errors block rendering, add story decorators, fixture props, or local mocks. Do not switch to full product integration just to see the UI.
|
|
79
|
+
9. Stop only with a concrete blocker: command run, URL attempted, error observed, and why no screenshot could be captured.
|
|
80
|
+
|
|
81
|
+
## Component-Level Browser Checks
|
|
82
|
+
|
|
83
|
+
Only use component-level Playwright or Storybook test-runner checks when the repo already exposes a script. Keep the test surface isolated and product-agnostic:
|
|
84
|
+
|
|
85
|
+
- Mount the smallest parent that owns the visual state instead of a deeply prop-driven child.
|
|
86
|
+
- Wrap only the providers the component actually reads: router, query client, theme, feature flags, or local context.
|
|
87
|
+
- Mock API data at the test/story boundary. Derive response shape from fixture/HAR/type usage; do not guess unknown response fields.
|
|
88
|
+
- For interactive components, encode pre-actions: click the drawer/menu trigger, select a tab, type into the invalid field, or advance the animation before capturing.
|
|
89
|
+
- Test desktop and mobile sizes when the component has responsive behavior.
|
|
90
|
+
- Assert at least one visible value or accessible control before taking a screenshot, so an empty render cannot pass as a visual baseline.
|
|
91
|
+
- Use short timeouts on the first iteration to expose missing providers or mocks quickly; remove the override once the surface is stable.
|
|
92
|
+
|
|
93
|
+
For visual claims, capture or report:
|
|
94
|
+
|
|
95
|
+
- Storybook URL or story ID.
|
|
96
|
+
- Viewport size.
|
|
97
|
+
- State being inspected.
|
|
98
|
+
- Console errors or missing assets.
|
|
99
|
+
- Screenshot path or a short screenshot summary.
|
|
100
|
+
|
|
101
|
+
For motion claims, also capture or report:
|
|
102
|
+
|
|
103
|
+
- The trigger used to start the motion.
|
|
104
|
+
- Whether the story can replay the motion deterministically.
|
|
105
|
+
- In-flight and settled visual states.
|
|
106
|
+
- Any reduced-motion behavior or gap.
|
|
107
|
+
|
|
108
|
+
## Agent Handoff Contract
|
|
109
|
+
|
|
110
|
+
When one agent prepares work for another, include:
|
|
111
|
+
|
|
112
|
+
- Repo, branch, and changed files.
|
|
113
|
+
- Source references used: Figma, Notion, Linear, screenshot, or code path.
|
|
114
|
+
- Exact Storybook story to open.
|
|
115
|
+
- Commands already run and their outcome.
|
|
116
|
+
- Remaining subjective design choices that need human confirmation.
|
|
117
|
+
|
|
118
|
+
Do not rely on agent-specific memory. Put durable instructions in the repo-owned skill, story, test, or ticket.
|
|
119
|
+
|
|
120
|
+
## Temporary Storybook Checkpoints
|
|
121
|
+
|
|
122
|
+
Temporary stories are acceptable for design confirmation when:
|
|
123
|
+
|
|
124
|
+
- The UI needs human visual approval before backend/auth/routing work.
|
|
125
|
+
- The real route is blocked by credentials, flags, data, or environment setup.
|
|
126
|
+
- Multiple agents need a stable isolated surface to inspect.
|
|
127
|
+
|
|
128
|
+
Before merge, remove the temporary story or convert it into a permanent story with realistic fixtures and useful states.
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# cspell:ignore dockerless
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
usage() {
|
|
6
|
+
cat <<'EOF'
|
|
7
|
+
Usage:
|
|
8
|
+
inspect-ui-verification-surface.sh inspect
|
|
9
|
+
inspect-ui-verification-surface.sh storybook-command
|
|
10
|
+
inspect-ui-verification-surface.sh storybook-build-command
|
|
11
|
+
inspect-ui-verification-surface.sh storybook-test-command
|
|
12
|
+
inspect-ui-verification-surface.sh component-test-command
|
|
13
|
+
inspect-ui-verification-surface.sh storybook-url <story-id>
|
|
14
|
+
inspect-ui-verification-surface.sh storybook-iframe-url <story-id>
|
|
15
|
+
inspect-ui-verification-surface.sh figma-story-files
|
|
16
|
+
|
|
17
|
+
Environment:
|
|
18
|
+
STORYBOOK_PORT Storybook port to use for URL commands. Defaults to 6006.
|
|
19
|
+
EOF
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if git rev-parse --show-toplevel >/dev/null 2>&1; then
|
|
23
|
+
repo_root="$(git rev-parse --show-toplevel)"
|
|
24
|
+
else
|
|
25
|
+
repo_root="$PWD"
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
cd "$repo_root"
|
|
29
|
+
|
|
30
|
+
command="${1:-inspect}"
|
|
31
|
+
storybook_port="${STORYBOOK_PORT:-6006}"
|
|
32
|
+
|
|
33
|
+
script_from_package_json() {
|
|
34
|
+
node -e '
|
|
35
|
+
const fs = require("fs");
|
|
36
|
+
const names = process.argv.slice(1);
|
|
37
|
+
if (!fs.existsSync("package.json")) process.exit(1);
|
|
38
|
+
const pkg = JSON.parse(fs.readFileSync("package.json", "utf8"));
|
|
39
|
+
const scripts = pkg.scripts || {};
|
|
40
|
+
for (const name of names) {
|
|
41
|
+
if (scripts[name]) {
|
|
42
|
+
console.log(`npm run ${name}`);
|
|
43
|
+
process.exit(0);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
process.exit(1);
|
|
47
|
+
' "$@"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
storybook_script() {
|
|
51
|
+
node -e '
|
|
52
|
+
const fs = require("fs");
|
|
53
|
+
if (!fs.existsSync("package.json")) process.exit(1);
|
|
54
|
+
const pkg = JSON.parse(fs.readFileSync("package.json", "utf8"));
|
|
55
|
+
const scripts = pkg.scripts || {};
|
|
56
|
+
if (!scripts.storybook) process.exit(1);
|
|
57
|
+
console.log("npm run storybook");
|
|
58
|
+
'
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
storybook_build_script() {
|
|
62
|
+
script_from_package_json "build-storybook" "storybook:build"
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
storybook_test_script() {
|
|
66
|
+
script_from_package_json "test-storybook" "storybook:test" "test:storybook" "test:a11y" "a11y"
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
component_test_script() {
|
|
70
|
+
script_from_package_json \
|
|
71
|
+
"test:playwright:ct-dockerless" \
|
|
72
|
+
"test:playwright:ct" \
|
|
73
|
+
"test:playwright:ct-update-screenshots" \
|
|
74
|
+
"test:ct" \
|
|
75
|
+
"test:ct:local" \
|
|
76
|
+
"ct:local"
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
figma_story_files() {
|
|
80
|
+
files="$(
|
|
81
|
+
for root in src/appV2/redesign src/appV2 src components app; do
|
|
82
|
+
if [ -d "$root" ]; then
|
|
83
|
+
find "$root" -name "*.stories.tsx" -o -name "*.stories.ts" -o -name "*.stories.mdx"
|
|
84
|
+
fi
|
|
85
|
+
done | sort -u
|
|
86
|
+
)"
|
|
87
|
+
|
|
88
|
+
if [ -z "$files" ]; then
|
|
89
|
+
return 0
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
printf "%s\n" "$files" | while IFS= read -r file; do
|
|
93
|
+
if grep -Eq 'figma\.com|design:[[:space:]]*\{' "$file"; then
|
|
94
|
+
printf "%s\n" "$file"
|
|
95
|
+
fi
|
|
96
|
+
done | head -n 80
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
case "$command" in
|
|
100
|
+
inspect)
|
|
101
|
+
;;
|
|
102
|
+
storybook-command)
|
|
103
|
+
storybook_script
|
|
104
|
+
exit 0
|
|
105
|
+
;;
|
|
106
|
+
storybook-build-command)
|
|
107
|
+
storybook_build_script
|
|
108
|
+
exit 0
|
|
109
|
+
;;
|
|
110
|
+
storybook-test-command)
|
|
111
|
+
storybook_test_script
|
|
112
|
+
exit 0
|
|
113
|
+
;;
|
|
114
|
+
component-test-command)
|
|
115
|
+
component_test_script
|
|
116
|
+
exit 0
|
|
117
|
+
;;
|
|
118
|
+
storybook-url)
|
|
119
|
+
if [ "${2:-}" = "" ]; then
|
|
120
|
+
echo "Missing story id." >&2
|
|
121
|
+
usage >&2
|
|
122
|
+
exit 2
|
|
123
|
+
fi
|
|
124
|
+
printf "http://localhost:%s/?path=/story/%s\n" "$storybook_port" "$2"
|
|
125
|
+
exit 0
|
|
126
|
+
;;
|
|
127
|
+
storybook-iframe-url)
|
|
128
|
+
if [ "${2:-}" = "" ]; then
|
|
129
|
+
echo "Missing story id." >&2
|
|
130
|
+
usage >&2
|
|
131
|
+
exit 2
|
|
132
|
+
fi
|
|
133
|
+
printf "http://localhost:%s/iframe.html?viewMode=story&id=%s\n" "$storybook_port" "$2"
|
|
134
|
+
exit 0
|
|
135
|
+
;;
|
|
136
|
+
figma-story-files)
|
|
137
|
+
figma_story_files
|
|
138
|
+
exit 0
|
|
139
|
+
;;
|
|
140
|
+
--help|-h|help)
|
|
141
|
+
usage
|
|
142
|
+
exit 0
|
|
143
|
+
;;
|
|
144
|
+
*)
|
|
145
|
+
echo "Unknown command: $command" >&2
|
|
146
|
+
usage >&2
|
|
147
|
+
exit 2
|
|
148
|
+
;;
|
|
149
|
+
esac
|
|
150
|
+
|
|
151
|
+
echo "Repository: $repo_root"
|
|
152
|
+
|
|
153
|
+
if [ -f package.json ]; then
|
|
154
|
+
echo
|
|
155
|
+
echo "Relevant package scripts:"
|
|
156
|
+
node -e '
|
|
157
|
+
const fs = require("fs");
|
|
158
|
+
const pkg = JSON.parse(fs.readFileSync("package.json", "utf8"));
|
|
159
|
+
const scripts = pkg.scripts || {};
|
|
160
|
+
for (const name of [
|
|
161
|
+
"storybook",
|
|
162
|
+
"build-storybook",
|
|
163
|
+
"storybook:build",
|
|
164
|
+
"test-storybook",
|
|
165
|
+
"storybook:test",
|
|
166
|
+
"test:storybook",
|
|
167
|
+
"test:a11y",
|
|
168
|
+
"a11y",
|
|
169
|
+
"test:playwright:ct-dockerless",
|
|
170
|
+
"test:playwright:ct",
|
|
171
|
+
"test:playwright:ct-update-screenshots",
|
|
172
|
+
"test:ct",
|
|
173
|
+
"test:ct:local",
|
|
174
|
+
"ct:local",
|
|
175
|
+
"test:v2",
|
|
176
|
+
"lint",
|
|
177
|
+
"lint:v2",
|
|
178
|
+
"typecheck",
|
|
179
|
+
"typecheck:v2",
|
|
180
|
+
]) {
|
|
181
|
+
if (scripts[name]) console.log(`- ${name}: ${scripts[name]}`);
|
|
182
|
+
}
|
|
183
|
+
'
|
|
184
|
+
fi
|
|
185
|
+
|
|
186
|
+
echo
|
|
187
|
+
echo "Deterministic Storybook commands:"
|
|
188
|
+
if storybook_command="$(storybook_script 2>/dev/null)"; then
|
|
189
|
+
echo "- Start: $storybook_command"
|
|
190
|
+
echo "- Default URL: http://localhost:${storybook_port}/"
|
|
191
|
+
else
|
|
192
|
+
echo "- Start: no storybook script detected"
|
|
193
|
+
fi
|
|
194
|
+
if storybook_build_command="$(storybook_build_script 2>/dev/null)"; then
|
|
195
|
+
echo "- Build: $storybook_build_command"
|
|
196
|
+
else
|
|
197
|
+
echo "- Build: no Storybook build script detected"
|
|
198
|
+
fi
|
|
199
|
+
if storybook_test_command="$(storybook_test_script 2>/dev/null)"; then
|
|
200
|
+
echo "- Storybook test/a11y: $storybook_test_command"
|
|
201
|
+
else
|
|
202
|
+
echo "- Storybook test/a11y: no native script detected"
|
|
203
|
+
fi
|
|
204
|
+
if component_test_command="$(component_test_script 2>/dev/null)"; then
|
|
205
|
+
echo "- Component browser test: $component_test_command"
|
|
206
|
+
else
|
|
207
|
+
echo "- Component browser test: no native script detected"
|
|
208
|
+
fi
|
|
209
|
+
echo "- Story URL: $0 storybook-url <story-id>"
|
|
210
|
+
echo "- Canvas URL: $0 storybook-iframe-url <story-id>"
|
|
211
|
+
|
|
212
|
+
echo
|
|
213
|
+
echo "Changed UI-related files:"
|
|
214
|
+
changed_files="$(
|
|
215
|
+
{
|
|
216
|
+
git diff --name-only HEAD -- 2>/dev/null || true
|
|
217
|
+
git ls-files --others --exclude-standard 2>/dev/null || true
|
|
218
|
+
} | sort -u
|
|
219
|
+
)"
|
|
220
|
+
if [ -n "$changed_files" ]; then
|
|
221
|
+
ui_files="$(printf "%s\n" "$changed_files" | grep -E '(\.tsx?$|\.stories\.(tsx?|jsx?)$|\.mdx$|\.css$|\.scss$)' || true)"
|
|
222
|
+
if [ -n "$ui_files" ]; then
|
|
223
|
+
printf "%s\n" "$ui_files" | sed "s#^#- #"
|
|
224
|
+
else
|
|
225
|
+
echo "- No changed UI files detected."
|
|
226
|
+
fi
|
|
227
|
+
else
|
|
228
|
+
echo "- No tracked changes relative to HEAD."
|
|
229
|
+
fi
|
|
230
|
+
|
|
231
|
+
echo
|
|
232
|
+
echo "Storybook files near common Clipboard frontend roots:"
|
|
233
|
+
story_files="$(
|
|
234
|
+
for root in src/appV2/redesign src components app; do
|
|
235
|
+
if [ -d "$root" ]; then
|
|
236
|
+
find "$root" -name "*.stories.tsx" -o -name "*.stories.ts" -o -name "*.stories.mdx"
|
|
237
|
+
fi
|
|
238
|
+
done | sort -u | head -n 80
|
|
239
|
+
)"
|
|
240
|
+
if [ -n "$story_files" ]; then
|
|
241
|
+
printf "%s\n" "$story_files" | sed "s#^#- #"
|
|
242
|
+
else
|
|
243
|
+
echo "- No Storybook files found in common roots."
|
|
244
|
+
fi
|
|
245
|
+
|
|
246
|
+
echo
|
|
247
|
+
echo "Figma tooling hints:"
|
|
248
|
+
if [ -f ".storybook/main.ts" ] && grep -q "@storybook/addon-designs" ".storybook/main.ts"; then
|
|
249
|
+
echo "- Storybook addon-designs detected in .storybook/main.ts"
|
|
250
|
+
fi
|
|
251
|
+
echo "- When a Figma URL exists, fetch screenshot and design context before coding."
|
|
252
|
+
echo "- Figma story files: $0 figma-story-files"
|
|
253
|
+
|
|
254
|
+
figma_files="$(figma_story_files)"
|
|
255
|
+
if [ -n "$figma_files" ]; then
|
|
256
|
+
echo
|
|
257
|
+
echo "Story files with Figma/design references:"
|
|
258
|
+
printf "%s\n" "$figma_files" | sed "s#^#- #"
|
|
259
|
+
fi
|
|
260
|
+
|
|
261
|
+
echo
|
|
262
|
+
echo "Suggested verification ladder:"
|
|
263
|
+
if storybook_command="$(storybook_script 2>/dev/null)"; then
|
|
264
|
+
echo "1. Run: $storybook_command"
|
|
265
|
+
echo "2. Open the changed story at http://localhost:${storybook_port}/"
|
|
266
|
+
echo "3. If the Storybook shell is noisy, open the iframe canvas URL."
|
|
267
|
+
echo "4. Use Browser, Chrome, or Playwright to capture mobile and desktop screenshots."
|
|
268
|
+
echo "5. If native storybook/component test commands are detected, use them for isolated interaction or a11y checks."
|
|
269
|
+
echo "6. If rendering fails, fix story decorators/fixtures before product integration."
|
|
270
|
+
else
|
|
271
|
+
echo "1. No storybook script detected. Use the repo's documented visual preview surface."
|
|
272
|
+
echo "2. Use Browser, Chrome, or Playwright to capture screenshots from that surface."
|
|
273
|
+
echo "3. If rendering fails, fix isolated fixtures/providers before product integration."
|
|
274
|
+
fi
|