openspec-playwright 0.3.43 → 0.3.45
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 +30 -11
- package/README.zh-CN.md +28 -11
- package/dist/commands/audit.js +22 -8
- package/dist/commands/audit.js.map +1 -1
- package/dist/commands/doctor.js +36 -10
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/editors.d.ts +63 -12
- package/dist/commands/editors.js +318 -39
- package/dist/commands/editors.js.map +1 -1
- package/dist/commands/explore.js +37 -35
- package/dist/commands/explore.js.map +1 -1
- package/dist/commands/init.js +39 -30
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/run.js +8 -1
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/uninstall.js +25 -41
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +35 -30
- package/dist/commands/update.js.map +1 -1
- package/dist/shared/mcp.d.ts +15 -16
- package/dist/shared/mcp.js +30 -66
- package/dist/shared/mcp.js.map +1 -1
- package/employee-standards.md +17 -3
- package/package.json +6 -2
- package/templates/e2e-command.md +2 -0
package/dist/shared/mcp.js
CHANGED
|
@@ -1,81 +1,45 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*/
|
|
5
|
-
import { execFileSync } from "node:child_process";
|
|
6
|
-
import { TIMEOUT } from "./constants.js";
|
|
7
|
-
import { needsShell } from "./platform.js";
|
|
8
|
-
function outputIncludesPlaywright(output) {
|
|
9
|
-
return String(output ?? "").includes("playwright");
|
|
1
|
+
/** Check if the named MCP server is installed in this editor. */
|
|
2
|
+
export function isMcpInstalled(adapter, serverName) {
|
|
3
|
+
return adapter.isMcpInstalled(process.cwd(), serverName);
|
|
10
4
|
}
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
* Note: `claude mcp list` may exit non-zero if another MCP server is
|
|
16
|
-
* pending approval or unhealthy, while still printing the list. In that
|
|
17
|
-
* case, read stdout/stderr from the thrown error before returning false.
|
|
18
|
-
*/
|
|
19
|
-
export function isPlaywrightMcpInstalled() {
|
|
20
|
-
try {
|
|
21
|
-
const output = execFileSync("claude", ["mcp", "list"], {
|
|
22
|
-
encoding: "utf-8",
|
|
23
|
-
timeout: TIMEOUT.MCP_LIST,
|
|
24
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
25
|
-
shell: needsShell,
|
|
26
|
-
});
|
|
27
|
-
return outputIncludesPlaywright(output);
|
|
28
|
-
}
|
|
29
|
-
catch (err) {
|
|
30
|
-
const e = err;
|
|
31
|
-
return outputIncludesPlaywright(e.stdout) || outputIncludesPlaywright(e.stderr);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Ensure Playwright MCP server is installed globally.
|
|
36
|
-
* Prints status messages. Throws on failure.
|
|
37
|
-
*/
|
|
38
|
-
export function ensurePlaywrightMcp() {
|
|
39
|
-
if (isPlaywrightMcpInstalled()) {
|
|
40
|
-
console.log(" ✓ Playwright MCP already installed");
|
|
5
|
+
/** Install an MCP server in this editor. Throws on failure. */
|
|
6
|
+
export function ensureMcp(adapter, serverName, command) {
|
|
7
|
+
if (isMcpInstalled(adapter, serverName)) {
|
|
8
|
+
console.log(` ✓ ${adapter.label}: ${serverName} MCP already installed`);
|
|
41
9
|
return;
|
|
42
10
|
}
|
|
43
11
|
try {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
timeout: TIMEOUT.MCP_LIST,
|
|
47
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
48
|
-
shell: needsShell,
|
|
49
|
-
});
|
|
50
|
-
console.log(" ✓ Playwright MCP installed globally");
|
|
12
|
+
adapter.installMcp(process.cwd(), serverName, command);
|
|
13
|
+
console.log(` ✓ ${adapter.label}: ${serverName} MCP installed`);
|
|
51
14
|
}
|
|
52
|
-
catch {
|
|
53
|
-
console.warn(
|
|
54
|
-
|
|
55
|
-
throw new Error("MCP installation failed");
|
|
15
|
+
catch (err) {
|
|
16
|
+
console.warn(` ⚠ ${adapter.label}: failed to install ${serverName} MCP`);
|
|
17
|
+
throw err;
|
|
56
18
|
}
|
|
57
19
|
}
|
|
58
|
-
/**
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
export function removePlaywrightMcp() {
|
|
63
|
-
if (!isPlaywrightMcpInstalled()) {
|
|
64
|
-
console.log(" ✓ Playwright MCP not installed (nothing to remove)");
|
|
20
|
+
/** Remove an MCP server from this editor. Does not throw if missing. */
|
|
21
|
+
export function removeMcp(adapter, serverName) {
|
|
22
|
+
if (!isMcpInstalled(adapter, serverName)) {
|
|
23
|
+
console.log(` - ${adapter.label}: ${serverName} MCP not installed (nothing to remove)`);
|
|
65
24
|
return;
|
|
66
25
|
}
|
|
67
26
|
try {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
timeout: TIMEOUT.MCP_LIST,
|
|
71
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
72
|
-
shell: needsShell,
|
|
73
|
-
});
|
|
74
|
-
console.log(" ✓ Playwright MCP removed");
|
|
27
|
+
adapter.removeMcp(process.cwd(), serverName);
|
|
28
|
+
console.log(` ✓ ${adapter.label}: ${serverName} MCP removed`);
|
|
75
29
|
}
|
|
76
30
|
catch {
|
|
77
|
-
console.warn(
|
|
78
|
-
console.log(" Run manually: claude mcp remove playwright");
|
|
31
|
+
console.warn(` ⚠ ${adapter.label}: failed to remove ${serverName} MCP`);
|
|
79
32
|
}
|
|
80
33
|
}
|
|
34
|
+
// ─── Playwright MCP conveniences ────────────────────────────────────────
|
|
35
|
+
const PLAYWRIGHT_MCP_COMMAND = ["npx", "@playwright/mcp@latest"];
|
|
36
|
+
export function isPlaywrightMcpInstalled(adapter) {
|
|
37
|
+
return isMcpInstalled(adapter, "playwright");
|
|
38
|
+
}
|
|
39
|
+
export function ensurePlaywrightMcp(adapter) {
|
|
40
|
+
ensureMcp(adapter, "playwright", PLAYWRIGHT_MCP_COMMAND);
|
|
41
|
+
}
|
|
42
|
+
export function removePlaywrightMcp(adapter) {
|
|
43
|
+
removeMcp(adapter, "playwright");
|
|
44
|
+
}
|
|
81
45
|
//# sourceMappingURL=mcp.js.map
|
package/dist/shared/mcp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/shared/mcp.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/shared/mcp.ts"],"names":[],"mappings":"AAUA,iEAAiE;AACjE,MAAM,UAAU,cAAc,CAAC,OAAsB,EAAE,UAAkB;IACvE,OAAO,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,CAAC,CAAC;AAC3D,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,SAAS,CACvB,OAAsB,EACtB,UAAkB,EAClB,OAAiB;IAEjB,IAAI,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,OAAO,OAAO,CAAC,KAAK,KAAK,UAAU,wBAAwB,CAAC,CAAC;QACzE,OAAO;IACT,CAAC;IACD,IAAI,CAAC;QACH,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,OAAO,OAAO,CAAC,KAAK,KAAK,UAAU,gBAAgB,CAAC,CAAC;IACnE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,OAAO,OAAO,CAAC,KAAK,uBAAuB,UAAU,MAAM,CAAC,CAAC;QAC1E,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,SAAS,CAAC,OAAsB,EAAE,UAAkB;IAClE,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,OAAO,OAAO,CAAC,KAAK,KAAK,UAAU,wCAAwC,CAAC,CAAC;QACzF,OAAO;IACT,CAAC;IACD,IAAI,CAAC;QACH,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,OAAO,OAAO,CAAC,KAAK,KAAK,UAAU,cAAc,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CAAC,OAAO,OAAO,CAAC,KAAK,sBAAsB,UAAU,MAAM,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC;AAED,2EAA2E;AAE3E,MAAM,sBAAsB,GAAG,CAAC,KAAK,EAAE,wBAAwB,CAAC,CAAC;AAEjE,MAAM,UAAU,wBAAwB,CAAC,OAAsB;IAC7D,OAAO,cAAc,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAsB;IACxD,SAAS,CAAC,OAAO,EAAE,YAAY,EAAE,sBAAsB,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAsB;IACxD,SAAS,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;AACnC,CAAC"}
|
package/employee-standards.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# AI Coding Assistant Employee-Grade Standards
|
|
2
2
|
|
|
3
3
|
> 员工级行为规范。
|
|
4
4
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## 0. 适用范围
|
|
8
8
|
|
|
9
|
-
本规范适用于 OpenSpec + openspec-playwright
|
|
9
|
+
本规范适用于 OpenSpec + openspec-playwright 项目(使用 AI 编码助手,如 Claude Code 或 OpenCode)。
|
|
10
10
|
|
|
11
11
|
**项目规范**:动手前读 `openspec/config.yaml`(技术栈、结构、约定、约束等),无内容则忽略。
|
|
12
12
|
|
|
@@ -72,8 +72,22 @@
|
|
|
72
72
|
|
|
73
73
|
按需叠加的评审:`/plan-ceo-review`(产品战略)/ `/plan-eng-review`(架构)/ `/plan-design-review`(UX)。
|
|
74
74
|
|
|
75
|
-
阶段命令即触发器:`/opsx:propose` → `/opsx:apply` → `/opsx:verify` → `/opsx:e2e
|
|
75
|
+
阶段命令即触发器:`/opsx:propose` → `/opsx:apply` → `/opsx:verify` → e2e 命令(Claude Code 用 `/opsx:e2e`,OpenCode 用 `/opsx-e2e`)→ `/opsx:archive`。**所有阶段由用户手动触发,AI 不自动进入下一阶段**(详见 §2 阶段隔离)。
|
|
76
76
|
|
|
77
77
|
可用 `npx openspec --help` 查看更多 OpenSpec 命令。
|
|
78
78
|
|
|
79
79
|
方向不明时可用 `/office-hours` 做创意验证。**Healer 需要 Playwright 环境**;非 Node.js 项目请参考各自语言的 OpenSpec 测试集成。
|
|
80
|
+
|
|
81
|
+
## 6. 禁止编撰数据
|
|
82
|
+
|
|
83
|
+
无论前后端一体还是纯前端项目,AI 助手**严禁**主动编撰任何数据填充代码,除非用户明确同意。
|
|
84
|
+
|
|
85
|
+
**适用范围**:mock 用户 / 邮箱 / 手机号;编造的测试期望值("期望返回 `{ success: true }`" 等);凭空出现的配置默认值(API URL、feature flag、密钥);假装存在的接口 / 字段 / 枚举值。
|
|
86
|
+
|
|
87
|
+
**强制流程**:
|
|
88
|
+
1. 遇需数据的代码位 → **必须**显式询问用户
|
|
89
|
+
2. 用户同意占位 → 用 `TODO(user)` 标注并附问询上下文
|
|
90
|
+
3. 用户提供数据 → 使用真实数据
|
|
91
|
+
4. 用户拒绝提供 → 用 stub / `throw` / `return null` 让代码显式失败,**禁止**静默编造值
|
|
92
|
+
|
|
93
|
+
**纯前端项目**:若存在 OpenAPI / 接口文档 / MCP 暴露的接口,必须查阅真实定义后引用,并标注来源(例如 `// 来源: docs/api/openapi.yaml#/paths/...`),禁止凭印象编造 endpoint / path / 字段名。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openspec-playwright",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.45",
|
|
4
4
|
"description": "OpenSpec + Playwright E2E verification setup tool for Claude Code",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -22,8 +22,9 @@
|
|
|
22
22
|
"chalk": "^5.3.0",
|
|
23
23
|
"commander": "^12.1.0",
|
|
24
24
|
"glob": "^13.0.6",
|
|
25
|
+
"jsonc-parser": "^3.3.1",
|
|
25
26
|
"playwright": "^1.50.0",
|
|
26
|
-
"tar": "^7.5.
|
|
27
|
+
"tar": "^7.5.16"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
29
30
|
"@types/glob": "^8.1.0",
|
|
@@ -37,6 +38,9 @@
|
|
|
37
38
|
"typescript": "^5.6.0",
|
|
38
39
|
"vitest": "^4.1.2"
|
|
39
40
|
},
|
|
41
|
+
"overrides": {
|
|
42
|
+
"vite": "^8.0.16"
|
|
43
|
+
},
|
|
40
44
|
"engines": {
|
|
41
45
|
"node": ">=20"
|
|
42
46
|
},
|
package/templates/e2e-command.md
CHANGED
|
@@ -666,6 +666,8 @@ if (cachedSelectors && cachedSelectors.length > 0) {
|
|
|
666
666
|
|
|
667
667
|
**Test coverage — empty states**: For list/detail pages, explore the empty state. If the app shows a "no data" UI when the list is empty, generate a test to verify it. Empty states are often missing from specs but are real user paths.
|
|
668
668
|
|
|
669
|
+
**Test data fabrication**: never invent user accounts, product lists, or API responses. Follow §6 of the employee standards — explicitly ask the user for test data; use `TODO(user)` markers for approved placeholders; fail loudly rather than fabricate.
|
|
670
|
+
|
|
669
671
|
**Test coverage — special elements**: Check `app-exploration.md` → **Special Elements Detected** table. For each special element, generate tests using the following strategies:
|
|
670
672
|
- Canvas: screenshot + boundingBox → dimensions > 0, or 2D pixel verification
|
|
671
673
|
- WebGL: screenshot only (no pixel comparison — rendering varies)
|