openspec-playwright 0.1.16

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.
Files changed (38) hide show
  1. package/.claude/commands/opsx/e2e.md +8 -0
  2. package/.claude/skills/openspec-e2e/SKILL.md +138 -0
  3. package/.github/workflows/release.yml +41 -0
  4. package/README.md +133 -0
  5. package/README.zh-CN.md +118 -0
  6. package/bin/openspec-pw +4 -0
  7. package/bin/openspec-pw.js +2 -0
  8. package/dist/commands/doctor.d.ts +1 -0
  9. package/dist/commands/doctor.js +110 -0
  10. package/dist/commands/doctor.js.map +1 -0
  11. package/dist/commands/init.d.ts +6 -0
  12. package/dist/commands/init.js +174 -0
  13. package/dist/commands/init.js.map +1 -0
  14. package/dist/commands/run.d.ts +5 -0
  15. package/dist/commands/run.js +135 -0
  16. package/dist/commands/run.js.map +1 -0
  17. package/dist/commands/update.d.ts +5 -0
  18. package/dist/commands/update.js +91 -0
  19. package/dist/commands/update.js.map +1 -0
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.js +40 -0
  22. package/dist/index.js.map +1 -0
  23. package/docs/plans/2026-03-26-openspec-playwright-design.md +180 -0
  24. package/package.json +39 -0
  25. package/schemas/playwright-e2e/schema.yaml +56 -0
  26. package/schemas/playwright-e2e/templates/e2e-test.ts +55 -0
  27. package/schemas/playwright-e2e/templates/playwright.config.ts +52 -0
  28. package/schemas/playwright-e2e/templates/report.md +27 -0
  29. package/schemas/playwright-e2e/templates/test-plan.md +24 -0
  30. package/src/commands/doctor.ts +114 -0
  31. package/src/commands/init.ts +209 -0
  32. package/src/commands/run.ts +172 -0
  33. package/src/commands/update.ts +130 -0
  34. package/src/index.ts +47 -0
  35. package/templates/auth.setup.ts +77 -0
  36. package/templates/credentials.yaml +33 -0
  37. package/templates/seed.spec.ts +63 -0
  38. package/tsconfig.json +18 -0
@@ -0,0 +1,8 @@
1
+ ---
2
+ name: OPSX: E2E
3
+ description: Run Playwright E2E verification for an OpenSpec change
4
+ ---
5
+
6
+ Run Playwright E2E verification for an OpenSpec change.
7
+
8
+ Invoke the `/openspec-e2e` skill to run Playwright E2E verification.
@@ -0,0 +1,138 @@
1
+ ---
2
+ name: openspec-e2e
3
+ description: Run Playwright E2E verification for an OpenSpec change. Use when the user wants to validate that the implementation works end-to-end by running Playwright tests generated from the specs.
4
+ license: MIT
5
+ compatibility: Requires openspec CLI, Playwright (with browsers installed), and @playwright/mcp (globally installed via claude mcp add).
6
+ metadata:
7
+ author: openspec-playwright
8
+ version: "2.0"
9
+ ---
10
+
11
+ 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.
12
+
13
+ **Architecture**: Schema owns templates. CLI handles execution. Skill handles cognitive work.
14
+
15
+ ## Steps
16
+
17
+ ### 1. Select the change
18
+
19
+ If a name is provided (e.g., `/opsx:e2e add-auth`), use it. Otherwise:
20
+ - Infer from conversation context if the user mentioned a change
21
+ - Auto-select if only one active change exists
22
+ - If ambiguous, run `openspec list --json` and use the **AskUserQuestion tool** to let the user select
23
+
24
+ After selecting, announce: "Using change: `<name>`" and how to override.
25
+
26
+ Verify specs exist:
27
+ ```bash
28
+ openspec status --change "<name>" --json
29
+ ```
30
+ If `openspec/changes/<name>/specs/` is empty, inform the user and stop. E2E requires specs.
31
+
32
+ ### 2. Read specs and detect auth
33
+
34
+ Read all files from `openspec/changes/<name>/specs/*.md`. Extract functional requirements.
35
+
36
+ Detect if auth is required. Mark as **auth required** only when BOTH conditions are met:
37
+
38
+ **Condition A — Explicit markers**: "login", "signin", "logout", "authenticate", "protected", "authenticated", "session", "unauthorized"
39
+
40
+ **Condition B — Context indicators**: Protected routes ("/dashboard", "/profile", "/admin"), role mentions ("admin", "user"), redirect flows
41
+
42
+ **Exclude false positives** — HTTP header examples (`Authorization: Bearer ...`) and code snippets do not count.
43
+
44
+ **Confidence levels**:
45
+ - High (auto-proceed): Multiple explicit markers AND context indicators
46
+ - Medium (proceed with note): Single explicit marker, context unclear
47
+ - Low (skip auth): No explicit markers found
48
+
49
+ ### 3. Generate test plan
50
+
51
+ Create `openspec/changes/<name>/specs/playwright/test-plan.md` by:
52
+ - Listing each functional requirement as a test case
53
+ - Marking each with `@role(user|admin|guest|none)` and `@auth(required|none)`
54
+ - Including happy path AND key error paths
55
+ - Referencing the route/page each test targets
56
+
57
+ **Idempotency**: If test-plan.md already exists → read it, use it, do NOT regenerate unless user explicitly asks.
58
+
59
+ ### 4. Generate test file
60
+
61
+ Create `tests/playwright/<name>.spec.ts`:
62
+ - Follow the page object pattern from `tests/playwright/seed.spec.ts`
63
+ - Prefer `data-testid` selectors, fall back to semantic selectors
64
+ - Each test maps to one test case from the test-plan
65
+ - Use `@project(admin)` / `@project(user)` for role-specific tests
66
+ - Cover happy path AND key error paths
67
+
68
+ **Idempotency**: If test file exists → diff against test-plan, add only missing test cases, preserve existing implementations.
69
+
70
+ ### 5. Configure auth (if required)
71
+
72
+ If auth is required:
73
+
74
+ **API login**: If specs mention `/api/auth/login` or similar → generate `tests/playwright/auth.setup.ts` using API login with `E2E_USERNAME`/`E2E_PASSWORD`.
75
+
76
+ **UI login**: Otherwise → generate `tests/playwright/auth.setup.ts` using UI login. Update selectors to match the login page (look for `data-testid` attributes or fallback to `input[name="..."]`).
77
+
78
+ **Multi-user**: If specs mention multiple roles (admin + user) → generate separate `auth.setup.ts` blocks for each role with different `storageState` paths.
79
+
80
+ **Prompt user** with:
81
+ ```
82
+ Auth required. To set up credentials:
83
+
84
+ 1. Customize tests/playwright/credentials.yaml with your test user
85
+ 2. Export: export E2E_USERNAME=xxx E2E_PASSWORD=yyy
86
+ 3. Run auth: npx playwright test --project=setup
87
+ 4. Then re-run /opsx:e2e to execute tests
88
+ ```
89
+
90
+ **Idempotency**: If `auth.setup.ts` already exists → verify format, update only if stale.
91
+
92
+ ### 6. Configure playwright.config.ts (non-destructive)
93
+
94
+ 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:
95
+ - **BASE_URL**: from `process.env.BASE_URL`, falling back to `tests/playwright/seed.spec.ts` → `BASE_URL` value, then `http://localhost:3000`
96
+ - **Dev command**: from `package.json` → scripts in order: `dev` → `start` → `serve` → `preview` → `npm run dev`
97
+
98
+ 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.
99
+
100
+ ### 7. Execute tests via CLI
101
+
102
+ ```bash
103
+ openspec-pw run <name> --project=<role>
104
+ ```
105
+ (Add `--project=user` or `--project=admin` for role-specific tests.)
106
+
107
+ The CLI handles:
108
+ - Server lifecycle (start → wait for HTTP → test → stop)
109
+ - Port mismatch detection
110
+ - Report generation at `openspec/reports/playwright-e2e-<name>-<timestamp>.md`
111
+
112
+ If tests fail → analyze failures, use Playwright MCP tools to inspect UI state, fix selectors in the test file, and re-run.
113
+
114
+ **Cap auto-heal attempts at 3** to prevent infinite loops.
115
+
116
+ ### 8. Report results
117
+
118
+ Read the report generated by `openspec-pw run` and present it to the user:
119
+ - Summary table (tests run, passed, failed, duration, final status)
120
+ - Any auto-heal notes
121
+ - Recommendations for failed tests (with specific file:line references)
122
+
123
+ ---
124
+
125
+ ## Verification Heuristics
126
+
127
+ - **Coverage**: Every functional requirement → at least one test
128
+ - **Selector robustness**: Prefer `data-testid`, fallback to semantic selectors
129
+ - **False positives**: If test fails due to test bug (not app bug) → fix the test
130
+ - **Actionability**: Every failed test needs a specific recommendation
131
+
132
+ ## Guardrails
133
+
134
+ - Read specs from `openspec/changes/<name>/specs/` as source of truth
135
+ - Do NOT generate tests that contradict the specs
136
+ - Do NOT overwrite files outside: `specs/playwright/`, `tests/playwright/`, `openspec/reports/`, `playwright.config.ts`, `tests/auth.setup.ts`
137
+ - Cap auto-heal at 3 attempts
138
+ - If no change specified → always ask user to select
@@ -0,0 +1,41 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ jobs:
9
+ release:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: write
13
+
14
+ steps:
15
+ - name: Checkout
16
+ uses: actions/checkout@v4
17
+
18
+ - name: Setup Node.js
19
+ uses: actions/setup-node@v4
20
+ with:
21
+ node-version: '20'
22
+ registry-url: 'https://registry.npmjs.org'
23
+
24
+ - name: Install dependencies
25
+ run: npm ci
26
+
27
+ - name: Build
28
+ run: npm run build
29
+
30
+ - name: Create GitHub Release
31
+ uses: softprops/action-gh-release@v2
32
+ with:
33
+ generate_release_notes: true
34
+ files: dist/**/*
35
+ env:
36
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37
+
38
+ - name: Publish to npm
39
+ run: npm publish --access public
40
+ env:
41
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/README.md ADDED
@@ -0,0 +1,133 @@
1
+ # OpenSpec + Playwright E2E Verification
2
+
3
+ [中文说明](./README.zh-CN.md)
4
+
5
+ A setup tool that integrates OpenSpec's spec-driven development with Playwright's three-agent test pipeline for automated E2E verification.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install -g https://github.com/wxhou/openspec-playwright/archive/refs/heads/main.tar.gz
11
+ ```
12
+
13
+ ## Setup
14
+
15
+ ```bash
16
+ # In your project directory
17
+ openspec init # Initialize OpenSpec
18
+ openspec-pw init # Install Playwright E2E integration
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ### In Claude Code
24
+
25
+ ```bash
26
+ /opsx:e2e my-feature # Primary command (OpenSpec convention)
27
+ /openspec-e2e # Alternative from skill
28
+ ```
29
+
30
+ ### CLI Commands
31
+
32
+ ```bash
33
+ openspec-pw init # Initialize integration (one-time setup)
34
+ openspec-pw update # Update CLI and skill to latest version
35
+ openspec-pw doctor # Check prerequisites
36
+ ```
37
+
38
+ ## How It Works
39
+
40
+ ```
41
+ /openspec-e2e <change-name>
42
+
43
+ ├── 1. Read OpenSpec specs from openspec/changes/<name>/specs/
44
+
45
+ ├── 2. Planner Agent → generates test-plan.md
46
+
47
+ ├── 3. Generator Agent → creates tests/playwright/<name>.spec.ts
48
+
49
+ └── 4. Healer Agent → runs tests + auto-heals failures
50
+
51
+ └── Report: openspec/reports/playwright-e2e-<name>.md
52
+ ```
53
+
54
+ ### Two Verification Layers
55
+
56
+ | Layer | Command | What it checks |
57
+ |-------|---------|----------------|
58
+ | Static | `/opsx:verify` | Implementation matches artifacts |
59
+ | E2E | `/opsx:e2e` | App works when running |
60
+
61
+ ## Prerequisites
62
+
63
+ 1. **Node.js >= 20**
64
+ 2. **OpenSpec** initialized: `npm install -g @fission-ai/openspec && openspec init`
65
+ 3. **Claude Code** with Playwright MCP configured
66
+
67
+ ## What `openspec-pw init` Does
68
+
69
+ 1. Installs Playwright MCP globally via `claude mcp add`
70
+ 2. Installs `/opsx:e2e` command and `/openspec-e2e` skill
71
+ 3. Generates `tests/playwright/seed.spec.ts`, `auth.setup.ts`, `credentials.yaml`
72
+
73
+ > **Note**: After running `openspec-pw init`, manually install Playwright browsers: `npx playwright install --with-deps`
74
+
75
+ ## Authentication
76
+
77
+ If your app requires login, set up credentials once, then all tests run authenticated automatically.
78
+
79
+ ```bash
80
+ # 1. Edit credentials
81
+ vim tests/playwright/credentials.yaml
82
+
83
+ # 2. Set environment variables
84
+ export E2E_USERNAME=your-email@example.com
85
+ export E2E_PASSWORD=your-password
86
+
87
+ # 3. Record login (one-time — opens browser, log in manually)
88
+ npx playwright test --project=setup
89
+
90
+ # 4. All subsequent tests use the saved session
91
+ /opsx:e2e my-feature
92
+ ```
93
+
94
+ Supports **API login** (preferred) and **UI login** (fallback). For multi-user tests (admin vs user), add multiple users in `credentials.yaml` and run `/opsx:e2e` — it auto-detects roles from specs.
95
+
96
+ ## Customization
97
+
98
+ ### Customize seed test
99
+
100
+ Edit `tests/playwright/seed.spec.ts` to match your app's:
101
+ - Base URL
102
+ - Common selectors
103
+ - Page object methods
104
+
105
+ ### Authentication credentials
106
+
107
+ Edit `tests/playwright/credentials.yaml`:
108
+ - Set login API endpoint (or leave empty for UI login)
109
+ - Configure test user credentials
110
+ - Add multiple users for role-based tests
111
+
112
+ ### MCP server
113
+
114
+ Playwright MCP is installed globally via `claude mcp add`. Restart Claude Code after setup to activate.
115
+
116
+ ## Architecture
117
+
118
+ ```
119
+ openspec-pw (CLI - setup only)
120
+ ├── Installs Playwright agents (.github/)
121
+ ├── Installs Playwright MCP globally via claude mcp add
122
+ ├── Installs Claude Code skill (/openspec-e2e)
123
+ └── Installs command (/opsx:e2e)
124
+
125
+ /openspec-e2e (Claude Code skill - runs in Claude)
126
+ ├── Reads OpenSpec specs
127
+ ├── Triggers Playwright agents via MCP
128
+ └── Generates E2E verification report
129
+ ```
130
+
131
+ ## License
132
+
133
+ MIT
@@ -0,0 +1,118 @@
1
+ # OpenSpec + Playwright E2E 验证
2
+
3
+ [English version](./README.md)
4
+
5
+ 将 OpenSpec 的规格驱动开发工作流与 Playwright 三 Agent 测试管道集成,实现自动化 E2E 验证。
6
+
7
+ ## 安装
8
+
9
+ ```bash
10
+ npm install -g https://github.com/wxhou/openspec-playwright/archive/refs/heads/main.tar.gz
11
+ ```
12
+
13
+ ## 初始化
14
+
15
+ ```bash
16
+ # 在项目目录下
17
+ openspec init # 初始化 OpenSpec
18
+ openspec-pw init # 安装 Playwright E2E 集成
19
+ ```
20
+
21
+ ## 使用
22
+
23
+ ### 在 Claude Code 中
24
+
25
+ ```bash
26
+ /opsx:e2e my-feature # 主命令(遵循 OpenSpec 规范)
27
+ /openspec-e2e # 来自 skill 的别名
28
+ ```
29
+
30
+ ### CLI 命令
31
+
32
+ ```bash
33
+ openspec-pw init # 初始化集成(一次性设置)
34
+ openspec-pw update # 更新 CLI 和 skill 到最新版本
35
+ openspec-pw doctor # 检查前置条件
36
+ ```
37
+
38
+ ## 工作原理
39
+
40
+ ```
41
+ /openspec-e2e <change-name>
42
+
43
+ ├── 1. 从 openspec/changes/<name>/specs/ 读取 OpenSpec specs
44
+
45
+ ├── 2. Planner Agent → 生成 test-plan.md
46
+
47
+ ├── 3. Generator Agent → 创建 tests/playwright/<name>.spec.ts
48
+
49
+ └── 4. Healer Agent → 运行测试 + 自动修复失败
50
+
51
+ └── 报告: openspec/reports/playwright-e2e-<name>.md
52
+ ```
53
+
54
+ ### 两层验证
55
+
56
+ | 层级 | 命令 | 验证内容 |
57
+ |------|------|---------|
58
+ | 静态验证 | `/opsx:verify` | 实现是否符合 artifacts |
59
+ | E2E 验证 | `/opsx:e2e` | 应用运行是否正常 |
60
+
61
+ ## 前置条件
62
+
63
+ 1. **Node.js >= 20**
64
+ 2. **OpenSpec** 已初始化: `npm install -g @fission-ai/openspec && openspec init`
65
+ 3. **Claude Code** 已配置 Playwright MCP
66
+
67
+ ## `openspec-pw init` 做了什么
68
+
69
+ 1. 通过 `claude mcp add` 全局安装 Playwright MCP
70
+ 2. 安装 `/opsx:e2e` 命令和 `/openspec-e2e` skill
71
+ 3. 生成 `tests/playwright/seed.spec.ts`、`auth.setup.ts`、`credentials.yaml`
72
+
73
+ > **注意**:运行 `openspec-pw init` 后,手动安装 Playwright 浏览器:`npx playwright install --with-deps`
74
+
75
+ ## 认证
76
+
77
+ 如果你的应用需要登录,配置一次凭证后,所有测试自动以已登录状态运行。
78
+
79
+ ```bash
80
+ # 1. 编辑凭证
81
+ vim tests/playwright/credentials.yaml
82
+
83
+ # 2. 设置环境变量
84
+ export E2E_USERNAME=your-email@example.com
85
+ export E2E_PASSWORD=your-password
86
+
87
+ # 3. 录制登录(一次性 — 打开浏览器,手动登录一次)
88
+ npx playwright test --project=setup
89
+
90
+ # 4. 后续所有测试自动复用登录状态
91
+ /opsx:e2e my-feature
92
+ ```
93
+
94
+ 支持 **API 登录**(推荐)和 **UI 登录**(备选)。多用户测试(管理员 vs 普通用户)在 `credentials.yaml` 中添加多个用户,`/opsx:e2e` 会从 specs 自动检测角色。
95
+
96
+ ## 自定义
97
+
98
+ ### 自定义 seed 测试
99
+
100
+ 编辑 `tests/playwright/seed.spec.ts` 以匹配你的应用:
101
+ - 基础 URL
102
+ - 常用选择器
103
+ - Page Object 方法
104
+
105
+ ### 认证凭证
106
+
107
+ 编辑 `tests/playwright/credentials.yaml`:
108
+ - 设置登录 API 端点(或留空使用 UI 登录)
109
+ - 配置测试用户凭证
110
+ - 为角色测试添加多用户
111
+
112
+ ### MCP 服务器
113
+
114
+ Playwright MCP 通过 `claude mcp add` 全局安装。设置后需重启 Claude Code 生效。
115
+
116
+ ## 许可
117
+
118
+ MIT
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ # openspec-pw CLI wrapper
3
+ DIR="$(cd "$(dirname "$0")" && pwd)"
4
+ node "$DIR/dist/index.js" "$@"
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/index.js';
@@ -0,0 +1 @@
1
+ export declare function doctor(): Promise<void>;
@@ -0,0 +1,110 @@
1
+ import { existsSync, readFileSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { execSync } from 'child_process';
4
+ import chalk from 'chalk';
5
+ export async function doctor() {
6
+ console.log(chalk.blue('\n🔍 OpenSpec + Playwright E2E Prerequisites Check\n'));
7
+ const projectRoot = process.cwd();
8
+ let allOk = true;
9
+ // Node.js
10
+ console.log(chalk.blue('─── Node.js ───'));
11
+ try {
12
+ const node = execSync('node --version', { encoding: 'utf-8' }).trim();
13
+ console.log(chalk.green(` ✓ Node.js ${node}`));
14
+ }
15
+ catch {
16
+ console.log(chalk.red(' ✗ Node.js not found'));
17
+ allOk = false;
18
+ }
19
+ // npm
20
+ console.log(chalk.blue('\n─── npm ───'));
21
+ try {
22
+ const npm = execSync('npm --version', { encoding: 'utf-8' }).trim();
23
+ console.log(chalk.green(` ✓ npm ${npm}`));
24
+ }
25
+ catch {
26
+ console.log(chalk.red(' ✗ npm not found'));
27
+ allOk = false;
28
+ }
29
+ // OpenSpec
30
+ console.log(chalk.blue('\n─── OpenSpec ───'));
31
+ const hasOpenSpec = existsSync(join(projectRoot, 'openspec'));
32
+ if (hasOpenSpec) {
33
+ console.log(chalk.green(' ✓ OpenSpec initialized'));
34
+ }
35
+ else {
36
+ console.log(chalk.red(' ✗ OpenSpec not initialized'));
37
+ console.log(chalk.gray(' Run: openspec init'));
38
+ allOk = false;
39
+ }
40
+ // Playwright browsers
41
+ console.log(chalk.blue('\n─── Playwright Browsers ───'));
42
+ try {
43
+ const pw = execSync('npx playwright --version', { encoding: 'utf-8' }).trim();
44
+ console.log(chalk.green(` ✓ Playwright ${pw}`));
45
+ }
46
+ catch {
47
+ console.log(chalk.red(' ✗ Playwright browsers not installed'));
48
+ console.log(chalk.gray(' Run: npx playwright install --with-deps'));
49
+ allOk = false;
50
+ }
51
+ // Playwright MCP (global)
52
+ console.log(chalk.blue('\n─── Playwright MCP ───'));
53
+ const homeDir = process.env.HOME ?? '';
54
+ const claudeJsonPath = join(homeDir, '.claude.json');
55
+ let mcpInstalled = false;
56
+ if (existsSync(claudeJsonPath)) {
57
+ try {
58
+ const claudeJson = JSON.parse(readFileSync(claudeJsonPath, 'utf-8'));
59
+ const globalMcp = claudeJson?.mcpServers ?? {};
60
+ const localMcp = claudeJson?.projects?.[projectRoot]?.mcpServers ?? {};
61
+ if (globalMcp['playwright'] || localMcp['playwright']) {
62
+ mcpInstalled = true;
63
+ }
64
+ }
65
+ catch {
66
+ // ignore
67
+ }
68
+ }
69
+ if (mcpInstalled) {
70
+ console.log(chalk.green(' ✓ Playwright MCP installed globally'));
71
+ }
72
+ else {
73
+ console.log(chalk.red(' ✗ Playwright MCP not configured'));
74
+ console.log(chalk.gray(' Run: openspec-pw init'));
75
+ allOk = false;
76
+ }
77
+ // Skill
78
+ console.log(chalk.blue('\n─── Claude Code Skill ───'));
79
+ const hasSkill = existsSync(join(projectRoot, '.claude', 'skills', 'openspec-e2e', 'SKILL.md'));
80
+ if (hasSkill) {
81
+ console.log(chalk.green(' ✓ /openspec-e2e skill installed'));
82
+ }
83
+ else {
84
+ console.log(chalk.red(' ✗ Skill not installed'));
85
+ console.log(chalk.gray(' Run: openspec-pw init'));
86
+ allOk = false;
87
+ }
88
+ // Seed test
89
+ console.log(chalk.blue('\n─── Seed Test ───'));
90
+ const hasSeed = existsSync(join(projectRoot, 'tests', 'playwright', 'seed.spec.ts'));
91
+ if (hasSeed) {
92
+ console.log(chalk.green(' ✓ seed.spec.ts found'));
93
+ }
94
+ else {
95
+ console.log(chalk.yellow(' ⚠ seed.spec.ts not found (optional)'));
96
+ console.log(chalk.gray(' Run: openspec-pw init'));
97
+ }
98
+ // Summary
99
+ console.log(chalk.blue('\n─── Summary ───'));
100
+ if (allOk) {
101
+ console.log(chalk.green(' ✅ All prerequisites met!\n'));
102
+ console.log(chalk.gray(' Run: /opsx:e2e <change-name> in Claude Code\n'));
103
+ }
104
+ else {
105
+ console.log(chalk.red(' ❌ Some prerequisites are missing\n'));
106
+ console.log(chalk.gray(' Run: openspec-pw init to fix\n'));
107
+ process.exit(1);
108
+ }
109
+ }
110
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export interface InitOptions {
2
+ change?: string;
3
+ mcp?: boolean;
4
+ seed?: boolean;
5
+ }
6
+ export declare function init(options: InitOptions): Promise<void>;