openspec-playwright 0.1.27 → 0.1.29

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.
@@ -7,12 +7,33 @@ compatibility: Requires openspec CLI, Playwright (with browsers installed), and
7
7
  **Architecture**: Uses CLI + SKILLs (not `init-agents`). This follows Playwright's recommended approach for coding agents — CLI is more token-efficient than loading MCP tool schemas into context. MCP is used only for Healer (UI inspection on failure).
8
8
  metadata:
9
9
  author: openspec-playwright
10
- version: "2.2"
10
+ version: "2.4"
11
11
  ---
12
12
 
13
- Run Playwright E2E verification for an OpenSpec change. This skill reads specs from `openspec/changes/<name>/specs/`, generates test files, detects auth requirements, and delegates test execution to the `openspec-pw run` CLI.
13
+ ## Input
14
14
 
15
- **Architecture**: Schema owns templates. CLI handles execution. Skill handles cognitive work.
15
+ - **Change name**: `/opsx:e2e <name>` or auto-detected from context
16
+ - **Specs**: `openspec/changes/<name>/specs/*.md`
17
+ - **Credentials**: `E2E_USERNAME` + `E2E_PASSWORD` env vars
18
+
19
+ ## Output
20
+
21
+ - **Test file**: `tests/playwright/<name>.spec.ts`
22
+ - **Auth setup**: `tests/playwright/auth.setup.ts` (if auth required)
23
+ - **Report**: `openspec/reports/playwright-e2e-<name>-<timestamp>.md`
24
+ - **Test plan**: `openspec/changes/<name>/specs/playwright/test-plan.md`
25
+
26
+ ## Architecture
27
+
28
+ This skill implements the Playwright Test Agents pipeline:
29
+
30
+ - **🎭 Planner** (Step 4): Consumes OpenSpec specs (`specs/*.md`) and produces `test-plan.md` — combines OpenSpec's structured requirements with LLM编排.
31
+ - **🎭 Generator** (Step 5): Transforms the Markdown test-plan into real Playwright `.spec.ts` files using LLM code generation.
32
+ - **🎭 Healer** (Step 8): Executes the test suite and automatically repairs failing selectors via Playwright MCP tools.
33
+
34
+ Uses CLI + SKILLs (not `init-agents`). This follows Playwright's recommended approach for coding agents — CLI is more token-efficient than loading MCP tool schemas into context. MCP is used only for Healer (UI inspection on failure).
35
+
36
+ **Schema owns templates. CLI handles execution. Skill handles cognitive work.**
16
37
 
17
38
  ## Steps
18
39
 
@@ -48,7 +69,24 @@ Detect if auth is required. Mark as **auth required** only when BOTH conditions
48
69
  - Medium (proceed with note): Single explicit marker, context unclear
49
70
  - Low (skip auth): No explicit markers found
50
71
 
51
- ### 3. Generate test plan
72
+ ### 3. Validate environment
73
+
74
+ Before generating tests, verify the environment is ready by running the seed test:
75
+
76
+ ```bash
77
+ npx playwright test tests/playwright/seed.spec.ts --project=chromium
78
+ ```
79
+
80
+ **What this validates**:
81
+ - App server is reachable (BASE_URL accessible)
82
+ - Auth fixtures (`storageState`) are initialized if auth is required
83
+ - Playwright browser and config are working
84
+
85
+ **If seed test fails**: Stop and report the failure. User must fix the environment before proceeding.
86
+
87
+ **If seed test passes or no auth required**: Proceed to Step 4.
88
+
89
+ ### 4. Generate test plan
52
90
 
53
91
  Create `openspec/changes/<name>/specs/playwright/test-plan.md` by:
54
92
  - Listing each functional requirement as a test case
@@ -58,7 +96,7 @@ Create `openspec/changes/<name>/specs/playwright/test-plan.md` by:
58
96
 
59
97
  **Idempotency**: If test-plan.md already exists → read it, use it, do NOT regenerate unless user explicitly asks.
60
98
 
61
- ### 4. Generate test file (LLM-driven)
99
+ ### 5. Generate test file (LLM-driven)
62
100
 
63
101
  Use your file writing capability to create `tests/playwright/<name>.spec.ts`.
64
102
 
@@ -100,7 +138,7 @@ test.describe('Feature Name', () => {
100
138
 
101
139
  **Selector guidance**: If no `data-testid` exists in the app, prefer `getByRole`, `getByLabel`, `getByText` over fragile selectors like CSS paths.
102
140
 
103
- ### 5. Configure auth (if required)
141
+ ### 6. Configure auth (if required)
104
142
 
105
143
  If auth is required:
106
144
 
@@ -122,7 +160,7 @@ Auth required. To set up credentials:
122
160
 
123
161
  **Idempotency**: If `auth.setup.ts` already exists → verify format, update only if stale.
124
162
 
125
- ### 6. Configure playwright.config.ts (non-destructive)
163
+ ### 7. Configure playwright.config.ts (non-destructive)
126
164
 
127
165
  If `playwright.config.ts` does not exist → generate it from the schema template at `openspec/schemas/playwright-e2e/templates/playwright.config.ts`. The template auto-detects:
128
166
  - **BASE_URL**: from `process.env.BASE_URL`, falling back to `tests/playwright/seed.spec.ts` → `BASE_URL` value, then `http://localhost:3000`
@@ -130,7 +168,7 @@ If `playwright.config.ts` does not exist → generate it from the schema templat
130
168
 
131
169
  If `playwright.config.ts` exists → READ it first. Extract existing `webServer`, `use.baseURL`, and `projects`. Preserve ALL existing fields. Add `webServer` block if missing. Do NOT replace existing config values.
132
170
 
133
- ### 7. Execute tests via CLI
171
+ ### 8. Execute tests via CLI
134
172
 
135
173
  ```bash
136
174
  openspec-pw run <name> --project=<role>
@@ -145,19 +183,20 @@ The CLI handles:
145
183
  If tests fail → analyze failures, use **Playwright MCP tools** to inspect UI state, fix selectors in the test file, and re-run.
146
184
 
147
185
  **Healer MCP tools** (in order of use):
186
+ <!-- MCP_VERSION: 0.0.68 -->
148
187
 
149
188
  | Tool | Purpose |
150
189
  |------|---------|
151
- | `Navigate to a URL` | Go to the failing test's page |
152
- | `Page snapshot` | Get page structure to find equivalent selectors |
153
- | `Get console messages` | Diagnose JS errors that may cause failures |
154
- | `Take a screenshot` | Visually compare before/after fixes |
155
- | `Run Playwright code` | Execute custom fix logic (optional) |
190
+ | `browser_navigate` | Go to the failing test's page |
191
+ | `browser_snapshot` | Get page structure to find equivalent selectors |
192
+ | `browser_console_messages` | Diagnose JS errors that may cause failures |
193
+ | `browser_take_screenshot` | Visually compare before/after fixes |
194
+ | `browser_run_code` | Execute custom fix logic (optional) |
156
195
 
157
196
  **Healer workflow**:
158
197
  1. Read the failing test file — identify the broken selector or assertion
159
- 2. Navigate to the target page with `Navigate to a URL`
160
- 3. Take a `Page snapshot` — find an equivalent stable selector
198
+ 2. Navigate to the target page with `browser_navigate`
199
+ 3. Take a `browser_snapshot` — find an equivalent stable selector
161
200
  4. Fix the selector in the test file using the Edit tool
162
201
  5. Re-run: `openspec-pw run <name>`
163
202
  6. Repeat until pass or 3 attempts reached
@@ -166,7 +205,7 @@ If tests fail → analyze failures, use **Playwright MCP tools** to inspect UI s
166
205
 
167
206
  **Cap auto-heal attempts at 3** to prevent infinite loops.
168
207
 
169
- ### 8. Report results
208
+ ### 9. Report results
170
209
 
171
210
  Read the report at `openspec/reports/playwright-e2e-<name>-<timestamp>.md`.
172
211
 
@@ -181,9 +220,55 @@ Read the report at `openspec/reports/playwright-e2e-<name>-<timestamp>.md`.
181
220
  - Append a verification note: e.g. `✅ Verified via Playwright E2E (<timestamp>)`
182
221
  - Write the updated content back using the Edit tool
183
222
 
184
- **If tests fail**: Suggest which spec items remain unverified and what needs fixing.
223
+ ## Output Format
185
224
 
186
- ---
225
+ ### Report Structure (`openspec/reports/playwright-e2e-<name>-<timestamp>.md`)
226
+
227
+ ```
228
+ # Playwright E2E Report — <name>
229
+
230
+ ## Summary
231
+ | Tests | Passed | Failed | Duration | Status |
232
+ |-------|--------|--------|----------|--------|
233
+ | N | N | N | Xm Xs | ✅/❌ |
234
+
235
+ ## Results
236
+
237
+ ### Passed
238
+ | Test | Duration | Notes |
239
+ |------|----------|-------|
240
+ | ... | ... | ... |
241
+
242
+ ### Failed
243
+ | Test | Error | Recommendation |
244
+ |------|-------|----------------|
245
+ | ... | ... | file:line — fix |
246
+
247
+ ## Auto-Heal Log
248
+ - Attempt N: selector fix → result
249
+
250
+ ## Coverage
251
+ - [x] Requirement 1
252
+ - [ ] Requirement 2 (unverified)
253
+ ```
254
+
255
+ ### Updated tasks.md
256
+ ```
257
+ - [x] Implement feature X ✅ Verified via Playwright E2E (2026-03-28)
258
+ ```
259
+
260
+ ## Graceful Degradation
261
+
262
+ | Scenario | Behavior |
263
+ |----------|----------|
264
+ | No specs found | Stop with info message — E2E requires specs |
265
+ | Seed test fails | Stop with failure — fix environment before proceeding |
266
+ | No auth required | Skip auth setup entirely |
267
+ | test-plan.md exists | Read and use it — never regenerate |
268
+ | auth.setup.ts exists | Verify format — update only if stale |
269
+ | playwright.config.ts exists | Read and preserve all fields — add only missing |
270
+ | Test fails (selector) | Healer: snapshot → fix → re-run, cap at 3 attempts |
271
+ | Test fails (app bug) | Report as failed with recommendation |
187
272
 
188
273
  ## Verification Heuristics
189
274
 
@@ -3,6 +3,7 @@ import { existsSync, readFileSync, writeFileSync, mkdirSync, } from 'fs';
3
3
  import { join } from 'path';
4
4
  import chalk from 'chalk';
5
5
  import { readFile } from 'fs/promises';
6
+ import { syncMcpTools } from './mcpSync.js';
6
7
  const TEMPLATE_DIR = new URL('../../templates', import.meta.url).pathname;
7
8
  const SCHEMA_DIR = new URL('../../schemas', import.meta.url).pathname;
8
9
  const SKILL_SRC = new URL('../../.claude/skills/openspec-e2e', import.meta.url).pathname;
@@ -61,15 +62,19 @@ export async function init(options) {
61
62
  // 4. Copy skill files
62
63
  console.log(chalk.blue('\n─── Installing Claude Code Skill ───'));
63
64
  await installSkill(projectRoot);
64
- // 5. Install OpenSpec schema
65
+ // 5. Sync Healer tools with latest @playwright/mcp
66
+ console.log(chalk.blue('\n─── Syncing Healer Tools ───'));
67
+ const skillDest = join(projectRoot, '.claude', 'skills', 'openspec-e2e', 'SKILL.md');
68
+ await syncMcpTools(skillDest, true);
69
+ // 6. Install OpenSpec schema
65
70
  console.log(chalk.blue('\n─── Installing OpenSpec Schema ───'));
66
71
  await installSchema(projectRoot);
67
- // 6. Generate seed test
72
+ // 7. Generate seed test
68
73
  if (options.seed !== false) {
69
74
  console.log(chalk.blue('\n─── Generating Seed Test ───'));
70
75
  await generateSeedTest(projectRoot);
71
76
  }
72
- // 7. Summary
77
+ // 8. Summary
73
78
  console.log(chalk.blue('\n─── Summary ───'));
74
79
  console.log(chalk.green(' ✓ Setup complete!\n'));
75
80
  console.log(chalk.bold('Next steps:'));
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ export declare const MCP_VERSION_MARKER = "<!-- MCP_VERSION:";
2
+ export declare const DEFAULT_HEALER_TOOLS: {
3
+ name: string;
4
+ purpose: string;
5
+ }[];
6
+ /** Extract MCP version from SKILL.md marker */
7
+ export declare function getStoredMcpVersion(skillContent: string): string | null;
8
+ /** Replace the Healer tools table in SKILL.md */
9
+ export declare function updateHealerTable(skillContent: string, version: string, tools: Array<{
10
+ name: string;
11
+ purpose: string;
12
+ }>): string;
13
+ /** Fetch latest @playwright/mcp version from npm registry */
14
+ export declare function getLatestMcpVersion(): Promise<string | null>;
15
+ /**
16
+ * Fetch @playwright/mcp tools from npm package.
17
+ * Downloads the tarball, extracts README, parses tool names.
18
+ */
19
+ export declare function fetchMcpTools(version: string): Promise<Array<{
20
+ name: string;
21
+ purpose: string;
22
+ }>>;
23
+ /**
24
+ * Sync Healer tools table in SKILL.md with latest @playwright/mcp.
25
+ * Returns true if updated, false if already current or failed.
26
+ */
27
+ export declare function syncMcpTools(skillDest: string, verbose?: boolean): Promise<boolean>;
@@ -0,0 +1,124 @@
1
+ import { exec } from 'child_process';
2
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
3
+ import chalk from 'chalk';
4
+ export const MCP_VERSION_MARKER = '<!-- MCP_VERSION:';
5
+ export const DEFAULT_HEALER_TOOLS = [
6
+ { name: 'browser_navigate', purpose: "Go to the failing test's page" },
7
+ { name: 'browser_snapshot', purpose: 'Get page structure to find equivalent selectors' },
8
+ { name: 'browser_console_messages', purpose: 'Diagnose JS errors that may cause failures' },
9
+ { name: 'browser_take_screenshot', purpose: 'Visually compare before/after fixes' },
10
+ { name: 'browser_run_code', purpose: 'Execute custom fix logic (optional)' },
11
+ ];
12
+ /** Extract MCP version from SKILL.md marker */
13
+ export function getStoredMcpVersion(skillContent) {
14
+ const idx = skillContent.indexOf(MCP_VERSION_MARKER);
15
+ if (idx === -1)
16
+ return null;
17
+ const end = skillContent.indexOf(' -->', idx);
18
+ return skillContent.slice(idx + MCP_VERSION_MARKER.length, end).trim();
19
+ }
20
+ /** Build the Healer tools table markdown */
21
+ function buildHealerTable(version, tools) {
22
+ const rows = tools.map(t => `| \`${t.name}\` | ${t.purpose} |`).join('\n');
23
+ return `${MCP_VERSION_MARKER} ${version} -->\n\n| Tool | Purpose |\n|------|---------|\n${rows}`;
24
+ }
25
+ /** Replace the Healer tools table in SKILL.md */
26
+ export function updateHealerTable(skillContent, version, tools) {
27
+ const start = skillContent.indexOf('| Tool | Purpose |');
28
+ if (start === -1)
29
+ return skillContent;
30
+ let end = skillContent.indexOf('\n\n', start);
31
+ if (end === -1)
32
+ end = skillContent.length;
33
+ const before = skillContent.slice(0, start);
34
+ const after = skillContent.slice(end);
35
+ return before + buildHealerTable(version, tools) + after;
36
+ }
37
+ /** Fetch latest @playwright/mcp version from npm registry */
38
+ export function getLatestMcpVersion() {
39
+ return new Promise((resolve) => {
40
+ exec('npm show @playwright/mcp version --json', { timeout: 15000 }, (err, stdout) => {
41
+ if (err) {
42
+ resolve(null);
43
+ return;
44
+ }
45
+ try {
46
+ resolve(JSON.parse(stdout.trim()));
47
+ }
48
+ catch {
49
+ resolve(null);
50
+ }
51
+ });
52
+ });
53
+ }
54
+ /** Parse README markdown to extract browser_* tool entries */
55
+ function parseMcpReadme(content) {
56
+ const tools = [];
57
+ const re = /-\s+\*\*`?([^`*\n]+)`?\*\*\s*-\s*Title:\s*([^\n]+)/g;
58
+ let m;
59
+ while ((m = re.exec(content)) !== null) {
60
+ const name = m[1].trim();
61
+ if (name.startsWith('browser_')) {
62
+ const purpose = m[2].trim().replace(/\.$/, '');
63
+ tools.push({ name, purpose });
64
+ }
65
+ }
66
+ return tools;
67
+ }
68
+ /**
69
+ * Fetch @playwright/mcp tools from npm package.
70
+ * Downloads the tarball, extracts README, parses tool names.
71
+ */
72
+ export function fetchMcpTools(version) {
73
+ return new Promise((resolve) => {
74
+ const tmpDir = `/tmp/openspec-pw-mcp-${version}`;
75
+ exec(`rm -rf ${tmpDir} && mkdir -p ${tmpDir} && npm pack @playwright/mcp@${version} --pack-destination ${tmpDir} 2>/dev/null && tar -xzf ${tmpDir}/playwright-mcp-${version}.tgz -C ${tmpDir} --strip-components=1 && cat ${tmpDir}/package/README.md`, { timeout: 30000 }, (err, stdout) => {
76
+ if (err) {
77
+ resolve([]);
78
+ return;
79
+ }
80
+ const tools = parseMcpReadme(stdout);
81
+ resolve(tools);
82
+ });
83
+ });
84
+ }
85
+ /**
86
+ * Sync Healer tools table in SKILL.md with latest @playwright/mcp.
87
+ * Returns true if updated, false if already current or failed.
88
+ */
89
+ export async function syncMcpTools(skillDest, verbose = false) {
90
+ const latestVersion = await getLatestMcpVersion();
91
+ if (!latestVersion) {
92
+ if (verbose)
93
+ console.log(chalk.yellow(' ⚠ Could not fetch latest @playwright/mcp version'));
94
+ return false;
95
+ }
96
+ if (!existsSync(skillDest)) {
97
+ if (verbose)
98
+ console.log(chalk.gray(' - SKILL.md not found, skipping MCP sync'));
99
+ return false;
100
+ }
101
+ const skillContent = readFileSync(skillDest, 'utf-8');
102
+ const storedVersion = getStoredMcpVersion(skillContent);
103
+ if (storedVersion === latestVersion) {
104
+ if (verbose)
105
+ console.log(chalk.gray(` - Healer tools current (${latestVersion})`));
106
+ return false;
107
+ }
108
+ if (verbose)
109
+ console.log(chalk.blue(` - Updating from ${storedVersion ?? 'unknown'} → ${latestVersion}`));
110
+ const tools = await fetchMcpTools(latestVersion);
111
+ const toolSet = tools.length > 0 ? tools : DEFAULT_HEALER_TOOLS;
112
+ const updated = updateHealerTable(skillContent, latestVersion, toolSet);
113
+ writeFileSync(skillDest, updated);
114
+ if (verbose) {
115
+ if (tools.length > 0) {
116
+ console.log(chalk.green(` ✓ Healer tools synced to ${latestVersion} (${tools.length} tools)`));
117
+ }
118
+ else {
119
+ console.log(chalk.green(` ✓ Healer tools synced to ${latestVersion} (default set)`));
120
+ }
121
+ }
122
+ return true;
123
+ }
124
+ //# sourceMappingURL=mcpSync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpSync.js","sourceRoot":"","sources":["../../src/commands/mcpSync.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import { execSync } from 'child_process';
2
2
  import { existsSync, readFileSync, writeFileSync, mkdirSync, } from 'fs';
3
3
  import { join } from 'path';
4
4
  import chalk from 'chalk';
5
+ import { syncMcpTools } from './mcpSync.js';
5
6
  const SKILL_SRC = new URL('../../.claude/skills/openspec-e2e', import.meta.url).pathname;
6
7
  const CMD_SRC = new URL('../../.claude/commands/opsx', import.meta.url).pathname;
7
8
  const SCHEMA_DIR = new URL('../../schemas', import.meta.url).pathname;
@@ -24,12 +25,10 @@ export async function update(options) {
24
25
  if (options.skill !== false) {
25
26
  console.log(chalk.blue('\n─── Updating Skill & Command ───'));
26
27
  try {
27
- // Download npm tarball and extract
28
28
  const tmpDir = '/tmp/openspec-e2e-update';
29
29
  execSync(`rm -rf ${tmpDir} && mkdir -p ${tmpDir}`, { stdio: 'pipe', cwd: projectRoot });
30
30
  execSync(`npm pack openspec-playwright --pack-destination ${tmpDir}`, { stdio: 'pipe', cwd: projectRoot });
31
31
  const tarball = execSync(`ls -t ${tmpDir}/openspec-playwright-*.tgz | head -1`, { encoding: 'utf-8', cwd: projectRoot }).trim();
32
- // Move tarball out before extracting to avoid "overwrite archive" error
33
32
  const tmpTarball = `${tmpDir}/package.tgz`;
34
33
  execSync(`mv "${tarball}" "${tmpTarball}"`, { stdio: 'pipe', cwd: projectRoot });
35
34
  execSync(`tar -xzf "${tmpTarball}" -C ${tmpDir} --strip-components=1`, { stdio: 'pipe', cwd: projectRoot });
@@ -45,6 +44,10 @@ export async function update(options) {
45
44
  installSkill(projectRoot);
46
45
  }
47
46
  }
47
+ // 3. Sync Healer tools with latest @playwright/mcp
48
+ console.log(chalk.blue('\n─── Syncing Healer Tools ───'));
49
+ const skillDest = join(projectRoot, '.claude', 'skills', 'openspec-e2e', 'SKILL.md');
50
+ await syncMcpTools(skillDest, true);
48
51
  // Summary
49
52
  console.log(chalk.blue('\n─── Summary ───'));
50
53
  console.log(chalk.green(' ✓ Update complete!\n'));
@@ -70,12 +73,10 @@ function installSkillFrom(skillSrc, cmdSrc, schemaSrc, projectRoot) {
70
73
  function installSchemaFrom(schemaSrc, projectRoot) {
71
74
  const schemaDest = join(projectRoot, 'openspec', 'schemas', 'playwright-e2e');
72
75
  mkdirSync(schemaDest, { recursive: true });
73
- // Copy schema.yaml
74
76
  const schemaYamlSrc = join(schemaSrc, 'schema.yaml');
75
77
  if (existsSync(schemaYamlSrc)) {
76
78
  writeFileSync(join(schemaDest, 'schema.yaml'), readFileSync(schemaYamlSrc));
77
79
  }
78
- // Copy templates
79
80
  const templatesSrc = join(schemaSrc, 'templates');
80
81
  const templatesDest = join(schemaDest, 'templates');
81
82
  if (existsSync(templatesSrc)) {
@@ -1 +1 @@
1
- {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openspec-playwright",
3
- "version": "0.1.27",
3
+ "version": "0.1.29",
4
4
  "description": "OpenSpec + Playwright E2E verification setup tool for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {
package/release-notes.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ## What's Changed
2
2
 
3
- - feat(skill): document Healer MCP tools and architecture rationale
3
+ - feat: add MCP version sync for Healer tools (init + update)
4
4
 
5
- **Full Changelog**: https://github.com/wxhou/openspec-playwright/releases/tag/v0.1.27
5
+ **Full Changelog**: https://github.com/wxhou/openspec-playwright/releases/tag/v0.1.29
@@ -8,6 +8,7 @@ import {
8
8
  import { join } from 'path';
9
9
  import chalk from 'chalk';
10
10
  import { readFile } from 'fs/promises';
11
+ import { syncMcpTools } from './mcpSync.js';
11
12
 
12
13
  const TEMPLATE_DIR = new URL('../../templates', import.meta.url).pathname;
13
14
  const SCHEMA_DIR = new URL('../../schemas', import.meta.url).pathname;
@@ -82,17 +83,22 @@ export async function init(options: InitOptions) {
82
83
  console.log(chalk.blue('\n─── Installing Claude Code Skill ───'));
83
84
  await installSkill(projectRoot);
84
85
 
85
- // 5. Install OpenSpec schema
86
+ // 5. Sync Healer tools with latest @playwright/mcp
87
+ console.log(chalk.blue('\n─── Syncing Healer Tools ───'));
88
+ const skillDest = join(projectRoot, '.claude', 'skills', 'openspec-e2e', 'SKILL.md');
89
+ await syncMcpTools(skillDest, true);
90
+
91
+ // 6. Install OpenSpec schema
86
92
  console.log(chalk.blue('\n─── Installing OpenSpec Schema ───'));
87
93
  await installSchema(projectRoot);
88
94
 
89
- // 6. Generate seed test
95
+ // 7. Generate seed test
90
96
  if (options.seed !== false) {
91
97
  console.log(chalk.blue('\n─── Generating Seed Test ───'));
92
98
  await generateSeedTest(projectRoot);
93
99
  }
94
100
 
95
- // 7. Summary
101
+ // 8. Summary
96
102
  console.log(chalk.blue('\n─── Summary ───'));
97
103
  console.log(chalk.green(' ✓ Setup complete!\n'));
98
104
 
@@ -0,0 +1,133 @@
1
+ import { exec } from 'child_process';
2
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
3
+ import { join } from 'path';
4
+ import chalk from 'chalk';
5
+
6
+ export const MCP_VERSION_MARKER = '<!-- MCP_VERSION:';
7
+
8
+ export const DEFAULT_HEALER_TOOLS = [
9
+ { name: 'browser_navigate', purpose: "Go to the failing test's page" },
10
+ { name: 'browser_snapshot', purpose: 'Get page structure to find equivalent selectors' },
11
+ { name: 'browser_console_messages', purpose: 'Diagnose JS errors that may cause failures' },
12
+ { name: 'browser_take_screenshot', purpose: 'Visually compare before/after fixes' },
13
+ { name: 'browser_run_code', purpose: 'Execute custom fix logic (optional)' },
14
+ ];
15
+
16
+ /** Extract MCP version from SKILL.md marker */
17
+ export function getStoredMcpVersion(skillContent: string): string | null {
18
+ const idx = skillContent.indexOf(MCP_VERSION_MARKER);
19
+ if (idx === -1) return null;
20
+ const end = skillContent.indexOf(' -->', idx);
21
+ return skillContent.slice(idx + MCP_VERSION_MARKER.length, end).trim();
22
+ }
23
+
24
+ /** Build the Healer tools table markdown */
25
+ function buildHealerTable(version: string, tools: Array<{ name: string; purpose: string }>): string {
26
+ const rows = tools.map(t => `| \`${t.name}\` | ${t.purpose} |`).join('\n');
27
+ return `${MCP_VERSION_MARKER} ${version} -->\n\n| Tool | Purpose |\n|------|---------|\n${rows}`;
28
+ }
29
+
30
+ /** Replace the Healer tools table in SKILL.md */
31
+ export function updateHealerTable(
32
+ skillContent: string,
33
+ version: string,
34
+ tools: Array<{ name: string; purpose: string }>
35
+ ): string {
36
+ const start = skillContent.indexOf('| Tool | Purpose |');
37
+ if (start === -1) return skillContent;
38
+ let end = skillContent.indexOf('\n\n', start);
39
+ if (end === -1) end = skillContent.length;
40
+
41
+ const before = skillContent.slice(0, start);
42
+ const after = skillContent.slice(end);
43
+ return before + buildHealerTable(version, tools) + after;
44
+ }
45
+
46
+ /** Fetch latest @playwright/mcp version from npm registry */
47
+ export function getLatestMcpVersion(): Promise<string | null> {
48
+ return new Promise((resolve) => {
49
+ exec('npm show @playwright/mcp version --json', { timeout: 15000 }, (err, stdout) => {
50
+ if (err) { resolve(null); return; }
51
+ try { resolve(JSON.parse(stdout.trim())); } catch { resolve(null); }
52
+ });
53
+ });
54
+ }
55
+
56
+ /** Parse README markdown to extract browser_* tool entries */
57
+ function parseMcpReadme(content: string): Array<{ name: string; purpose: string }> {
58
+ const tools: Array<{ name: string; purpose: string }> = [];
59
+ const re = /-\s+\*\*`?([^`*\n]+)`?\*\*\s*-\s*Title:\s*([^\n]+)/g;
60
+ let m;
61
+ while ((m = re.exec(content)) !== null) {
62
+ const name = m[1].trim();
63
+ if (name.startsWith('browser_')) {
64
+ const purpose = m[2].trim().replace(/\.$/, '');
65
+ tools.push({ name, purpose });
66
+ }
67
+ }
68
+ return tools;
69
+ }
70
+
71
+ /**
72
+ * Fetch @playwright/mcp tools from npm package.
73
+ * Downloads the tarball, extracts README, parses tool names.
74
+ */
75
+ export function fetchMcpTools(version: string): Promise<Array<{ name: string; purpose: string }>> {
76
+ return new Promise((resolve) => {
77
+ const tmpDir = `/tmp/openspec-pw-mcp-${version}`;
78
+ exec(
79
+ `rm -rf ${tmpDir} && mkdir -p ${tmpDir} && npm pack @playwright/mcp@${version} --pack-destination ${tmpDir} 2>/dev/null && tar -xzf ${tmpDir}/playwright-mcp-${version}.tgz -C ${tmpDir} --strip-components=1 && cat ${tmpDir}/package/README.md`,
80
+ { timeout: 30000 },
81
+ (err, stdout) => {
82
+ if (err) { resolve([]); return; }
83
+ const tools = parseMcpReadme(stdout);
84
+ resolve(tools);
85
+ }
86
+ );
87
+ });
88
+ }
89
+
90
+ /**
91
+ * Sync Healer tools table in SKILL.md with latest @playwright/mcp.
92
+ * Returns true if updated, false if already current or failed.
93
+ */
94
+ export async function syncMcpTools(
95
+ skillDest: string,
96
+ verbose = false
97
+ ): Promise<boolean> {
98
+ const latestVersion = await getLatestMcpVersion();
99
+ if (!latestVersion) {
100
+ if (verbose) console.log(chalk.yellow(' ⚠ Could not fetch latest @playwright/mcp version'));
101
+ return false;
102
+ }
103
+
104
+ if (!existsSync(skillDest)) {
105
+ if (verbose) console.log(chalk.gray(' - SKILL.md not found, skipping MCP sync'));
106
+ return false;
107
+ }
108
+
109
+ const skillContent = readFileSync(skillDest, 'utf-8');
110
+ const storedVersion = getStoredMcpVersion(skillContent);
111
+
112
+ if (storedVersion === latestVersion) {
113
+ if (verbose) console.log(chalk.gray(` - Healer tools current (${latestVersion})`));
114
+ return false;
115
+ }
116
+
117
+ if (verbose) console.log(chalk.blue(` - Updating from ${storedVersion ?? 'unknown'} → ${latestVersion}`));
118
+
119
+ const tools = await fetchMcpTools(latestVersion);
120
+ const toolSet = tools.length > 0 ? tools : DEFAULT_HEALER_TOOLS;
121
+
122
+ const updated = updateHealerTable(skillContent, latestVersion, toolSet);
123
+ writeFileSync(skillDest, updated);
124
+
125
+ if (verbose) {
126
+ if (tools.length > 0) {
127
+ console.log(chalk.green(` ✓ Healer tools synced to ${latestVersion} (${tools.length} tools)`));
128
+ } else {
129
+ console.log(chalk.green(` ✓ Healer tools synced to ${latestVersion} (default set)`));
130
+ }
131
+ }
132
+ return true;
133
+ }
@@ -7,6 +7,7 @@ import {
7
7
  } from 'fs';
8
8
  import { join } from 'path';
9
9
  import chalk from 'chalk';
10
+ import { syncMcpTools } from './mcpSync.js';
10
11
 
11
12
  const SKILL_SRC = new URL('../../.claude/skills/openspec-e2e', import.meta.url).pathname;
12
13
  const CMD_SRC = new URL('../../.claude/commands/opsx', import.meta.url).pathname;
@@ -43,7 +44,6 @@ export async function update(options: UpdateOptions) {
43
44
  if (options.skill !== false) {
44
45
  console.log(chalk.blue('\n─── Updating Skill & Command ───'));
45
46
  try {
46
- // Download npm tarball and extract
47
47
  const tmpDir = '/tmp/openspec-e2e-update';
48
48
  execSync(`rm -rf ${tmpDir} && mkdir -p ${tmpDir}`, { stdio: 'pipe', cwd: projectRoot });
49
49
  execSync(
@@ -54,7 +54,6 @@ export async function update(options: UpdateOptions) {
54
54
  `ls -t ${tmpDir}/openspec-playwright-*.tgz | head -1`,
55
55
  { encoding: 'utf-8', cwd: projectRoot }
56
56
  ).trim();
57
- // Move tarball out before extracting to avoid "overwrite archive" error
58
57
  const tmpTarball = `${tmpDir}/package.tgz`;
59
58
  execSync(`mv "${tarball}" "${tmpTarball}"`, { stdio: 'pipe', cwd: projectRoot });
60
59
  execSync(`tar -xzf "${tmpTarball}" -C ${tmpDir} --strip-components=1`, { stdio: 'pipe', cwd: projectRoot });
@@ -72,6 +71,11 @@ export async function update(options: UpdateOptions) {
72
71
  }
73
72
  }
74
73
 
74
+ // 3. Sync Healer tools with latest @playwright/mcp
75
+ console.log(chalk.blue('\n─── Syncing Healer Tools ───'));
76
+ const skillDest = join(projectRoot, '.claude', 'skills', 'openspec-e2e', 'SKILL.md');
77
+ await syncMcpTools(skillDest, true);
78
+
75
79
  // Summary
76
80
  console.log(chalk.blue('\n─── Summary ───'));
77
81
  console.log(chalk.green(' ✓ Update complete!\n'));
@@ -110,13 +114,11 @@ function installSchemaFrom(schemaSrc: string, projectRoot: string) {
110
114
  const schemaDest = join(projectRoot, 'openspec', 'schemas', 'playwright-e2e');
111
115
 
112
116
  mkdirSync(schemaDest, { recursive: true });
113
- // Copy schema.yaml
114
117
  const schemaYamlSrc = join(schemaSrc, 'schema.yaml');
115
118
  if (existsSync(schemaYamlSrc)) {
116
119
  writeFileSync(join(schemaDest, 'schema.yaml'), readFileSync(schemaYamlSrc));
117
120
  }
118
121
 
119
- // Copy templates
120
122
  const templatesSrc = join(schemaSrc, 'templates');
121
123
  const templatesDest = join(schemaDest, 'templates');
122
124
  if (existsSync(templatesSrc)) {
Binary file