Skip to content

feat: add playwright plugin#65

Merged
kyle-sexton merged 3 commits into
mainfrom
feat/publish-playwright
Jul 11, 2026
Merged

feat: add playwright plugin#65
kyle-sexton merged 3 commits into
mainfrom
feat/publish-playwright

Conversation

@kyle-sexton

@kyle-sexton kyle-sexton commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Publishes the playwright plugin per melodic-software/medley#1295 and docs/MIGRATION-PLAYBOOK.md.

What this ships

One skill, /playwright:playwright — live E2E browser automation via Microsoft's @playwright/cli: named sessions, accessibility-ref snapshots (click/fill by ref), screenshots, console/network capture, mocking, tracing, video, auth state. Disk-first artifacts keep large snapshots out of context.

  • Hub SKILL.md + 10 distilled reference/*.md topic files (progressive disclosure)
  • Original overlays: Windows/Git Bash quirks (+ a force-chrome-foreground.ps1 helper), locally-orchestrated-stack recipe (Aspire / docker-compose / tilt) with Blazor gotchas
  • Vendored upstream baseline (vendor/, verbatim from the npm package, markdownlint disabled via nested config) + maintainer-facing scripts/update.sh (--check/--apply, npm-pack based, never mutates global state) with network-free contract tests (update.test.sh, 22 checks)
  • Marketplace entry: category: testing, tags include tooling; explicit version: 0.1.0 in plugin.json only

De-coupling from the source repo

All medley references removed: repo-scoped conventions generalized, the Aspire-specific recipe rewritten orchestrator-neutral, medley skill/rule/schedule cross-references replaced with graceful-degradation prose, script re-anchored to its own directory and rewritten from a transient .claude/skills/ install flow to npm pack into a temp dir (removes the stray-skill-dir failure class).

Gate evidence

  • claude plugin validate plugins/playwright — PASS; claude plugin validate --strict . (catalog) — PASS; scripts/validate-plugins.sh — PASS
  • claude plugin details playwrightalways-on ~245 tok, on-invoke ~2.6k
  • --plugin-dir smoke test in a clean non-medley repo: plugin skill listed as playwright:playwright; invoking /playwright:playwright loaded the skill and returned quick-start guidance
  • update.test.sh 22/22 PASS; shellcheck + shfmt clean; markdownlint 0 errors (25 files)

Security review (playbook acceptance)

  • No hooks, no MCP servers, no telemetry, no userConfig, no data egress on normal invocation
  • Scripts: update.sh is maintainer-facing, runs only npm view/npm pack (npm registry reads) and writes only inside the plugin dir + a temp dir; force-chrome-foreground.ps1 is local Win32 focus P/Invoke, no-op off Windows
  • vendor/ is third-party (Microsoft, MIT) and documented as untrusted data — the skill instructs never to follow instructions embedded in it

Note: upstream is at 0.1.17; the vendored baseline ships at 0.1.13 as harvested. Syncing is a follow-up maintainer update --apply + version bump, deliberately out of scope here.


Note

Low Risk
Additive documentation and skill content with no hooks or MCP; maintainer update script only touches npm metadata/tarballs and the plugin tree, while normal invocation is limited to playwright-cli Bash.

Overview
Adds a new playwright marketplace plugin so Claude can drive live E2E flows through Microsoft's @playwright/cli (/playwright:playwright), with disk-first snapshots/screenshots to keep context small.

The plugin ships a hub SKILL.md (quick start, conventions, progressive disclosure), 10 distilled reference/*.md topics, and original overlays for Windows/Git Bash quirks (plus force-chrome-foreground.ps1) and locally orchestrated stacks (Aspire, docker-compose, tilt, Blazor notes). A verbatim vendor/ baseline from the npm skill supports maintainer update --check / update --apply via scripts/update.sh (npm registry only, writes inside the plugin + temp dir) and update.test.sh contract tests.

marketplace.json and the root README catalog gain the new entry (category: testing, plugin.json v0.1.0). Normal use is scoped to Bash(playwright-cli:*); vendor/ is documented as untrusted data for drift sync only.

Reviewed by Cursor Bugbot for commit 435ba64. Bugbot is set up for automated code reviews on this repo. Configure here.

@cursor

cursor Bot commented Jul 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_893a4d8f-8ba1-45e9-837f-9cb93314470f)

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Risk: medium. Cursor Bugbot did not complete successfully (check skipped — usage limit reached), so I am not approving. Human review is needed before merge; no reviewers were assigned because the only human repository contributor is the PR author.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e6c66a23b6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/playwright/README.md Outdated
Ports the playwright skill from melodic-software/medley#1295 per the
migration playbook: repo-agnostic body, bundled reference files, vendored
upstream baseline, and a maintainer-facing npm-based drift-check update
script with network-free contract tests.

Closes melodic-software/medley#1295 (tracked there).
@kyle-sexton
kyle-sexton force-pushed the feat/publish-playwright branch from e6c66a2 to b378826 Compare July 11, 2026 13:02
@cursor

cursor Bot commented Jul 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_85dcd934-6304-446e-8cd6-cacd231f2c76)

@claude

claude Bot commented Jul 11, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 3m 16s —— View job


PR Review — feat: add playwright plugin

  • Gather context (PR diff, CLAUDE.md, changed files)
  • Review plugin structure and manifest
  • Review skill content and documentation
  • Review scripts and vendor files
  • Check security posture
  • Check license/attribution
  • Post findings

Overall this is a well-structured, thoughtful plugin that follows the marketplace design rules. Security posture is clean (no hooks, no MCP, no telemetry, no egress), the update workflow is maintainer-safe, and the progressive disclosure architecture is a genuine improvement over the upstream monolith. Four issues to address before merge, one of which is meaningful from a security/behavior standpoint.


Findings

1. Distilled SKILL.md is missing allowed-tools — more permissive than upstream

File: plugins/playwright/skills/playwright/SKILL.md

The upstream vendor skill explicitly gates execution to Bash(playwright-cli:*), Bash(npx:*), and Bash(npm:*):

# vendor/SKILL.md (line 4)
allowed-tools: Bash(playwright-cli:*) Bash(npx:*) Bash(npm:*)

The distilled SKILL.md has no allowed-tools field. When invoked, Claude is therefore unconstrained to any Bash command, unlike the upstream skill it wraps. For a browser automation skill the primary action should be playwright-cli calls — leaving the full Bash surface open widens the blast radius if the skill is misused or the page under test attempts prompt injection.

Suggestion: Add allowed-tools to the frontmatter, at minimum matching upstream, and extending it only for the update action (which legitimately needs npm view/npm pack):

allowed-tools: Bash(playwright-cli:*) Bash(npm:*) Bash(tar:*) Bash(diff:*)

Fix this →


2. Version mismatch in commands.md attribution line

File: plugins/playwright/skills/playwright/reference/commands.md:3

Distilled from upstream `@playwright/cli@0.1.8` SKILL.md.

The SKILL.md frontmatter records upstream-version: 0.1.13 — the version at which the vendor baseline was harvested. 0.1.8 is stale. Maintainers diffing the vendor tree after an --apply will be confused about which upstream version the distilled reference actually reflects.

Suggestion: Update this line to @playwright/cli@0.1.13 to match the frontmatter.

Fix this →


3. Repo-specific language in storage-and-auth.md

File: plugins/playwright/skills/playwright/reference/storage-and-auth.md:18

For this repo's E2E fixtures, prefer test accounts with rotatable tokens.

"This repo" is medley-specific language. Installed in any consumer's project it becomes confusing or outright wrong. The CLAUDE.md design rule is explicit: no hardcoded repo-specific values.

Suggestion: Replace with: For your project's E2E fixtures, prefer test accounts with rotatable tokens.

Fix this →


4. No upstream LICENSE file bundled with vendor/

File: plugins/playwright/skills/playwright/vendor/

The vendor directory redistributes Microsoft's @playwright/cli@0.1.13 skill content (MIT) but does not include the upstream MIT LICENSE or NOTICE file. The README.md acknowledges the upstream license in prose, but best practice for redistributed third-party content is to include the original license alongside the files. This is also what the Codex reviewer flagged (their Apache-2.0 claim is incorrect — @playwright/cli is MIT, not Apache-2.0, and the README is right on this — but the absence of the file is still a gap).

Suggestion: When running update --apply for the initial or next sync, confirm whether the npm tarball bundles a LICENSE file alongside the skill directory and, if so, preserve it in vendor/. The .markdownlint-cli2.jsonc is already preserved across replace cycles — apply the same treatment to LICENSE if present.


Notes (no action required)

  • Codex's Apache-2.0 claim is a false positive. @playwright/cli is MIT-licensed. The README is correct.
  • run_apply non-atomicity: rm -rf vendor/ then copy is interruptible. If the script is killed mid-way, vendor/ is empty — recoverable by re-running --apply. Acceptable for a maintainer-only tool.
  • replace_metadata_field temp file: uses mv "$tmp" "$FRONTMATTER_FILE". On Linux, mv falls back to copy+delete across filesystem boundaries, so this works but is worth knowing.
  • The test suite (22 checks) is solid — covers help contract, arg handling, frontmatter parsing, key anchoring, mutation, and live file contracts.
  • Progressive disclosure map is a genuine UX improvement over the upstream monolith — the always-on token footprint (~245 tok) vs on-demand reference loading is well-calibrated.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Risk: medium. Cursor Bugbot did not complete successfully (check skipped — usage limit reached), so I am not approving. Human review is needed before merge; no reviewers were assigned because the only human repository contributor is the PR author.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b3788267d7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/playwright/skills/playwright/reference/test-generation.md Outdated
- Correct the upstream license: @playwright/cli is Apache-2.0 (verified via
  npm registry metadata and the package's bundled LICENSE), not MIT as the
  harvested source claimed; ship vendor/LICENSE (from the 0.1.13 tarball),
  refresh it on update --apply, set plugin.json license to MIT AND Apache-2.0
- Fix stale upstream version stamp in reference/commands.md (0.1.8 -> 0.1.13)
- Remove leftover repo-specific phrasing in reference/storage-and-auth.md
- Grant allowed-tools: Bash(playwright-cli:*) — pre-approves the skill's
  primary command; npm deliberately not pre-approved (maintainer-only update
  flow, deny-by-default posture)
@cursor

cursor Bot commented Jul 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_0bfbf860-47ec-46f0-86dd-247467d2f62d)

@claude

claude Bot commented Jul 11, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 25s —— View job


PR Review — feat: add playwright plugin

  • Gather context — checked what changed since the previous review
  • Re-examine files mentioned in prior findings
  • Review the fix commit (9d489cb)
  • Post updated findings

The fix commit (9d489cb) squarely addresses all four findings from the initial review. Overall posture is solid — this is close to merge-ready with one remaining issue to resolve.


Prior findings — status after fix commit

1. Missing allowed-tools — ✅ Fixed

SKILL.md:8 now has:

allowed-tools: Bash(playwright-cli:*)

The deliberate exclusion of npm from pre-approval is the right call: npm is only needed in the maintainer-only update flow, so deny-by-default for it is the correct posture. This is actually more conservative than my initial suggestion.

2. Version mismatch in commands.md — ✅ Fixed

reference/commands.md:3 now reads @playwright/cli@0.1.13.

3. Repo-specific language — ✅ Fixed

reference/storage-and-auth.md:18 now reads "For your project's E2E fixtures…".

4. Missing vendor/LICENSE — ✅ Fixed (with a license correction)

vendor/LICENSE is now included. The fix also correctly identified that the upstream license is Apache-2.0 (not MIT as originally attributed), updated plugin.json to "license": "MIT AND Apache-2.0", and updated the update.sh --apply path to refresh the LICENSE file on each vendor sync. This is the right way to handle redistributed content.


Remaining issue

--raw flag misused in test-generation.md — breaks captured output

File: plugins/playwright/skills/playwright/reference/test-generation.md

The vendor SKILL.md explicitly documents (line 182):

The global --raw option strips page status, generated code, and snapshot sections from the output, returning only the result value.

The distilled reference recommends using --raw with open/click to capture generated TypeScript:

# test-generation.md, lines 68-76
playwright-cli --raw open https://example.com > capture.log
playwright-cli --raw click e3 >> capture.log

But since --raw strips the "generated code" sections, capture.log would be empty or near-empty after these commands. The workflow step 3 on line 42 ("Collect the emitted code — pipe to a file with --raw") is similarly incorrect.

The upstream vendor reference (vendor/references/test-generation.md) shows --raw used only for generate-locator, eval, and snapshot — commands that return discrete values — not for open/click/fill. The correct workflow for collecting generated code is to copy it from terminal output.

Suggested fix: Remove the "Capture raw code with --raw" subsection (lines 66-76), update step 3 to say "Copy the generated code from terminal output" and optionally mention tee for logging:

# Log full session output (including generated code sections):
playwright-cli open https://example.com 2>&1 | tee session.log
playwright-cli click e3 2>&1 | tee -a session.log

Or simply drop the capture-to-file guidance entirely and leave step 3 as "Copy the generated code from terminal output."

Fix this →


Notes (no action required)

  • update.sh LICENSE handling is correct: The --apply path explicitly copies ${TMPDIR_RUN}/package/LICENSE into vendor/LICENSE and errors if absent — so future vendor syncs won't silently drop the license.
  • The Codex --raw finding stands. It was filed against the original commit and is still open. The finding that @playwright/cli is Apache-2.0 (not MIT) was a false positive on the license label — the fix commit corrected this.

@kyle-sexton

Copy link
Copy Markdown
Contributor Author

Review findings addressed in 9d489cb:

  • Codex P2 (upstream license) — CONFIRMED and fixed. @playwright/cli is Apache-2.0 (verified via npm view @playwright/cli license and the LICENSE + package.json inside both the 0.1.13 and 0.1.17 tarballs). The harvested source's MIT claim was wrong, and the Claude review's "false positive" note on this point was itself incorrect. vendor/LICENSE now ships the upstream Apache-2.0 text (0.1.13, matching the vendored baseline), update.sh --apply refreshes it from the package root, attribution prose is corrected, and plugin.json declares MIT AND Apache-2.0.
  • Claude fix: correct plugin-system inaccuracies and harden references #2 (stale @0.1.8 stamp) — fixed to 0.1.13.
  • Claude feat: markdown-formatter plugin (pilot migration) #3 ("this repo" phrasing) — fixed.
  • Claude chore: initialize marketplace scaffold #1 (allowed-tools) — partially adopted. Added allowed-tools: Bash(playwright-cli:*). Note the premise is off per the official skills doc: allowed-tools pre-approves the listed tools, it does not restrict the rest. Granting it still improves UX for the skill's primary command. npm is deliberately NOT pre-approved — it's only needed by the maintainer-facing update flow, and silently pre-approving npm (including installs) widens the trust surface for every consumer session.
  • Claude ci: onboard to the CI platform (ci-workflows + standards) #4 (bundle upstream LICENSE) — done as part of the license fix above.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Risk: medium. Cursor Bugbot did not complete successfully (check skipped — usage limit reached), so I am not approving. Human review is needed before merge; no reviewers were assigned because the only human repository contributor is the PR author.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

Upstream documents --raw as stripping page status, generated code, and
snapshots — the opposite of what the capture workflow needed. Redirect
normal stdout instead (Codex review finding, verified against
vendor/SKILL.md "Raw output").
@cursor

cursor Bot commented Jul 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_846c1321-b203-403c-84d2-1c497d200ed8)

@claude

claude Bot commented Jul 11, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 57s —— View job


PR Review — feat: add playwright plugin

  • Gather context — checked latest commit (435ba64)
  • Verify the --raw fix in test-generation.md
  • Review overall PR state
  • Post findings

Fix verification — 435ba64

This commit addresses the last remaining finding from the prior review round: the --raw flag being incorrectly recommended for capturing generated TypeScript code.

Before (9d489cb):

  • Workflow step 3: "Collect the emitted code — pipe to a file with --raw, or just copy from the terminal"
  • A "Capture raw code with --raw" section showed playwright-cli --raw open / playwright-cli --raw click, which would produce empty output

After (435ba64):

# Step 3 (line 42):
3. **Collect the emitted code** — copy the `### Ran Playwright code` blocks from the output (do NOT use `--raw`, which strips them)
# Capture section now uses correct stdout redirect:
playwright-cli open https://example.com | tee -a capture.log
playwright-cli click e3 | tee -a capture.log
# ... then pull the code lines out of the "### Ran Playwright code" blocks

The fix is accurate. The vendor SKILL.md (line 182) documents exactly this: "The global --raw option strips page status, generated code, and snapshot sections from the output, returning only the result value." The corrected section now correctly uses | tee -a for normal stdout capture and explicitly warns against --raw.


All findings resolved ✅

# Finding Status
1 Missing allowed-tools in distilled SKILL.md ✅ Fixed (9d489cb)
2 Stale @0.1.8 version stamp in commands.md ✅ Fixed (9d489cb)
3 Repo-specific language ("this repo") in storage-and-auth.md ✅ Fixed (9d489cb)
4 Missing vendor/LICENSE for redistributed Apache-2.0 content ✅ Fixed (9d489cb)
5 --raw misused for code capture in test-generation.md ✅ Fixed (435ba64)

This PR is merge-ready. The plugin follows the marketplace design rules (repo-agnostic, versioned, no hooks/MCP/egress, security-reviewed), license attribution is correct (MIT AND Apache-2.0), and all review findings across all rounds have been addressed.


@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Risk: medium. Cursor Bugbot did not complete successfully (check skipped — usage limit reached), so I am not approving. Human review is needed before merge; no reviewers were assigned because the only human repository contributor is the PR author.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@kyle-sexton
kyle-sexton merged commit eeef1d9 into main Jul 11, 2026
22 checks passed
@kyle-sexton
kyle-sexton deleted the feat/publish-playwright branch July 11, 2026 13:26

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 435ba642e5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

[[ -f "$lint_override" ]] && cp "$lint_override" "$lint_backup"
rm -rf "$VENDOR_DIR"
mkdir -p "$VENDOR_DIR"
cp -r "$upstream_dir"/. "$VENDOR_DIR"/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Stop apply when vendor copy fails

When --apply runs on a checkout where vendor/ cannot be populated completely (for example disk full, permission errors, or an interrupted copy), this cp failure is ignored because the script intentionally does not use set -e; execution then continues to copy the license, bump metadata.upstream-version/synced, and return success. That can leave maintainers with an empty or partial vendored baseline that is marked as synced, so guard these mutating steps with explicit error checks before updating frontmatter.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant