create-dwy 0.19.1 → 0.20.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 (98) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/package.json +1 -1
  3. package/src/cli-help.js +28 -2
  4. package/src/sync-all.js +95 -583
  5. package/src/sync-codex.js +14 -7
  6. package/src/sync-opencode.js +8 -22
  7. package/src/sync.js +60 -149
  8. package/src/tab-multiselect.js +15 -53
  9. package/templates/ai-tools/CHANGELOG.md +195 -0
  10. package/templates/ai-tools/CLAUDE.md +39 -58
  11. package/templates/ai-tools/VERSION +1 -1
  12. package/templates/ai-tools/hooks/Git/pre-git-commit-ai-signature-check.sh +5 -4
  13. package/templates/ai-tools/rules/Android/dwy-android-core.md +147 -13
  14. package/templates/ai-tools/rules/Android/dwy-android-layering.md +142 -0
  15. package/templates/ai-tools/rules/Android/dwy-android-mvp.md +55 -0
  16. package/templates/ai-tools/rules/Android/dwy-android-support-only.md +2 -0
  17. package/templates/ai-tools/rules/Docker/dwy-docker.md +23 -1
  18. package/templates/ai-tools/rules/Flutter/dwy-flutter-core.md +2 -0
  19. package/templates/ai-tools/rules/Flutter/dwy-flutter-testing.md +1 -1
  20. package/templates/ai-tools/rules/HarmonyOS/dwy-arkts-ui-build.md +12 -8
  21. package/templates/ai-tools/rules/Python/dwy-python-backend.md +4 -43
  22. package/templates/ai-tools/rules/Python/dwy-python-layering.md +169 -0
  23. package/templates/ai-tools/rules/Vue/dwy-vue-core.md +11 -49
  24. package/templates/ai-tools/rules/Vue/dwy-vue-layering.md +153 -0
  25. package/templates/ai-tools/rules/iOS/dwy-apple-layering.md +133 -0
  26. package/templates/ai-tools/rules/iOS/dwy-swift-core.md +2 -0
  27. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-code-craft.md +83 -0
  28. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-dependency-freshness.md +27 -66
  29. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-git-commit.md +8 -219
  30. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-oss-commercial-license.md +27 -123
  31. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-prod-branch.md +31 -0
  32. package/templates/ai-tools/rules//346/225/260/346/215/256/345/272/223/dwy-postgres.md +17 -10
  33. package/templates/ai-tools/rules//346/225/260/346/215/256/345/272/223/dwy-redis.md +6 -3
  34. package/templates/ai-tools/skills/Docker/dwy-deploy-first/SKILL.md +14 -14
  35. package/templates/ai-tools/skills/Docker/dwy-deploy-first/references/chapter-01-mirrors.md +2 -2
  36. package/templates/ai-tools/skills/Docker/dwy-docker/SKILL.md +21 -13
  37. package/templates/ai-tools/skills/Docker/dwy-docker/references/ask-templates.md +13 -12
  38. package/templates/ai-tools/skills/Docker/dwy-docker/references/templates.md +3 -1
  39. package/templates/ai-tools/skills/Docker/dwy-docker/references/version-rules.md +10 -6
  40. package/templates/ai-tools/skills/Docker/dwy-docker/scripts/query_dockerhub.py +21 -6
  41. package/templates/ai-tools/skills/Docker/dwy-docker/scripts/scan_images.sh +2 -2
  42. package/templates/ai-tools/skills/Docker/dwy-mirror-source/SKILL.md +44 -30
  43. package/templates/ai-tools/skills/Docker/dwy-mirror-source/references/dockerfile-snippets.md +2 -0
  44. package/templates/ai-tools/skills/Docker/dwy-mirror-source/references/mirror-providers.md +8 -8
  45. package/templates/ai-tools/skills/Docker/dwy-mirror-source/scripts/apply_mirrors.py +14 -1
  46. package/templates/ai-tools/skills/Docker/dwy-mirror-source/scripts/check_mirrors.py +4 -0
  47. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/SKILL.md +8 -6
  48. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/references/digest/python-sdk.md +3 -3
  49. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/references/digest/stream-engine.md +2 -2
  50. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/references/review-rules/anti-patterns.md +3 -1
  51. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/references/review-rules/change-checklist.md +4 -4
  52. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/references/review-rules/lethal-violations.md +5 -5
  53. package/templates/ai-tools/skills/DolphinDB/dwy-dolphindb/references/review-rules/perf-baselines.md +5 -5
  54. package/templates/ai-tools/skills/Python/dwy-eapi/SKILL.md +2 -2
  55. package/templates/ai-tools/skills/Python/dwy-eapi/v0/breaking.md +3 -0
  56. package/templates/ai-tools/skills/Python/dwy-eapi/v0/email-canonical.md +28 -3
  57. package/templates/ai-tools/skills/Python/dwy-eapi/v0/index.md +2 -2
  58. package/templates/ai-tools/skills/Python/dwy-eapi/v0/providers-email.md +12 -2
  59. package/templates/ai-tools/skills/Vue/dwy-eui/references/eui-design-guide.md +1 -1
  60. package/templates/ai-tools/skills//344/272/247/345/223/2010/345/210/2601/dwy-architecture/SKILL.md +11 -14
  61. package/templates/ai-tools/skills//344/272/247/345/223/2010/345/210/2601/dwy-product-launcher/references/state-and-contract.md +1 -1
  62. package/templates/ai-tools/skills//344/272/247/345/223/2010/345/210/2601/dwy-prototype/SKILL.md +1 -1
  63. 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
  64. 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
  65. 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
  66. 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
  67. 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
  68. 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
  69. 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
  70. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/SKILL.md +4 -3
  71. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/android.md +1 -1
  72. 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
  73. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/changelog.md +45 -27
  74. 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
  75. 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
  76. 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
  77. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/harmony.md +1 -1
  78. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/ios.md +1 -1
  79. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-semver/SKILL.md +8 -0
  80. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/SKILL.md +7 -7
  81. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/references/checks-runtime.md +63 -59
  82. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/scripts/check_base.sh +10 -1
  83. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/scripts/check_capacity.sh +21 -23
  84. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/scripts/check_db.sh +9 -1
  85. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/scripts/check_docker.sh +20 -24
  86. package/templates/ai-tools/skills//345/256/211/345/205/250/dwy-deploy-audit/scripts/check_logs.sh +3 -3
  87. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/SKILL.md +4 -2
  88. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/references/api.md +1 -1
  89. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/scripts/synthesize.py +1 -0
  90. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/SKILL.md +7 -5
  91. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/references/platform-copy-examples.md +5 -3
  92. package/templates/ai-tools/skills//351/200/232/347/224/250/dwy-dependency-choice/SKILL.md +140 -0
  93. package/templates/ai-tools/skills//351/200/232/347/224/250/dwy-git-commit/SKILL.md +113 -0
  94. package/templates/ai-tools/skills//351/200/232/347/224/250/dwy-shared/SKILL.md +16 -13
  95. package/templates/ai-tools/skills//351/200/232/347/224/250/dwy-whiteboard-prototype/SKILL.md +1 -1
  96. package/src/sync-packs.js +0 -223
  97. package/src/sync-scene.js +0 -178
  98. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-tdd-development.md +0 -115
@@ -52,6 +52,201 @@
52
52
 
53
53
  ---
54
54
 
55
+ ## 0.31.0 — 2026-10-10
56
+
57
+ ### Changed
58
+ - `rules/开发流程/dwy-prod-branch.md`:只保留 `develop` 和 `preview`。`develop` 发测试环境,版本只能是 `beta` 或 `rc`;正式版只从 `preview` 发。仓库没按这个来先提醒,不自行建分支。
59
+ - `skills/发布发版/dwy-semver` 与 `dwy-publish`:定版本和发版时遵守同一条。
60
+
61
+ ## 0.30.0 — 2026-10-10
62
+
63
+ ### Changed
64
+ - `skills/发布发版/dwy-publish`:changelog 仍只在发版时写。工厂下有多个项目时,先查出哪些项目的前端或后端有变更,再分别写入该端自己的 `CHANGELOG.md`。没变更的端不写、不打 tag。
65
+
66
+ ## 0.29.0 — 2026-10-10
67
+
68
+ ### Added
69
+ - `skills/通用/dwy-dependency-choice`:新装依赖时查正式版发布时间(满 7 天)和闭源商用许可。新鲜度与许可的长流程只在这里。
70
+ - `skills/通用/dwy-git-commit`:提交顺序、冲突处理、敏感扫描、message 格式、AI 署名。通用包会一起同步。
71
+
72
+ ### Changed
73
+ - `rules/开发流程/dwy-dependency-freshness.md`、`dwy-oss-commercial-license.md`、`dwy-git-commit.md` 收成硬约束短文,给没有 skill 的工具(如 Cursor)用。长流程见上面两个 skill。
74
+ - `rules/开发流程/dwy-code-craft.md` 写入行为变更先写失败测试、测试目录和 `TEST_CASES.md`。
75
+ - Android / iOS / Vue / Python 分层和 Flutter 规则里的版本选型改为指向 `dwy-dependency-choice`。
76
+
77
+ ### Removed
78
+ - `rules/开发流程/dwy-tdd-development.md`。行为变更与测试位置改由 `dwy-code-craft.md` 在编辑源码时注入,不再单独占一份全文。
79
+
80
+ ## 0.28.1 — 2026-10-10
81
+
82
+ ### Changed
83
+ - `CLAUDE.md`:路径改仓库内相对路径;连接串不回显密码;注释只要求公共 API 和非显而易见的约束;精简规则不再禁「的」;开源选型只在新增运行时依赖时触发。删掉「无 block 必须多 Agent」和全局输入限长。
84
+ - 输入限长落到 `rules/Vue/dwy-vue-core.md` 与 `rules/Python/dwy-python-backend.md`(图片补像素上限)。
85
+ - `rules/Android/dwy-android-core.md`:字号默认 `sp`,移动端不再 `setExcludeFontScale(true)`。
86
+ - `rules/数据库/dwy-postgres.md`:敏感字段不再默认 AES;要加密时用 AES-GCM。
87
+ - `rules/数据库/dwy-redis.md`:缓存必须 TTL;长期 key 要写原因。
88
+ - `rules/开发流程/dwy-tdd-development.md`:只对行为变更要求测试先行。
89
+ - 无路径的 DB / 许可 / TDD / Docker / 依赖新鲜度 / 编码大局观 / 正式环境分支补上 `paths`。`dwy-git-commit.md` 只在提交相关任务生效。
90
+ - `skills/产品0到1/dwy-prototype` 与 `skills/通用/dwy-whiteboard-prototype` 拆开触发词。
91
+ - `skills/通用/dwy-shared`:远程改为 GitHub `danweiyuancircle/dwy-ai-experience`,同步命令改为 `dwy`。
92
+
93
+ ### Fixed
94
+ - 自成长节不再写已删除的 `dwy codex sync`,也不再把 DWY-RULES 注释标记写进基线正文(该标记会截断 `dwy-cli/AGENTS.md` 托管块)。
95
+
96
+ ## 0.28.0 — 2026-09-29
97
+
98
+ ### Changed
99
+
100
+ - 会变的外部事实改为当前先验:探测失败就换源,当次结果不写回模板。团队栈(Support / Dio / SQLAlchemy、分层、署名、schema_version)不动。
101
+ - `rules/Android/`:AndroidAutoSize 只锁 Support 兼容线,`v1.2.1` 是起点先验。
102
+ - `rules/Flutter/`:Riverpod、freezed、mocktail 的 caret 标明不是该装的版本,实际走依赖新鲜度。
103
+ - `rules/HarmonyOS/dwy-arkts-ui-build.md`:DevEco 路径、模拟器名、hdc 目标改为本机探测。
104
+ - `rules/开发流程/dwy-dependency-freshness.md`:各栈查发布时间的 URL 是先验。PyPI 取最早 `upload_time`,Maven `lastUpdated` 不能单独当首次发布。
105
+ - `rules/数据库/dwy-postgres.md`:连接池 20/10 改为冷启动先验。无上限或打满 `max_connections` 才算违规。
106
+ - `skills/发布发版/dwy-github-action-publish/`:action tag、runner、manylinux、setuptools 下限复制前现查。
107
+ - `skills/发布发版/dwy-ios-app-store-release/`:商店字段字数是先验。内购截图像素只留在 `screenshot-specs.yaml`。
108
+ - `skills/安全/dwy-deploy-audit/`:镜像源名单不再打通过。公网 IP 多源探测,失败标 unknown,不用内网地址顶上。
109
+ - `skills/自媒体/media-platform-packaging/`:小红书 20 字、视频号 16 字、YouTube 逗号改为发布页先验。
110
+ - `skills/自媒体/dwy-doubao-tts/`:endpoint 和 `seed-icl-2.0` 移出硬约束。
111
+ - `skills/通用/dwy-shared/SKILL.md`:npm 官方源是先验。传播延迟和源不可达分开。
112
+ - `skills/DolphinDB/dwy-dolphindb/`:某次机器的 IP、内存、SDK `3.0.4`、500K / 65536 / 255 改为先验。语言约束仍要改。
113
+
114
+ ## 0.27.0 — 2026-09-29
115
+
116
+ ### Changed
117
+
118
+ - `skills/安全/dwy-deploy-audit/references/checks-runtime.md`:内存和日志配额表改为冷启动先验。有 `docker stats` 或日志日增量时按实测判定。偏离表不再算违规。75% 内存合计和约 5% 日志天花板仍是安全上限。
119
+ - `skills/安全/dwy-deploy-audit/scripts/check_capacity.sh`、`check_logs.sh`、`check_docker.sh`:不再把「与 10m/50m/100m 或 65% 一致」印成通过。缺上限、硬限低于实测占用、配额能占满盘,才报问题。
120
+ - `rules/Docker/dwy-docker.md`:compose 里的 `512m` / `10m` 标明是字段示例,不是配额。
121
+
122
+ ---
123
+
124
+ ## 0.26.0 — 2026-09-29
125
+
126
+ ### Changed
127
+
128
+ - `rules/Docker/dwy-docker.md`:镜像版本示例不再当推荐版本。镜像源是当前候选,当次探测后在内容正确的源里取延迟最低的,连通不算通过。
129
+ - `skills/Docker/dwy-docker/`:版本必须来自当次 tag 列表。`query_dockerhub.py` 只是 Docker Hub 先验,失败要换 registry。N-1 是偏好。`version-rules.md` / `ask-templates.md` / `templates.md` 里的版本号禁止照抄。
130
+ - `skills/Docker/dwy-mirror-source/`:取消「默认阿里云 / DaoCloud 首选」。写入前测延迟。`apply_mirrors.py` 增加 `--docker-mirrors`,按探测顺序覆盖内置列表。
131
+ - `skills/Docker/dwy-deploy-first/`:第 1 章合规标准改为当次选出的源或私服,不再把阿里云域名写成唯一合格项。
132
+ - `skills/安全/dwy-deploy-audit/`:镜像版本和镜像源的修复提示改指向上述探测,不再写死 N-1 数字和 `*.m.daocloud.io`。
133
+ - `rules/开发流程/dwy-dependency-freshness.md`:Docker 一行改为查 tag 首次发布时间。Hub `last_updated` 不能当成首次发布,Hub 不通时换镜像所在 registry。
134
+
135
+ ---
136
+
137
+ ## 0.25.0 — 2026-09-27
138
+
139
+ ### Changed
140
+
141
+ - `rules/开发流程/dwy-git-commit.md`:提交前必须删掉 AI 署名,含环境自动塞入的 Cursor 署名。写死名单之外的由 AI 自行判断。hook 拦住后删掉再交,禁止绕过。
142
+ - `hooks/Git/pre-git-commit-ai-signature-check.sh`:拦截提示改为删掉署名后重试,不再建议手动提交绕过 hook。
143
+
144
+ ---
145
+
146
+ ## 0.24.0 — 2026-09-27
147
+
148
+ ### Added
149
+
150
+ - `rules/开发流程/dwy-prod-branch.md`:`develop` 只更新测试环境,正式环境用 `preview`。AI 自行判断是否在用 `develop` 部署正式环境;是则按固定提示让用户确认,并建议合并到 `preview`。未确认不部署。
151
+
152
+ ### Changed
153
+
154
+ - `skills/发布发版/dwy-publish/SKILL.md`:发布前若判断是 `develop` 部署正式环境,先按 `dwy-prod-branch` 问用户。
155
+
156
+ ---
157
+
158
+ ## 0.23.0 — 2026-09-21
159
+
160
+ ### Changed
161
+
162
+ - `rules/Android/dwy-android-mvp.md`:实际 MVP 架构以当前项目上下文为准;写页面前必须先读本仓 Presenter / Contract / 业务 Base。本文件只定行为,不定骨架。静态页可不写 Presenter。业务 Base 仍落 BizFoundation。
163
+ - `rules/Android/dwy-android-core.md` / `dwy-android-layering.md`:去掉强制 Contract 示例与命名
164
+
165
+ ---
166
+
167
+ ## 0.22.0 — 2026-09-21
168
+
169
+ ### Added
170
+
171
+ - `rules/Android/dwy-android-mvp.md`:手写 Contract MVP;`BaseActivity` / `BaseFragment` / `BaseDialog` 落在 BizFoundation。简单静态页和确认框允许无 Presenter;复杂 Dialog 走 Contract。不引 Mosby / Moxy。
172
+
173
+ ### Changed
174
+
175
+ - `rules/Android/dwy-android-core.md`:架构改指向 `dwy-android-mvp`;包组织示例 ViewModel 改为 Contract / Presenter
176
+ - `rules/Android/dwy-android-layering.md`:域内改为 Presenter;点明业务 Base 在 `:biz-foundation`
177
+
178
+ ---
179
+
180
+ ## 0.21.0 — 2026-09-20
181
+
182
+ ### Changed
183
+
184
+ - `rules/Android/dwy-android-core.md`:分端只保留设计基准(移动 `390×844` / TV `1280×720`)+ AutoSize `design_width`。去掉 `values-television`、flavor、`uiMode` 运行时切换等区分方式
185
+ - `rules/Android/dwy-android-support-only.md`:同步去掉资源分目录要求
186
+
187
+ ---
188
+
189
+ ## 0.20.0 — 2026-09-20
190
+
191
+ ### Added
192
+
193
+ - `rules/Android/dwy-android-core.md`:屏幕适配分端设计基准。移动端 `390×844` dp(AutoSize 宽 `390`),TV 端 `1280×720` dp(AutoSize 宽 `1280`);资源 `values` / `values-television`;双端禁止共用 `design_width` 与 dimens
194
+
195
+ ### Changed
196
+
197
+ - `rules/Android/dwy-android-support-only.md`:Support 仓同步上述分端宽
198
+
199
+ ---
200
+
201
+ ## 0.19.0 — 2026-09-20
202
+
203
+ ### Added
204
+
205
+ - `rules/Android/dwy-android-core.md`:屏幕适配固定 AndroidAutoSize `v1.2.1`,只按宽度(`design_width_in_dp` 对齐设计稿宽,手机稿 `390`);禁止按高适配、禁止副单位;页面基类必须 `getResources()` + `AutoSizeCompat`
206
+ - `rules/Android/dwy-android-support-only.md`:Support 仓屏幕适配同样走 AutoSize,禁止改用 `androidx.window`
207
+
208
+ ---
209
+
210
+ ## 0.18.0 — 2026-09-20
211
+
212
+ ### Added
213
+
214
+ - `rules/Android/dwy-android-core.md`:尺寸与字号一律 `dp`,禁止 `px` / `sp`(文字不跟系统字体缩放);数值走 `dimens.xml`
215
+
216
+ ---
217
+
218
+ ## 0.17.0 — 2026-09-20
219
+
220
+ ### Added
221
+
222
+ - `CLAUDE.md`:新增「团队基础库缺口回流」。AI 读当前项目识别用户自研基础库;落点按当场情况动态判断(改基础库还是改业务),不写死库名、也不写死「一律先改业务」。落在业务侧则事后总结提问。
223
+
224
+ ---
225
+
226
+ ## 0.16.0 — 2026-09-15
227
+
228
+ ### Added
229
+
230
+ - `rules/开发流程/dwy-code-craft.md`:编码大局观(无 `paths`,通用包始终注入)。动笔前四问、第二次才抽、扩展靠加文件、反屎山预警、任务内收口 + `project-rules` 自进化;与「简单优先 / 精准改动」的边界写死在借口对照表
231
+
232
+ ---
233
+
234
+ ## 0.15.0 — 2026-09-15
235
+
236
+ ### Added
237
+
238
+ - `rules/Python/dwy-python-layering.md`:四层目录(`app` / `features` / `biz_foundation` / `foundation`)、Feature 零互依、uv 根 `constraint-dependencies`
239
+ - `rules/Vue/dwy-vue-layering.md`:四层目录(`apps/web` / `packages/features` / `biz-foundation` / `foundation`)、Feature 零互依、pnpm `catalog:`
240
+ - `rules/Android/dwy-android-layering.md`:四层模块(`:app` / `:features:*` / `:biz-foundation` / `:foundation`)、禁止透传越层、Gradle Version Catalog
241
+ - `rules/iOS/dwy-apple-layering.md`:iOS+macOS 双壳、`DesktopKit` 仅桌面壳、根 `Package.swift` 锁定 `from:`
242
+
243
+ ### Changed
244
+
245
+ - `dwy-python-backend` / `dwy-vue-core` / `dwy-android-core` / `dwy-swift-core`:项目结构改指向对应 layering,不再维护第二套目录树
246
+ - `skills/产品0到1/dwy-architecture/SKILL.md`:四层表改为引用 `dwy-*-layering`
247
+
248
+ ---
249
+
55
250
  ## 0.14.0 — 2026-09-02
56
251
 
57
252
  ### Changed
@@ -2,20 +2,16 @@
2
2
 
3
3
  ## 输出完整性要求
4
4
 
5
- - **文件路径**:必须输出完整的绝对路径(如 `/Users/chances/WebstormProjects/dwy-shared/frontend/eui/src/components/input/EInput.vue`),禁止省略为相对路径或只写文件名
6
- - **服务地址**:必须输出完整的 URL(如 `http://localhost:8000/api/users`),禁止省略协议、端口或路径
7
- - **数据库连接串**:必须输出完整连接字符串(如 `postgresql+asyncpg://user:pass@localhost:5432/mydb`),禁止只写主机名或库名
8
-
9
- ## 团队执行任务
10
-
11
- 任务执行前必须先分析 block;无 block 的任务使用多 Agent 并行执行以提高效率。
5
+ - **文件路径**:写出从仓库根开始的完整相对路径(如 `frontend/eui/src/components/input/EInput.vue`)。不要只写文件名。不要把本机绝对路径写进规则、代码、文档或提交说明。
6
+ - **服务地址**:写出完整 URL,包含协议、主机、端口和路径(如 `http://localhost:8000/api/users`)。
7
+ - **数据库连接串**:说明它来自哪个环境变量或配置项。回复、日志、示例里不写密码和 token。需要示意时用占位符,如 `postgresql+asyncpg://USER:PASSWORD@localhost:5432/DBNAME`。
12
8
 
13
9
  ## 代码注释
14
10
 
15
- - 所有代码都必须有注释。
16
- - 类、接口、私有方法、函数、重要参数与重要字段都必须写明用途、约束与边界。
17
- - 每个类顶部要有简短功能说明。
18
- - 注释重点写“为什么”和“约束”,避免仅复述代码实现。
11
+ - 导出的类、函数、组件 props 写清用途和调用约束。
12
+ - 不看代码就看不出的约束要写:线程、生命周期、为什么不用更直的写法。
13
+ - 私有方法、getter、一行就能看懂的语句不写注释。
14
+ - 注释写「为什么」和「约束」,不复述代码在做什么。
19
15
 
20
16
  ## 图标规范
21
17
 
@@ -105,42 +101,36 @@
105
101
 
106
102
  ## 输出精简规则
107
103
 
108
- 输出保持精简,去掉冗余,保留技术精确性。
104
+ 输出保持精简,去掉冗余,保留技术精确性。句子要能读通。
109
105
 
110
106
  ### 核心规则
111
107
 
112
- - **去掉填充词**:不用"了/的/吧/吗/呢"等语气助词,不用"我认为/可能/也许/似乎"等模糊词
113
- - **不用客套话**:不用"你好/请/谢谢/不客气"等社交用语,直入主题
114
- - **允许碎片句**:不用强制完整主谓宾,短语表达即可
115
- - **短优先**:能用短词就不用长词,能用一句话就不用两句话
116
- - **技术术语精确**:变量名、函数名、错误信息、代码块等保持原样,不缩写
117
- - **代码块完整**:代码必须完整可运行,不受精简规则影响
108
+ - **去掉口头填充**:不用「你好 / 请 / 谢谢」。不用「我认为」这类没有信息的空话。
109
+ - **不确定就直说**:哪一点不确定,直接写出来。可以用「可能 / 也许」。
110
+ - 「了 / 的 / 吗」该用就用。不要为了短把中文写成残句。
111
+ - **短优先**:能用短词就不用长词,能用一句话就不用两句话。
112
+ - **技术术语精确**:变量名、函数名、错误信息、代码块保持原样,不缩写。
113
+ - **代码块完整**:代码必须完整可运行,不受精简规则影响。
118
114
 
119
- ### 例外场景(恢复完整语气)
115
+ ### 例外场景(写清楚,不省略风险)
120
116
 
121
- 以下场景不得精简,必须清晰明确:
117
+ 以下场景必须清晰明确:
122
118
  - 安全警告和风险提示
123
119
  - 不可逆操作确认(删除、强制推送等)
124
120
  - 需要用户决策的复杂多步骤流程
125
121
  - 用户明确要求详细解释时
126
122
 
127
- ## 必须使用成熟开源方案
123
+ ## 新增依赖才做开源选型
128
124
 
129
- 开发新功能时,先给出 3 到 5 个成熟开源方案,用户确认后再实现。默认不手写已有成熟方案。
125
+ 修 bug、改已有功能、用仓库里已有的依赖或标准库,直接做。不要为了选型停下来。
130
126
 
131
- ### 决策流程(必须执行)
127
+ 只有这次改动要**新增运行时依赖**(新的 npm / PyPI / Gradle / SPM 等包)时才走下面的流程:
132
128
 
133
- 1. 用户需求触发:确认功能范围与技术栈约束。
134
- 2. 候选检索:给出 3 到 5 个成熟开源项目(按 npm/PyPI/GitHub stars、维护活跃度、许可证兼容性排序)并说明选型理由。
135
- 3. 用户选择:先不改代码,向用户返回“候选列表 + 选型对比 + 推荐项”,等待用户明确选择。
136
- 4. 选型确认后:仅对确认方案进行适配实现;未确认方案不落地。
137
- 5. 跨语言备选:若当前技术栈无合适方案,允许并必须先列出其他语言生态(如 Kotlin/Compose、Jetpack、Flutter、React Native、Web 生态)中可借鉴且成熟的 3 到 5 个替代方案,由用户确认后再继续落地;禁止直接从 0 开始造轮子。
129
+ 1. 先看项目已有依赖和标准库能不能做。能做就用已有的。
130
+ 2. 不能做:列出 3 到 5 个当前技术栈里的成熟开源方案,写明维护情况、许可证、是否和已有依赖重复,给出推荐,等用户选定再加依赖。
131
+ 3. 候选不足 3 个:说明找过什么,问用户是否允许自研。不要为了凑数改去列别的语言生态。
138
132
 
139
- ### 强制规则
140
-
141
- - **禁止**手写已有主流开源方案的功能,一律使用社区主流库
142
- - 选用开源库优先级:项目已在用的依赖 > 社区主流方案 > 小众但适合的方案
143
- - 当候选不足 3 个且无可用替代时,说明原因并请求用户确认是否允许自研。
133
+ 禁止手写已经有成熟库、并且项目允许引入该库的能力。选型优先级:项目已在用的依赖 > 当前生态的主流库 > 小众但匹配的库。
144
134
 
145
135
  ## 代码简约原则
146
136
 
@@ -168,34 +158,24 @@
168
158
  | 用户输入、外部 API 响应、文件 / 网络读入 | 必须校验 |
169
159
  | 内部模块调用(已有类型签名) | 信任,不重复校验 |
170
160
 
171
- ## 用户输入长度限制
172
-
173
- 所有用户输入必须限长 / 限大小,**前端 + 后端双层**:
174
-
175
- - 前端:即时反馈,避免无效输入浪费带宽
176
- - 后端:防绕过、防 DoS、防内存耗尽(前端可被绕过,后端必须再校验一次)
177
-
178
- 具体数字按业务语义推断(用户名几十字符、描述几百、正文几千、图片几 MB),无须硬编码统一表。
179
-
180
- ### 前端
181
-
182
- 凡接收用户输入的控件(`input` / `textarea` / 富文本 / 文件选择 / 批量项)→ 都必须有长度 / 大小上限,并配 schema 层校验兜底(防粘贴绕过原生 maxlength)。
161
+ ## 团队基础库缺口回流
183
162
 
184
- ### 后端
163
+ 自己的基础库 = 用户自己开发的库。AI **读当前项目上下文**识别,禁止把库名写死进本规则。社区库不是。读不出 → 当没有。已经在该基础库源码上改 → 本节不适用。
185
164
 
186
- 凡接收用户数据的字段 / Query / Path / Header → 必须显式声明长度上限。
165
+ 落点**按当场情况动态判断**,不要写死「一律改业务」或「一律改基础库」。结合本轮时间与难度、改基础库的成本、复用收益、是不是一次性业务,选更合适的一侧动手。
187
166
 
188
- - 分页 `page_size` 必须有上限
189
- - 禁止用「松散字典 / map / any 类型」直接接收 body,必须有 schema
190
- - 图片上传额外校验像素尺寸,防 decompression bomb
167
+ 本轮落在业务侧、且能力其实通用时,**事后**再总结提问:
191
168
 
192
- ### 禁止
169
+ ```
170
+ 【基础库抽取候选】
171
+ - 识别到的基础库:…(读到的依据)
172
+ - 本轮业务侧做了:…
173
+ - 建议抽到:哪个库的哪个模块
174
+ - 本轮为何没直接改基础库:…
175
+ 要不要抽?抽了之后这处业务补丁可以删。
176
+ ```
193
177
 
194
- - 任一层无限制上线
195
- - 仅前端限而后端不校验
196
- - 后端用 dict / map / any 接收 body
197
- - 分页 `page_size` 无上限
198
- - 图片只校验文件大小不校验像素
178
+ 用户说抽才回头改基础库;说不抽 → 停。
199
179
 
200
180
  ## 自成长项目规则(project-rules)
201
181
 
@@ -204,7 +184,8 @@
204
184
  - **触发**:写代码 / 排查问题时,同一类问题踩坑 **≥2 次**(重复的报错根因、踩同一个坑、被反复纠正同一处写法)。
205
185
  - **动作**:把教训沉淀成一条可复用规则(写清「现象 / 根因 / 怎么避免」),追加到 `project-rules.md`;已有同类规则补充进去,不重复立条。
206
186
  - **落盘位置**(按当前工具自动选):
207
- - **Claude Code** → 项目 `.claude/rules/project-rules.md`(放进去即自动加载,无需注册)。
208
- - **Codex** → 项目根 `AGENTS.md`,写在 `<!-- DWY-RULES:START/END -->` 托管块**之外**的 `## [自成长] 项目规则` 节下。托管块内会被 `dwy codex sync` 整块覆盖,自成长内容**必落块外**。
187
+ - **Claude Code 与 Grok** → 项目 `.claude/rules/project-rules.md`(两边都会加载这个目录)。
188
+ - **Codex** → 项目根 `AGENTS.md` 里 DWY-RULES 托管块之外的 `## [自成长] 项目规则`。托管块会被 `dwy sync` 整块覆盖,自成长内容必须写在块外。
209
189
  - **方式**:自动沉淀,事后输出一行告知「已沉淀 <规则> 到 project-rules」,不打断当前任务、不逐条问用户。
210
190
  - **边界**:只沉淀**可复用、跨任务**的教训;一次性 / 本任务特有的问题不立规则,避免噪音堆积。
191
+ - **不要**在基线正文里写 DWY-BASELINE 或 DWY-RULES 的 HTML 注释标记。同步用这两个标记切块,写进正文会把托管块截断。
@@ -1 +1 @@
1
- 0.14.0
1
+ 0.31.0
@@ -3,7 +3,8 @@
3
3
  # 拦截 git commit message 中的 AI 署名 / 生成声明
4
4
  #
5
5
  # 背景:AI agent 常在 commit message 中附加 Co-Authored-By: Claude / Generated with Claude Code 等署名。
6
- # 本 hook 检出此类模式后硬拦截(exit 2),要求人工确认或清理后再提交。
6
+ # 本 hook 只拦下面写死的模式(exit 2)。
7
+ # 名单以外的 AI 署名由规则要求模型在提交前自行判断并删除,不要等拦截后再绕过。
7
8
  #
8
9
  # 覆盖模式(不区分大小写):
9
10
  # Co-Authored-By: <ai-name> <noreply@...>
@@ -47,9 +48,9 @@ if [ -n "$HIT" ]; then
47
48
  echo "$HIT"
48
49
  echo ""
49
50
  echo "commit message 中禁止出现 Co-Authored-By / Generated with 等 AI 署名。"
50
- echo "请清理 AI 署名后再提交。"
51
- echo ""
52
- echo "如果要强制提交,请手动执行 git commit(绕过 hook)。"
51
+ echo "删掉命中的署名后重新 commit。同一种署名一起删。"
52
+ echo "名单之外的 AI 署名也要自行判断并删除。"
53
+ echo "不要绕过 hook,不要改让用户手动提交。"
53
54
  echo "========================================"
54
55
  exit 2 # 暂停等待人工审批
55
56
  fi
@@ -13,7 +13,7 @@ paths:
13
13
 
14
14
  适用于 **Android 原生项目**(Java + Kotlin 混编,XML 布局,Gradle 构建脚本)。本规范**重点是代码注释**,兼带最小必要的命名 / 简约 / 反模式约束。
15
15
 
16
- 不限制构建工具、UI 框架、架构模式、SDK 版本、依赖库选型 —— 与老项目兼容。
16
+ 不限制构建工具、UI 框架、SDK 版本、依赖库选型 —— 与老项目兼容。页面架构走 `dwy-android-mvp`(实际 MVP 读当前项目上下文;本文件只定行为);模块四层走 `dwy-android-layering`。
17
17
 
18
18
  ## 全面屏 / 刘海屏适配
19
19
 
@@ -23,6 +23,136 @@ paths:
23
23
  - 全屏背景、沉浸式遮罩可以延伸到系统栏区域,但前景可交互内容默认留在安全显示区内。
24
24
  - 禁止写死状态栏高度、导航栏高度、刘海高度,统一通过系统 inset 获取。
25
25
 
26
+ ## 尺寸单位
27
+
28
+ 布局、间距、圆角、描边用 `dp`。字号用 `sp`,跟随系统字体缩放。禁止 `px`。数值走 `dimens.xml`,禁止在 XML / 代码里裸写 `16dp` / `16sp`。
29
+
30
+ **为什么字号用 sp**:系统大字是可访问性能力。把字号锁成 `dp`、或除掉 `fontScale`,大字模式会失效。
31
+
32
+ **例外**:电视,或设计明确要求不跟随系统字号的固定版式,字号资源才用 `dp`,并在资源旁写明原因。
33
+
34
+ ### 禁止 / 必须
35
+
36
+
37
+ | 场景 | 禁止 | 必须 |
38
+ | --- | --- | --- |
39
+ | XML 宽高 / 间距 / 圆角 / 描边 | `16px`、裸数字 | `@dimen/xxx`,资源值 `16dp` |
40
+ | XML / style 字号 | `16px`、裸 `16sp`、用 `dp` 锁死字号 | `@dimen/xxx`,资源值 `16sp` |
41
+ | 代码设字号 | 裸数字、再除一次 `fontScale` | `setTextSize(COMPLEX_UNIT_PX, getDimension(R.dimen.xxx))`。dimen 是 `sp` 时 `getDimension` 已按当前字号缩放换成 px |
42
+ | Jetpack Compose 布局 | `16.px`、裸 `.dp` 字面量 | `dimensionResource(R.dimen.xxx)` |
43
+ | Jetpack Compose 字号 | 裸 `16.sp`、`toPx() / fontScale` | 从 `sp` 的 dimen 读出后再 `.toSp()`,让系统字体缩放只生效一次 |
44
+
45
+
46
+ 系统 API 返回值本身是 px(`View.getWidth()`、`MotionEvent`、Canvas、`getDimension()`)——那是运行时像素,不是声明单位。声明布局尺寸仍用 dp,声明字号仍用 sp。
47
+
48
+ ```xml
49
+ <!-- res/values/dimens.xml -->
50
+ <dimen name="text_size_title">18sp</dimen>
51
+ <dimen name="padding_page">16dp</dimen>
52
+ ```
53
+
54
+ ```xml
55
+ <!-- ❌ -->
56
+ <AppCompatTextView android:textSize="16sp" android:layout_width="100px" />
57
+ <AppCompatTextView android:textSize="16dp" />
58
+
59
+ <!-- ✅ 字号 sp、间距 dp,都走资源 -->
60
+ <AppCompatTextView
61
+ android:textSize="@dimen/text_size_title"
62
+ android:padding="@dimen/padding_page" />
63
+ ```
64
+
65
+ ```kotlin
66
+ // ❌
67
+ textView.textSize = 16f
68
+ textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f)
69
+ Text("标题", fontSize = 16.sp)
70
+
71
+ // ✅ View:dimen 是 sp。getDimension 已按 fontScale 换成 px,不要再套一层 SP,也不要除 fontScale。
72
+ textView.setTextSize(
73
+ TypedValue.COMPLEX_UNIT_PX,
74
+ resources.getDimension(R.dimen.text_size_title)
75
+ )
76
+
77
+ // ✅ Compose:dimensionResource 把 sp 资源按当前 fontScale 收成 Dp。toSp() 除掉这一次,绘制时系统再乘一次。
78
+ val titleSize = with(LocalDensity.current) {
79
+ dimensionResource(R.dimen.text_size_title).toSp()
80
+ }
81
+ Text("标题", fontSize = titleSize)
82
+ ```
83
+
84
+ 布局用 `dimensionResource(R.dimen.xxx)` 读 dimens,不要散落裸 `.dp`。字号不要写裸 `.sp`。
85
+
86
+ ## 屏幕适配(AndroidAutoSize,只按宽)
87
+
88
+ 屏幕适配用 [JessYan AndroidAutoSize](https://github.com/JessYanCoding/AndroidAutoSize) `1.2.1`(今日头条 density 方案)。**只按宽度适配**,不按高度。布局写 `dp`、字号写 `sp`(见上一节),由框架改 `density`,让屏幕逻辑宽等于设计稿宽。字号仍跟随系统字体缩放。
89
+
90
+ **为什么只按宽**:高度含状态栏 / 刘海 / 手势条,按高适配会把系统栏算进设计高,全面屏变形。宽是稳定轴。
91
+
92
+ `1.2.0+` 同时兼容 Support 与 AndroidX,按当前项目推断,**禁止**为接本库引入 `androidx.*`。Support 老项目见 `dwy-android-support-only`。
93
+
94
+ 分端只体现在 **设计稿尺寸 + `design_width_in_dp`**。AutoSize 按宽铺满,不必再用 `values-television`、`productFlavor`、`UI_MODE_TYPE_TELEVISION` 去拆资源或运行时切换。
95
+
96
+ ### 设计基准
97
+
98
+ 单位一律 `dp`。`design_width_in_dp` 填当前产品那一行的宽。
99
+
100
+ | 端 | 画布 | 方向 | `design_width_in_dp` | `design_height_in_dp`(只记录,不参与适配) |
101
+ | --- | --- | --- | --- | --- |
102
+ | 移动端 | **390 × 844** | 竖屏 | **390** | 844 |
103
+ | TV 端 | **1280 × 720** | 横屏 | **1280** | 720 |
104
+
105
+ ### 依赖
106
+
107
+ JCenter 已停,走 JitPack。用仍兼容 Support、不引入 AndroidX 的正式版。已核对过的起点是 `v1.2.1`(`1.2.0+` 才兼容 Support)。新 tag 先看传递依赖,拉进 AndroidX 就丢掉。具体 tag 按依赖新鲜度现查,不要把 `v1.2.1` 当成永远唯一坐标。
108
+
109
+ ```gradle
110
+ // 起点先验。写入前确认该 tag 仍不带 androidx
111
+ implementation 'com.github.JessYanCoding:AndroidAutoSize:v1.2.1'
112
+ ```
113
+
114
+ ### 配置(强制)
115
+
116
+ Manifest 按上表填当前产品。下面是移动端;TV 把宽改成 `1280`、高改成 `720`。
117
+
118
+ ```xml
119
+ <application>
120
+ <meta-data
121
+ android:name="design_width_in_dp"
122
+ android:value="390" />
123
+ <meta-data
124
+ android:name="design_height_in_dp"
125
+ android:value="844" />
126
+ </application>
127
+ ```
128
+
129
+ ```java
130
+ // 移动端保留系统字体缩放。TV、或设计写明固定字号的界面,才 setExcludeFontScale(true)。
131
+ AutoSizeConfig.getInstance()
132
+ .setBaseOnWidth(true)
133
+ .setExcludeFontScale(false);
134
+ ```
135
+
136
+ 页面基类必须重写 `getResources()`,防止厂商 ROM / Dialog / 三方把 `density` 改回去导致偶发错位:
137
+
138
+ ```java
139
+ @Override
140
+ public Resources getResources() {
141
+ AutoSizeCompat.autoConvertDensityOfGlobal(super.getResources());
142
+ return super.getResources();
143
+ }
144
+ ```
145
+
146
+ 三方 WebView / 扫码 / 系统 Dialog 错乱:该页实现 `CancelAdapt`,或 `show()` 前再调一次 `AutoSizeCompat.autoConvertDensityOfGlobal`。
147
+
148
+ ### 禁止
149
+
150
+ - `setBaseOnWidth(false)` 或按高度适配
151
+ - 移动端 `setExcludeFontScale(true)`,或用除 `fontScale` 把字号锁死
152
+ - 副单位 `pt` / `in` / `mm`
153
+ - 再接 `sdp` / 百分比库 / 另一套改 `density` 的方案
154
+ - 布局改回 `px`
155
+
26
156
  ## 控件选型(AppCompat)
27
157
 
28
158
  XML 布局、代码 `new`、自定义 View:**只要存在 AppCompat 对应类,就必须用 AppCompat 版**,禁止 `android.widget` 平台控件。没有 AppCompat 对应类的布局容器 / 列表(LinearLayout、ConstraintLayout、RecyclerView 等)保持原样。
@@ -101,6 +231,7 @@ class PriceText(context: Context, attrs: AttributeSet?) : AppCompatTextView(cont
101
231
  | Fragment | `XxxFragment` | `HomeFragment` |
102
232
  | Adapter / ViewHolder | `XxxAdapter` / `XxxViewHolder` | `OrderAdapter` |
103
233
  | Dialog | `XxxDialog` | `ConfirmDialog` |
234
+ | MVP 相关 | 跟当前项目已有命名 | 常见 `XxxPresenter`(有 Contract 则跟本仓) |
104
235
  | 布尔变量 / 方法 | `is`* / `has*` / `can*` / `should*` | `isLoading`、`hasNext` |
105
236
 
106
237
 
@@ -114,7 +245,7 @@ class PriceText(context: Context, attrs: AttributeSet?) : AppCompatTextView(cont
114
245
  | drawable | `<用途>_<状态>` | `bg_button_primary`、`ic_arrow_right`、`shape_card_corner` |
115
246
  | color | `<语义>` | `color_primary`、`color_text_secondary` |
116
247
  | string | `<场景>_<语义>` | `login_button_submit`、`home_title` |
117
- | dimen | `<语义>` | `padding_normal`、`text_size_title` |
248
+ | dimen | `<语义>`。布局 `dp`,字号 `sp`(禁止 `px`) | `padding_normal`、`text_size_title` |
118
249
  | anim / animator | `<逻辑名>_<方向|序号>` 或通用动画名 | `fade_in.xml`、`push_bottom_in.xml`、`loading_001.xml` |
119
250
  | menu | `menu_<场景>.xml` | `menu_order_detail.xml` |
120
251
  | style / theme | `PascalCase`,点号继承,从通用到特殊 | `Widget.App.Button`、`Theme.App.Dark` |
@@ -219,10 +350,10 @@ class UserActivity : AppCompatActivity() {
219
350
 
220
351
  ```xml
221
352
  <!-- ❌ 裸文案 / 裸数字 -->
222
- <TextView android:text="登录" android:textSize="16sp" />
353
+ <AppCompatTextView android:text="登录" android:textSize="16dp" />
223
354
 
224
- <!-- ✅ 走资源 -->
225
- <TextView android:text="@string/login_button_submit" android:textSize="@dimen/text_size_normal" />
355
+ <!-- ✅ 走资源;字号单位也是 dp,见「尺寸单位(强制 dp)」 -->
356
+ <AppCompatTextView android:text="@string/login_button_submit" android:textSize="@dimen/text_size_normal" />
226
357
  ```
227
358
 
228
359
  ## 二、代码注释
@@ -792,7 +923,7 @@ for (Order o : orders) {
792
923
 
793
924
  | 覆盖 | 不覆盖 |
794
925
  | ---- | ------ |
795
- | Model / Entity / DTO / VO / Bean 及同类数据载体 | Activity / Fragment / Adapter / ViewHolder / Repository / ViewModel 等非数据载体 |
926
+ | Model / Entity / DTO / VO / Bean 及同类数据载体 | Activity / Fragment / Adapter / ViewHolder / Repository / Presenter 等非数据载体 |
796
927
  | 含功能包内私有、`internal` 实体 | `enum`;仅含常量的 `object` / `Constants` 类 |
797
928
  | 网络响应体、跨层传递的数据对象 | 纯 UI 状态若仅为页面内部临时结构且不跨层,可豁免(跨层则按实体处理) |
798
929
 
@@ -926,9 +1057,11 @@ class User(val id: Long, val name: String)
926
1057
 
927
1058
  ### 包组织(按功能聚合)
928
1059
 
1060
+ **Gradle 模块四层(`:app` / `:features:*` / `:biz-foundation` / `:foundation`)与依赖边 → 见 `dwy-android-layering`。** 本节只约束**模块内部** Java/Kotlin 包。
1061
+
929
1062
  **按功能聚合(package-by-feature),不按技术分层(package-by-layer)。**
930
1063
 
931
- 同一个功能/页面相关的所有类 —— 页面(Activity / Fragment)、其数据实体、业务逻辑(ViewModel / Presenter / UseCase)、数据访问(Repository)、列表 Adapter、UI 状态等 —— 放在**同一个功能包**下聚合,而不是按类型横切成 `activities/`、`models/`、`adapters/`、`repositories/` 这种分层包。
1064
+ 同一个功能/页面相关的所有类 —— 页面(Activity / Fragment)、其数据实体、业务逻辑(Presenter 或本仓对等角色)、数据访问(Repository)、列表 Adapter、UI 状态等 —— 放在**同一个功能包**下聚合,而不是按类型横切成 `activities/`、`models/`、`adapters/`、`presenters/` 这种分层包。页面架构见 `dwy-android-mvp`(切法跟当前项目)。
932
1065
 
933
1066
  **理由**:改一个功能时,相关文件都在一个包内,无需在多个分层目录间跳转;包之间按业务边界解耦,删除/迁移一个功能只动一个包;高内聚低耦合,符合就近维护。
934
1067
 
@@ -937,24 +1070,23 @@ class User(val id: Long, val name: String)
937
1070
  com.example.app/
938
1071
  login/ <!-- 登录功能,自包含 -->
939
1072
  LoginActivity.kt
940
- LoginViewModel.kt
1073
+ LoginPresenter.kt <!-- 或本仓已有的 Contract / XxxView,跟项目 -->
941
1074
  LoginRepository.kt
942
- LoginUiState.kt
943
1075
  Credential.kt <!-- 该功能私有实体 -->
944
1076
  order/ <!-- 订单功能 -->
945
1077
  OrderListActivity.kt
946
1078
  OrderDetailActivity.kt
947
- OrderViewModel.kt
1079
+ OrderListPresenter.kt <!-- 同上,不强制 Contract 文件 -->
948
1080
  OrderRepository.kt
949
1081
  OrderAdapter.kt
950
1082
  Order.kt
951
- common/ <!-- 跨功能共享:基类、工具、网络、通用实体 -->
1083
+ common/ <!-- 未拆四层时:本产品 Base / 工具。有 :biz-foundation 则 Base 放那个模块 -->
952
1084
  base/ network/ util/ model/
953
1085
 
954
1086
  // ❌ 按技术分层横切 —— 改一个功能要在多个目录间反复跳
955
1087
  com.example.app/
956
1088
  activities/ LoginActivity.kt OrderListActivity.kt OrderDetailActivity.kt
957
- viewmodels/ LoginViewModel.kt OrderViewModel.kt
1089
+ presenters/ LoginPresenter.kt OrderListPresenter.kt
958
1090
  repositories/ LoginRepository.kt OrderRepository.kt
959
1091
  adapters/ OrderAdapter.kt
960
1092
  models/ Credential.kt Order.kt
@@ -1090,7 +1222,7 @@ if (trimmed.isNotEmpty()) { ... }
1090
1222
  | Kotlin 顶层 `var` | `val`;需可变用类封装 + 同步原语 |
1091
1223
  | 内部类持有外部 Activity | `static` 内部类 + `WeakReference` |
1092
1224
  | 拼接 SQL 字符串 | 参数化查询 |
1093
- | 硬编码 dp / sp 值 | `@dimen/` |
1225
+ | 硬编码尺寸 / 字号用 `px` 或用 `dp` 锁死字号 | 布局 `@dimen/` 值 `dp`,字号 `@dimen/` 值 `sp` |
1094
1226
  | 硬编码颜色值 `#FF0000` | `@color/color_primary` |
1095
1227
  | 用户可见文案硬编码 | `@string/...` |
1096
1228
  | 单行 `if` / `for` / `while` / `do-while` 无 `{}`(Kotlin 表达式 `if` 除外) | 即使只一行也写 `{}`;详见 §四「控制流大括号」 |
@@ -1131,6 +1263,8 @@ if (trimmed.isNotEmpty()) { ... }
1131
1263
  | 22 | 数据实体(Model/DTO/VO/Bean 等):Java 字段 `private` + get/set + `toString`;Kotlin 优先 `data class`+`val`(自带 toString),禁止 `@JvmField`,非 data class 必须手写 `toString` | ✓ |
1132
1264
  | 23 | 字符串空判断用 `isEmpty` / `isNotEmpty` / `isNotBlank`,禁止 `length() > 0` / `== 0` / `!= 0` 及 `trim().length() > 0` 判空;详见 §八「字符串空判断」 | ✓ |
1133
1265
  | 24 | 有 AppCompat 对应类的控件必须用 AppCompat 版(XML / `new` / 自定义 View 父类),包名按当前项目推断;Switch 用 `SwitchCompat`;无对应类的布局容器保持原样 | ✓ |
1266
+ | 25 | 布局 `dp`、字号 `sp`,禁止 `px` 和裸字面量(含 Compose `16.sp` / `16.px`);数值走 `dimens.xml`。不要除掉 `fontScale`。TV / 固定版式才允许字号用 `dp` 并写明原因 | ✓ |
1267
+ | 26 | 屏幕适配走 AndroidAutoSize(Support 兼容线,起点先验 `v1.2.1`,不锁死这个 tag),只按宽;移动端 `design_width=390`(画布 `390×844`),TV `design_width=1280`(画布 `1280×720`);禁止按高适配、禁止副单位;页面基类重写 `getResources()` 调 `AutoSizeCompat` | ✓ |
1134
1268
 
1135
1269
 
1136
1270
  **不执行自检就提交代码 = 违规。**