prizmkit 1.1.53 → 1.1.55

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 (29) hide show
  1. package/bin/create-prizmkit.js +2 -0
  2. package/bundled/VERSION.json +3 -3
  3. package/bundled/rules/_rules-metadata.json +6 -1
  4. package/bundled/rules/general/cohesive-modeling.md +27 -0
  5. package/bundled/skills/_metadata.json +1 -1
  6. package/bundled/skills/app-planner/SKILL.md +114 -4
  7. package/bundled/skills/app-planner/references/rules/backend/derivation-rules.md +609 -0
  8. package/bundled/skills/app-planner/references/rules/backend/fixed-rules.md +285 -0
  9. package/bundled/skills/app-planner/references/rules/backend/question-bank.md +249 -0
  10. package/bundled/skills/app-planner/references/rules/backend/template.md +173 -0
  11. package/bundled/skills/app-planner/references/rules/database/derivation-rules.md +373 -0
  12. package/bundled/skills/app-planner/references/rules/database/fixed-rules.md +211 -0
  13. package/bundled/skills/app-planner/references/rules/database/question-bank.md +184 -0
  14. package/bundled/skills/app-planner/references/rules/database/template.md +158 -0
  15. package/bundled/skills/app-planner/references/rules/frontend/derivation-rules.md +810 -0
  16. package/bundled/skills/app-planner/references/rules/frontend/fixed-rules.md +188 -0
  17. package/bundled/skills/app-planner/references/rules/frontend/question-bank.md +302 -0
  18. package/bundled/skills/app-planner/references/rules/frontend/template.md +320 -0
  19. package/bundled/skills/app-planner/references/rules/mobile/derivation-rules.md +639 -0
  20. package/bundled/skills/app-planner/references/rules/mobile/fixed-rules.md +290 -0
  21. package/bundled/skills/app-planner/references/rules/mobile/question-bank.md +232 -0
  22. package/bundled/skills/app-planner/references/rules/mobile/template.md +175 -0
  23. package/bundled/skills/prizm-kit/SKILL.md +1 -1
  24. package/bundled/skills/prizmkit-init/SKILL.md +47 -6
  25. package/bundled/skills/prizmkit-init/references/config-schema.md +7 -3
  26. package/bundled/skills/prizmkit-init/references/rules/layer-detection.md +41 -0
  27. package/package.json +1 -1
  28. package/src/index.js +10 -0
  29. package/src/scaffold.js +124 -7
@@ -0,0 +1,175 @@
1
+ # Mobile Rules — {{ project_name }}
2
+
3
+ > This document was generated by the `mobile-rules` skill on {{ generated_at }}
4
+ > Audience: All mobile developers + all AI coding assistants on this project
5
+ >
6
+ > **Usage**:
7
+ > 1. All AI coding assistants must read this file before generating or modifying any mobile code
8
+ > 2. This document takes precedence over "general best practices" in AI training data
9
+ > 3. Code conflicting with this document must not be committed
10
+
11
+ ---
12
+
13
+ ## 0. TL;DR — Key Decisions at a Glance
14
+
15
+ | Dimension | Decision |
16
+ |-----------|----------|
17
+ | Platform | {{ platform }} |
18
+ | Min OS Version | {{ min_os_version }} |
19
+ | Architecture Pattern | {{ architecture }} |
20
+ | UI Framework | {{ ui_framework }} |
21
+ | Navigation | {{ navigation }} |
22
+ | State Management | {{ state_management }} |
23
+ | Networking | {{ networking }} |
24
+ | Local Persistence | {{ persistence }} |
25
+ | Push Notifications | {{ push_notifications }} |
26
+ | Background Tasks | {{ background_tasks }} |
27
+ | Permissions Strategy | {{ permissions_strategy }} |
28
+ | Test Coverage | {{ test_coverage }} |
29
+ | Unit Test Framework | {{ unit_test_framework }} |
30
+ | E2E Test Framework | {{ e2e_framework }} |
31
+ | Distribution | {{ distribution }} |
32
+ | Performance Target | {{ performance_target }} |
33
+ | Accessibility Target | {{ a11y_target }} |
34
+
35
+ ---
36
+
37
+ ## 1. Project Structure
38
+
39
+ {{ FIXED_RULES_STRUCTURE }}
40
+
41
+ {{ tech_stack_rules }}
42
+
43
+ ---
44
+
45
+ ## 2. UI Development
46
+
47
+ {{ FIXED_RULES_UI }}
48
+
49
+ {{ ui_rules }}
50
+
51
+ ---
52
+
53
+ ## 3. Navigation & Deep Linking
54
+
55
+ {{ FIXED_RULES_NAVIGATION }}
56
+
57
+ {{ navigation_rules }}
58
+
59
+ ---
60
+
61
+ ## 4. State Management
62
+
63
+ {{ FIXED_RULES_STATE }}
64
+
65
+ {{ state_rules }}
66
+
67
+ ---
68
+
69
+ ## 5. Networking
70
+
71
+ {{ FIXED_RULES_NETWORKING }}
72
+
73
+ {{ networking_rules }}
74
+
75
+ ---
76
+
77
+ ## 6. Data Persistence
78
+
79
+ {{ FIXED_RULES_PERSISTENCE }}
80
+
81
+ {{ persistence_rules }}
82
+
83
+ ---
84
+
85
+ ## 7. Platform Features
86
+
87
+ {{ FIXED_RULES_PLATFORM_FEATURES }}
88
+
89
+ {{ platform_features_rules }}
90
+
91
+ ---
92
+
93
+ ## 8. Performance
94
+
95
+ {{ FIXED_RULES_PERFORMANCE }}
96
+
97
+ {{ performance_rules }}
98
+
99
+ ---
100
+
101
+ ## 9. Accessibility
102
+
103
+ {{ FIXED_RULES_A11Y }}
104
+
105
+ {{ a11y_rules }}
106
+
107
+ ---
108
+
109
+ ## 10. Security
110
+
111
+ {{ FIXED_RULES_SECURITY }}
112
+
113
+ ---
114
+
115
+ ## 11. Testing
116
+
117
+ {{ FIXED_RULES_TEST }}
118
+
119
+ {{ test_rules }}
120
+
121
+ ---
122
+
123
+ ## 12. App Distribution
124
+
125
+ {{ FIXED_RULES_DISTRIBUTION }}
126
+
127
+ {{ distribution_rules }}
128
+
129
+ ---
130
+
131
+ ## 13. AI Vibecoding Behavior Constraints
132
+
133
+ ### 13.1 Baseline Constraints (project-agnostic, always active)
134
+
135
+ {{ FIXED_RULES_AI_BASE }}
136
+
137
+ ### 13.2 Project-Specific Hard Constraints
138
+
139
+ - **Adding dependencies**: {{ ai_dependency_rule }}
140
+ - **Modifying shared code**: {{ ai_breaking_change_rule }}
141
+ - **Platform-specific code**: {{ ai_platform_rule }}
142
+
143
+ ### 13.3 Mandatory Pre-Actions (before every code generation)
144
+
145
+ AI must complete the following in order before generating or modifying any mobile code:
146
+
147
+ 1. Read this file (`mobile-rules.md`)
148
+ 2. Read existing files in the target feature's directory to confirm whether similar functionality already exists
149
+ 3. If modifying shared widgets/components/services, search all callers and assess platform impact
150
+ 4. If modifying navigation routes or deep link schemes, assess all entry points
151
+
152
+ ---
153
+
154
+ ## 14. Architecture
155
+
156
+ {{ arch_rules }}
157
+
158
+ ---
159
+
160
+ ## Appendix A: Deny List (Quick Reference)
161
+
162
+ > This appendix is auto-generated by AI in Phase 4 by extracting all forbidden entries from each section.
163
+
164
+ {{ deny_list_summary }}
165
+
166
+ ## Appendix B: Recommended Libraries & Tools
167
+
168
+ > This appendix is auto-generated by AI in Phase 4 to recommend the supporting ecosystem based on platform and framework choices.
169
+
170
+ {{ recommended_libs }}
171
+
172
+ ---
173
+
174
+ **Version**: v1.0 — Generated on {{ generated_at }}
175
+ **Next review recommended**: before tech stack changes or platform migration
@@ -18,7 +18,7 @@ Each task begins by reading context at two levels:
18
18
 
19
19
  **Application level** (read every session):
20
20
  - `.prizmkit/prizm-docs/root.prizm` — L0 project architecture index (modules, tech stack, conventions)
21
- - `.prizmkit/plans/project-brief.md` — user's product vision checklist (generated by app-planner)
21
+ - `.prizmkit/plans/project-brief.md` — user's product vision checklist (generated during project initialization)
22
22
  - `.prizmkit/config.json` — tech stack config, deploy strategy
23
23
 
24
24
  **Task level** (read for the specific task):
@@ -90,9 +90,22 @@ BROWNFIELD WORKFLOW (existing project):
90
90
 
91
91
  **IMPORTANT**: Not all projects have all fields. A pure backend API will have no `frontend_framework` or `frontend_styling`. A library may have no database. Only record what is actually detected — never generate empty or placeholder values.
92
92
 
93
- **Phase 4.5: Infrastructure Quick Scan**
93
+ **Phase 4.5: Layer Detection**
94
94
 
95
- Detect database and deployment signals, then ask 1-2 brief questions. This phase is **optional**users can skip and configure later via `app-planner` or `/prizmkit-deploy`.
95
+ After tech stack detection, determine which development layers exist in the project — these are code domains that may benefit from custom dev rules (frontend, backend, database, mobile). This is a quick detection step, not an interactive Q&A rules can be configured later based on detected layers.
96
+
97
+ 1. Read `${SKILL_DIR}/references/rules/layer-detection.md` for the detection signal table and AI judgment guidelines.
98
+ 2. Scan the project against each signal, and supplement with your own judgment — the signal table is a guide, not exhaustive. If you see clear evidence of a layer not covered by the table, include it. If a signal matches but context is misleading, downgrade or ignore it:
99
+ - **frontend**: React/Vue/Angular/etc. in dependencies, or `src/components/` with UI files
100
+ - **backend**: Express/FastAPI/Gin/etc. in dependencies, or `routes/`/`controllers/` with server code
101
+ - **database**: Prisma/TypeORM/SQLAlchemy/etc. in dependencies, or `migrations/`/`prisma/` directory
102
+ - **mobile**: `pubspec.yaml` (Flutter), `react-native` in package.json, or simultaneous `ios/`+`android/` directories
103
+ 3. For mobile signals — if ambiguous (e.g., monorepo with web + ios/android dirs), use `AskUserQuestion` to confirm: "Mobile platform signals detected. Is this project a mobile app?" Options: "Yes, this is a mobile app" / "No, these are for another purpose".
104
+ 4. Assemble `detected_layers` array (e.g., `["frontend", "backend", "database"]`). If no layers detected (library/CLI project), array is empty.
105
+
106
+ **Phase 4.6: Infrastructure Quick Scan**
107
+
108
+ Detect database and deployment signals, then ask 1-2 brief questions. This phase is **optional** — users can skip and configure later.
96
109
 
97
110
  - **BROWNFIELD**: Auto-detect infrastructure signals from existing files, then ask 1-2 brief questions (pre-filled with detection results)
98
111
  - **GREENFIELD**: No auto-detection possible — ask the 2 brief questions directly (database need and deployment target)
@@ -136,7 +149,7 @@ Detect database and deployment signals, then ask 1-2 brief questions. This phase
136
149
  #### Deployment
137
150
  - **Target**: [platform name or "undecided"]
138
151
  ```
139
- → This is intentionally minimal (Quick Scan). Full conventions and deployment details will be added by app-planner or prizmkit-deploy later.
152
+ → This is intentionally minimal (Quick Scan). Full conventions and deployment details can be added later.
140
153
  - If user selects "Skip — decide later" for BOTH topics: write deferred marker instead:
141
154
  ```markdown
142
155
  ### Infrastructure
@@ -148,6 +161,20 @@ Detect database and deployment signals, then ask 1-2 brief questions. This phase
148
161
  <!-- database: deferred -->
149
162
  ```
150
163
 
164
+ **Phase 4.7: Rules Quick Entry**
165
+
166
+ After Infrastructure Quick Scan completes, check if `detected_layers` is non-empty (from Phase 4.5). If layers were detected, offer a lightweight entry point for rules configuration.
167
+
168
+ 1. If `detected_layers` is empty (library/CLI project) → skip this phase entirely, proceed to Phase 5.
169
+ 2. If layers detected, use `AskUserQuestion`:
170
+
171
+ **Question**: "Detected **{list detected layers}** code. Would you like to set up custom development rules for AI to follow? This helps AI generate code that matches your conventions."
172
+ - **Configure later (Recommended)** — Record layers and configure rules later
173
+ - **Skip entirely** — no custom rules, AI uses general best practices
174
+
175
+ 3. If user picked "Skip entirely" → clear `detected_layers` to empty array, proceed to Phase 5.
176
+ 4. If user picked "Configure later" → keep `detected_layers`, proceed to Phase 5. The layers will be written to config.json in Phase 6.
177
+
151
178
  **Phase 5: Prizm Documentation Generation**
152
179
  Invoke prizmkit-prizm-docs (Init operation), passing the two-tier module structure from Phase 4:
153
180
  - Create `.prizmkit/prizm-docs/` directory structure mirroring the source tree (sub-module dirs become subdirectories under `.prizmkit/prizm-docs/<top-level>/`)
@@ -166,6 +193,12 @@ Invoke prizmkit-prizm-docs (Init operation), passing the two-tier module structu
166
193
  6b. Write detected tech stack to `.prizmkit/config.json`:
167
194
  → Read `${SKILL_DIR}/references/config-schema.md` for merge strategy, field definitions, and examples.
168
195
 
196
+ 6c. Write `detected_layers` to `.prizmkit/config.json` (alongside `tech_stack`):
197
+ - Field: `"detected_layers": ["frontend", "backend"]` — the layers from Phase 4.5
198
+ - If user chose "Skip entirely" in Phase 4.7, write empty array `[]`
199
+ - For greenfield projects (Phase 4.5 skipped): write `[]` — no code layers to configure rules for yet; user can configure rules later when code exists
200
+ - This field indicates which development layers exist in the project and can be used to determine available rule configuration options.
201
+
169
202
  **Phase 7: Project Brief Generation**
170
203
 
171
204
  If action for project brief == skip, output "Project brief: skipped (exists)" and proceed to Phase 8 (Report).
@@ -225,11 +258,12 @@ Saved to: `.prizmkit/config.json` → `tech_stack` field
225
258
  Next step: "Use `/prizmkit-plan` to start your first feature"
226
259
 
227
260
  GREENFIELD WORKFLOW (new project):
228
- - Skip Phase 4 (no code to scan)but ask the user about their intended tech stack:
261
+ - Skip Phase 4 code scanning (no code to scan — Phase 4.5 Layer Detection and Phase 4.7 Rules Quick Entry are skipped; no layers to detect yet):
262
+ - Ask the user about their intended tech stack:
229
263
  - "What language/framework will you use?" (e.g. React + Node.js, Python + FastAPI, etc.)
230
264
  - Record answers in `config.json` `tech_stack` with `"_auto_detected": false` (user-provided, not auto-detected)
231
265
  - If user is unsure, skip tech_stack — it can be populated later on re-init after code exists
232
- - Phase 4.5: Run Infrastructure Quick Scan — in greenfield mode, no auto-detection is possible, so only ask the 2 brief questions (database need and deployment target). If user is unsure, skip — these can be configured later via `app-planner` or `/prizmkit-deploy`.
266
+ - Phase 4.6: Run Infrastructure Quick Scan — in greenfield mode, no auto-detection is possible, so only ask the 2 brief questions (database need and deployment target). If user is unsure, skip — these can be configured later.
233
267
  - Phase 5: Create minimal `.prizmkit/prizm-docs/` with just `root.prizm` skeleton (populate TECH_STACK from user answers if provided)
234
268
  - Phase 7: Generate project brief (greenfield flow — ask user about project goals, see Phase 7 above)
235
269
  - Phases 6, 8: Same as brownfield (Phase 8 Report recommends `/prizmkit-plan` for first feature)
@@ -259,11 +293,18 @@ Tech stack detected:
259
293
  Bundler: Vite
260
294
  Project type: fullstack
261
295
 
296
+ Layer Detection:
297
+ Detected layers: frontend, backend, database (from dependency + directory signals)
298
+ → Stored for config.json
299
+
262
300
  Infrastructure Quick Scan:
263
301
  Database: PostgreSQL (Prisma) — detected from dependencies
264
302
  Deployment: Vercel — detected from vercel.json
265
303
  → Written to CLAUDE.md ### Infrastructure
266
304
 
305
+ Rules Quick Entry:
306
+ Matched layers: frontend (React), backend (Express.js), database (Prisma) → keeping default rules
307
+
267
308
  Modules discovered:
268
309
  src/routes/ → .prizmkit/prizm-docs/routes.prizm (12 files)
269
310
  src/models/ → .prizmkit/prizm-docs/models.prizm (8 files)
@@ -274,7 +315,7 @@ Project brief: inferred from codebase → confirmed by user
274
315
  → .prizmkit/plans/project-brief.md
275
316
 
276
317
  Generated: root.prizm + 4 L1 docs + changelog.prizm
277
- Saved: .prizmkit/config.json (tech_stack recorded)
318
+ Saved: .prizmkit/config.json (tech_stack + detected_layers recorded)
278
319
 
279
320
  Next: Use /prizmkit-plan to start your first feature
280
321
  ```
@@ -7,10 +7,11 @@ Handles re-init without losing user edits:
7
7
  - Read existing `config.json` if present
8
8
  - If `tech_stack` field exists AND `_auto_detected` is `false` or absent:
9
9
  → **SKIP** — user has manually configured tech stack, preserve their settings
10
+ - Always update `detected_layers` with new layer detection results on every init run — layer detection is based on code that exists, not user preference. This ensures greenfield projects that later gain code get their `detected_layers` populated correctly. Note: the final value written is still determined by Phase 6c (e.g., if user chose "Skip entirely" in Phase 4.7, Phase 6c writes `[]` regardless of detection results).
10
11
  - If `tech_stack` field exists AND `_auto_detected` is `true`:
11
- → **MERGE** — overwrite auto-detected values with new detection results, but preserve any keys the user added manually (keys not in the new detection result)
12
+ → **MERGE** — overwrite auto-detected values with new detection results, but preserve any keys the user added manually (keys not in the new detection result). Overwrite `detected_layers` with new layer detection results.
12
13
  - If `tech_stack` field does NOT exist:
13
- → **WRITE** full detected tech stack with `"_auto_detected": true`
14
+ → **WRITE** full detected tech stack with `"_auto_detected": true`, and write `detected_layers` from layer detection
14
15
  - Only include fields that were actually detected (no empty/null values)
15
16
 
16
17
  ## Field Definitions
@@ -21,6 +22,7 @@ Handles re-init without losing user edits:
21
22
  | `platform` | string | `"codebuddy"` \| `"claude"` \| `"both"` |
22
23
  | `tech_stack` | object | Detected or user-provided tech stack |
23
24
  | `tech_stack._auto_detected` | boolean | `true` if auto-detected, `false` if user-provided |
25
+ | `detected_layers` | string[] | Development layers detected in the project. Written by prizmkit-init Phase 4.5. Used to determine available rule configuration options. Values: `frontend` / `backend` / `database` / `mobile`. Empty array when no layers detected or user skipped rules. Always updated on every init run based on fresh code detection — not gated by `_auto_detected` (see Merge Strategy above). |
24
26
 
25
27
  ## Examples
26
28
 
@@ -29,6 +31,7 @@ Fullstack project:
29
31
  {
30
32
  "adoption_mode": "passive",
31
33
  "platform": "claude",
34
+ "detected_layers": ["frontend", "backend", "database"],
32
35
  "tech_stack": {
33
36
  "language": "TypeScript",
34
37
  "runtime": "Node.js 20",
@@ -59,6 +62,7 @@ Pure Python backend:
59
62
  "testing": "pytest",
60
63
  "project_type": "backend",
61
64
  "_auto_detected": true
62
- }
65
+ },
66
+ "detected_layers": ["backend", "database"]
63
67
  }
64
68
  ```
@@ -0,0 +1,41 @@
1
+ # Layer Detection — Signal Reference Table
2
+
3
+ > Load this file in Phase 4.5 to determine which development layers exist in the project.
4
+ > A "layer" means a distinct code domain that may benefit from custom dev rules.
5
+
6
+ ## Detection Signals
7
+
8
+ > **This table is a reference guide, not an exhaustive checklist.** The signals below cover common frameworks and patterns, but the list cannot be complete — new frameworks emerge, projects use unconventional setups, and context matters more than any single string match. In addition to matching against these signals, **apply your own judgment**: if you see files, directories, or dependencies that clearly indicate a development layer (even if not listed below), include it. If a signal matches but context suggests it's misleading (e.g., a dependency present but not actually used as the primary tech), downgrade or ignore it. The goal is to accurately reflect what the project contains, not to mechanically match strings.
9
+
10
+ | Layer | Signal Source | Detection Rule |
11
+ |-------|--------------|----------------|
12
+ | **frontend** | `package.json` dependencies | Contains `react`, `vue`, `angular`, `next`, `nuxt`, `svelte`, `solid-js`, `preact`, `remix`, `astro`, `qwik` |
13
+ | **frontend** | `package.json` devDependencies | Contains `vite`, `webpack`, `parcel`, `turbo` |
14
+ | **frontend** | Directory | `src/components/`, `pages/`, `app/` with `.tsx`/`.jsx`/`.vue` files |
15
+ | **backend** | `package.json` dependencies | Contains `express`, `fastify`, `koa`, `hono`, `nest`, `next` (API routes) |
16
+ | **backend** | `requirements.txt` / `pyproject.toml` | Contains `fastapi`, `django`, `flask`, `sanic`, `litestar` |
17
+ | **backend** | `go.mod` | Contains `gin-gonic`, `echo`, `fiber`, `chi` |
18
+ | **backend** | `pom.xml` / `build.gradle` | Contains `spring-boot`, `quarkus`, `micronaut`, `ktor` |
19
+ | **backend** | Directory | `routes/`, `controllers/`, `handlers/`, `api/`, `internal/` with server code |
20
+ | **database** | `package.json` dependencies | Contains `prisma`, `typeorm`, `sequelize`, `mongoose`, `knex`, `drizzle-orm`, `kysely` |
21
+ | **database** | `requirements.txt` / `pyproject.toml` | Contains `sqlalchemy`, `django` (ORM), `pony`, `peewee`, `tortoise-orm` |
22
+ | **database** | `go.mod` | Contains `gorm`, `sqlx`, `sqlc`, `ent`, `bun` |
23
+ | **database** | Directory | `migrations/`, `prisma/`, `alembic/`, `db/`, `schema/` |
24
+ | **database** | Environment | `.env*` contains `DATABASE_URL`, `DB_HOST`, `DB_NAME`, `MONGO_URI` |
25
+ | **mobile** | File | `pubspec.yaml` exists (Flutter) |
26
+ | **mobile** | `package.json` dependencies | Contains `react-native`, `expo` |
27
+ | **mobile** | Directory | Both `ios/*.xcodeproj` + `android/build.gradle` exist simultaneously |
28
+
29
+ ## Mobile Confirmation
30
+
31
+ When mobile signals are detected but ambiguous (e.g., a monorepo with web + mobile), use `AskUserQuestion`:
32
+
33
+ > "Mobile platform signals detected (ios/ + android/ directories). Is this project
34
+ > a mobile app, or are these directories for another purpose?"
35
+ > Options: "Yes, this is a mobile app" / "No, these are for another purpose"
36
+
37
+ ## Output
38
+
39
+ After detection (signals + your own judgment), assemble `detected_layers` array (e.g., `["frontend", "backend", "database"]`).
40
+ Store in memory for Phase 6 config.json writing.
41
+ If no layers detected (library/CLI project), array is empty.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prizmkit",
3
- "version": "1.1.53",
3
+ "version": "1.1.55",
4
4
  "description": "Create a new PrizmKit-powered project with clean initialization — no framework dev files, just what you need.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/index.js CHANGED
@@ -69,6 +69,7 @@ export async function runScaffold(directory, options) {
69
69
  pipeline: options.pipeline !== false,
70
70
  playwrightCli: options.playwrightCli !== false,
71
71
  openCli: options.openCli !== false,
72
+ openCliAutoDownload: options.openCliAutoDownload !== false,
72
73
  rules: options.rules || 'recommended',
73
74
  aiCli: options.aiCli || '',
74
75
  externalSkills: options.externalSkills ? options.externalSkills.split(',').map(s => s.trim()).filter(Boolean) : [],
@@ -198,6 +199,14 @@ export async function runScaffold(directory, options) {
198
199
  default: true,
199
200
  });
200
201
 
202
+ let openCliAutoDownload = true;
203
+ if (openCli) {
204
+ openCliAutoDownload = await confirm({
205
+ message: '检测到 Chrome Browser Bridge 扩展缺失时,自动下载扩展包?\n (仍需手动在 Chrome 中加载,但可省去下载解压步骤)',
206
+ default: true,
207
+ });
208
+ }
209
+
201
210
  // 5. Rules 预设
202
211
  const rulesPreset = await select({
203
212
  message: '安装 AI 行为规则 (rules):',
@@ -248,6 +257,7 @@ export async function runScaffold(directory, options) {
248
257
  pipeline,
249
258
  playwrightCli,
250
259
  openCli,
260
+ openCliAutoDownload,
251
261
  rules: rulesPreset,
252
262
  aiCli: aiCli || '',
253
263
  externalSkills: selectedExternalSkills,
package/src/scaffold.js CHANGED
@@ -778,6 +778,27 @@ export async function installPlaywrightCli(projectRoot, dryRun) {
778
778
  console.log(chalk.yellow(` ⚠ Skills install skipped: ${e.message}`));
779
779
  console.log(chalk.yellow(' ⚠ Run manually: playwright-cli install --skills'));
780
780
  }
781
+
782
+ // Install Playwright browser binary (needed for E2E testing via prizmkit-test)
783
+ try {
784
+ const cacheDir = process.env.PLAYWRIGHT_BROWSERS_PATH
785
+ || path.join(process.env.HOME || process.env.USERPROFILE || '.',
786
+ process.platform === 'darwin' ? 'Library/Caches/ms-playwright'
787
+ : process.platform === 'win32' ? 'AppData/Local/ms-playwright'
788
+ : '.cache/ms-playwright');
789
+ const hasChromium = fs.pathExistsSync(cacheDir)
790
+ && fs.readdirSync(cacheDir).some(d => d.startsWith('chromium-'));
791
+ if (hasChromium) {
792
+ console.log(chalk.green(' ✓ Playwright Chromium (already installed)'));
793
+ } else {
794
+ console.log(chalk.blue(' ⏳ Installing Playwright Chromium (needed for E2E testing)...'));
795
+ execSync('npx --yes playwright install chromium', { stdio: 'pipe', timeout: 180000 });
796
+ console.log(chalk.green(' ✓ Playwright Chromium installed'));
797
+ }
798
+ } catch (e) {
799
+ console.log(chalk.yellow(` ⚠ Playwright browser install skipped: ${e.message}`));
800
+ console.log(chalk.yellow(' ⚠ Run manually: npx playwright install chromium'));
801
+ }
781
802
  }
782
803
 
783
804
  // ============================================================
@@ -788,7 +809,7 @@ export async function installPlaywrightCli(projectRoot, dryRun) {
788
809
  * 安装 opencli(全局 npm 包)
789
810
  * 用于浏览器交互验证,复用 Chrome 已登录会话(OAuth/SSO/第三方集成)
790
811
  */
791
- export async function installOpenCli(projectRoot, dryRun) {
812
+ export async function installOpenCli(projectRoot, dryRun, autoDownload = true) {
792
813
  if (dryRun) {
793
814
  console.log(chalk.gray(' [dry-run] @jackwener/opencli (global install)'));
794
815
  return;
@@ -811,10 +832,105 @@ export async function installOpenCli(projectRoot, dryRun) {
811
832
  }
812
833
  }
813
834
 
814
- // Note: opencli requires Chrome + Browser Bridge extension for browser-backed commands.
815
- // The extension must be installed manually — see: https://github.com/jackwener/opencli
816
- console.log(chalk.gray(' OpenCLI requires Chrome + Browser Bridge extension for browser commands'));
817
- console.log(chalk.gray(' Run "opencli doctor" to verify connectivity'));
835
+ // Verify opencli connectivity Chrome Browser Bridge extension is a manual install
836
+ try {
837
+ const doctorOutput = execSync('opencli doctor 2>&1', { stdio: 'pipe', timeout: 15000 }).toString();
838
+ if (doctorOutput.includes('[MISSING] Extension') || doctorOutput.includes('[FAIL] Connectivity')) {
839
+ console.log(chalk.yellow(' ⚠ Chrome Browser Bridge extension is NOT connected'));
840
+
841
+ if (autoDownload) {
842
+ await downloadOpenCliExtension(projectRoot);
843
+ } else {
844
+ printOpenCliManualSteps();
845
+ }
846
+ } else {
847
+ console.log(chalk.green(' ✓ opencli connectivity verified'));
848
+ }
849
+ } catch {
850
+ // doctor command itself failed — already warned about install issues
851
+ }
852
+ }
853
+
854
+ // ============================================================
855
+ // OpenCLI Extension 下载/指引
856
+ // ============================================================
857
+
858
+ /**
859
+ * 从 GitHub releases 下载并解压 opencli Chrome 扩展。
860
+ * 省去用户手动下载解压步骤,但仍需在 Chrome 中手动加载。
861
+ */
862
+ async function downloadOpenCliExtension(projectRoot) {
863
+ const extDir = path.join(process.env.HOME || process.env.USERPROFILE || '.', '.opencli', 'extension');
864
+
865
+ // Check if already downloaded
866
+ const manifestPath = path.join(extDir, 'manifest.json');
867
+ if (fs.pathExistsSync(manifestPath)) {
868
+ console.log(chalk.green(` ✓ Extension already downloaded at ${extDir}`));
869
+ printOpenCliLoadSteps(extDir);
870
+ return;
871
+ }
872
+
873
+ try {
874
+ console.log(chalk.blue(' ⏳ Fetching latest extension release info...'));
875
+ const releaseJson = execSync(
876
+ 'curl -sL https://api.github.com/repos/jackwener/OpenCLI/releases/latest',
877
+ { stdio: 'pipe', timeout: 30000 }
878
+ ).toString();
879
+ const release = JSON.parse(releaseJson);
880
+ const extAsset = release.assets?.find(a => a.name?.startsWith('opencli-extension-') && a.name?.endsWith('.zip'));
881
+
882
+ if (!extAsset) {
883
+ console.log(chalk.yellow(' ⚠ Could not find extension asset in latest release'));
884
+ printOpenCliManualSteps();
885
+ return;
886
+ }
887
+
888
+ console.log(chalk.blue(` ⏳ Downloading ${extAsset.name}...`));
889
+ const tmpZip = path.join(extDir, '..', '.opencli-ext-tmp.zip');
890
+ await fs.ensureDir(path.dirname(tmpZip));
891
+ execSync(`curl -sL "${extAsset.browser_download_url}" -o "${tmpZip}"`, { stdio: 'pipe', timeout: 60000 });
892
+
893
+ // Extract (use unzip on macOS/Linux, tar on Windows fallback)
894
+ console.log(chalk.blue(` ⏳ Extracting to ${extDir}...`));
895
+ await fs.ensureDir(extDir);
896
+ execSync(`unzip -o "${tmpZip}" -d "${extDir}"`, { stdio: 'pipe', timeout: 30000 });
897
+ await fs.remove(tmpZip);
898
+
899
+ console.log(chalk.green(` ✓ Extension extracted to ${extDir}`));
900
+ printOpenCliLoadSteps(extDir);
901
+ } catch (e) {
902
+ console.log(chalk.yellow(` ⚠ Extension download failed: ${e.message}`));
903
+ printOpenCliManualSteps();
904
+ }
905
+ }
906
+
907
+ /**
908
+ * 显示手动安装步骤(兜底路径)。
909
+ */
910
+ function printOpenCliManualSteps() {
911
+ console.log(chalk.cyan(' ┌─────────────────────────────────────────────────────────────┐'));
912
+ console.log(chalk.cyan(' │ To enable opencli browser control: │'));
913
+ console.log(chalk.cyan(' │ 1. Download extension from: │'));
914
+ console.log(chalk.cyan(' │ https://github.com/jackwener/opencli/releases │'));
915
+ console.log(chalk.cyan(' │ 2. Unzip the extension file │'));
916
+ console.log(chalk.cyan(' │ 3. Open chrome://extensions/ → Enable Developer Mode │'));
917
+ console.log(chalk.cyan(' │ 4. Click "Load unpacked" → select the extension folder │'));
918
+ console.log(chalk.cyan(' │ 5. Run "opencli doctor" to verify connectivity │'));
919
+ console.log(chalk.cyan(' └─────────────────────────────────────────────────────────────┘'));
920
+ }
921
+
922
+ /**
923
+ * 显示加载已解压扩展的指引(已自动下载解压后)。
924
+ */
925
+ function printOpenCliLoadSteps(extDir) {
926
+ console.log(chalk.yellow(' ⚠ Browser commands will NOT work until the extension is loaded in Chrome'));
927
+ console.log(chalk.cyan(' ┌─────────────────────────────────────────────────────────────┐'));
928
+ console.log(chalk.cyan(' │ To complete setup: │'));
929
+ console.log(chalk.cyan(` │ 1. Open chrome://extensions/ → Enable Developer Mode │`));
930
+ console.log(chalk.cyan(` │ 2. Click "Load unpacked" → select: │`));
931
+ console.log(chalk.cyan(` │ ${extDir}`));
932
+ console.log(chalk.cyan(' │ 3. Run "opencli doctor" to verify connectivity │'));
933
+ console.log(chalk.cyan(' └─────────────────────────────────────────────────────────────┘'));
818
934
  }
819
935
 
820
936
  // ============================================================
@@ -852,11 +968,12 @@ export const EXTRAS_REGISTRY = {
852
968
  * @param {string[]} [config.externalSkills] - 要安装的外部 skill 名称列表
853
969
  * @param {boolean} [config.playwrightCli] - 是否安装 playwright-cli
854
970
  * @param {boolean} [config.openCli] - 是否安装 opencli
971
+ * @param {boolean} [config.openCliAutoDownload] - opencli 扩展缺失时是否自动下载
855
972
  * @param {string} config.projectRoot - 目标项目根目录
856
973
  * @param {boolean} config.dryRun - 是否为预览模式
857
974
  */
858
975
  export async function scaffold(config) {
859
- const { platform, skills, team, pipeline, rules, aiCli, externalSkills, playwrightCli, openCli, projectRoot, dryRun } = config;
976
+ const { platform, skills, team, pipeline, rules, aiCli, externalSkills, playwrightCli, openCli, openCliAutoDownload, projectRoot, dryRun } = config;
860
977
  const platforms = platform === 'both' ? ['codebuddy', 'claude'] : [platform];
861
978
 
862
979
  if (dryRun) {
@@ -961,7 +1078,7 @@ export async function scaffold(config) {
961
1078
  if (openCli) {
962
1079
  activeExtras.push('opencli');
963
1080
  console.log(chalk.blue(` ${EXTRAS_REGISTRY['opencli'].label}:`));
964
- await installOpenCli(projectRoot, dryRun);
1081
+ await installOpenCli(projectRoot, dryRun, openCliAutoDownload);
965
1082
  console.log('');
966
1083
  }
967
1084