create-dwy 0.16.1 → 0.17.1

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 (105) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/bin/index.js +23 -19
  3. package/package.json +1 -1
  4. package/src/cli-help.js +44 -0
  5. package/src/sync-all.js +303 -59
  6. package/src/sync-global-skills.js +167 -0
  7. package/src/sync.js +21 -11
  8. package/templates/ai-tools/CHANGELOG.md +134 -0
  9. package/templates/ai-tools/VERSION +1 -1
  10. package/templates/ai-tools/rules/Android/dwy-android-core.md +65 -1
  11. package/templates/ai-tools/rules/Python/dwy-python-core.md +47 -0
  12. package/templates/ai-tools/rules/Vue/dwy-vue-core.md +55 -0
  13. package/templates/ai-tools/rules/iOS/dwy-swift-core.md +46 -0
  14. package/templates/ai-tools/rules//345/274/200/345/217/221/346/265/201/347/250/213/dwy-oss-commercial-license.md +128 -0
  15. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/SKILL.md +65 -0
  16. 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 +43 -0
  17. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/references/api-workflow.md +17 -0
  18. 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 +16 -0
  19. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/references/screenshot-workflow.md +16 -0
  20. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-ios-app-store-release/scripts/appstore_config.sh +140 -0
  21. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/SKILL.md +11 -8
  22. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/android.md +2 -1
  23. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/backend-deploy.md +2 -1
  24. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/changelog.md +24 -4
  25. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/frontend-deploy.md +2 -1
  26. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/generic-release.md +2 -1
  27. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/git-tag.md +82 -0
  28. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/harmony.md +2 -1
  29. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/ios.md +3 -2
  30. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-publish/references/monitor-notify.md +2 -2
  31. package/templates/ai-tools/skills//345/217/221/345/270/203/345/217/221/347/211/210/dwy-semver/SKILL.md +1 -1
  32. package/templates/ai-tools/skills//345/237/272/347/241/200/345/272/223/dwy-eapi/references/tasks-integration-guide.md +2 -2
  33. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/README.md +57 -0
  34. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/SKILL.md +147 -0
  35. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/references/api.md +43 -0
  36. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/references/config.example.yaml +33 -0
  37. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/scripts/global_config.py +89 -0
  38. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/scripts/setup_config.py +175 -0
  39. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/dwy-doubao-tts/scripts/synthesize.py +339 -0
  40. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/SKILL.md +127 -0
  41. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/assets/cover-style-master-v1.png +0 -0
  42. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/references/platform-copy-examples.md +37 -0
  43. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/media-platform-packaging/references/platform-posting-times.md +193 -0
  44. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0005-ideation/SKILL.md +42 -0
  45. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0005-ideation/templates/topic-backlog.template.md +50 -0
  46. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0005-ideation/templates//351/200/211/351/242/230/346/261/240.template.md +16 -0
  47. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0010-product/SKILL.md +106 -0
  48. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0010-product/templates/channel-profile.template.md +52 -0
  49. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0010-product/templates//344/272/247/345/223/201/345/215/241.template.md +132 -0
  50. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0030-facts/SKILL.md +60 -0
  51. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0030-facts/scripts/build_facts_html.py +430 -0
  52. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0030-facts/scripts/generate_html.py +1287 -0
  53. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0030-facts/scripts/generate_report.py +189 -0
  54. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0030-facts/templates//344/272/213/345/256/236/350/265/204/346/226/231/345/272/223.template.md +55 -0
  55. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/SKILL.md +36 -0
  56. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/templates/README.md +10 -0
  57. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/templates//344/272/213/345/256/236.template.md +82 -0
  58. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/templates//345/215/225/351/233/206/346/226/207/346/241/243.template.md +175 -0
  59. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/templates//350/204/232/346/234/254.template.md +69 -0
  60. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0040-script/templates//351/252/250/346/236/266-v1.1.md +174 -0
  61. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0050-design/SKILL.md +55 -0
  62. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0060-assets/SKILL.md +29 -0
  63. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package/SKILL.md +42 -0
  64. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package/scripts/validate_shots.py +207 -0
  65. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package/shots.schema.json +186 -0
  66. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package//344/272/272/345/256/241/345/214/205.template.md +1 -0
  67. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package//344/272/272/345/256/241/350/257/264/346/230/216.md +15 -0
  68. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0070-package//346/210/220/347/211/207/345/214/205.template.md +49 -0
  69. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-0080-factory/SKILL.md +58 -0
  70. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-comic-kit/SKILL.md +424 -0
  71. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-comic-kit/evals.md +41 -0
  72. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-flow/CONTRACT.md +123 -0
  73. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-flow/SKILL.md +81 -0
  74. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-flow//346/211/247/350/241/214/346/270/205/345/215/225.template.md +60 -0
  75. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/SKILL.md +78 -0
  76. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/agents/openai.yaml +4 -0
  77. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/knowledge-town-paper-film-v1.json +80 -0
  78. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/remotion/AudioTracks.tsx +20 -0
  79. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/remotion/CaptionLayer.tsx +18 -0
  80. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/remotion/CueTimeline.ts +24 -0
  81. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/assets/remotion/KnowledgeTownComposition.tsx +21 -0
  82. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/references/cinematic-direction.md +73 -0
  83. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/references/sticker-asset-production.md +30 -0
  84. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/references/style-guide.md +43 -0
  85. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/scripts/build_cue_timeline.py +75 -0
  86. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/scripts/validate_cue_timeline.py +68 -0
  87. package/templates/ai-tools/skills//350/207/252/345/252/222/344/275/223/uc-media-knowledge-town/scripts/validate_style_preset.py +22 -0
  88. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/SKILL.md +0 -511
  89. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/references/checks-data.md +0 -126
  90. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/references/checks-network.md +0 -88
  91. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/references/checks-runtime.md +0 -195
  92. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/references/security-doc-search.md +0 -179
  93. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_base.sh +0 -39
  94. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_capacity.sh +0 -278
  95. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_db.sh +0 -147
  96. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_docker.sh +0 -230
  97. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_env.sh +0 -64
  98. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_https.sh +0 -60
  99. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_logs.sh +0 -209
  100. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_nginx.sh +0 -100
  101. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_resilience.sh +0 -157
  102. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_secrets.sh +0 -265
  103. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_services.sh +0 -94
  104. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/check_ssh.sh +0 -56
  105. package/templates/ai-tools/skills/unitcircle/uc-deploy-audit/scripts/run_all.sh +0 -105
@@ -0,0 +1,128 @@
1
+ ---
2
+ description: 商用/销售类应用的开源依赖许可合规(禁不可商用与强 copyleft;仅强制署名时在隐私协议附录声明含版本)
3
+ ---
4
+
5
+ # 商用开源依赖许可合规(强制)
6
+
7
+ > 销售、SaaS、付费 App、对外交付的商业产品引入开源库时,
8
+ > 许可不合规会带来版权/违约风险。本规则约束:选型禁区 + 强制署名时的声明义务。
9
+
10
+ ## 一、适用边界
11
+
12
+ - **适用**:任何面向收费/销售/对外商用的应用(含内部先试用后商用的产品)
13
+ - **不适用**:纯学习/练手/未商用的 builder 原型(一旦要上架/收费,必须补齐本规则)
14
+ - **覆盖栈**:npm/pnpm、PyPI/uv、CocoaPods/SPM、Gradle/Maven、ohpm、pub、Docker 基础镜像、字体/图标/素材、模型权重与 SDK
15
+ - **声明范围**:仅 **直接依赖**;不强制盘传递依赖
16
+
17
+ ## 二、核心原则(三条)
18
+
19
+ 1. **先查许可,再装依赖** — 未确认 license 的包禁止引入
20
+ 2. **明确不可商用 / 强 copyleft → 禁止直接使用** — 换可商用替代,或购买商业授权
21
+ 3. **仅当许可强制要求署名 / NOTICE 时**,才在隐私协议附录中声明(含版本);**不强制署名的库不必写**
22
+
23
+ ## 三、禁止引入(不可商用 / 高法律风险)
24
+
25
+ 以下类型**默认禁止**写入依赖树(直接依赖必须查;已知会把禁区 license 顶进运行时链接的包也不得引):
26
+
27
+ | 类型 | 常见标识 | 原因 |
28
+ |---|---|---|
29
+ | 明确非商业 | `CC-BY-NC*`、`CC-NC`、`PolyForm-Noncommercial`、许可证写 Non-Commercial / No Commercial Use | 商用即侵权 |
30
+ | 强传染 copyleft(闭源商用) | `GPL-2.0`、`GPL-3.0`、`AGPL-3.0`、`SSPL` | 可能强制整包开源或限制网络服务形态;**闭源商用一律禁止** |
31
+ | 限制竞争/生产用途 | `BUSL`(未到 Change Date 且限制 Production)、Commons Clause、部分 Source-Available | 表面开源,实则禁商用或禁竞争 |
32
+ | 仅免费个人/评估 | 字体/图标/SDK 写 "free for personal use only"、"evaluation only" | 商用需买授权 |
33
+ | 无 license / 自定义模糊条款 | 仓库无 LICENSE、或 "all rights reserved" 却当开源用 | 默认不可用 |
34
+
35
+ ### 例外(必须显式记录)
36
+
37
+ - 已购买**商业授权**且合同覆盖当前用途 → 可引入,记录授权方、合同编号、到期日
38
+ - LGPL 等边界许可 → 不得默认通过,须单独评估后再定
39
+
40
+ ### 选型动作(强制)
41
+
42
+ 引入新依赖时在选型对比中增加一列 **License**,并标注:
43
+
44
+ - `OK-商用`(可商用;若无强制署名义务则声明页可不写)
45
+ - `OK-商用+强制署名`(MIT/BSD/Apache-2.0/ISC 等要求保留版权与许可声明 → 须进隐私协议附录)
46
+ - `OK-商用+额外义务`(如 Apache NOTICE、MPL 文件级 copyleft 等 → 按义务处理,署名类进附录)
47
+ - `禁-不可商用/高风险`(上表)→ **不得推荐为默认项**
48
+
49
+ ## 四、强制署名时的声明义务
50
+
51
+ ### 4.1 何时必须声明(仅此场景)
52
+
53
+ 直接依赖的 license **明确要求** attribution / copyright notice / NOTICE / 保留许可文本时,必须声明。
54
+
55
+ **不强制署名则不写**:无保留声明义务的可商用库,不必塞进隐私协议或开源列表。
56
+
57
+ ### 4.2 声明落点
58
+
59
+ - **唯一约定落点**:隐私协议 **附录**「第三方开源组件」
60
+ - 不与个人信息处理条款正文混写;附录与正文分节
61
+ - 若产品另有「关于 / 法律信息」页,可链到该附录,不替代附录本身
62
+
63
+ ### 4.3 每条声明最低字段(强制)
64
+
65
+ | 字段 | 说明 | 示例 |
66
+ |---|---|---|
67
+ | 组件名 | 直接依赖包名 | `axios` |
68
+ | 版本 | **实际锁定版本**(lockfile / 构建锁定) | `1.7.9` |
69
+ | 许可证 | SPDX 标识 | `MIT` |
70
+ | 版权声明 | 来自 LICENSE / 包元数据 | `Copyright (c) 2014-present Matt Zabriskie` |
71
+ | 许可全文或链接 | 全文或稳定 URL | `https://opensource.org/licenses/MIT` |
72
+
73
+ **版本必须写锁定版本**,禁止只写 `latest` 或不写版本。
74
+
75
+ ### 4.4 声明模板(可直接贴进隐私协议附录)
76
+
77
+ ```text
78
+ 附录:第三方开源组件
79
+
80
+ 本产品直接使用的、且许可证要求保留声明的开源组件如下:
81
+
82
+ 1. axios 1.7.9
83
+ License: MIT
84
+ Copyright (c) 2014-present Matt Zabriskie
85
+ https://github.com/axios/axios/blob/v1.7.9/LICENSE
86
+
87
+ 2. dayjs 1.11.13
88
+ License: MIT
89
+ Copyright (c) 2018-present, iamkun
90
+ https://github.com/iamkun/dayjs/blob/v1.11.13/LICENSE
91
+ ```
92
+
93
+ 仅列 **直接依赖 + 许可强制署名** 的项;无强制署名义务的直接依赖不列。
94
+
95
+ ### 4.5 何时更新声明
96
+
97
+ - 新增/替换直接依赖,且其许可强制署名
98
+ - 已声明组件的主版本或锁定版本变更
99
+ - 发版前:附录中的版本 vs lockfile **必须一致**;已移除的组件从附录删掉
100
+
101
+ ## 五、执行检查清单(引入依赖 / 发版前)
102
+
103
+ - [ ] 直接依赖均有明确 SPDX license(或等价官方许可文本)
104
+ - [ ] 无 NC / 非商业 / GPL / AGPL / SSPL / 评估版字体图标等禁区
105
+ - [ ] 无未评估的 LGPL / 商业授权到期风险
106
+ - [ ] 仅对「许可强制署名」的直接依赖写入隐私协议附录(含版本号)
107
+ - [ ] 不强制署名的库未滥写进附录
108
+ - [ ] 附录版本与 lockfile 一致
109
+
110
+ ## 六、AI 行为约束
111
+
112
+ - 推荐开源方案时:**必须带 license 与商用结论**(OK / OK+强制署名 / 禁 / 需商业授权)
113
+ - 候选为 NC / GPL / AGPL / SSPL / 无 license:**不得作为推荐默认项**;列出可商用替代
114
+ - 生成/修改隐私协议时:扫描直接依赖,**只把强制署名的项**写入附录「第三方开源组件」
115
+ - 不得以「业界都在用」跳过 license 核查
116
+ - 不得把无强制署名义务的库整表刷进隐私协议
117
+
118
+ ## 七、常见许可速查(非穷尽)
119
+
120
+ | SPDX | 商用闭源 | 是否强制进隐私协议附录 |
121
+ |---|---|---|
122
+ | MIT / ISC / BSD-2/3 | 可 | **是**(要求保留版权与许可声明) |
123
+ | Apache-2.0 | 可 | **是**(保留 NOTICE / 声明) |
124
+ | MPL-2.0 | 通常可 | 按义务;修改过的 MPL 文件另有开源义务 |
125
+ | LGPL-2.1/3.0 | 须单独评估 | 评估通过后再定声明 |
126
+ | GPL / AGPL / SSPL | **禁** | —(不得引入) |
127
+ | CC-BY-NC* | **禁** | —(不得引入) |
128
+ | 无 license | **禁** | —(不得引入) |
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: dwy-ios-app-store-release
3
+ description: "iOS/macOS App Store 上架编排。用户要求创建或填写 App Store Connect 应用资料、生成并上传 iOS/macOS 截图、配置全地区定价、创建内购/自动续期订阅、提交 TestFlight 或 App Review 时使用。使用 App Store Connect API 自动填充,使用已登录 Playwright 补齐网页专属步骤;首次运行在用户私有目录缓存 API 配置。"
4
+ ---
5
+
6
+ # iOS/macOS App Store 上架
7
+
8
+ 将开发完成的 Apple 应用整理为可确认、可审计、可重复执行的发布包。API 优先;新建 App Record、App Privacy 等 API 外页面才使用已登录 Playwright。
9
+
10
+ ## 安全边界
11
+
12
+ - Skill 模板目录禁止保存任何 API Key、`.p8` 私钥、Cookie、审核账号密码或税务材料。
13
+ - 只从 `/Users/chances/.dwy/app-store-connect/` 读取用户私有配置。首次运行时询问 Issuer ID、Key ID、团队和私钥文件位置,再调用 `scripts/appstore_config.sh` 写入。
14
+ - 不将秘密写入项目、Git、`appstore-submission.yaml` 或执行日志。审核账号在发布包中只能使用钥匙串或环境变量引用。
15
+ - 提交审核、正式发布、价格上调前,必须显示变更并获得用户二次确认。
16
+
17
+ ## 首次配置
18
+
19
+ 1. 执行 `scripts/appstore_config.sh init`,创建权限 `0700` 的用户私有目录。
20
+ 2. 逐项询问用户,再执行 `set --issuer-id <id> --key-id <id> [--team-id <id>]`。
21
+ 3. 用户提供现有 `.p8` 文件路径后,执行 `import-key --path <absolute-path>`;禁止让用户在聊天中粘贴私钥内容。
22
+ 4. 使用 `get` 验证非秘密标识;不要打印私钥或会话文件。
23
+
24
+ ## 发布包与资料收集
25
+
26
+ 将 `assets/appstore-submission.yaml` 复制到用户私有目录下 `submissions/<bundle-id>/`,逐步收集并在每步确认:
27
+
28
+ 1. 应用身份:Bundle ID、SKU、名称、分类、版权、年龄分级和构建。
29
+ 2. 产品页:只维护 `zh-Hans`、`en-US` 的名称、副标题、描述、关键词、支持/营销/隐私 URL。
30
+ 3. 截图:按 [截图工作流](references/screenshot-workflow.md) 从真实应用采集 iOS 与 macOS 图,分别校验后上传。
31
+ 4. 合规:隐私、第三方 SDK、内容权利、加密、审核账号和测试路径。法律真实性由用户确认。
32
+ 5. 商业:应用价格、全地区可售、内购或订阅的权益、价格、地区和审核截图。
33
+
34
+ ## 地区、ICP 与本地化
35
+
36
+ - 默认应用、内购和订阅均为 `all_territories`;产品页本地化仅 `zh-Hans`、`en-US`。
37
+ - ICP/APP 备案号为非阻塞字段。缺失时继续配置其它全部地区,并在执行报告标记中国大陆待办。
38
+ - 用户后续提供备案号后,单独写入并启用中国大陆;不得重新填写其它已确认资料。
39
+
40
+ ## 自动化顺序
41
+
42
+ 1. 读取发布包、项目构建信息和 API 配置,先输出完整 diff。
43
+ 2. 用 API 写入 App 信息、版本本地化、价格、地区、年龄分级、审核资料、截图、内购和订阅。
44
+ 3. 对 API 未覆盖项复用用户已登录 Playwright 会话:创建 App Record、填写 App Privacy 或处理网页专属确认。
45
+ 4. 关联构建与审核提交。仅在用户再次确认后调用提交审核或发布动作。
46
+ 5. 输出成功、失败、待补 ICP 和人工确认项,保存无秘密执行记录。
47
+
48
+ ## 内购与订阅
49
+
50
+ - 校验 `product_id` 与 StoreKit 代码一致,再创建消耗型、非消耗型内购或自动续期订阅。
51
+ - 每个内购必须提交一张用于审核的 `1280 × 800` 像素截图;按 [内购审核截图](references/in-app-purchase-review.md) 从真实购买流程采集并校验。
52
+ - 默认全地区可售;以美国区目标价格查询 Apple 价格点,并由 Apple 自动等价换算其它地区价格。
53
+ - 价格修改必须展示旧价、新价、生效时间和受影响地区;用户二次确认后才执行。
54
+
55
+ ## 网页自动化限制
56
+
57
+ - 只使用用户已登录会话,不索取 Apple ID 密码或二次验证码。
58
+ - 遇到验证码、实名核验、协议、税务、银行、证照上传或法律声明时暂停并交由用户完成。
59
+ - App Review 拒审后整理证据、修复清单与回复草稿;回复或重新提交前确认。
60
+
61
+ ## 参考资料
62
+
63
+ - API 与网页动作:见 [references/api-workflow.md](references/api-workflow.md)。
64
+ - iOS/macOS 截图采集与规格:见 [references/screenshot-workflow.md](references/screenshot-workflow.md)。
65
+ - 内购审核截图:见 [references/in-app-purchase-review.md](references/in-app-purchase-review.md)。
@@ -0,0 +1,43 @@
1
+ # 已确认的发布包模板;秘密仅使用外部引用,不能填入此文件。
2
+ schema_version: 1
3
+ application:
4
+ bundle_id: ""
5
+ sku: ""
6
+ platforms: [ios, macos]
7
+ availability: all_territories
8
+ china_mainland:
9
+ icp_status: not_started
10
+ icp_filing_number: ""
11
+ localizations:
12
+ zh-Hans:
13
+ name: ""
14
+ subtitle: ""
15
+ description: ""
16
+ keywords: ""
17
+ support_url: ""
18
+ privacy_policy_url: ""
19
+ en-US:
20
+ name: ""
21
+ subtitle: ""
22
+ description: ""
23
+ keywords: ""
24
+ support_url: ""
25
+ privacy_policy_url: ""
26
+ screenshots:
27
+ ios: { zh-Hans: [], en-US: [] }
28
+ macos: { zh-Hans: [], en-US: [] }
29
+ # 每个内购条目必须带 `review_screenshot`,尺寸固定为 1280x800 像素。
30
+ in_app_purchases: []
31
+ subscriptions: []
32
+ review:
33
+ contact_name: ""
34
+ contact_email: ""
35
+ contact_phone: ""
36
+ demo_credentials_reference: ""
37
+ notes: ""
38
+ confirmations:
39
+ metadata_confirmed: false
40
+ privacy_confirmed: false
41
+ pricing_confirmed: false
42
+ submit_for_review_confirmed: false
43
+ release_confirmed: false
@@ -0,0 +1,17 @@
1
+ # App Store Connect API 与网页补齐
2
+
3
+ ## API 优先动作
4
+
5
+ 使用 App Store Connect API 创建或更新版本本地化、App 信息、分类、年龄分级、地区可售性、应用价格、内购、订阅、审核资料、截图和审核提交。每次写入前读取当前资源并生成字段 diff。
6
+
7
+ ## 网页补齐动作
8
+
9
+ 只在 API 无法覆盖时,使用用户已登录的 Playwright 会话:创建 App Record、App Privacy 问卷和 Apple 要求的网页专属确认。不得自动绕过验证码或复用未授权会话。
10
+
11
+ ## 中国大陆
12
+
13
+ 默认请求全地区可售。若 Apple 返回 ICP 缺失或无效状态,保留其它地区配置并在执行记录中登记备案待办。用户提供有效备案号后,单独重试中国大陆。
14
+
15
+ ## 最终门禁
16
+
17
+ 下列动作必须再次询问用户:提交审核、正式发布、提高价格、启用中国大陆(当备案资料刚补齐时)。
@@ -0,0 +1,16 @@
1
+ # 内购审核截图
2
+
3
+ ## 本项目固定规格
4
+
5
+ 每个内购项目提交一张 `1280 × 800` 像素、16:10 的审核截图。图片必须来自真实购买路径,清晰展示商品或服务、价格入口与购买后的可获得权益;禁止使用与应用不一致的概念图。
6
+
7
+ ## 采集与上传
8
+
9
+ 1. 使用审核账号或 StoreKit 测试环境进入目标商品购买页。
10
+ 2. 在 macOS 16:10 画布导出 `1280 × 800` PNG 或 JPG,移除用户身份、支付凭据和生产数据。
11
+ 3. 上传前校验精确像素、RGB、无透明通道和单张文件约束。
12
+ 4. 通过 `inAppPurchaseAppStoreReviewScreenshots` 的预留、上传、提交流程写入对应内购;上传后读取资源状态确认成功。
13
+
14
+ ## Apple 规格关系
15
+
16
+ Apple 将内购审核截图用于审核而非商店展示,并要求它符合应用支持的平台截图规格。本项目将 `1280 × 800` 作为固定的 macOS 审核画布;如果 Apple 后续针对目标平台返回更严格的校验错误,停止上传并提示用户确认平台规格,不擅自缩放或裁剪。
@@ -0,0 +1,16 @@
1
+ # iOS/macOS 截图工作流
2
+
3
+ ## 采集
4
+
5
+ 从真实 iOS 模拟器和 macOS 应用构建采集截图。先向用户确认截图剧本:启动方式、测试账号引用、页面路径、测试数据、脱敏规则和中英文文案。禁止以与实际应用不一致的生成图替代功能展示。
6
+
7
+ ## 分平台输出
8
+
9
+ - iOS 和 macOS 必须分别采集、设计、校验和上传,不能将同一图片简单缩放复用。
10
+ - 每种平台、设备尺寸和语言输出 1 到 10 张 JPEG/JPG/PNG;不得包含 Alpha 通道。
11
+ - macOS 使用 16:10:`1280x800`、`1440x900`、`2560x1600` 或 `2880x1800`。
12
+ - iOS 根据目标 iPhone 展示尺寸选择 Apple 当前接受的规格;执行时先读取 Apple 官方截图规格,避免使用过期机型尺寸。
13
+
14
+ ## 上传前检查
15
+
16
+ 检查尺寸、方向、格式、无透明通道、语言目录、页面顺序、隐私脱敏和平台归属。先生成本地预览和上传清单,用户确认后才上传。
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env bash
2
+ # App Store Connect 用户级配置管理:只保存非秘密标识与私钥文件,禁止向 Skill 或项目目录写入凭据。
3
+
4
+ set -euo pipefail
5
+
6
+ default_root="/Users/$(id -un)/.dwy/app-store-connect"
7
+
8
+ # 输出用法,避免调用者猜测参数格式而误把私钥内容传入命令行。
9
+ usage() {
10
+ cat <<'EOF'
11
+ Usage:
12
+ appstore_config.sh init [--root <directory>]
13
+ appstore_config.sh get [--root <directory>]
14
+ appstore_config.sh set --issuer-id <id> --key-id <id> [--team-id <id>] [--root <directory>]
15
+ appstore_config.sh import-key --path <AuthKey.p8> [--root <directory>]
16
+ appstore_config.sh reset [--root <directory>]
17
+ EOF
18
+ }
19
+
20
+ # 创建私有目录并收紧权限,防止同机其他用户读取配置或私钥。
21
+ ensure_root() {
22
+ mkdir -p "$root/private_keys" "$root/sessions" "$root/submissions"
23
+ chmod 700 "$root" "$root/private_keys" "$root/sessions" "$root/submissions"
24
+ }
25
+
26
+ # 将非秘密配置初始化为 JSON;私钥单独存放,避免在 get 输出中泄漏。
27
+ ensure_config() {
28
+ ensure_root
29
+ if [[ ! -f "$config_file" ]]; then
30
+ jq -n '{version: 1}' > "$config_file"
31
+ chmod 600 "$config_file"
32
+ fi
33
+ if ! jq empty "$config_file" >/dev/null 2>&1; then
34
+ echo "ERROR: configuration is not valid JSON: $config_file" >&2
35
+ exit 2
36
+ fi
37
+ }
38
+
39
+ # 校验受外部输入控制的标识长度,避免错误或过大的配置写入本地缓存。
40
+ validate_id() {
41
+ local label="$1" value="$2" limit="$3"
42
+ if [[ -z "$value" || ${#value} -gt "$limit" ]]; then
43
+ echo "ERROR: $label must contain 1-$limit characters" >&2
44
+ exit 2
45
+ fi
46
+ }
47
+
48
+ # 解析共享根目录参数;其他参数由具体子命令处理。
49
+ parse_root() {
50
+ while [[ $# -gt 0 ]]; do
51
+ case "$1" in
52
+ --root)
53
+ root="$2"
54
+ shift 2
55
+ ;;
56
+ *)
57
+ remaining+=("$1")
58
+ remaining_count=$((remaining_count + 1))
59
+ shift
60
+ ;;
61
+ esac
62
+ done
63
+ }
64
+
65
+ action="${1:-}"
66
+ if [[ -z "$action" ]]; then
67
+ usage >&2
68
+ exit 2
69
+ fi
70
+ shift
71
+
72
+ root="$default_root"
73
+ remaining=()
74
+ remaining_count=0
75
+ parse_root "$@"
76
+ # macOS 自带 Bash 在 `nounset` 下会将空数组视为未绑定,因此空参数必须避免展开数组。
77
+ if [[ "$remaining_count" -eq 0 ]]; then
78
+ set --
79
+ else
80
+ set -- "${remaining[@]}"
81
+ fi
82
+ config_file="$root/config.json"
83
+
84
+ case "$action" in
85
+ init)
86
+ [[ $# -eq 0 ]] || { usage >&2; exit 2; }
87
+ ensure_config
88
+ echo "OK: initialized $root"
89
+ ;;
90
+ get)
91
+ [[ $# -eq 0 ]] || { usage >&2; exit 2; }
92
+ ensure_config
93
+ cat "$config_file"
94
+ ;;
95
+ set)
96
+ issuer_id=""
97
+ key_id=""
98
+ team_id=""
99
+ while [[ $# -gt 0 ]]; do
100
+ case "$1" in
101
+ --issuer-id) issuer_id="$2"; shift 2 ;;
102
+ --key-id) key_id="$2"; shift 2 ;;
103
+ --team-id) team_id="$2"; shift 2 ;;
104
+ *) usage >&2; exit 2 ;;
105
+ esac
106
+ done
107
+ validate_id "issuer id" "$issuer_id" 128
108
+ validate_id "key id" "$key_id" 64
109
+ if [[ -n "$team_id" ]]; then validate_id "team id" "$team_id" 64; fi
110
+ ensure_config
111
+ jq -n --arg issuer "$issuer_id" --arg key "$key_id" --arg team "$team_id" \
112
+ '{version: 1, issuer_id: $issuer, key_id: $key, team_id: $team}' > "$config_file"
113
+ chmod 600 "$config_file"
114
+ echo "OK: stored non-secret API identifiers in $config_file"
115
+ ;;
116
+ import-key)
117
+ [[ $# -eq 2 && "$1" == "--path" ]] || { usage >&2; exit 2; }
118
+ source_key="$2"
119
+ [[ -f "$source_key" && "${source_key##*.}" == "p8" ]] || {
120
+ echo "ERROR: --path must reference an existing .p8 file" >&2
121
+ exit 2
122
+ }
123
+ ensure_config
124
+ target_key="$root/private_keys/$(basename "$source_key")"
125
+ cp "$source_key" "$target_key"
126
+ chmod 600 "$target_key"
127
+ echo "OK: imported private key to $target_key"
128
+ ;;
129
+ reset)
130
+ [[ $# -eq 0 ]] || { usage >&2; exit 2; }
131
+ if [[ -f "$config_file" ]]; then
132
+ rm "$config_file"
133
+ fi
134
+ echo "OK: removed non-secret configuration; private keys and submissions were preserved"
135
+ ;;
136
+ *)
137
+ usage >&2
138
+ exit 2
139
+ ;;
140
+ esac
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  name: dwy-publish
3
- description: "发版/部署编排器。触发条件:用户说\"发版\"\"部署\"\"发布上线\"\"release\"\"publish\"\"走发版流程\"时。按应用目录确认发布方式并缓存,串起定版本→changelog→安全检查→build/发布→监控→通知。版本号决策单独走 dwy-semver,GA 打包走 dwy-github-action-publish,发布前安全检查走 dwy-sdk-spec——本 skill 负责编排,按路径主动调它们。"
3
+ description: "发版/部署编排器。触发条件:用户说\"发版\"\"部署\"\"发布上线\"\"release\"\"publish\"\"走发版流程\"时。按应用目录确认发布方式并缓存,串起定版本→changelog→安全检查→打 tag→build/发布→监控→通知。每次更新版本必须打 git tag,tag 版本串与 changelog 新版本标题完全一致。版本号决策单独走 dwy-semver,GA 打包走 dwy-github-action-publish,发布前安全检查走 dwy-sdk-spec——本 skill 负责编排,按路径主动调它们。"
4
4
  ---
5
5
 
6
6
  # 发版编排器
7
7
 
8
8
  一条发版链的编排执行。进入前测试已完成。
9
9
 
10
- **先**读仓库上下文,判目标平台(前端/后端/Android/iOS/鸿蒙/通用)+ 定位应用目录(相对项目根的相对路径)。**再**按下表执行 8 步。
10
+ **先**读仓库上下文,判目标平台(前端/后端/Android/iOS/鸿蒙/通用)+ 定位应用目录(相对项目根的相对路径)。**再**按下表执行 9 步。
11
11
 
12
12
  | # | 步骤 | 类型 | 调用 |
13
13
  |---|------|------|------|
@@ -16,16 +16,19 @@ description: "发版/部署编排器。触发条件:用户说\"发版\"\"部
16
16
  | 3 | 定版本号 + 多文件同步 | 通用步 | `../dwy-semver` + `references/version-sync.md` |
17
17
  | 4 | 写 changelog(按平台子目录) | 通用步 | `references/changelog.md` |
18
18
  | 5 | 安全检查(闸门,未过不发) | 通用步 | `../dwy-sdk-spec` |
19
- | 6 | build + 触发发布 | 项目步 | `references/<平台>.md`;走 GA 引 `../dwy-github-action-publish` |
20
- | 7 | 监控发布进程 | 项目步 | `references/monitor-notify.md` |
21
- | 8 | 通知结果(输出结果文本) | — | `references/monitor-notify.md` |
19
+ | 6 | commit 版本变更 + 打 tag 并推送 | 通用步 | `references/git-tag.md` |
20
+ | 7 | build + 触发发布 | 项目步 | `references/<平台>.md`;走 GA 引 `../dwy-github-action-publish` |
21
+ | 8 | 监控发布进程 | 项目步 | `references/monitor-notify.md` |
22
+ | 9 | 通知结果(输出结果文本) | — | `references/monitor-notify.md` |
22
23
 
23
24
  平台流程文件:`frontend-deploy.md` / `backend-deploy.md` / `ios.md` / `android.md` / `harmony.md` / `generic-release.md`。
24
25
 
25
26
  ## 编排约束
26
27
 
27
- - **通用步固化**(定版本/changelog/安全检查跨项目一致,走子 skill/脚本);**项目步读上下文+缓存**(build/deploy/监控命令因项目而异,**绝不写死**,探测不到问用户后缓存)。
28
- - 安全检查(第 5 步)是闸门,未过不进发布。
29
- - 全程 AI 自动判断、自动跑,仅搞不定时才问用户(版本级别拿不准、命令探测不到、配置缺失、构建/发布失败)。
28
+ - **通用步固化**(定版本/changelog/安全检查/打 tag 跨项目一致,走子 skill/脚本);**项目步读上下文+缓存**(build/deploy/监控命令因项目而异,**绝不写死**,探测不到问用户后缓存)。
29
+ - 安全检查(第 5 步)是闸门,未过不进 tag / 发布。
30
+ - **每次更新版本必须打 tag**(第 6 步):tag 版本串与本次 changelog 新版本标题(`## x.y.z`)完全一致;细则见 `references/git-tag.md`。无 bump 的纯重发可不打新 tag。
31
+ - 若 GA workflow 由 tag 触发,第 6 步 push tag 即触发第 7 步发布。
32
+ - 全程 AI 自动判断、自动跑,仅搞不定时才问用户(版本级别拿不准、命令探测不到、配置缺失、构建/发布失败、需删远端 tag)。
30
33
  - 编排时按文件路径主动加载子 skill(`../dwy-semver`、`../dwy-sdk-spec`、`../dwy-github-action-publish`);这些 skill 也可被用户独立触发。
31
34
  - `.dwy/` 缓存提醒用户加进 `.gitignore`。
@@ -24,8 +24,9 @@
24
24
  - `github-action` → 引 `../dwy-github-action-publish`(先过通用检查)
25
25
  - `local` → 缓存的本地构建/发布命令
26
26
 
27
- ## changelog / 安全检查 / 监控
27
+ ## changelog / tag / 安全检查 / 监控
28
28
 
29
29
  - changelog → `changelog.md`(写 `android/CHANGELOG.md`)
30
+ - tag → `git-tag.md`(每次 bump 必打;版本串与 changelog `##` 标题一致)
30
31
  - 安全检查 → `../dwy-sdk-spec`
31
32
  - 监控 + 结果 → `monitor-notify.md`
@@ -17,7 +17,8 @@
17
17
  - `github-action` → 引 `../dwy-github-action-publish`(CI 推荐 OIDC,先过通用检查)
18
18
  - `local` → 缓存的本地构建/部署命令(打镜像 / 部署脚本)
19
19
 
20
- ## changelog / 监控
20
+ ## changelog / tag / 监控
21
21
 
22
22
  - changelog → `changelog.md`(写 `backend/CHANGELOG.md`)
23
+ - tag → `git-tag.md`(每次 bump 必打;版本串与 changelog `##` 标题一致)
23
24
  - 监控 + verify → `monitor-notify.md`(后端信号:健康检查 / 版本接口 / 运行日志 / 镜像 tag)
@@ -10,7 +10,26 @@ monorepo 下一个仓库可能同时含 android / ios / harmony / frontend / bac
10
10
  - `frontend/CHANGELOG.md`
11
11
  - `backend/CHANGELOG.md`
12
12
 
13
- 子目录名按仓库实际结构定(先在第 0 步识别平台目录)。
13
+ 子目录名按仓库实际结构定(先在第 0 步识别平台目录)。单包仓库可在根目录一份;monorepo 按包目录(如 `dwy-cli/CHANGELOG.md`、`frontend/eui/CHANGELOG.md`)。
14
+
15
+ ## 版本标题格式(与 git tag 对齐)
16
+
17
+ 新版本必须用二级标题,版本串单独成标题,供第 6 步打 tag 原样取用:
18
+
19
+ ```markdown
20
+ # <包标识> ← monorepo 建议有 H1,作为 tag 的包前缀(如 create-dwy、@dwydev/eui)
21
+
22
+ ## 0.16.1 ← 新版本标题;tag 版本串必须与此完全一致
23
+
24
+ ### Patch Changes
25
+
26
+ - ...
27
+ ```
28
+
29
+ 约束:
30
+
31
+ - 标题里只写 SemVer 版本串(可含预发布,如 `1.0.0-rc.1`),不要写 `v0.16.1`、日期或其它后缀
32
+ - 该版本串 = 版本来源文件里的 version = 即将打的 tag 中的版本部分(见 `git-tag.md`)
14
33
 
15
34
  ## 写法
16
35
 
@@ -22,9 +41,9 @@ git log <last-tag>..HEAD --oneline -- <平台子目录>/
22
41
  ```
23
42
 
24
43
  3. 按 `feat` / `fix` / `refactor` / `chore` 分组
25
- 4. 写入该平台 `CHANGELOG.md`,标注新版本号
44
+ 4. 写入该平台 `CHANGELOG.md`,用 `## <新版本号>` 标注(格式见上)
26
45
 
27
- 如果仓库已有自动生成命令(changelogen 等),优先使用,但仍按平台目录过滤范围。
46
+ 如果仓库已有自动生成命令(changelogen 等),优先使用,但仍按平台目录过滤范围,且产出的版本标题须满足上述格式。
28
47
 
29
48
  ## 自动执行
30
49
 
@@ -33,5 +52,6 @@ changelog 由 AI 自动生成并写入,不强制逐步确认。仅当 commit
33
52
  ## 禁止
34
53
 
35
54
  - 禁止写一份全局 CHANGELOG 混入多平台变更
36
- - 禁止 changelog 未写完就进入部署
55
+ - 禁止 changelog 未写完就进入 tag / 部署
37
56
  - 禁止把其他平台的 commit 写进当前平台 CHANGELOG(必须按目录过滤)
57
+ - 禁止版本标题写成与即将打的 tag 版本串不一致的形式
@@ -17,7 +17,8 @@
17
17
  - `github-action` → 引 `../dwy-github-action-publish`(CI 推荐 OIDC,先过通用检查)
18
18
  - `local` → 缓存的本地构建/部署命令(推镜像 / 传 CDN·OSS / 部署脚本)
19
19
 
20
- ## changelog / 监控
20
+ ## changelog / tag / 监控
21
21
 
22
22
  - changelog → `changelog.md`(写 `frontend/CHANGELOG.md`)
23
+ - tag → `git-tag.md`(每次 bump 必打;版本串与 changelog `##` 标题一致)
23
24
  - 监控 + verify → `monitor-notify.md`(前端信号:页面访问 / 版本接口 / 产物 hash / CDN 刷新)
@@ -20,8 +20,9 @@
20
20
 
21
21
  **PyPI/npm 未配置 GA 时按 `publish-config.md` 主动推荐 OIDC。**
22
22
 
23
- ## changelog / 安全检查 / 监控
23
+ ## changelog / tag / 安全检查 / 监控
24
24
 
25
25
  - changelog → `changelog.md`(单包仓库根目录一份;monorepo 按包目录过滤)
26
+ - tag → `git-tag.md`(每次 bump 必打;版本串与 changelog `##` 标题一致;monorepo 例:`@dwydev/eui@2.2.3`、`create-dwy@0.16.1`)
26
27
  - 安全检查 → `../dwy-sdk-spec`(对外包必查泄露/产物)
27
28
  - 监控 + verify → `monitor-notify.md`(包仓库版本查询 / GitHub Release)
@@ -0,0 +1,82 @@
1
+ # 发版 git tag(强制)
2
+
3
+ **每次更新版本号都必须打 tag 并推远端。** 无版本 bump 的纯重发 / 仅重跑 workflow / 仅回滚,不打新 tag。
4
+
5
+ ## 时机
6
+
7
+ 在第 3 步版本同步 + 第 4 步 changelog 写完、第 5 步安全检查通过之后:
8
+
9
+ 1. 将版本来源文件 + CHANGELOG 一并 commit(若尚未提交)
10
+ 2. 按下方规则算出 tag 名
11
+ 3. 本地打 tag → push tag 到 origin
12
+ 4. 再进入 build / 发布(若 workflow 由 tag 触发,push tag 即触发发布)
13
+
14
+ ```bash
15
+ # 版本与 changelog 已落盘并 commit 后
16
+ git tag <tag>
17
+ git push origin <tag>
18
+ ```
19
+
20
+ ## tag 与 changelog 版本对齐(硬规则)
21
+
22
+ tag 中的**版本串**必须与本次 CHANGELOG **新版本标题**完全一致,禁止改写。
23
+
24
+ | CHANGELOG 写法 | 取出的版本串 |
25
+ |----------------|-------------|
26
+ | `## 0.16.1` | `0.16.1` |
27
+ | `## 2.2.3` | `2.2.3` |
28
+ | `## 1.0.0-rc.1` | `1.0.0-rc.1` |
29
+
30
+ 禁止:
31
+
32
+ - changelog 写 `## 0.16.1`,tag 打成 `v0.16.1` / `0.16.1.0` / `0.16`(格式不一致)
33
+ - tag 版本与 `package.json` / `pyproject.toml` 等来源文件不一致
34
+ - 未写 changelog 新版本标题就打 tag
35
+
36
+ ## tag 全名拼法
37
+
38
+ 先取 changelog 版本串 `VER`,再按仓库惯例拼全名:
39
+
40
+ | 场景 | 规则 | 例 |
41
+ |------|------|-----|
42
+ | monorepo 多包 / 多平台 | `{包标识}@{VER}`;包标识优先取该 CHANGELOG 顶部 H1(去掉 `# `),否则取 `package.json` 的 `name` | CHANGELOG H1 `# create-dwy` + `## 0.16.1` → `create-dwy@0.16.1`;H1 `# @dwydev/eui` + `## 2.2.3` → `@dwydev/eui@2.2.3` |
43
+ | 单包仓库且历史 tag 已有固定前缀 | 沿用历史前缀 + `VER`(仅当前缀不篡改 VER 本身时) | 历史 `v1.2.0` 且 changelog 为 `## 1.3.0` 时,若项目约定 `v` 前缀且 VER 仍完整出现 → 须在本仓库已有 tag 惯例中确认;**优先保证 VER 与 changelog 一致** |
44
+ | 单包仓库无历史惯例 | 直接用 `VER` | changelog `## 1.0.0` → tag `1.0.0` |
45
+
46
+ **冲突裁决**:若「历史 `v` 前缀」与「changelog 无 `v`」冲突,以 **changelog 标题里的版本串** 为准拼 tag(monorepo 用 `包@VER`,单包用 `VER`),不要为了凑 `v` 前缀改掉 VER。仓库若已有 workflow 写死 `v*` 触发,同步改 workflow 或 changelog 标题约定,二者必须一致。
47
+
48
+ 打 tag 前自检:
49
+
50
+ ```bash
51
+ # VER 必须等于 changelog 最新 ## 标题
52
+ # 包来源文件 version 字段必须等于 VER
53
+ git tag -l | head # 对照历史命名是否 monorepo 包前缀
54
+ ```
55
+
56
+ ## 推送与触发
57
+
58
+ - 必须 `git push origin <tag>`,只打本地 tag 不算完成
59
+ - method 为 `github-action` / `github-action-oidc` 且 workflow `on.push.tags` 时:push tag 即触发 CI,不必再另起发布命令
60
+ - method 为 local / testflight / maven 等:先 push tag,再跑缓存的 `publish_cmd`(或按项目既有顺序,但 tag 不可省)
61
+
62
+ ## 重发 / 删 tag
63
+
64
+ 远端已有错误 tag 需要覆盖时:
65
+
66
+ 1. **先确认用户允许**删除远端 tag / release
67
+ 2. 再删远端 + 本地,重打同名 tag 推送
68
+
69
+ ```bash
70
+ git push origin :refs/tags/<tag>
71
+ git tag -d <tag>
72
+ git tag <tag>
73
+ git push origin <tag>
74
+ ```
75
+
76
+ ## 禁止
77
+
78
+ - 禁止版本号已 bump 却不打 tag
79
+ - 禁止 tag 版本串与 changelog 新版本标题不一致
80
+ - 禁止 tag 与版本来源文件不一致
81
+ - 禁止未 push 远端就当发版完成
82
+ - 禁止未确认用户就删除远端已有 tag / release