openspec-playwright 0.3.55 → 0.3.57

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.
@@ -21,7 +21,7 @@
21
21
  | Change | `/opsx:e2e <name>` | OpenSpec specs | `changes/<name>/<name>.spec.ts` |
22
22
  | All | `/opsx:e2e all` | sitemap + homepage crawl | `pages/*.ts` (Page Objects) |
23
23
 
24
- > **Full regression is opt-in only.** `openspec-pw run <name>` one spec file. Do NOT run `npx playwright test` (no file) or `--only-changed` unless user explicitly requests.
24
+ > **Full regression is opt-in only.** Run `npx playwright test` for one spec file or full suite. Do NOT use `--only-changed` unless the user explicitly requests it.
25
25
  > **Roles**: Planner (Steps 4–5) → test-plan.md; Generator (Step 6) → `.spec.ts` + Page Objects; Healer (Step 9) → repairs failures via MCP.
26
26
 
27
27
  Browser exploration is tool-agnostic: Playwright MCP or `openspec-pw explore --parallel N`.
@@ -221,10 +221,10 @@ If missing → generate minimal config with webServer, projects, reporters. If e
221
221
  ### 9. Execute tests
222
222
 
223
223
  ```bash
224
- openspec-pw run <name> [options]
224
+ npx playwright test [options]
225
225
  ```
226
226
 
227
- Flags: `-p --project`, `-t --timeout`, `--json`, `-g --grep`, `--smoke`, `-w --workers`, `--headed`, `--update-snapshots`.
227
+ Common flags: `-p --project`, `-t --timeout`, `-g --grep`, `--headed`, `--update-snapshots`.
228
228
 
229
229
  When tests fail → **Healer** (3 phases):
230
230
 
@@ -52,7 +52,7 @@ jobs:
52
52
  run: openspec-pw doctor --json
53
53
 
54
54
  - name: Run E2E tests
55
- run: openspec-pw run all
55
+ run: npx playwright test
56
56
  env:
57
57
  E2E_USERNAME: ${{ secrets.E2E_USERNAME }}
58
58
  E2E_PASSWORD: ${{ secrets.E2E_PASSWORD }}
@@ -180,7 +180,7 @@ export default defineConfig({
180
180
  reuseExistingServer: true,
181
181
  },
182
182
 
183
- // Setup project (configured by openspec-pw run)
183
+ // Setup project (used by /opsx:e2e Healer and local auth setup)
184
184
  // Teardown project (optional): uncomment the two lines below + create tests/playwright/global.teardown.ts
185
185
  projects: [
186
186
  { name: 'setup', testMatch: /.*\.setup\.ts/ },
@@ -1,27 +0,0 @@
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>;
@@ -1,164 +0,0 @@
1
- import { exec } from "child_process";
2
- import { existsSync, readdirSync, readFileSync, writeFileSync, mkdirSync, rmSync, } from "fs";
3
- import { join } from "path";
4
- import { tmpdir } from "os";
5
- import { promisify } from "util";
6
- import chalk from "chalk";
7
- import * as tar from "tar";
8
- export const MCP_VERSION_MARKER = "<!-- MCP_VERSION:";
9
- export const DEFAULT_HEALER_TOOLS = [
10
- { name: "browser_navigate", purpose: "Go to the failing test's page" },
11
- {
12
- name: "browser_snapshot",
13
- purpose: "Get page structure to find equivalent selectors",
14
- },
15
- {
16
- name: "browser_console_messages",
17
- purpose: "Diagnose JS errors that may cause failures",
18
- },
19
- {
20
- name: "browser_take_screenshot",
21
- purpose: "Visually compare before/after fixes",
22
- },
23
- { name: "browser_run_code", purpose: "Execute custom fix logic (optional)" },
24
- ];
25
- /** Extract MCP version from SKILL.md marker */
26
- export function getStoredMcpVersion(skillContent) {
27
- const idx = skillContent.indexOf(MCP_VERSION_MARKER);
28
- if (idx === -1)
29
- return null;
30
- const end = skillContent.indexOf(" -->", idx);
31
- return skillContent.slice(idx + MCP_VERSION_MARKER.length, end).trim();
32
- }
33
- /** Remove all existing MCP_VERSION comment lines from content */
34
- function removeMcpVersionMarkers(content) {
35
- return content
36
- .split("\n")
37
- .filter((line) => !line.trim().startsWith(MCP_VERSION_MARKER))
38
- .join("\n");
39
- }
40
- /** Build the Healer tools table markdown */
41
- function buildHealerTable(version, tools) {
42
- const rows = tools.map((t) => `| \`${t.name}\` | ${t.purpose} |`).join("\n");
43
- return `${MCP_VERSION_MARKER} ${version} -->\n\n| Tool | Purpose |\n|------|---------|\n${rows}`;
44
- }
45
- /** Replace the Healer tools table in SKILL.md */
46
- export function updateHealerTable(skillContent, version, tools) {
47
- const noMarkers = removeMcpVersionMarkers(skillContent);
48
- const start = noMarkers.indexOf("| Tool | Purpose |");
49
- if (start === -1)
50
- return skillContent;
51
- let end = noMarkers.indexOf("\n\n", start);
52
- if (end === -1)
53
- end = noMarkers.length;
54
- const before = noMarkers.slice(0, start);
55
- const after = noMarkers.slice(end);
56
- return before + buildHealerTable(version, tools) + after;
57
- }
58
- /** Fetch latest @playwright/mcp version from npm registry */
59
- export function getLatestMcpVersion() {
60
- return new Promise((resolve) => {
61
- exec("npm show @playwright/mcp version --json", { timeout: 15000 }, (err, stdout) => {
62
- if (err) {
63
- resolve(null);
64
- return;
65
- }
66
- try {
67
- resolve(JSON.parse(stdout.trim()));
68
- }
69
- catch {
70
- resolve(null);
71
- }
72
- });
73
- });
74
- }
75
- const execAsync = promisify(exec);
76
- /** Extract a .tgz tarball to a destination directory (cross-platform) */
77
- async function extractTarball(tarballPath, destDir) {
78
- rmSync(destDir, { recursive: true, force: true });
79
- mkdirSync(destDir, { recursive: true });
80
- await tar.extract({ file: tarballPath, cwd: destDir, strip: 1 });
81
- }
82
- /** Parse README markdown to extract browser_* tool entries */
83
- function parseMcpReadme(content) {
84
- const tools = [];
85
- const re = /-\s+\*\*`?([^`*\n]+)`?\*\*\s*-\s*Title:\s*([^\n]+)/g;
86
- let m;
87
- while ((m = re.exec(content)) !== null) {
88
- const name = m[1].trim();
89
- if (name.startsWith("browser_")) {
90
- const purpose = m[2].trim().replace(/\.$/, "");
91
- tools.push({ name, purpose });
92
- }
93
- }
94
- if (tools.length === 0) {
95
- console.error("[openspec-pw] Warning: @playwright/mcp README format changed, no tools parsed. Healer will use default tools.");
96
- }
97
- return tools;
98
- }
99
- /**
100
- * Fetch @playwright/mcp tools from npm package.
101
- * Downloads the tarball, extracts README, parses tool names.
102
- */
103
- export async function fetchMcpTools(version) {
104
- const tmpDir = join(tmpdir(), `openspec-pw-mcp-${version}`);
105
- try {
106
- await execAsync(`npm pack @playwright/mcp@${version} --pack-destination ${tmpDir}`, { timeout: 30000 });
107
- const tgzFiles = readdirSync(tmpDir).filter((f) => f.startsWith("playwright-mcp-") && f.endsWith(".tgz"));
108
- if (tgzFiles.length === 0)
109
- return [];
110
- const tarballPath = join(tmpDir, tgzFiles[0]);
111
- const extractDir = join(tmpDir, "pkg");
112
- await extractTarball(tarballPath, extractDir);
113
- const readmePath = join(extractDir, "README.md");
114
- const content = existsSync(readmePath)
115
- ? readFileSync(readmePath, "utf-8")
116
- : "";
117
- rmSync(tmpDir, { recursive: true, force: true });
118
- return parseMcpReadme(content);
119
- }
120
- catch {
121
- console.log(chalk.yellow(" ⚠ Failed to fetch MCP tools — using default set"));
122
- return [];
123
- }
124
- }
125
- /**
126
- * Sync Healer tools table in SKILL.md with latest @playwright/mcp.
127
- * Returns true if updated, false if already current or failed.
128
- */
129
- export async function syncMcpTools(skillDest, verbose = false) {
130
- const latestVersion = await getLatestMcpVersion();
131
- if (!latestVersion) {
132
- if (verbose)
133
- console.log(chalk.yellow(" ⚠ Could not fetch latest @playwright/mcp version"));
134
- return false;
135
- }
136
- if (!existsSync(skillDest)) {
137
- if (verbose)
138
- console.log(chalk.gray(" - SKILL.md not found, skipping MCP sync"));
139
- return false;
140
- }
141
- const skillContent = readFileSync(skillDest, "utf-8");
142
- const storedVersion = getStoredMcpVersion(skillContent);
143
- if (storedVersion === latestVersion) {
144
- if (verbose)
145
- console.log(chalk.gray(` - Healer tools current (${latestVersion})`));
146
- return false;
147
- }
148
- if (verbose)
149
- console.log(chalk.blue(` - Updating from ${storedVersion ?? "unknown"} → ${latestVersion}`));
150
- const tools = await fetchMcpTools(latestVersion);
151
- const toolSet = tools.length > 0 ? tools : DEFAULT_HEALER_TOOLS;
152
- const updated = updateHealerTable(skillContent, latestVersion, toolSet);
153
- writeFileSync(skillDest, updated);
154
- if (verbose) {
155
- if (tools.length > 0) {
156
- console.log(chalk.green(` ✓ Healer tools synced to ${latestVersion} (${tools.length} tools)`));
157
- }
158
- else {
159
- console.log(chalk.green(` ✓ Healer tools synced to ${latestVersion} (default set)`));
160
- }
161
- }
162
- return true;
163
- }
164
- //# sourceMappingURL=mcpSync.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mcpSync.js","sourceRoot":"","sources":["../../src/commands/mcpSync.ts"],"names":[],"mappings":"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"}
@@ -1,34 +0,0 @@
1
- export interface RunOptions {
2
- project?: string;
3
- timeout?: number;
4
- json?: boolean;
5
- grep?: string;
6
- smoke?: boolean;
7
- workers?: number;
8
- appBugs?: number;
9
- healed?: number;
10
- raft?: number;
11
- escalated?: number;
12
- headed?: boolean;
13
- updateSnapshots?: boolean;
14
- }
15
- export declare function run(changeName: string, options: RunOptions): Promise<void>;
16
- interface TestResults {
17
- total: number;
18
- passed: number;
19
- failed: number;
20
- duration: string;
21
- authRequired?: boolean;
22
- appBugCount?: number;
23
- healedCount?: number;
24
- raftCount?: number;
25
- escalatedCount?: number;
26
- tests: Array<{
27
- name: string;
28
- status: "passed" | "failed";
29
- screenshot?: string;
30
- failureType?: string;
31
- }>;
32
- }
33
- export declare function parsePlaywrightOutput(output: string): TestResults;
34
- export {};
@@ -1,270 +0,0 @@
1
- import { execFileSync } from "child_process";
2
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
3
- import { join } from "path";
4
- import chalk from "chalk";
5
- import { needsShell } from "../shared/index.js";
6
- import { detectAdapters } from "./editors.js";
7
- const REPORTS_DIR = "openspec/reports";
8
- export async function run(changeName, options) {
9
- console.log(chalk.blue(`\n🔍 OpenSpec Playwright E2E: ${changeName}\n`));
10
- const projectRoot = process.cwd();
11
- // Validate changeName to prevent path traversal
12
- if (changeName !== "all" && (changeName.includes("/") || changeName.includes("\\") || changeName.includes(".."))) {
13
- console.log(chalk.red(` ✗ Invalid change name: ${changeName}`));
14
- console.log(chalk.gray(" Change name cannot contain path separators or '..'.\n"));
15
- process.exit(1);
16
- }
17
- // 1. Verify test file exists
18
- const testFileName = changeName === "all"
19
- ? "app-all.spec.ts"
20
- : `${changeName}.spec.ts`;
21
- const testFile = join(projectRoot, "tests", "playwright", changeName === "all" ? testFileName : `changes/${changeName}/${testFileName}`);
22
- if (!existsSync(testFile)) {
23
- const testFileDisplayPath = changeName === "all"
24
- ? `tests/playwright/${testFileName}`
25
- : `tests/playwright/changes/${changeName}/${testFileName}`;
26
- console.log(chalk.red(` ✗ Test file not found: ${testFileDisplayPath}`));
27
- const detected = detectAdapters(projectRoot);
28
- const slashes = detected.length
29
- ? detected
30
- .map((a) => (a.id === "claude" ? "/opsx:e2e" : "/opsx-e2e"))
31
- .join(" or ")
32
- : "/opsx:e2e (Claude) or /opsx-e2e (OpenCode)";
33
- console.log(chalk.gray(` Run ${slashes} first to generate tests.\n`));
34
- process.exit(1);
35
- }
36
- // 2. Setup reports dir
37
- mkdirSync(join(projectRoot, REPORTS_DIR), { recursive: true });
38
- // 3. Detect auth credentials
39
- const credsPath = join(projectRoot, "tests", "playwright", "credentials.yaml");
40
- const hasCredentials = existsSync(credsPath);
41
- if (!hasCredentials) {
42
- console.log(chalk.yellow(" ⚠ No credentials.yaml found — tests may fail if auth required"));
43
- }
44
- // 4. Run Playwright tests — JSON reporter for structured results + screenshot paths
45
- console.log(chalk.blue("─── Running Tests ───"));
46
- const testResultsDir = join(projectRoot, "test-results");
47
- const jsonReportPath = join(testResultsDir, "results.json");
48
- const args = [
49
- "npx",
50
- "playwright", "test", testFile,
51
- "--reporter=json",
52
- "--output=" + testResultsDir,
53
- ];
54
- if (options.project) {
55
- args.push("--project=" + options.project);
56
- }
57
- // Escape regex special chars in grep to prevent injection.
58
- // Note: | is escaped too, so grep "a|b" matches the literal string "a|b",
59
- // not "a OR b". For OR semantics, run two separate commands.
60
- const escapeGrep = (s) => s.replace(/[.*+?()[\]{}|\\^$]/g, "\\$&");
61
- if (options.grep && options.smoke) {
62
- // Match tests containing both @smoke AND the grep pattern (order-flexible: @smoke or pattern may appear first)
63
- const eg = escapeGrep(options.grep);
64
- args.push("--grep", `@smoke.*${eg}|${eg}.*@smoke`);
65
- }
66
- else if (options.grep) {
67
- args.push("--grep=" + options.grep);
68
- }
69
- else if (options.smoke) {
70
- args.push("--grep", "@smoke");
71
- }
72
- if (options.workers) {
73
- args.push("--workers=" + options.workers);
74
- }
75
- if (options.headed) {
76
- args.push("--headed");
77
- }
78
- if (options.updateSnapshots) {
79
- args.push("--update-snapshots");
80
- }
81
- let testOutput = "";
82
- try {
83
- const result = execFileSync(args[0], args.slice(1), { shell: needsShell,
84
- cwd: projectRoot,
85
- encoding: "utf-8",
86
- stdio: ["pipe", "pipe", "pipe"],
87
- timeout: (options.timeout ?? (process.env.OPENSPEC_TIMEOUT ? Number(process.env.OPENSPEC_TIMEOUT) : undefined) ?? 300) * 1000,
88
- });
89
- testOutput = result;
90
- }
91
- catch (err) {
92
- const error = err;
93
- testOutput = (error.stdout ?? "") + (error.stderr ?? "");
94
- }
95
- // 5. Parse results from JSON reporter output (authoritative) or fallback to stdout
96
- const results = parsePlaywrightJsonReport(jsonReportPath) ?? parsePlaywrightOutput(testOutput);
97
- // 6. Detect port mismatch
98
- if (testOutput.includes("net::ERR_CONNECTION_REFUSED") ||
99
- testOutput.includes("listen EADDRINUSE") ||
100
- testOutput.includes("0.0.0.0:")) {
101
- console.log(chalk.yellow(" ⚠ Port mismatch detected. Check BASE_URL and webServer port."));
102
- }
103
- // 7. Generate markdown report
104
- const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
105
- const reportPath = join(projectRoot, REPORTS_DIR, `playwright-e2e-${changeName}-${timestamp}.md`);
106
- const reportContent = generateReport(changeName, timestamp, results, options);
107
- writeFileSync(reportPath, reportContent);
108
- // 8. Summary
109
- if (options.json) {
110
- const output = JSON.stringify({
111
- change: changeName,
112
- total: results.total,
113
- passed: results.passed,
114
- failed: results.failed,
115
- duration: results.duration,
116
- report: reportPath,
117
- tests: results.tests,
118
- ok: results.failed === 0,
119
- }, null, 2);
120
- console.log(output);
121
- if (results.failed > 0)
122
- process.exit(1);
123
- return;
124
- }
125
- console.log(chalk.blue("\n─── Results ───"));
126
- console.log(` Tests: ${results.total} ` +
127
- chalk.green(`✓ ${results.passed}`) +
128
- " " +
129
- (results.failed > 0
130
- ? chalk.red(`✗ ${results.failed}`)
131
- : chalk.gray(`✗ ${results.failed}`)) +
132
- ` Duration: ${results.duration}`);
133
- console.log(chalk.blue("\n─── Report ───"));
134
- console.log(chalk.green(` ✓ ${reportPath}\n`));
135
- if (results.failed > 0) {
136
- console.log(chalk.red(`✗ E2E verification FAILED (${results.failed} tests)`));
137
- process.exit(1);
138
- }
139
- else {
140
- console.log(chalk.green("✓ E2E verification PASSED"));
141
- }
142
- }
143
- function parsePlaywrightJsonReport(jsonPath) {
144
- if (!existsSync(jsonPath))
145
- return null;
146
- let raw;
147
- try {
148
- raw = JSON.parse(readFileSync(jsonPath, "utf-8"));
149
- }
150
- catch {
151
- return null;
152
- }
153
- const data = raw;
154
- if (!data?.suites?.length)
155
- return null;
156
- const results = {
157
- total: 0,
158
- passed: 0,
159
- failed: 0,
160
- duration: "0s",
161
- tests: [],
162
- };
163
- // Collect duration across all suites
164
- let totalDurationMs = 0;
165
- for (const suite of data.suites) {
166
- for (const test of suite.tests) {
167
- for (const result of test.results) {
168
- const status = result.status === "passed" ? "passed" : "failed";
169
- // Find first screenshot attachment (image/png) if any
170
- const screenshotAtt = result.attachments.find((a) => a.contentType === "image/png" && a.path);
171
- results.tests.push({
172
- name: test.title,
173
- status,
174
- screenshot: screenshotAtt?.path ?? undefined,
175
- });
176
- results.total++;
177
- if (status === "passed")
178
- results.passed++;
179
- else
180
- results.failed++;
181
- totalDurationMs += result.duration;
182
- }
183
- }
184
- }
185
- if (results.total > 0 && totalDurationMs > 0) {
186
- const secs = Math.round(totalDurationMs / 1000);
187
- results.duration = secs < 60 ? `${secs}s` : `${Math.floor(secs / 60)}m ${secs % 60}s`;
188
- }
189
- return results;
190
- }
191
- // ─── Fallback: stdout parser ───────────────────────────────────────────────────
192
- // Parses Playwright's --reporter=list stdout when JSON report is unavailable.
193
- export function parsePlaywrightOutput(output) {
194
- const results = {
195
- total: 0,
196
- passed: 0,
197
- failed: 0,
198
- duration: "0s",
199
- tests: [],
200
- };
201
- // Parse: "✓ my-test (1.2s)" or "✗ my-test (0.5s)"
202
- const testLineRegex = /([✓✗x]) (.+?) \((\d+(?:\.\d+)?[a-z]+)\)/g;
203
- let match;
204
- while ((match = testLineRegex.exec(output)) !== null) {
205
- const status = match[1] === "✓" ? "passed" : "failed";
206
- results.tests.push({ name: match[2], status });
207
- results.total++;
208
- if (status === "passed")
209
- results.passed++;
210
- else
211
- results.failed++;
212
- }
213
- // Parse duration: "N tests ran (1m 30s)" or "1 test ran (5s)"
214
- const durationMatch = output.match(/\d+ tests? ran \((\d+(?:m\s*\d+)?s?)\)/);
215
- if (durationMatch)
216
- results.duration = durationMatch[1];
217
- return results;
218
- }
219
- function generateReport(changeName, timestamp, results, options) {
220
- const duration = timestamp.replace("T", " ").slice(0, 16);
221
- const status = results.failed === 0 ? "✅ PASS" : "❌ FAIL";
222
- const lines = [
223
- `# E2E Verify Report: ${changeName}`,
224
- "",
225
- `**Change**: \`${changeName}\` | **Generated**: ${duration} UTC | **Auth**: ${results.authRequired ? "required" : "none"}`,
226
- "",
227
- "## Summary",
228
- "",
229
- "| Metric | Value |",
230
- "|--------|-------|",
231
- `| Tests Run | ${results.total} |`,
232
- `| Passed | ${results.passed} |`,
233
- `| Failed | ${results.failed} |`,
234
- `| Duration | ${results.duration} |`,
235
- `| App Bugs (skipped) | ${options.appBugs ?? "—"} |`,
236
- `| Test Bugs (healed) | ${options.healed ?? "—"} |`,
237
- `| Flaky/RAFT | ${options.raft ?? "—"} |`,
238
- `| Human Escalations | ${options.escalated ?? "—"} |`,
239
- `| Final Status | ${status} |`,
240
- "",
241
- ];
242
- if (results.tests.length === 0) {
243
- lines.push("_(No test output captured — check Playwright configuration)_", "");
244
- }
245
- else {
246
- lines.push("## Test Results", "");
247
- lines.push("| Test | Status | Failure Type | Healed? | Screenshot |");
248
- lines.push("|------|--------|------------|---------|-----------|");
249
- for (const test of results.tests) {
250
- const icon = test.status === "passed" ? "✅" : "❌";
251
- const type = test.failureType ?? (test.status === "passed" ? "—" : "pending");
252
- const healed = test.status === "passed" ? "—" : (test.failureType ? "pending" : "—");
253
- const screenshot = test.screenshot
254
- ? `[screenshot](${test.screenshot})`
255
- : "-";
256
- lines.push(`| ${test.name} | ${icon} ${test.status} | ${type} | ${healed} | ${screenshot} |`);
257
- }
258
- lines.push("");
259
- }
260
- lines.push("## Failure Classification", "", "_(Populated by Healer after Phase 1/2/3 — see e2e-command.md Step 9)_", "", "| Test | Failure Type | Action | Healed? |", "|------|-------------|--------|---------|", "| ... | ... | ... | ... |", "", "## Auto-Heal Log", "", "_(Populated by Healer — see e2e-command.md Step 9 Phase 2)_", "", "## RAFT Summary", "", "_(If RAFTs detected: mark with test.skip() in suite, investigate infrastructure coupling)_", "", "## Human Escalations", "", "_(If Phase 3 escalations: present 4 options to user, wait for decision)_", "");
261
- lines.push("## Recommendations", "");
262
- if (results.failed > 0) {
263
- lines.push("Review failed tests above.", "For Healer guidance: see e2e-command.md Step 9 — Phase 1 Triage → Phase 2 Repair → Phase 3 Escalate.", "For full interactive reports: `npx playwright show-report`", "");
264
- }
265
- else {
266
- lines.push("All tests passed. No action needed.", "");
267
- }
268
- return lines.join("\n");
269
- }
270
- //# sourceMappingURL=run.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"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"}
@@ -1,23 +0,0 @@
1
- /** Record of tool name -> purpose description */
2
- export interface McpTool {
3
- name: string;
4
- title: string;
5
- description: string;
6
- purpose: string;
7
- }
8
- /**
9
- * Download and parse the @playwright/mcp README to extract all browser_* tools.
10
- */
11
- export declare function fetchMcpTools(): McpTool[];
12
- /**
13
- * Update the Healer MCP tools table in SKILL.md.
14
- * Only syncs the 5 core Healer tools; all other MCP tools are
15
- * general-purpose automation not specific to healing.
16
- * Deduplicates by tool name.
17
- */
18
- export declare function updateSkillHealerTable(skillPath: string, tools: McpTool[]): void;
19
- /**
20
- * Main entry point: fetch tools and update SKILL.md.
21
- * Call this after installing the skill in init.ts and update.ts.
22
- */
23
- export declare function syncMcpTools(skillPath: string): void;