@jesdi/skills 0.0.32 → 0.0.33
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/README.md
CHANGED
|
@@ -144,11 +144,12 @@ them afterwards). `external-skills.json` lists them under `forks`.
|
|
|
144
144
|
|
|
145
145
|
### The box set
|
|
146
146
|
|
|
147
|
-
`external-skills.json` → `sets.box` names the skills the
|
|
148
|
-
receives
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
147
|
+
`external-skills.json` → `sets.box.external` names the third-party skills the
|
|
148
|
+
agent-ops box receives from the pinned upstream. `pr` is in this set and is
|
|
149
|
+
installed directly from mattpocock/skills. agent-ops-infra lists the own skills
|
|
150
|
+
of the box (`provision/my-skills.json`) and pins the commit of this file it
|
|
151
|
+
reads (`provision/external-skills.pin`); this repo's job is to publish the set
|
|
152
|
+
and keep the pins resolvable.
|
|
152
153
|
|
|
153
154
|
## Authoring skills
|
|
154
155
|
|
package/package.json
CHANGED
|
@@ -45,7 +45,7 @@ file as JSON:
|
|
|
45
45
|
| `deviceProjects` | the config's `projects` (default to a desktop + a mobile project) |
|
|
46
46
|
| `baseBranch` | the repo's default branch (`main`/`master`; `git symbolic-ref refs/remotes/origin/HEAD`) |
|
|
47
47
|
| `packageManager` | infer from lockfile: `pnpm-lock.yaml`→pnpm, `package-lock.json`→npm, `yarn.lock`→yarn, `bun.lockb`→bun |
|
|
48
|
-
| `spinnerSelector` | the app
|
|
48
|
+
| `spinnerSelector` | every loading indicator of the app, as one selector list: spinners and skeletons (search for a spinner, `role="status"`, `aria-busy`, a skeleton component, `animate-pulse`), e.g. `.animate-spin, .animate-pulse`. A skeleton left out lets a half-loaded view pass as a good shot |
|
|
49
49
|
|
|
50
50
|
### Preconditions gate
|
|
51
51
|
|
|
@@ -77,6 +77,14 @@ compact report: the screenshot file names + pinned URLs, the PR-body
|
|
|
77
77
|
markdown, and any views it flagged. The main context creates/edits the PR from
|
|
78
78
|
that report — it never reads a PNG.
|
|
79
79
|
|
|
80
|
+
## Where the capture runs
|
|
81
|
+
|
|
82
|
+
- **Local** (the default): steps 3–5 below, on this machine.
|
|
83
|
+
- **Remote**: when the session instructions say so (the agent-ops box does),
|
|
84
|
+
or when this machine cannot start a Playwright browser. A GitHub workflow of
|
|
85
|
+
the target repo captures both sides and pushes the hidden ref; see "Remote
|
|
86
|
+
capture". Steps 1, 2 and 6 stay the same.
|
|
87
|
+
|
|
80
88
|
## Workflow
|
|
81
89
|
|
|
82
90
|
### 1. Map the diff to views, then get the user's go-ahead
|
|
@@ -96,6 +104,10 @@ hidden ref on the remote and embed them in the PR. Include the proposed plan: wh
|
|
|
96
104
|
device projects — default to the config's `deviceProjects`; add more only when
|
|
97
105
|
the change is layout-sensitive. If they decline, create the PR normally and stop.
|
|
98
106
|
|
|
107
|
+
In an unattended session (nobody answers questions, as on the agent-ops box),
|
|
108
|
+
do not ask: run the capture with the plan above and name the plan in the PR
|
|
109
|
+
body.
|
|
110
|
+
|
|
99
111
|
### 2. Write the capture spec
|
|
100
112
|
|
|
101
113
|
Copy `references/capture-spec-template.ts` from this skill into
|
|
@@ -133,7 +145,10 @@ That assertion is a backstop, not a substitute for looking: the subagent still
|
|
|
133
145
|
Reads each PNG after capture — an empty state, error toast, or wrong content
|
|
134
146
|
passes the spinner check but is still wrong. On a genuine failure, fix the spec
|
|
135
147
|
(add mock stubs, a wait for a stable element, or correct the spinner selector)
|
|
136
|
-
rather than shipping a bad screenshot.
|
|
148
|
+
rather than shipping a bad screenshot. A fixed element (a mobile bottom nav, a
|
|
149
|
+
sticky header) is drawn where the viewport was, so in a full-page shot it can
|
|
150
|
+
float over the middle of the page: give such a view `fullPage: false`, or one
|
|
151
|
+
shot per scroll position.
|
|
137
152
|
|
|
138
153
|
### 4. Capture "before" (merge base, temp worktree)
|
|
139
154
|
|
|
@@ -239,6 +254,74 @@ cell instead of an image:
|
|
|
239
254
|
| **Mobile** | _New view_ |  |
|
|
240
255
|
```
|
|
241
256
|
|
|
257
|
+
## Remote capture
|
|
258
|
+
|
|
259
|
+
Replaces steps 3–5. The subagent rule above still holds.
|
|
260
|
+
|
|
261
|
+
The steps run in one shared workflow, `.github/workflows/pr-visual-diff.yml` of
|
|
262
|
+
jesdi/general-skills. Each target repo has a short caller of it, made from
|
|
263
|
+
`references/capture-caller.yml` of this skill, which follows the main branch
|
|
264
|
+
of general-skills: GitHub starts `workflow_dispatch` only in the target repo.
|
|
265
|
+
|
|
266
|
+
**Precondition.** The default branch of the target repo has the caller,
|
|
267
|
+
`.github/workflows/pr-visual-diff.yml`:
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
|
|
271
|
+
gh api "repos/$REPO/contents/.github/workflows/pr-visual-diff.yml" --silent
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
If it does not, take no screenshots. Say in the PR body that the repo has no
|
|
275
|
+
pr-visual-diff workflow, and that `references/capture-caller.yml` of this
|
|
276
|
+
skill, filled from the discovery cache and merged to the default branch, adds
|
|
277
|
+
it. Do not add it in this PR: `workflow_dispatch` runs only from the default
|
|
278
|
+
branch.
|
|
279
|
+
|
|
280
|
+
**Dispatch.** Push the PR branch first: the workflow checks out commits of
|
|
281
|
+
origin. Write the filled spec of step 2 to a file, and a second copy whose
|
|
282
|
+
`VIEWS` holds only the views that exist at the merge base (none: no Before).
|
|
283
|
+
Then:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
HEAD_SHA=$(git rev-parse HEAD)
|
|
287
|
+
BASE=$(git merge-base origin/<baseBranch> HEAD)
|
|
288
|
+
SLUG=$(git branch --show-current | tr / -)
|
|
289
|
+
CAPTURE="${HEAD_SHA:0:12}-$(date +%s)"
|
|
290
|
+
gh workflow run pr-visual-diff.yml --ref <baseBranch> \
|
|
291
|
+
-f capture="$CAPTURE" -f slug="$SLUG" -f head="$HEAD_SHA" -f base="$BASE" \
|
|
292
|
+
-f after_spec="$(base64 < <after-spec> | tr -d '\n')" \
|
|
293
|
+
-f before_spec="$(base64 < <before-spec> | tr -d '\n')" \
|
|
294
|
+
-f projects="<deviceProject>,<deviceProject>"
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Leave `before_spec` empty when every view is new. `gh workflow run` prints no
|
|
298
|
+
run id: find the run by its name `pr-visual-diff $CAPTURE` (try for up to a
|
|
299
|
+
minute), then wait for it:
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
RUN=$(gh run list --workflow pr-visual-diff.yml --limit 20 --json databaseId,displayTitle \
|
|
303
|
+
--jq ".[] | select(.displayTitle == \"pr-visual-diff $CAPTURE\") | .databaseId")
|
|
304
|
+
gh run watch "$RUN" --exit-status
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**A failed run.** Read `gh run view "$RUN" --log-failed | tail -80`. Fix the
|
|
308
|
+
spec as in step 3 (a mock stub, a wait, the spinner selector) and dispatch
|
|
309
|
+
once more with a new `CAPTURE`. When the second run fails too, take no
|
|
310
|
+
screenshots and say why in the PR body.
|
|
311
|
+
|
|
312
|
+
**Read the shots back.** Fetch the hidden ref and look at every PNG, as in
|
|
313
|
+
step 3:
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
git fetch origin "refs/pr-screenshots/$SLUG/$CAPTURE"
|
|
317
|
+
SHA=$(git rev-parse FETCH_HEAD)
|
|
318
|
+
mkdir -p <scratchpad>/shots && git archive "$SHA" | tar -x -C <scratchpad>/shots
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
A wrong shot is a failed run: fix the spec and dispatch again, under the same
|
|
322
|
+
limit. Then embed with step 6, with `$SHA` in the URLs. The ref stays: it keeps
|
|
323
|
+
the images alive.
|
|
324
|
+
|
|
242
325
|
## Adding shots to an existing PR
|
|
243
326
|
|
|
244
327
|
Same flow; the only differences: diff against the PR's base branch
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# pr-visual-diff remote capture of this repo. Template of the pr-visual-diff
|
|
2
|
+
# skill (references/capture-caller.yml): copy it to
|
|
3
|
+
# .github/workflows/pr-visual-diff.yml, replace every __PVD_*__ marker with the
|
|
4
|
+
# value of the discovery cache, and merge it to the default branch:
|
|
5
|
+
# workflow_dispatch runs only from there. The steps live in jesdi/general-skills
|
|
6
|
+
# (.github/workflows/pr-visual-diff.yml) and follow its main branch, like every
|
|
7
|
+
# jesdi skill follows its latest release.
|
|
8
|
+
|
|
9
|
+
name: pr-visual-diff
|
|
10
|
+
run-name: pr-visual-diff ${{ inputs.capture }}
|
|
11
|
+
|
|
12
|
+
on:
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
inputs:
|
|
15
|
+
capture:
|
|
16
|
+
description: 'Unique id of this capture; the last part of the hidden ref'
|
|
17
|
+
required: true
|
|
18
|
+
slug:
|
|
19
|
+
description: 'The PR branch with / as -'
|
|
20
|
+
required: true
|
|
21
|
+
head:
|
|
22
|
+
description: 'Commit captured as After'
|
|
23
|
+
required: true
|
|
24
|
+
base:
|
|
25
|
+
description: 'Commit captured as Before (the merge base)'
|
|
26
|
+
required: true
|
|
27
|
+
after_spec:
|
|
28
|
+
description: 'The filled capture spec, base64'
|
|
29
|
+
required: true
|
|
30
|
+
before_spec:
|
|
31
|
+
description: 'The filled capture spec of the views that exist at base, base64; empty: no Before'
|
|
32
|
+
required: false
|
|
33
|
+
default: ''
|
|
34
|
+
projects:
|
|
35
|
+
description: 'Playwright projects, separated by commas'
|
|
36
|
+
required: true
|
|
37
|
+
|
|
38
|
+
jobs:
|
|
39
|
+
capture:
|
|
40
|
+
permissions:
|
|
41
|
+
contents: write # only its publish job uses it, to push the hidden ref
|
|
42
|
+
uses: jesdi/general-skills/.github/workflows/pr-visual-diff.yml@main
|
|
43
|
+
with:
|
|
44
|
+
capture: ${{ inputs.capture }}
|
|
45
|
+
slug: ${{ inputs.slug }}
|
|
46
|
+
head: ${{ inputs.head }}
|
|
47
|
+
base: ${{ inputs.base }}
|
|
48
|
+
after_spec: ${{ inputs.after_spec }}
|
|
49
|
+
before_spec: ${{ inputs.before_spec }}
|
|
50
|
+
projects: ${{ inputs.projects }}
|
|
51
|
+
runner: __PVD_RUNNER__
|
|
52
|
+
frontend_dir: __PVD_FRONTEND_DIR__
|
|
53
|
+
specs_dir: __PVD_SPECS_DIR__
|
|
54
|
+
browsers: __PVD_BROWSERS__
|
|
55
|
+
node_version: '__PVD_NODE_VERSION__'
|
|
56
|
+
pnpm_version: '__PVD_PNPM_VERSION__'
|
|
@@ -26,7 +26,7 @@ const OUT = process.env.PR_SHOT_DIR;
|
|
|
26
26
|
const LABEL = process.env.PR_SHOT_LABEL ?? 'after';
|
|
27
27
|
if (!OUT) throw new Error('PR_SHOT_DIR must be set to an absolute output directory');
|
|
28
28
|
|
|
29
|
-
//
|
|
29
|
+
// Every loading indicator of this app, spinners and skeletons. From config: <spinnerSelector>.
|
|
30
30
|
const SPINNER = '__PVD_SPINNER_SELECTOR__';
|
|
31
31
|
|
|
32
32
|
// Pin device-pixel-ratio to 1 for every project. Device descriptors (iPhone 14,
|
package/skills-manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-10-15T12:
|
|
3
|
+
"generatedAt": "2026-10-15T12:44:26.687Z",
|
|
4
4
|
"skills": [
|
|
5
5
|
{
|
|
6
6
|
"name": "backlog",
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
54
|
"name": "pr-visual-diff",
|
|
55
|
-
"version": "0.1.
|
|
56
|
-
"hash": "sha256-
|
|
55
|
+
"version": "0.1.2",
|
|
56
|
+
"hash": "sha256-df10fb424564e7721856a88a9bafeeb077041244faa949711ff92d5490fb7854",
|
|
57
57
|
"description": "Capture before/after screenshots of UI views with Playwright and embed them in a PR. Use this skill whenever creating or preparing a pull request that touches frontend code (components, views, styles, layout, Tailwind classes) — even if the user just says \"open a PR\" or \"create the PR\" after UI work, and especially if they mention screenshots, visual diff, before/after, or \"show what changed\". Also use when the user asks to add screenshots to an existing PR."
|
|
58
58
|
},
|
|
59
59
|
{
|