create-dwy 0.19.1 → 0.21.0

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 (113) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/package.json +1 -1
  3. package/src/cli-help.js +31 -2
  4. package/src/sync-all.js +168 -577
  5. package/src/sync-codex.js +42 -28
  6. package/src/sync-cursor.js +0 -25
  7. package/src/sync-global-skills.js +2 -2
  8. package/src/sync-opencode.js +7 -33
  9. package/src/sync.js +59 -226
  10. package/src/tab-multiselect.js +15 -53
  11. package/src/utils.js +0 -1
  12. package/templates/ai-tools/AGENTS.md +223 -0
  13. package/templates/ai-tools/CHANGELOG.md +195 -0
  14. package/templates/ai-tools/VERSION +1 -1
  15. package/templates/ai-tools/hooks/Git/pre-git-commit-ai-signature-check.sh +5 -4
  16. package/templates/ai-tools/rules/Android/dwy-android-core.md +147 -13
  17. package/templates/ai-tools/rules/Android/dwy-android-layering.md +142 -0
  18. package/templates/ai-tools/rules/Android/dwy-android-mvp.md +55 -0
  19. package/templates/ai-tools/rules/Android/dwy-android-support-only.md +2 -0
  20. package/templates/ai-tools/rules/Docker/dwy-docker.md +23 -1
  21. package/templates/ai-tools/rules/Flutter/dwy-flutter-core.md +2 -0
  22. package/templates/ai-tools/rules/Flutter/dwy-flutter-testing.md +1 -1
  23. package/templates/ai-tools/rules/HarmonyOS/dwy-arkts-ui-build.md +12 -8
  24. package/templates/ai-tools/rules/Python/dwy-python-backend.md +4 -43
  25. package/templates/ai-tools/rules/Python/dwy-python-layering.md +169 -0
  26. package/templates/ai-tools/rules/Vue/dwy-vue-core.md +11 -49
  27. package/templates/ai-tools/rules/Vue/dwy-vue-layering.md +153 -0
  28. package/templates/ai-tools/rules/iOS/dwy-apple-layering.md +133 -0
  29. package/templates/ai-tools/rules/iOS/dwy-swift-core.md +2 -0
  30. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-code-craft.md +83 -0
  31. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-dependency-freshness.md +27 -66
  32. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-git-commit.md +8 -219
  33. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-oss-commercial-license.md +27 -123
  34. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-prod-branch.md +31 -0
  35. package/templates/ai-tools/rules//346/225/260/346/215/256/345/272/223/dwy-postgres.md +17 -10
  36. package/templates/ai-tools/rules//346/225/260/346/215/256/345/272/223/dwy-redis.md +6 -3
  37. package/templates/ai-tools/skills/Docker/dwy-deploy-first/SKILL.md +14 -14
  38. package/templates/ai-tools/skills/Docker/dwy-deploy-first/references/chapter-01-mirrors.md +2 -2
  39. package/templates/ai-tools/skills/Docker/dwy-docker/SKILL.md +21 -13
  40. package/templates/ai-tools/skills/Docker/dwy-docker/references/ask-templates.md +13 -12
  41. package/templates/ai-tools/skills/Docker/dwy-docker/references/templates.md +3 -1
  42. package/templates/ai-tools/skills/Docker/dwy-docker/references/version-rules.md +10 -6
  43. package/templates/ai-tools/skills/Docker/dwy-docker/scripts/query_dockerhub.py +21 -6
  44. package/templates/ai-tools/skills/Docker/dwy-docker/scripts/scan_images.sh +2 -2
  45. package/templates/ai-tools/skills/Docker/dwy-mirror-source/SKILL.md +44 -30
  46. package/templates/ai-tools/skills/Docker/dwy-mirror-source/references/dockerfile-snippets.md +2 -0
  47. package/templates/ai-tools/skills/Docker/dwy-mirror-source/references/mirror-providers.md +8 -8
  48. package/templates/ai-tools/skills/Docker/dwy-mirror-source/scripts/apply_mirrors.py +14 -1
  49. package/templates/ai-tools/skills/Docker/dwy-mirror-source/scripts/check_mirrors.py +4 -0
  50. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/SKILL.md +8 -6
  51. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/references/digest/python-sdk.md +3 -3
  52. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/references/digest/stream-engine.md +2 -2
  53. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/references/review-rules/anti-patterns.md +3 -1
  54. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/references/review-rules/change-checklist.md +4 -4
  55. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/references/review-rules/lethal-violations.md +5 -5
  56. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/references/review-rules/perf-baselines.md +5 -5
  57. package/templates/ai-tools/skills/Python/dwy-eapi/SKILL.md +2 -2
  58. package/templates/ai-tools/skills/Python/dwy-eapi/references/tasks-integration-guide.md +4 -4
  59. package/templates/ai-tools/skills/Python/dwy-eapi/v0/breaking.md +3 -0
  60. package/templates/ai-tools/skills/Python/dwy-eapi/v0/email-canonical.md +28 -3
  61. package/templates/ai-tools/skills/Python/dwy-eapi/v0/index.md +2 -2
  62. package/templates/ai-tools/skills/Python/dwy-eapi/v0/providers-email.md +12 -2
  63. package/templates/ai-tools/skills/Vue/dwy-eui/references/eui-design-guide.md +1 -1
  64. package/templates/ai-tools/skills/Vue/dwy-eui/references/eui-integration-guide.md +12 -0
  65. package/templates/ai-tools/skills/Vue/dwy-eui/shared/config-theme.md +2 -0
  66. package/templates/ai-tools/skills/Vue/dwy-eui/shared/form.md +10 -0
  67. package/templates/ai-tools/skills/Vue/dwy-eui/v2/index.md +5 -0
  68. package/templates/ai-tools/skills//344/272/247/345/223/2010/345/210/2601/dwy-architecture/SKILL.md +11 -14
  69. package/templates/ai-tools/skills//344/272/247/345/223/2010/345/210/2601/dwy-product-launcher/references/state-and-contract.md +1 -1
  70. package/templates/ai-tools/skills//344/272/247/345/223/2010/345/210/2601/dwy-prototype/SKILL.md +1 -1
  71. package/templates/ai-tools/skills//344/272/247/345/223/2010/345/210/2601/dwy-stage-dev/SKILL.md +1 -1
  72. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-github-action-publish/SKILL.md +32 -15
  73. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-github-action-publish/references/electron-release-workflow-template.yml +3 -1
  74. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-github-action-publish/references/release-workflow-template.yml +8 -5
  75. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/SKILL.md +1 -1
  76. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/assets/appstore-submission.yaml +1 -1
  77. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/references/aso.md +2 -0
  78. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/references/in-app-purchase-review.md +1 -1
  79. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/SKILL.md +4 -3
  80. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/android.md +1 -1
  81. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/backend-deploy.md +1 -1
  82. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/changelog.md +45 -27
  83. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/frontend-deploy.md +1 -1
  84. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/generic-release.md +1 -1
  85. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/git-tag.md +1 -1
  86. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/harmony.md +1 -1
  87. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/ios.md +1 -1
  88. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-semver/SKILL.md +8 -0
  89. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/SKILL.md +7 -7
  90. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/references/checks-runtime.md +63 -59
  91. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/scripts/check_base.sh +10 -1
  92. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/scripts/check_capacity.sh +21 -23
  93. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/scripts/check_db.sh +9 -1
  94. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/scripts/check_docker.sh +20 -24
  95. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/scripts/check_logs.sh +3 -3
  96. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/SKILL.md +4 -2
  97. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/references/api.md +1 -1
  98. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/scripts/synthesize.py +1 -0
  99. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/SKILL.md +7 -5
  100. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/references/platform-copy-examples.md +5 -3
  101. package/templates/ai-tools/skills//351/200/232/347/224/250/dwy-dependency-choice/SKILL.md +140 -0
  102. package/templates/ai-tools/skills//351/200/232/347/224/250/dwy-git-commit/SKILL.md +113 -0
  103. package/templates/ai-tools/skills//351/200/232/347/224/250/dwy-shared/SKILL.md +17 -14
  104. package/templates/ai-tools/skills//351/200/232/347/224/250/dwy-whiteboard-prototype/SKILL.md +1 -1
  105. package/templates/project/fullstack-monorepo/{CLAUDE.md.hbs → AGENTS.md.hbs} +1 -1
  106. package/src/sync-packs.js +0 -223
  107. package/src/sync-scene.js +0 -178
  108. package/templates/ai-tools/CLAUDE.md +0 -210
  109. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-tdd-development.md +0 -115
  110. /package/templates/project/backend/{CLAUDE.md.hbs → AGENTS.md.hbs} +0 -0
  111. /package/templates/project/fullstack-monorepo/backend/{CLAUDE.md.hbs → AGENTS.md.hbs} +0 -0
  112. /package/templates/project/fullstack-monorepo/frontend/{CLAUDE.md.hbs → AGENTS.md.hbs} +0 -0
  113. /package/templates/project/web/{CLAUDE.md.hbs → AGENTS.md.hbs} +0 -0
@@ -0,0 +1,169 @@
1
+ ---
2
+ description: Python 后端四层分包与依赖方向(Assembly / Features / BizFoundation / Foundation);uv workspace 根锁定第三方版本
3
+ paths:
4
+ - "**/*.py"
5
+ - "**/pyproject.toml"
6
+ ---
7
+
8
+ # Python 四层架构与依赖
9
+
10
+ 适用于 uv workspace 的 Python 后端。路由 / Schema / ORM / 安全编码见 `dwy-python-backend`。本文件只管**层、引用边、版本写在哪**。
11
+
12
+ 单壳项目**不建** PlatformFoundation。
13
+
14
+ ---
15
+
16
+ ## 一、层名(冻结)
17
+
18
+ 正式层名只有下表四个。目录 / 包可以叫 `app`、`biz_foundation`,文档可写「本仓包名 X = Foundation」。**禁止**把 `Domain` / `infra` / `core` 当层名。
19
+
20
+ | 层 | 判定(只用这一条) | 禁止 |
21
+ |---|---|---|
22
+ | **Foundation** | 换一个完全不同的产品仍原样拿走 | 出现本业务名词 |
23
+ | **BizFoundation** | 本产品才有,但跨多个 Feature 都要用 | 页面、导航、某一端壳状态 |
24
+ | **Features** | 可整包删/裁剪的业务域 | 被其他 Feature 直接引用 |
25
+ | **Assembly** | 生命周期、DI、路由挂载、把实现插进 Protocol | 业务规则、业务计算 |
26
+
27
+ 升层:第二个 Feature 或第二个产品**真在用**,才升到 BizFoundation / Foundation。禁止「可能复用」提前抽。
28
+
29
+ 业务内聚:一个业务域 = `features/` 下的一个包。域内 `router.py` / `service.py` / `schemas.py` / `models.py` 聚在一起。禁止全局 `routers/` `services/` `models/`。
30
+
31
+ ---
32
+
33
+ ## 二、依赖边(强制)
34
+
35
+ ```
36
+ app → features/* → biz_foundation → foundation
37
+ ✕ 互引
38
+ ```
39
+
40
+ | 谁 | 允许依赖 | 禁止 |
41
+ |---|---|---|
42
+ | `app/` | `features/*`、`biz_foundation`、`foundation`(仅 factories) | 业务计算 |
43
+ | `features/orders` | 仅 `biz_foundation` | `app`、`features/inventory`、`foundation` |
44
+ | `biz_foundation` | 仅 `foundation` | `app`、任何 Feature |
45
+ | `foundation` | 第三方库 | 任何本仓业务包 |
46
+
47
+ **Feature 互引为零。** 跨域只许三种:升到 `biz_foundation`;Feature 只依赖 Protocol,由 `app/factories.py` / `app/hooks.py` 注入实现;`app` 编排两次调用。
48
+
49
+ 依赖倒置原则:Feature 依赖 Protocol,不依赖 Doris/Http 具体类。具体实现只出现在 `app/`。
50
+
51
+ 声明与源码两道都查:
52
+
53
+ - `features/orders/pyproject.toml` 的 `dependencies` 只许出现 `biz_foundation` 与无版本第三方名
54
+ - 源码禁止 `from app.`、`from features.inventory`、`from foundation.`
55
+
56
+ ```python
57
+ # 合法:只认抽象,实现由装配层注入
58
+ class StockPort(Protocol):
59
+ """扣库存端口。orders 不 import inventory 包。"""
60
+
61
+ async def deduct(self, sku: str, qty: int) -> None: ...
62
+
63
+
64
+ class OrderService:
65
+ """下单。stock 由 app/factories.py 注入。"""
66
+
67
+ def __init__(self, stock: StockPort) -> None:
68
+ self._stock = stock
69
+ ```
70
+
71
+ ```python
72
+ # 禁止
73
+ from app.main import settings # Feature → Assembly
74
+ from features.inventory.service import deduct # Feature → Feature
75
+ from foundation.db import get_session # Feature 越层
76
+ ```
77
+
78
+ ---
79
+
80
+ ## 三、分包树
81
+
82
+ 打开 `backend/` 必须能数出四层。业务词只出现在 `features/` 下。
83
+
84
+ ```
85
+ backend/
86
+ app/ # Assembly
87
+ main.py # 注册 router、lifespan
88
+ factories.py # 唯一实例化具体实现的地方
89
+ hooks.py # 跨 Feature 桥
90
+ features/ # Features
91
+ orders/
92
+ pyproject.toml
93
+ src/orders/
94
+ router.py
95
+ service.py
96
+ schemas.py
97
+ models.py
98
+ inventory/
99
+ pyproject.toml
100
+ src/inventory/
101
+ router.py
102
+ service.py
103
+ schemas.py
104
+ models.py
105
+ biz_foundation/ # BizFoundation
106
+ pyproject.toml
107
+ src/biz_foundation/
108
+ auth/ # 内容:跨 Feature 鉴权,不是一层
109
+ protocols.py
110
+ foundation/ # Foundation
111
+ pyproject.toml
112
+ src/foundation/
113
+ db.py
114
+ redis.py
115
+ signing.py
116
+ pyproject.toml # workspace + 第三方版本只在这
117
+ uv.lock
118
+ ```
119
+
120
+ ```toml
121
+ # 根 pyproject.toml
122
+ [tool.uv.workspace]
123
+ members = ["features/*", "biz_foundation", "foundation"]
124
+ ```
125
+
126
+ `app/` 是根应用,不是 workspace member。测试镜像层:`tests/features/orders/`、`tests/biz_foundation/`。
127
+
128
+ ---
129
+
130
+ ## 四、Monorepo 版本(强制)
131
+
132
+ 第三方版本号**只**出现在仓库根 `pyproject.toml` 的 `constraint-dependencies`。成员包只写包名。内部包用 uv workspace,不写版本。一把锁:根 `uv.lock`。选哪个版本走 skill `dwy-dependency-choice`。
133
+
134
+ ```toml
135
+ # 根 pyproject.toml
136
+ [tool.uv.sources]
137
+ biz_foundation = { workspace = true }
138
+ foundation = { workspace = true }
139
+
140
+ [tool.uv]
141
+ constraint-dependencies = [
142
+ "fastapi==0.115.6",
143
+ "sqlalchemy==2.0.36",
144
+ ]
145
+ ```
146
+
147
+ ```toml
148
+ # features/orders/pyproject.toml
149
+ [project]
150
+ dependencies = [
151
+ "fastapi", # 无版本
152
+ "biz_foundation",
153
+ ]
154
+ ```
155
+
156
+ 禁止成员 `pyproject.toml` 写 `fastapi==0.115.6`。禁止每个包自己 `uv lock`。
157
+
158
+ ---
159
+
160
+ ## 五、检查清单
161
+
162
+ | 检查项 | 严重 |
163
+ |---|---|
164
+ | 顶层不是 `app` / `features` / `biz_foundation` / `foundation` 四层 | 高 |
165
+ | Feature `from app.` 或 pyproject 依赖 `app` | 高 |
166
+ | Feature import 另一 Feature | 高 |
167
+ | Feature 源码 `from foundation.` | 高 |
168
+ | 成员包写死第三方版本 | 高 |
169
+ | `Domain` / `infra` / `core` 当层名 | 中 |
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Vue 3 + TS + Vite + Tailwind 应用层通用规范(业务聚合结构、组件 / TS / 路由 / API / 模板 / 样式 / 错误处理 / 注释)
2
+ description: Vue 3 + TS + Vite + Tailwind 应用层通用规范(组件 / TS / 路由 / API / 模板 / 样式 / 错误处理 / 注释;仓库分层见 dwy-vue-layering)
3
3
  paths:
4
4
  - "**/*.vue"
5
5
  - "**/*.ts"
@@ -14,57 +14,11 @@ paths:
14
14
 
15
15
  ## 一、项目结构与业务聚合(强制)
16
16
 
17
- ### 核心原则
17
+ **仓库四层(`apps/web` / `packages/features` / `packages/biz-foundation` / `packages/foundation`)、Feature 互不依赖、pnpm catalog → 见 `dwy-vue-layering`。** 本节只约定 Feature **域内**文件名。
18
18
 
19
- **按功能模块(feature / domain)聚合,禁止按技术层散落。** 同一业务功能的 view / components / store / api / types 必须集中在同一个功能目录下;**禁止**全局存在 `views/` / `components/` / `stores/` / `api/` 等顶级"技术层"目录把不同功能的同类文件混放。
20
-
21
- ### 为什么
22
-
23
- - **跨项目迁移**:复制单个功能目录即可携带该功能全部代码;技术层散落需在 5+ 目录里翻找
24
- - **可读性**:阅读功能时所有相关代码在同一目录,无需跨目录跳转
25
- - **变更影响域清晰**:一次改动 diff 集中,code review 更高效
26
- - **删除友好**:删功能时整个目录删掉即可,不会留下孤儿文件
27
-
28
- ### 标准结构(参考)
29
-
30
- ```
31
- src/
32
- ├── features/ # 业务功能根目录
33
- │ ├── users/ # 用户功能
34
- │ │ ├── api.ts # 该业务的 API(用全局 HTTP 客户端)
35
- │ │ ├── store.ts # 该业务的 Pinia store
36
- │ │ ├── types.ts # 该业务的类型
37
- │ │ ├── views/ # 该业务的页面组件
38
- │ │ │ ├── UserListView.vue
39
- │ │ │ └── UserDetailView.vue
40
- │ │ ├── components/ # 该业务的内部组件
41
- │ │ │ └── UserCard.vue
42
- │ │ └── route.ts # 该业务的路由片段
43
- │ └── orders/
44
- │ ├── api.ts
45
- │ ├── store.ts
46
- │ └── views/
47
- ├── shared/ # 跨业务真正复用:UI 子组件 / composables / 常量
48
- │ ├── components/
49
- │ ├── composables/
50
- │ └── constants/
51
- ├── core/ # 全局基础设施:HTTP client / 路由根 / 主题 / 启动
52
- │ ├── http.ts # 全局唯一 HTTP 客户端实例
53
- │ ├── router.ts
54
- │ └── main.ts
55
- ├── App.vue
56
- └── style.css
57
- ```
58
-
59
- > 测试目录与 `src/` 并列、镜像业务聚合结构(详见 `dwy-vue-testing` rule)。
60
-
61
- ### 强制规则
62
-
63
- - **禁止**顶级 `views/` / `components/` / `stores/` / `api/` / `types/` 把不同功能的同类文件混放
64
19
  - 一个功能目录内文件名固定:`api.ts` / `store.ts` / `types.ts` / `route.ts`(单数、不带功能前缀)
65
- - 跨业务真正共享的代码放 `shared/` 或 `core/`,**禁止**为"可能复用"把单一功能逻辑提前抽离
66
20
  - 单文件超过约 400 行时再考虑拆分,**禁止**未到规模就预拆分
67
- - 模块间引用通过明确 import,**禁止**循环依赖
21
+ - 测试目录与源码并列、镜像业务聚合(详见 `dwy-vue-testing`)
68
22
 
69
23
  ## 二、组件规范
70
24
 
@@ -313,6 +267,14 @@ export function createUser(data: UserCreate) {
313
267
  - 模板中复杂表达式 / 内联多语句
314
268
  - `kebab-case` 组件名 / 模板中写 `.value`
315
269
 
270
+ ### 用户输入限长
271
+
272
+ 业务页里接收用户输入的控件(`input` / `textarea` / 富文本 / 文件 / 批量项)要有长度或大小上限,并用该页的 schema 再校验一次,防止粘贴绕过 `maxlength`。
273
+
274
+ 上限按字段语义定:用户名几十字符、描述几百、正文几千、图片几 MB。组件库的 Input 只提供 `maxlength` 这类 prop,不在组件内部写死业务上限。
275
+
276
+ 后端校验见 `dwy-python-backend`。只改组件库、没有业务表单时,不要给每个控件塞一套 schema。
277
+
316
278
  ---
317
279
 
318
280
  ## 八、样式规范
@@ -0,0 +1,153 @@
1
+ ---
2
+ description: Vue 四层分包与依赖方向(Assembly / Features / BizFoundation / Foundation);pnpm catalog 根锁定第三方版本
3
+ paths:
4
+ - "**/*.vue"
5
+ - "**/*.ts"
6
+ - "**/package.json"
7
+ - "**/pnpm-workspace.yaml"
8
+ ---
9
+
10
+ # Vue 四层架构与依赖
11
+
12
+ 适用于 pnpm workspace 的 Vue 3 应用。组件 / 路由 / Pinia 写法见 `dwy-vue-core` / `dwy-vue-pinia`。本文件只管**层、引用边、版本写在哪**。
13
+
14
+ 单壳项目**不建** PlatformFoundation。
15
+
16
+ ---
17
+
18
+ ## 一、层名(冻结)
19
+
20
+ 正式层名只有下表四个。目录 / 包可以叫 `apps/web`、`packages/biz-foundation`,文档可写「本仓包名 X = Foundation」。**禁止**把 `Domain` / `infra` / `core` 当层名。
21
+
22
+ | 层 | 判定(只用这一条) | 禁止 |
23
+ |---|---|---|
24
+ | **Foundation** | 换一个完全不同的产品仍原样拿走 | 出现本业务名词 |
25
+ | **BizFoundation** | 本产品才有,但跨多个 Feature 都要用 | 页面、导航、某一端壳状态 |
26
+ | **Features** | 可整包删/裁剪的业务域 | 被其他 Feature 直接引用 |
27
+ | **Assembly** | 生命周期、DI、路由挂载、把实现插进 Protocol | 业务规则、业务计算 |
28
+
29
+ 升层:第二个 Feature 或第二个产品**真在用**,才升到 BizFoundation / Foundation。禁止「可能复用」提前抽。
30
+
31
+ 业务内聚:一个业务域 = `packages/features/` 下的一个包。域内 `api.ts` / `store.ts` / `types.ts` / `route.ts` / `views/` 聚在一起。禁止全局 `views/` `stores/` `api/`。
32
+
33
+ 项目专用、绝不跨项目的页面可放 `apps/web/src/features/`,**依赖边与 `packages/features/*` 相同**:禁止互引、禁止 import `packages/foundation`。
34
+
35
+ ---
36
+
37
+ ## 二、依赖边(强制)
38
+
39
+ ```
40
+ apps/web → packages/features/* → packages/biz-foundation → packages/foundation
41
+ ✕ 互引
42
+ ```
43
+
44
+ | 谁 | 允许依赖 | 禁止 |
45
+ |---|---|---|
46
+ | `apps/web` | `features/*`、`biz-foundation`、`foundation`(仅装配 http 单例) | 业务计算写在壳里 |
47
+ | `@acme/orders` | 仅 `@acme/biz-foundation` + catalog 第三方 | `@acme/inventory`、`@/` 宿主路径、`@acme/foundation` |
48
+ | `@acme/biz-foundation` | 仅 `@acme/foundation` | `apps/web`、任何 Feature |
49
+ | `@acme/foundation` | catalog 第三方 | 任何业务包、Vue Router 业务路由 |
50
+
51
+ **Feature 互引为零。** 跨域只许三种:升到 `biz-foundation`;Feature 导出工厂 / Options,由 `apps/web` 注入回调;壳编排两个页面。
52
+
53
+ 可复用 Feature **禁止** `import { useXxxStore } from '@/stores/...'`。宿主 store 由 `apps/web` 经 Options 传入。
54
+
55
+ ```ts
56
+ // 合法:packages/features/orders 只认端口,不 import inventory
57
+ export interface StockPort {
58
+ /** 扣库存。实现由 apps/web 注入。 */
59
+ deduct(sku: string, qty: number): Promise<void>
60
+ }
61
+ ```
62
+
63
+ ```ts
64
+ // 禁止
65
+ import { useInventoryStore } from '@acme/inventory' // Feature → Feature
66
+ import { useAuthStore } from '@/stores/auth' // 可复用 Feature → 宿主
67
+ import { http } from '@acme/foundation' // 越层;经 biz-foundation 门面
68
+ ```
69
+
70
+ ---
71
+
72
+ ## 三、分包树
73
+
74
+ 打开仓库必须能数出四层。业务词只出现在 `packages/features/`(或壳内 `apps/web/src/features/`)。
75
+
76
+ ```
77
+ apps/
78
+ web/ # Assembly
79
+ src/
80
+ main.ts
81
+ router.ts
82
+ stores/ # 宿主 session,不放业务规则
83
+ packages/
84
+ features/ # Features
85
+ orders/
86
+ package.json
87
+ src/
88
+ api.ts
89
+ store.ts
90
+ types.ts
91
+ route.ts
92
+ views/
93
+ inventory/
94
+ biz-foundation/ # BizFoundation
95
+ src/
96
+ auth/ # 内容:跨 Feature 鉴权,不是一层
97
+ protocols.ts
98
+ foundation/ # Foundation
99
+ src/
100
+ http.ts
101
+ format.ts
102
+ pnpm-workspace.yaml # catalog 只在这
103
+ pnpm-lock.yaml
104
+ ```
105
+
106
+ 禁止把 `orders`、鉴权、http 工厂平铺在 `packages/` 根上,否则层不可见。
107
+
108
+ ```yaml
109
+ # pnpm-workspace.yaml
110
+ packages:
111
+ - apps/*
112
+ - packages/features/*
113
+ - packages/biz-foundation
114
+ - packages/foundation
115
+ ```
116
+
117
+ ---
118
+
119
+ ## 四、Monorepo 版本(强制)
120
+
121
+ 第三方版本号**只**出现在 `pnpm-workspace.yaml` 的 `catalog`。子包用 `"catalog:"`。内部包 `"workspace:*"`。选哪个版本走 skill `dwy-dependency-choice`。
122
+
123
+ ```yaml
124
+ # pnpm-workspace.yaml
125
+ catalog:
126
+ vue: 3.5.13
127
+ axios: 1.7.9
128
+ ```
129
+
130
+ ```json
131
+ {
132
+ "name": "@acme/orders",
133
+ "dependencies": {
134
+ "vue": "catalog:",
135
+ "@acme/biz-foundation": "workspace:*"
136
+ }
137
+ }
138
+ ```
139
+
140
+ 禁止子包 `"vue": "^3.5.13"`。禁止每个 Feature 各自锁 axios 版本。
141
+
142
+ ---
143
+
144
+ ## 五、检查清单
145
+
146
+ | 检查项 | 严重 |
147
+ |---|---|
148
+ | `packages/` 根平铺业务包,看不出 `features` / `biz-foundation` / `foundation` | 高 |
149
+ | Feature `package.json` 依赖另一 Feature | 高 |
150
+ | 可复用 Feature import `@/stores/*` | 高 |
151
+ | Feature 直接依赖 `@acme/foundation` | 高 |
152
+ | 子包写死第三方版本(不用 `catalog:`) | 高 |
153
+ | `Domain` / `infra` / `core` 当层名 | 中 |
@@ -0,0 +1,133 @@
1
+ ---
2
+ description: iOS / macOS 四层分包与依赖方向(双壳 Assembly + Features / BizFoundation / Foundation);根 Package.swift 锁定第三方版本
3
+ paths:
4
+ - "**/*.swift"
5
+ - "**/Package.swift"
6
+ - "**/project.yml"
7
+ ---
8
+
9
+ # Apple 四层架构与依赖
10
+
11
+ 适用于 iOS 17+ / macOS 14+ 的 SwiftUI 双端或单端应用。风格 / 安全区 / 国际化见 `dwy-swift-core`。本文件只管**层、引用边、版本写在哪**。
12
+
13
+ 单壳(只有 iPhone 或只有 Mac)**不建** PlatformFoundation。双壳且某端领域字节级不同时才加 `DesktopKit`。
14
+
15
+ 系统框架就叫 `Foundation`。SPM **target 禁止叫 `Foundation`**,层目录可以用这个名字。
16
+
17
+ ---
18
+
19
+ ## 一、层名(冻结)
20
+
21
+ 正式层名只有下表四个。目录 / target 可以叫 `AppPhone`、`BizFoundation`,文档可写「本仓 LogKit = Foundation 层的日志」。**禁止**把 `Domain` / `infra` / `core` 当层名。
22
+
23
+ | 层 | 判定(只用这一条) | 禁止 |
24
+ |---|---|---|
25
+ | **Foundation** | 换一个完全不同的产品仍原样拿走 | 出现本业务名词 |
26
+ | **BizFoundation** | 本产品才有,但跨多个 Feature 都要用 | 页面、导航、某一端壳状态 |
27
+ | **Features** | 可整包删/裁剪的业务域 | 被其他 Feature 直接引用 |
28
+ | **Assembly** | 生命周期、DI、路由挂载、把实现插进 Protocol | 业务规则、业务计算 |
29
+
30
+ 可选第五盒,**仅多壳**时出现:
31
+
32
+ | **PlatformFoundation** | 同一业务多个壳,且某端领域字节级不同 | 被其他壳 import;塞回 BizFoundation |
33
+
34
+ 升层:第二个 Feature 或第二个产品**真在用**,才升到 BizFoundation / Foundation。禁止「可能复用」提前抽。禁止为了共用而抽 `AppShared` 把壳状态(Store / Session)塞进 BizFoundation。
35
+
36
+ 业务内聚:一个业务域 = 壳内 `Features/<Name>/`。禁止按 `Views/` `ViewModels/` 横切。目录不等于层:Features 若与壳同一 target,仍遵守互不 import 的源码边界。
37
+
38
+ ---
39
+
40
+ ## 二、依赖边(强制)
41
+
42
+ ```
43
+ AppPhone ──► Features/* ──► BizFoundation ──► Foundation 层目录(LogKit / DesignKit)
44
+ AppDesktop ─┬► Features/*
45
+ ├► DesktopKit ──► BizFoundation ──► Foundation 层目录
46
+ └► BizFoundation
47
+ ```
48
+
49
+ | 谁 | 允许 | 禁止 |
50
+ |---|---|---|
51
+ | `AppPhone` | `BizFoundation`、Foundation 层 target、本壳 Features | `DesktopKit`、另一壳源码 |
52
+ | `AppDesktop` | `BizFoundation`、`DesktopKit`、Foundation 层 target、本壳 Features | `AppPhone/**/*.swift` |
53
+ | 本壳 `Features/Orders` | `BizFoundation`、本壳 App 装配类型 | `Features/Inventory`、另一壳 |
54
+ | `BizFoundation` | Foundation 层 target(日志 / 工具,**禁止** DesignKit) | 任一壳、DesktopKit |
55
+ | Foundation 层 target | 系统框架、风格无关工具 | 业务类型、壳 |
56
+ | `DesktopKit` | `BizFoundation`、Foundation 层 target | `AppPhone`、DesignKit(几何数字用测试锁同值,或升到壳) |
57
+
58
+ **Feature 互引为零。** 跨域走 BizFoundation Protocol,或壳编排。
59
+
60
+ `AppPhone` 禁止 `import DesktopKit`。不要抽 `AppShared`。
61
+
62
+ ```swift
63
+ // Package.swift:BizFoundation 不依赖壳
64
+ .target(
65
+ name: "BizFoundation",
66
+ dependencies: ["LogKit"] // Foundation 层 target,不是系统 Foundation
67
+ )
68
+ ```
69
+
70
+ ```swift
71
+ // 禁止
72
+ import DesktopKit // 写在 AppPhone
73
+ import AppPhone // 写在 BizFoundation
74
+ ```
75
+
76
+ ---
77
+
78
+ ## 三、分包树
79
+
80
+ 打开工程必须能数出:两个壳(或一个壳)+ `Features` + `BizFoundation` + Foundation 层目录。
81
+
82
+ ```
83
+ AppPhone/ # Assembly 壳
84
+ App/ # 装配:路由、DI、生命周期
85
+ Features/
86
+ Orders/
87
+ Inventory/
88
+ AppDesktop/ # 另一个 Assembly 壳(单壳则省略)
89
+ App/
90
+ Features/
91
+ Orders/
92
+ Inventory/
93
+ Sources/
94
+ BizFoundation/ # target: BizFoundation
95
+ Foundation/ # 层目录;target 用 LogKit / DesignKit
96
+ DesktopKit/ # PlatformFoundation,仅 AppDesktop 依赖
97
+ Package.swift # from: 只在这
98
+ project.yml # 壳引用这一份 package,不重复 from:
99
+ ```
100
+
101
+ ---
102
+
103
+ ## 四、Monorepo 版本(强制)
104
+
105
+ 第三方版本号**只**出现在根 `Package.swift` 的 `.package(..., from:)`。target 只写 product / 本地 target 名。`project.yml` 引用这一份 package,不重复版本。选哪个版本走 skill `dwy-dependency-choice`。
106
+
107
+ ```swift
108
+ dependencies: [
109
+ .package(url: "https://github.com/apple/swift-log.git", from: "1.5.0"),
110
+ ]
111
+ targets: [
112
+ .target(name: "LogKit", dependencies: [
113
+ .product(name: "Logging", package: "swift-log"),
114
+ ]),
115
+ .target(name: "BizFoundation", dependencies: ["LogKit"]),
116
+ ]
117
+ ```
118
+
119
+ 禁止第二个 `Package.swift` 再写同一依赖的 `from:`。禁止 target 注释里另写版本。
120
+
121
+ ---
122
+
123
+ ## 五、检查清单
124
+
125
+ | 检查项 | 严重 |
126
+ |---|---|
127
+ | `AppPhone` import `DesktopKit` 或编译另一壳 `.swift` | 高 |
128
+ | `BizFoundation` import 壳类型 / DesignKit | 高 |
129
+ | 壳内 Features 互相 import | 高 |
130
+ | SPM target 名为 `Foundation`(与系统框架撞名) | 高 |
131
+ | 第二个 Package.swift / project.yml 重复 `from:` | 高 |
132
+ | 抽 `AppShared` 把 Store / Session 塞进 BizFoundation | 高 |
133
+ | `Domain` / `infra` / `core` 当层名 | 中 |
@@ -4,6 +4,8 @@ paths:
4
4
  - "**/*.swift"
5
5
  ---
6
6
 
7
+ 分层、双壳依赖、Package.swift 版本锁定见 `dwy-apple-layering`。本文件只管写法与体验基线。
8
+
7
9
  ## iOS 目标与写法
8
10
 
9
11
  - iOS 最低版本 17.0+,不为 16 及以下做兼容分支。
@@ -0,0 +1,83 @@
1
+ ---
2
+ description: 编码大局观与行文准则(动笔前四问、第二次才抽、扩展靠加文件、反屎山、行为变更先写失败测试)。编辑源码时注入。
3
+ paths:
4
+ - "**/*.{py,ts,tsx,vue,js,jsx,kt,kts,swift,ets,dart}"
5
+ ---
6
+
7
+ # 编码大局观
8
+
9
+ 写代码不是完成这个函数,是让这个 Feature 六个月后还能改。
10
+ 可维护 = 改一处全处对,不是提前设计未来。可扩展 = 新需求落成新文件,不是到处留钩子。
11
+
12
+ 分层规则管包边界;本文件管「这一份代码怎么长」。
13
+
14
+ ## 一、动笔前四问
15
+
16
+ 写之前在思考里过完,不必问用户。答不出 → 先搜再写。
17
+
18
+ 1. 这段代码属于哪一层、哪个 Feature?
19
+ 2. 同 Feature 里有没有同类页 / 同类接口?
20
+ 3. 这次需求会让哪几处**一起变**?
21
+ 4. 同类需求再来一次:是**加新文件**,还是给这堆 `if` 加分支?
22
+
23
+ ## 二、五条行文
24
+
25
+ | 原则 | 判定 | 禁止的误读 |
26
+ |---|---|---|
27
+ | **第二次才抽** | 同一 UI 骨架 / 同一业务规则出现 ≥2 次才抽;1 次保持原地 | 第一份就抽 `BaseXxx`、`useCommon` |
28
+ | **扩展 = 加新文件,不改旧文件** | 新页面、新字段、新状态应能新增,不必改已有页面 | 预留 `options` / plugin / `if type ===` 大开关 |
29
+ | **先找同类,再写这一份** | 写前同 Feature 内搜列表/表单/详情,对齐结构;80% 相同抽组件或 composable,20% 用参数/slot | 每页从零写一套表格+筛选+分页 |
30
+ | **按「为什么会改」拆** | 筛选条件变了不该动列定义;权限变了不该动请求封装 | 一个文件里塞请求、表格、弹窗、权限、格式化 |
31
+ | **复制允许,分叉必须收口** | 第一份可以照着抄;第二份会出现且会一起改 → 本轮就抽 | 「先复制五份以后再整理」 |
32
+
33
+ ## 三、屎山预警
34
+
35
+ 出现任一条:**停手拆,不准继续往上堆。**
36
+
37
+ - 第三份复制
38
+ - 一个文件混了 ≥3 种变化原因(请求 / 表格 / 弹窗 / 权限搅在一起)
39
+ - 用 `type` / `flag` 区分本该是新文件的行为
40
+ - 在已经难读的文件末尾再追加大段逻辑
41
+ - 跨 Feature 直接 import「图省事」(升层 / Protocol / 壳编排,见对应 `dwy-*-layering`)
42
+
43
+ ## 四、自进化
44
+
45
+ 两环,**不改本文件**。项目私货写 `project-rules`,不往全局准则里追加。
46
+
47
+ | 环 | 何时 | 做什么 | 不做什么 |
48
+ |---|---|---|---|
49
+ | **任务内收口** | 本轮会变成第 2 份重复,或正在改的文件因本次变更更乱 | 本轮抽/拆完才能说做完 | 不顺手重构无关文件 |
50
+ | **仓库自成长** | 同类屎山/坑 ≥2 次 | 写入 `project-rules`(现象 / 根因 / 怎么避免) | 一次性问题不立条 |
51
+
52
+ 发现本 Feature 已有更好结构:新代码跟那个结构;抽出时把旧的那份一并收口。禁止发明第三套风格。
53
+
54
+ ## 五、和「简单优先 / 精准改动」共存
55
+
56
+ | 借口 | 现实 |
57
+ |---|---|
58
+ | 「先写完以后再抽」 | 第 2 份出现就是抽的时机,本轮做完 |
59
+ | 「用户只要这个页面」 | 要的是可维护的页,不是又一座孤岛 |
60
+ | 「和精准改动冲突」 | 为消灭重复而改第一份,算本需求,不算「改进相邻代码」 |
61
+ | 「先留 options 方便扩展」 | 扩展靠加文件,不靠预留钩子 |
62
+ | 「这是简单优先」 | 简单 = 少概念、短路径;不是复制五份 |
63
+
64
+ 红线仍在:大重构、换架构、清理无关死代码,仍须用户明确要求。
65
+
66
+ ## 六、行为变更与测试位置
67
+
68
+ 行为变更(新功能、修 bug、会改变可观察行为的重构)先写失败测试,再写实现。文案、注释、Markdown、CI 配置直接改。
69
+
70
+ - 测试放独立目录并镜像源码:`src/foo/bar.ts` → `tests/foo/bar.test.ts`;Python 用 `tests/test_*.py`。禁止把测试和 fixture 写进业务 `src/`。
71
+ - Android 用 Gradle 测试源集 `src/test/`、`src/androidTest/`,与 `src/main` 分开,这是合规写法。
72
+ - 上面没覆盖的栈:独立测试目录 + 镜像源码 + 该生态主流 runner。栈内目录细则见对应 `dwy-*-testing`。
73
+ - 改完只跑受影响的测试。改了公共 fixture 或 `conftest.py` 就全量。提交前不要求全量,全量留给 CI。
74
+ - 基础库的 `TEST_CASES.md` 跟测试目录走(`tests/TEST_CASES.md`),和测试文件一起改。
75
+
76
+ ## 七、提交前检查
77
+
78
+ - [ ] 四问过完,同类已搜过
79
+ - [ ] 没有新增第 2 份未抽取的重复
80
+ - [ ] 没有用 flag/type 把本该新文件的行为塞进旧文件
81
+ - [ ] 正在改的文件没有因本次变更更难拆
82
+ - [ ] 踩同类坑 ≥2 次已写入 `project-rules`
83
+ - [ ] 行为变更先有失败测试,测试不在业务 `src/` 里