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.
- package/bin/create-prizmkit.js +2 -0
- package/bundled/VERSION.json +3 -3
- package/bundled/rules/_rules-metadata.json +6 -1
- package/bundled/rules/general/cohesive-modeling.md +27 -0
- package/bundled/skills/_metadata.json +1 -1
- package/bundled/skills/app-planner/SKILL.md +114 -4
- package/bundled/skills/app-planner/references/rules/backend/derivation-rules.md +609 -0
- package/bundled/skills/app-planner/references/rules/backend/fixed-rules.md +285 -0
- package/bundled/skills/app-planner/references/rules/backend/question-bank.md +249 -0
- package/bundled/skills/app-planner/references/rules/backend/template.md +173 -0
- package/bundled/skills/app-planner/references/rules/database/derivation-rules.md +373 -0
- package/bundled/skills/app-planner/references/rules/database/fixed-rules.md +211 -0
- package/bundled/skills/app-planner/references/rules/database/question-bank.md +184 -0
- package/bundled/skills/app-planner/references/rules/database/template.md +158 -0
- package/bundled/skills/app-planner/references/rules/frontend/derivation-rules.md +810 -0
- package/bundled/skills/app-planner/references/rules/frontend/fixed-rules.md +188 -0
- package/bundled/skills/app-planner/references/rules/frontend/question-bank.md +302 -0
- package/bundled/skills/app-planner/references/rules/frontend/template.md +320 -0
- package/bundled/skills/app-planner/references/rules/mobile/derivation-rules.md +639 -0
- package/bundled/skills/app-planner/references/rules/mobile/fixed-rules.md +290 -0
- package/bundled/skills/app-planner/references/rules/mobile/question-bank.md +232 -0
- package/bundled/skills/app-planner/references/rules/mobile/template.md +175 -0
- package/bundled/skills/prizm-kit/SKILL.md +1 -1
- package/bundled/skills/prizmkit-init/SKILL.md +47 -6
- package/bundled/skills/prizmkit-init/references/config-schema.md +7 -3
- package/bundled/skills/prizmkit-init/references/rules/layer-detection.md +41 -0
- package/package.json +1 -1
- package/src/index.js +10 -0
- 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
|
|
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:
|
|
93
|
+
**Phase 4.5: Layer Detection**
|
|
94
94
|
|
|
95
|
-
|
|
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
|
|
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
|
|
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.
|
|
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
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
|
-
//
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
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
|
|