android2harmony 0.1.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 (82) hide show
  1. package/README.md +407 -0
  2. package/agents/build-fixer.md +385 -0
  3. package/agents/code-reviewer.md +478 -0
  4. package/agents/logic-coder.md +212 -0
  5. package/agents/logic-context-builder.md +199 -0
  6. package/agents/scripts/hmos-precheck/arkts.mjs +534 -0
  7. package/agents/scripts/hmos-precheck/codelinter.mjs +362 -0
  8. package/agents/scripts/hmos-precheck/index.mjs +926 -0
  9. package/agents/scripts/platform_query.mjs +535 -0
  10. package/dist/index.js +179 -0
  11. package/dist/index.js.map +7 -0
  12. package/package.json +29 -0
  13. package/skills/hmos-batch-ui-align/SKILL.md +141 -0
  14. package/skills/hmos-batch-ui-align/references/conversion-procedure.md +217 -0
  15. package/skills/hmos-batch-ui-align/references/mappings/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2533 -0
  16. package/skills/hmos-batch-ui-align/references/mappings/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -0
  17. package/skills/hmos-batch-ui-align/references/mappings/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -0
  18. package/skills/hmos-batch-ui-align/references/mvvm/@Link/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/217/214/345/220/221/345/220/214/346/255/245.md +648 -0
  19. package/skills/hmos-batch-ui-align/references/mvvm/@Observed/350/243/205/351/245/260/345/231/250/345/222/214@ObjectLink/350/243/205/351/245/260/345/231/250/357/274/232/345/265/214/345/245/227/347/261/273/345/257/271/350/261/241/345/261/236/346/200/247/345/217/230/345/214/226.md +2089 -0
  20. package/skills/hmos-batch-ui-align/references/mvvm/@Prop/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/215/225/345/220/221/345/220/214/346/255/245.md +1033 -0
  21. package/skills/hmos-batch-ui-align/references/mvvm/@Provide/350/243/205/351/245/260/345/231/250/345/222/214@Consume/350/243/205/351/245/260/345/231/250/357/274/232/344/270/216/345/220/216/344/273/243/347/273/204/344/273/266/345/217/214/345/220/221/345/220/214/346/255/245.md +1183 -0
  22. package/skills/hmos-batch-ui-align/references/mvvm/@State/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/206/205/347/212/266/346/200/201.md +576 -0
  23. package/skills/hmos-batch-ui-align/references/mvvm/@Track/350/243/205/351/245/260/345/231/250/357/274/232class/345/257/271/350/261/241/345/261/236/346/200/247/347/272/247/346/233/264/346/226/260.md +297 -0
  24. package/skills/hmos-batch-ui-align/references/mvvm/@Watch/350/243/205/351/245/260/345/231/250/357/274/232/347/212/266/346/200/201/345/217/230/351/207/217/346/233/264/346/224/271/351/200/232/347/237/245.md +395 -0
  25. package/skills/hmos-batch-ui-align/references/mvvm/AppStorage/357/274/232/345/272/224/347/224/250/345/205/250/345/261/200/347/232/204UI/347/212/266/346/200/201/345/255/230/345/202/250.md +903 -0
  26. package/skills/hmos-batch-ui-align/references/mvvm/Environment/357/274/232/350/256/276/345/244/207/347/216/257/345/242/203/346/237/245/350/257/242.md +106 -0
  27. package/skills/hmos-batch-ui-align/references/mvvm/LocalStorage/357/274/232/351/241/265/351/235/242/347/272/247UI/347/212/266/346/200/201/345/255/230/345/202/250.md +1178 -0
  28. package/skills/hmos-batch-ui-align/references/mvvm/MVVM/346/250/241/345/274/217/357/274/210V1/357/274/211.md +911 -0
  29. package/skills/hmos-batch-ui-align/references/mvvm/PersistentStorage/357/274/232/346/214/201/344/271/205/345/214/226/345/255/230/345/202/250UI/347/212/266/346/200/201.md +355 -0
  30. package/skills/hmos-batch-ui-align/references/mvvm//347/256/241/347/220/206/345/272/224/347/224/250/346/213/245/346/234/211/347/232/204/347/212/266/346/200/201/346/246/202/350/277/260.md +11 -0
  31. package/skills/hmos-batch-ui-align/scripts/android_parse_fast.ts +1750 -0
  32. package/skills/hmos-convert-pipeline/SKILL.md +446 -0
  33. package/skills/hmos-fix-build-errors/SKILL.md +281 -0
  34. package/skills/hmos-fix-build-errors/references/arkts-strict-patterns.md +219 -0
  35. package/skills/hmos-fix-build-errors/references/known-patterns.md +157 -0
  36. package/skills/hmos-fix-build-errors/references/rdb-entity-pattern.md +131 -0
  37. package/skills/hmos-resources-convert/SKILL.md +654 -0
  38. package/skills/hmos-resources-convert/references/conversion-rules.md +663 -0
  39. package/skills/hmos-resources-convert/references/dependency-analysis-rules.md +388 -0
  40. package/skills/hmos-resources-convert/references/resource-mapping-rules.md +457 -0
  41. package/skills/hmos-resources-convert/references/xml-drawable-to-svg-rules.md +513 -0
  42. package/skills/hmos-resources-convert/template/AppScope/app.json5 +10 -0
  43. package/skills/hmos-resources-convert/template/AppScope/resources/base/element/string.json +8 -0
  44. package/skills/hmos-resources-convert/template/AppScope/resources/base/media/background.png +0 -0
  45. package/skills/hmos-resources-convert/template/AppScope/resources/base/media/foreground.png +0 -0
  46. package/skills/hmos-resources-convert/template/AppScope/resources/base/media/layered_image.json +7 -0
  47. package/skills/hmos-resources-convert/template/build-profile.json5 +42 -0
  48. package/skills/hmos-resources-convert/template/code-linter.json5 +32 -0
  49. package/skills/hmos-resources-convert/template/entry/build-profile.json5 +33 -0
  50. package/skills/hmos-resources-convert/template/entry/hvigorfile.ts +6 -0
  51. package/skills/hmos-resources-convert/template/entry/obfuscation-rules.txt +23 -0
  52. package/skills/hmos-resources-convert/template/entry/oh-package.json5 +10 -0
  53. package/skills/hmos-resources-convert/template/entry/src/main/ets/entryability/EntryAbility.ets +48 -0
  54. package/skills/hmos-resources-convert/template/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets +16 -0
  55. package/skills/hmos-resources-convert/template/entry/src/main/ets/pages/Index.ets +23 -0
  56. package/skills/hmos-resources-convert/template/entry/src/main/module.json5 +55 -0
  57. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/element/color.json +8 -0
  58. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/element/float.json +8 -0
  59. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/element/string.json +16 -0
  60. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/background.png +0 -0
  61. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/foreground.png +0 -0
  62. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/layered_image.json +7 -0
  63. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/startIcon.png +0 -0
  64. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/profile/backup_config.json +3 -0
  65. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/profile/main_pages.json +5 -0
  66. package/skills/hmos-resources-convert/template/entry/src/main/resources/dark/element/color.json +8 -0
  67. package/skills/hmos-resources-convert/template/entry/src/mock/mock-config.json5 +2 -0
  68. package/skills/hmos-resources-convert/template/entry/src/ohosTest/ets/test/Ability.test.ets +35 -0
  69. package/skills/hmos-resources-convert/template/entry/src/ohosTest/ets/test/List.test.ets +5 -0
  70. package/skills/hmos-resources-convert/template/entry/src/ohosTest/module.json5 +16 -0
  71. package/skills/hmos-resources-convert/template/entry/src/test/List.test.ets +5 -0
  72. package/skills/hmos-resources-convert/template/entry/src/test/LocalUnit.test.ets +33 -0
  73. package/skills/hmos-resources-convert/template/hvigor/hvigor-config.json5 +23 -0
  74. package/skills/hmos-resources-convert/template/hvigorfile.ts +6 -0
  75. package/skills/hmos-resources-convert/template/oh-package-lock.json5 +28 -0
  76. package/skills/hmos-resources-convert/template/oh-package.json5 +10 -0
  77. package/skills/hmos-spec-generate/SKILL.md +413 -0
  78. package/skills/hmos-spec-generate/references/android-platform-tokens.md +105 -0
  79. package/skills/hmos-spec-generate/references/spec-sample-1.md +78 -0
  80. package/skills/hmos-spec-generate/references/spec-sample-2.md +58 -0
  81. package/skills/hmos-spec-generate/references/spec-sample-3.md +116 -0
  82. package/skills/hmos-spec-generate/references/step4-report-template.md +33 -0
@@ -0,0 +1,413 @@
1
+ ---
2
+ name: hmos-spec-generate
3
+ description: "Generate requirement specification (spec) documents for Android-to-HarmonyOS migration. For each .txt requirement file in a folder, explore the Android codebase via homegraph and decompose the requirement into atomic user scenarios, emitting one markdown spec per file. Use when generating spec docs from a folder of raw requirement descriptions, decomposing requirements into atomic scenarios, or preparing scenario-based specs for HarmonyOS migration. Triggers: spec generation, 生成spec, requirement to spec, atomic scenarios, 拆分场景, scenario decomposition, 需求转spec."
4
+ license: MIT
5
+ allowed-tools:
6
+ - Read
7
+ - Write
8
+ - Edit
9
+ - Bash
10
+ - Glob
11
+ - Grep
12
+ - AskUserQuestion
13
+ - TaskCreate
14
+ - TaskList
15
+ - TaskUpdate
16
+ - mcp__homegraph__search
17
+ - mcp__homegraph__explore
18
+ - mcp__homegraph__node
19
+ - mcp__homegraph__impact
20
+ - mcp__homegraph__callers
21
+ - mcp__homegraph__callees
22
+ - mcp__homegraph__files
23
+ ---
24
+
25
+ # Spec Generator Skill
26
+
27
+ You are a **Spec Generator** that produces high-quality requirement specification (spec) documents for Android-to-HarmonyOS migration projects. Given a folder of raw requirement `.txt` files, explore the corresponding Android codebase via homegraph and emit a clean, atomic-scenario-based spec markdown for every requirement.
28
+
29
+ ## Quick Reference
30
+
31
+ | Item | Value |
32
+ |------|-------|
33
+ | **Input** | `requirement-description-dir` + `android-project-path` + `spec-output-dir` |
34
+ | **Output** | One `<source_filename_without_ext>.md` per input `.txt` under `spec-output-dir` |
35
+ | **homegraph (Index CLI)** | `homegraph` CLI via `Bash` (`status` / `init` / `sync` / `index`) |
36
+ | **homegraph (Code queries)** | `mcp__homegraph__*` tools (`search` / `explore` / `node` / `impact` / `callers` / `callees` / `files`) |
37
+ | **Processing Mode** | Per-file end-to-end loop (no batch pre-read) |
38
+
39
+ ## Expected Input
40
+
41
+ - `requirement-description-dir`: Absolute path to a directory containing one or more `.txt` files. Each `.txt` file's content is the raw requirement description of a single requirement (required).
42
+ - `android-project-path`: Absolute path to the Android project root (required).
43
+ - `spec-output-dir`: Absolute path to the directory where the generated spec files (`xxx.md`) will be written (required).
44
+
45
+ ## Expected Output
46
+
47
+ - One markdown spec file per input `.txt` requirement file, written under `spec-output-dir`. The spec filename mirrors the source filename with `.md` extension (e.g. `create_playlist.txt` → `create_playlist.md`).
48
+
49
+ ---
50
+
51
+ ## Principles
52
+
53
+ These are the authoring rules the final spec MUST follow:
54
+
55
+ 1. Requirements must be decomposed into atomic scenarios. Atomic scenarios combine to form a requirement.
56
+ 2. Each atomic scenario corresponds to one normal case or one edge/boundary case.
57
+ 3. Atomic scenarios must be comprehensive and non-redundant.
58
+ 4. The spec document must include a requirement semantic description, scenario semantic descriptions, and scenario flow descriptions.
59
+ 5. The scenario flow description in the spec document must include the trigger operation sequence and the logical execution steps for that scenario.
60
+ 6. The spec document must not contain any Android-related knowledge descriptions, design descriptions, or code descriptions.
61
+
62
+ ---
63
+
64
+ ## Spec Few-shot Samples
65
+
66
+ ### Sample 1
67
+ ```
68
+ # 新建歌单SPEC
69
+
70
+ 创建新歌单
71
+
72
+ ## 场景一
73
+
74
+ ### 场景概述
75
+
76
+ 用户点击创建歌单,但输入的歌单名称为空并且创建歌单
77
+
78
+ ### 场景逻辑步骤
79
+
80
+ - 1. 用户在“歌单页面”点击“更多菜单”中的“新建歌单按钮”或者用户在“添加到歌单弹窗”中点击“新建歌单按钮”
81
+ - 2. 弹出“新建歌单对话框”
82
+ - 3. 用户在输入框中输入空白歌单名称并点击确定按钮
83
+ - 4. 弹出toast”歌单名称不得为空“并且关闭“新建歌单对话框”
84
+
85
+ ## 场景二
86
+
87
+ ### 场景概述
88
+
89
+ 用户点击创建歌单,但输入的歌单名称超过最大长度并且创建歌单
90
+
91
+ ### 场景逻辑步骤
92
+
93
+ - 1. 用户在“歌单页面”点击“更多菜单”中的“新建歌单按钮”或者用户在“添加到歌单弹窗”中点击“新建歌单按钮”
94
+ - 2. 弹出“新建歌单对话框”
95
+ - 3. 用户在输入框中输入歌单名称并且歌单名称超过100个字符,然后点击确定按钮
96
+ - 4. 弹出toast“歌单名称过长”并且关闭“新建歌单对话框”
97
+
98
+ ## 场景三
99
+
100
+ ### 场景概述
101
+
102
+ 用户点击创建歌单,输入有效歌单名称并且创建歌单
103
+
104
+ ### 场景逻辑步骤
105
+
106
+ - 1. 用户在“歌单页面”点击“更多菜单”中的“新建歌单按钮”或者用户在“添加到歌单弹窗”中点击“新建歌单按钮”
107
+ - 2. 弹出“新建歌单对话框”
108
+ - 3. 用户在输入框中输入有效歌单名称,即用户输入到歌单名称不为空并且歌单名称没有超过100个字符,然后点击确定按钮
109
+ - 4. 去除歌单名称首尾空白字符
110
+ - 5. 把新建的歌单数据写入数据库中的歌单数据库表
111
+ - 6. 如果是在“歌单页面”,那么从数据库中读取新建歌单的数据,并且在“歌单页面”创建新建歌单item,实时刷新歌单页面,在歌单页面列表中的第一个位置上显示新建的歌单
112
+ - 7. 如果是在“添加到歌单弹窗”,那么从数据库中读取新建歌单的数据,并且在“添加到歌单弹窗”创建新建歌单item,实时刷新歌单页面,在添加到歌单弹窗列表中的第一个位置上显示新建的歌单
113
+
114
+ ## 场景四
115
+
116
+ ### 场景概述
117
+
118
+ 用户点击创建歌单,输入或者不输入歌单名称,然后点击取消按钮
119
+
120
+ ### 场景逻辑步骤
121
+
122
+ - 1. 用户在“歌单页面”点击“更多菜单”中的“新建歌单按钮”或者用户在“添加到歌单弹窗”中点击“新建歌单按钮”
123
+ - 2. 弹出“新建歌单对话框”
124
+ - 3. 无论用户是否在输入框中输入歌单名称,只要用户点击取消按钮,那么就关闭“新建歌单对话框”,无需执行其他操作
125
+ ```
126
+
127
+ ### Sample 2
128
+ ```
129
+ # 歌曲信息页信息展示与信息更新SPEC
130
+
131
+ 歌曲信息页展示音频信息、出自专辑、参与创作的艺术家,以及播放界面保持屏幕唤醒、沉浸模式内容。
132
+
133
+ ## 场景一
134
+
135
+ ### 场景概述
136
+
137
+ 进入歌曲信息页后,展示当前播放歌曲的信息及相关功能入口
138
+
139
+ ### 场景逻辑步骤
140
+
141
+ - 1. 在播放页右滑进入歌曲信息页
142
+ - 2. 歌曲信息页读取信息并展示:
143
+ - 2.1 音频信息展示:
144
+ - 当当前播放歌曲的音频格式存在时,显示当前播放歌曲的音频格式
145
+ - 当当前播放歌曲的音频格式缺失时,显示当前播放歌曲的文件扩展名;若文件扩展名也为空,则显示为空白
146
+ - 当当前播放歌曲的声道数存在时,显示声道数
147
+ - 当当前播放歌曲的声道数缺失时,隐藏该字段
148
+ - 当当前播放歌曲的采样率存在时,显示采样率
149
+ - 当当前播放歌曲的采样率缺失时,隐藏该字段
150
+ - 当当前播放歌曲的比特率存在时,显示比特率
151
+ - 当当前播放歌曲的比特率缺失时,显示 0 Kbps
152
+ - 2.2 出自专辑展示:
153
+ - 当当前播放歌曲的专辑封面存在时,显示专辑封面
154
+ - 当当前播放歌曲的专辑封面缺失时,显示默认专辑封面图标
155
+ - 当当前播放歌曲的专辑标题存在时,显示专辑标题
156
+ - 当当前播放歌曲的专辑标题缺失时,显示“未知专辑标题”
157
+ - 当当前播放歌曲的专辑艺术家存在时,显示专辑艺术家
158
+ - 当当前播放歌曲的专辑艺术家缺失时,显示“未知专辑艺术家”
159
+ - 2.3 参与创作的艺术家展示:
160
+ - 当当前播放歌曲的艺术家头像存在时,显示艺术家头像
161
+ - 当当前播放歌曲的艺术家头像缺失时,显示默认歌曲封面图标
162
+ - 当当前播放歌曲的艺术家名称存在时,显示艺术家名称
163
+ - 当当前播放歌曲的艺术家名称缺失时,显示“未知艺术家”
164
+ - 当当前播放歌曲的艺术家音轨数量(歌曲数量)存在时,显示艺术家音轨数量(歌曲数量)
165
+ - 当当前播放歌曲的艺术家音轨数量(歌曲数量)缺失时,显示 0
166
+
167
+
168
+ ## 场景二
169
+
170
+ ### 场景概述
171
+
172
+ 切换播放歌曲后,歌曲信息页面同步刷新
173
+
174
+ ### 场景逻辑步骤
175
+
176
+ - 1. 在播放页右滑进入歌曲信息页
177
+ - 2. 用户通过上一首、下一首、播放队列切歌或自动切歌等方式切换当前播放歌曲
178
+ - 3. 歌曲信息页中的音频信息、专辑信息、艺术家信息同步刷新为新歌曲对应内容
179
+ ```
180
+
181
+ ### Sample 3
182
+ ```
183
+ # 添加到歌单SPEC
184
+
185
+ 用户可通过多种入口将单首或多首歌曲添加到歌单,歌单详情页按配置的排序规则展示歌曲,并新增"按添加到歌单时间排序"选项。
186
+
187
+ ## 场景一
188
+
189
+ ### 场景概述
190
+
191
+ 用户从歌曲列表页,通过单首歌曲的更多操作-添加到歌单,将一首歌曲添加到歌单
192
+
193
+ ### 场景逻辑步骤
194
+
195
+ - 1. 用户在歌曲列表页点击某首歌曲的"更多操作"按钮
196
+ - 2. 用户在弹出菜单中点击"添加到歌单",弹出歌单选择弹窗
197
+ - 3. 歌单选择弹窗中包含当前所有已经创建好的歌单以及新建歌单按钮
198
+ - 3.1 用户可以在歌单选择弹窗中点击已有的歌单将歌曲添加到歌单中,触发toast提示“已添加到歌单”
199
+ - 3.2 用户可以点击新建歌单按钮创建新歌单,歌单创建成功后返回歌单选择弹窗,弹窗的当前歌单列表刷新后,新创建的歌单位于最上面,点击新歌单将歌曲添加到新创建的歌单中,触发toast提示“已添加到歌单”
200
+ - 4. 歌曲被添加到目标歌单,并按目标歌单当前的排序规则刷新歌曲列表
201
+ - 4.1 如果目标歌单排序规则为"按添加到歌单时间排序",则该歌曲直接添加到歌曲列表最上方
202
+ - 4.2 如果目标歌单排序规则为其他规则,则按相应规则刷新歌曲列表进行排序
203
+ - 5. 歌单封面刷新为该歌曲对应的封面
204
+
205
+ ## 场景二
206
+
207
+ ### 场景概述
208
+
209
+ 用户从歌曲列表页,通过多选操作-添加到歌单,将多首歌曲同时添加到歌单
210
+
211
+ ### 场景逻辑步骤
212
+
213
+ - 1. 用户在歌曲列表页进入多选模式,依次选中多首歌曲
214
+ - 2. 用户点击"添加到歌单"按钮,弹出歌单选择弹窗
215
+ - 3. 歌单选择弹窗中包含当前所有已经创建好的歌单以及新建歌单按钮
216
+ - 3.1 用户可以在歌单选择弹窗中点击已有的歌单将歌曲添加到歌单中,触发toast提示“已添加到歌单”
217
+ - 3.2 用户可以点击新建歌单按钮创建新歌单,歌单创建成功后返回歌单选择弹窗,弹窗的当前歌单列表刷新后,新创建的歌单位于最上面,点击新歌单将歌曲添加到新创建的歌单中,触发toast提示“已添加到歌单”
218
+ - 4. 所选歌曲添加到目标歌单,并按目标歌单当前的排序规则刷新歌曲列表
219
+ - 4.1 如果目标歌单排序规则为"按添加到歌单时间排序",则按用户多选过程中每首歌的选中顺序决定添加次序,最先选中的歌曲在最上方(即添加到歌单的时间最晚)
220
+ - 4.2 如果目标歌单排序规则为其他规则,则按相应规则刷新歌曲列表进行排序
221
+ - 5. 歌单封面刷新为最后添加到歌单中的歌曲对应的封面
222
+
223
+ ## 场景三
224
+
225
+ ### 场景概述
226
+
227
+ 用户从专辑详情页,通过单首歌曲的更多操作入口,将一首歌曲添加到歌单
228
+
229
+ ### 场景逻辑步骤
230
+
231
+ - 1. 用户在专辑详情页点击某首歌曲的"更多操作"按钮
232
+ - 2. 用户在弹出菜单中点击"添加到歌单",弹出歌单选择弹窗
233
+ - 3. 歌单选择弹窗中包含当前所有已经创建好的歌单以及新建歌单按钮
234
+ - 3.1 用户可以在歌单选择弹窗中点击已有的歌单将歌曲添加到歌单中,触发toast提示“已添加到歌单”
235
+ - 3.2 用户可以点击新建歌单按钮创建新歌单,歌单创建成功后返回歌单选择弹窗,弹窗的当前歌单列表刷新后,新创建的歌单位于最上面,点击新歌单将歌曲添加到新创建的歌单中,触发toast提示“已添加到歌单”
236
+ - 4. 歌曲被添加到目标歌单,并按目标歌单当前的排序规则刷新歌曲列表
237
+ - 4.1 如果目标歌单排序规则为"按添加到歌单时间排序",则该歌曲直接添加到歌曲列表最上方
238
+ - 4.2 如果目标歌单排序规则为其他规则,则按相应规则刷新歌曲列表进行排序
239
+ - 5. 歌单封面刷新为该歌曲对应的封面
240
+
241
+ ## 场景四
242
+
243
+ ### 场景概述
244
+
245
+ 用户从艺术家详情页,通过单首歌曲的更多操作入口,将一首歌曲添加到歌单
246
+
247
+ ### 场景逻辑步骤
248
+
249
+ - 1. 用户在艺术家详情页点击某首歌曲的"更多操作"按钮
250
+ - 2. 用户在弹出菜单中点击"添加到歌单",弹出歌单选择弹窗
251
+ - 3. 歌单选择弹窗中包含当前所有已经创建好的歌单以及新建歌单按钮
252
+ - 3.1 用户可以在歌单选择弹窗中点击已有的歌单将歌曲添加到歌单中,触发toast提示“已添加到歌单”
253
+ - 3.2 用户可以点击新建歌单按钮创建新歌单,歌单创建成功后返回歌单选择弹窗,弹窗的当前歌单列表刷新后,新创建的歌单位于最上面,点击新歌单将歌曲添加到新创建的歌单中,触发toast提示“已添加到歌单”
254
+ - 4. 歌曲被添加到目标歌单,并按目标歌单当前的排序规则刷新歌曲列表
255
+ - 4.1 如果目标歌单排序规则为"按添加到歌单时间排序",则该歌曲直接添加到歌曲列表最上方
256
+ - 4.2 如果目标歌单排序规则为其他规则,则按相应规则刷新歌曲列表进行排序
257
+ - 5. 歌单封面刷新为该歌曲对应的封面
258
+
259
+ ## 场景五
260
+
261
+ ### 场景概述
262
+
263
+ 用户从文件夹详情页,通过单首歌曲的更多操作入口,将一首歌曲添加到歌单
264
+
265
+ ### 场景逻辑步骤
266
+
267
+ - 1. 用户在文件夹详情页点击某首歌曲的"更多操作"按钮
268
+ - 2. 用户在弹出菜单中点击"添加到歌单",弹出歌单选择弹窗
269
+ - 3. 歌单选择弹窗中包含当前所有已经创建好的歌单以及新建歌单按钮
270
+ - 3.1 用户可以在歌单选择弹窗中点击已有的歌单将歌曲添加到歌单中,触发toast提示“已添加到歌单”
271
+ - 3.2 用户可以点击新建歌单按钮创建新歌单,歌单创建成功后返回歌单选择弹窗,弹窗的当前歌单列表刷新后,新创建的歌单位于最上面,点击新歌单将歌曲添加到新创建的歌单中,触发toast提示“已添加到歌单”
272
+ - 4. 歌曲添加到目标歌单,并按目标歌单当前的排序规则刷新歌曲列表
273
+ - 4.1 如果目标歌单排序规则为"按添加到歌单时间排序",则该歌曲直接添加到歌曲列表最上方
274
+ - 4.2 如果目标歌单排序规则为其他规则,则按相应规则刷新歌曲列表进行排序
275
+ - 5. 歌单封面刷新为该歌曲对应的封面
276
+
277
+ ## 场景六
278
+
279
+ ### 场景概述
280
+
281
+ 用户从文件夹详情页,通过多选操作,将多首歌曲同时添加到歌单
282
+
283
+ ### 场景逻辑步骤
284
+
285
+ - 1. 用户在文件夹详情页进入多选模式,依次选中多首歌曲
286
+ - 2. 用户点击"添加到歌单"按钮,弹出歌单选择弹窗
287
+ - 3. 歌单选择弹窗中包含当前所有已经创建好的歌单以及新建歌单按钮
288
+ - 3.1 用户可以在歌单选择弹窗中点击已有的歌单将歌曲添加到歌单中,触发toast提示“已添加到歌单”
289
+ - 3.2 用户可以点击新建歌单按钮创建新歌单,歌单创建成功后返回歌单选择弹窗,弹窗的当前歌单列表刷新后,新创建的歌单位于最上面,点击新歌单将歌曲添加到新创建的歌单中,触发toast提示“已添加到歌单”
290
+ - 4. 所选歌曲添加到目标歌单,并按目标歌单当前的排序规则刷新歌曲列表
291
+ - 4.1 如果目标歌单排序规则为"按添加到歌单时间排序",则按用户多选过程中每首歌的选中顺序决定添加次序,最先选中的歌曲在最上方(即添加到歌单的时间最晚)
292
+ - 4.2 如果目标歌单排序规则为其他规则,则按相应规则刷新歌曲列表进行排序
293
+ - 5. 歌单封面刷新为最后添加到歌单中的歌曲对应的封面
294
+
295
+ ## 场景七
296
+
297
+ ### 场景概述
298
+
299
+ 用户进入歌单详情页,查看歌单名称及歌曲列表
300
+
301
+ ### 场景逻辑步骤
302
+
303
+ - 1. 用户点击某个歌单进入歌单详情页
304
+ - 2. 页面顶部展示歌单名字
305
+ - 3. 页面下方展示歌单包含的歌曲列表,歌曲按照当前歌单配置的排序规则进行展示
306
+ - 4. 新建歌单的默认排序规则为"按添加到歌单时间排序"(后添加到歌单的歌曲排在上面)
307
+
308
+ ## 场景八
309
+
310
+ ### 场景概述
311
+
312
+ 用户在歌单详情页切换排序规则为"按添加到歌单时间排序"以外的其他规则
313
+
314
+ ### 场景逻辑步骤
315
+
316
+ - 1. 用户在歌单详情页点击排序选项入口
317
+ - 2. 用户选择其他排序规则(如标题、艺术家等)
318
+ - 3. 歌曲列表按所选规则重新排序并刷新展示
319
+ - 4. 该排序规则在用户再次切换前保持生效,后续新添加的歌曲按该规则插入对应位置
320
+
321
+ ## 场景九
322
+
323
+ ### 场景概述
324
+
325
+ 当用户尝试将已存在于目标歌单中的歌曲再次添加到该歌单时,不会重复添加
326
+
327
+ ### 场景逻辑步骤
328
+
329
+ - 1. 用户通过任意入口(单首或多选)选择歌曲并添加到目标歌单,触发toast提示“已添加到歌单”
330
+ - 2. 如果所选歌曲中存在已在目标歌单中的歌曲,该歌曲不会被重复添加,其原有的添加时间保持不变
331
+ - 3. 对于本次操作中尚未在目标歌单中的歌曲,按对应排序规则正常添加
332
+
333
+ ## 场景十
334
+
335
+ ### 场景概述
336
+
337
+ 用户在歌单选择弹窗中取消添加到歌单操作
338
+
339
+ ### 场景逻辑步骤
340
+
341
+ - 1. 用户通过任意入口触发"添加到歌单",弹出歌单选择弹窗
342
+ - 2. 用户通过点击弹窗外部区域关闭弹窗
343
+ - 3. 歌单内容不发生任何变化,用户返回操作前的页面状态
344
+
345
+
346
+ ## 场景十一
347
+
348
+ ### 场景概述
349
+
350
+ 歌单选择弹窗需要包含当前所有已创建的歌单及歌曲信息
351
+
352
+ ### 场景逻辑步骤
353
+
354
+ - 1. 用户通过添加到歌单操作触发歌单选择弹窗
355
+ - 2. 歌单选择弹窗通过列表形式展示当前所有已经创建好的歌单,每个歌单对应的歌曲数目是准确的
356
+
357
+ ## 场景十二
358
+
359
+ ### 场景概述
360
+
361
+ 添加歌曲到歌单后,歌单的歌曲数量需要实时刷新
362
+
363
+ ### 场景逻辑步骤
364
+
365
+ - 1. 用户将歌曲添加到歌单
366
+ - 2. 歌单列表页,歌单详情页,歌单选择弹窗中该歌单对应的歌曲数目需要实时刷新
367
+ ```
368
+
369
+ ---
370
+
371
+ ## Workflow
372
+
373
+ ### Step 0 — Validate inputs
374
+
375
+ 1. Verify `requirement-description-dir` exists and is a directory. List all `.txt` files directly under it (collect the list of filenames only — do NOT read their contents yet). If there are no `.txt` files, stop and report the error.
376
+ 2. Verify `android-project-path` exists and is a directory.
377
+ 3. Ensure `spec-output-dir` exists (create it if it does not).
378
+
379
+ ### Step 1 — Ensure homegraph has a fresh index for the project
380
+
381
+ homegraph exposes two surfaces:
382
+
383
+ - **Index management** (`status`, `init`, `sync`, `index`) → run the `homegraph` CLI via `Bash`.
384
+ - **Code queries** (`search`, `explore`, `node`, `impact`, `callers`, `callees`, `files`) → call `mcp__homegraph__*` tools directly.
385
+
386
+ homegraph indexes per-project into a local `.homegraph/` directory; there is no central repo registry. Scope every code query to the Android project with `projectPath: "<android-project-path>"` (this skill's working directory is the spec project, NOT the Android project, so the parameter is mandatory — omitting it queries the wrong project).
387
+
388
+ Procedure:
389
+
390
+ 1. Run `homegraph status <android-project-path>` to inspect the index state.
391
+ 2. Decide based on the output:
392
+ - **Not indexed** (no `.homegraph/`) → run `homegraph init -i <android-project-path>`, wait for completion.
393
+ - **Stale** (`homegraph status` output does NOT contain `[OK] Index is up to date`) → run `homegraph sync <android-project-path>` (incremental; use `homegraph index <android-project-path> --force` for a full rebuild), wait for completion.
394
+ - **Fresh** → proceed to Step 2.
395
+
396
+ **Hard fail policy** — any of the following stops the skill and surfaces the error to the user; do NOT degrade to `Read` + `Grep`:
397
+
398
+ - `homegraph` CLI is not found on PATH → ask the user to install it (`npm install -g homegraph`).
399
+ - `homegraph status`, `init`, `sync`, or `index` returns an error → surface the error verbatim and stop. Do not attempt spec generation without an index — the resulting spec would miss code-grounded scenarios.
400
+ - Any `mcp__homegraph__*` call reports the project is not indexed → verify `init -i` ran against `android-project-path`.
401
+
402
+ ### Step 2 — Process each requirement file independently, one at a time
403
+
404
+ For each `.txt` filename collected in Step 0, in order, run 2.1 → 2.4 end-to-end before moving to the next file. Do NOT pre-read all `.txt` files.
405
+
406
+ - **2.1 Read**: Read this file's content verbatim. If empty, warn and skip to the next file.
407
+ - **2.2 Analyze**: Explore the Android codebase for this requirement using the `mcp__homegraph__*` tools to retrieve the complete code implementation (entry points, end-to-end call chains, state writes / persistence keys, manifest declarations). Use `search` → `explore` / `node` to locate and read symbols; `callers` / `callees` / `impact` to walk call chains up and down; `files` to enumerate; and `Grep` for exact literals (settings keys, DAO columns, `android:key`) that live outside the code graph. Scope EVERY `mcp__homegraph__*` call with `projectPath: "<android-project-path>"` (a missing or wrong `projectPath` queries the wrong project). Use these tools directly — do NOT invoke any nested exploration skill. If any `mcp__homegraph__*` call fails unexpectedly, surface the error and stop.
408
+ - **2.3 Decompose**: Using the raw requirement + code from 2.2, generate the spec per `## Principles` and `## Spec Few-shot Samples`.
409
+ - **2.4 Write**: Write the spec to `<spec-output-dir>/<source_filename_without_ext>.md` (overwrite if exists), then move on to the next file.
410
+
411
+ ### Step 3 — Report
412
+
413
+ After all requirement files have been processed (or skipped with a warning), report a brief summary listing each generated spec file path and any files that were skipped.
@@ -0,0 +1,105 @@
1
+ # Android Platform Tokens — Strip List
2
+
3
+ **Read when**: 3.5 Synthesize, for the platform-token strip list (Principle 6).
4
+
5
+ The spec MUST NOT contain Android platform tokens. During 3.5 synthesis, strip every match from the trace's natural-language behavior text and replace with behavior-level Chinese vocabulary. The trace itself may use these tokens (they live in `file:line` anchors and code-layer notes); only the **final spec** must be platform-token-free.
6
+
7
+ ## Strip list (by category)
8
+
9
+ ### Components
10
+ `Activity`, `Fragment`, `Composable`, `Service`, `ForegroundService`, `BroadcastReceiver`, `ContentProvider`, `Application`, `Worker`, `IntentService`, `JobIntentService`, `JobScheduler`
11
+
12
+ ### IPC / data carriers
13
+ `Intent`, `PendingIntent`, `Bundle`, `Parcelable`, `Messenger`, `AIDL`, `Binder`, `IBinder`
14
+
15
+ ### State / architecture
16
+ `ViewModel`, `LiveData`, `MutableLiveData`, `StateFlow`, `SharedFlow`, `Flow` (when meaning Kotlin Flow), `mutableStateOf`, `ViewBinding`, `DataBinding`, `Repository`, `UseCase`, `Presenter`
17
+
18
+ ### Persistence
19
+ `Room`, `RoomDatabase`, `DAO`, `@Entity`, `DataStore`, `Preferences DataStore`, `Proto DataStore`, `SharedPreferences`, `MMKV`, `SQLiteOpenHelper`, `ContentResolver`
20
+
21
+ ### Lifecycle
22
+ `onCreate`, `onStart`, `onResume`, `onPause`, `onStop`, `onDestroy`, `Lifecycle`, `LifecycleOwner`, `ProcessLifecycleOwner`, `viewLifecycleOwner`, `lifecycleScope`
23
+
24
+ ### UI containers / widgets
25
+ `RecyclerView`, `Adapter`, `ViewHolder`, `ConstraintLayout`, `LinearLayout`, `FrameLayout`, `RelativeLayout`, `ScrollView`, `ListView`, `Spinner`, `ViewPager`, `TabLayout`
26
+
27
+ ### UI feedback
28
+ `Toast`, `Snackbar`, `Dialog`, `AlertDialog`, `BottomSheetDialog`, `ProgressDialog`, `FloatingActionButton`
29
+
30
+ ### Navigation
31
+ `NavController`, `NavGraph`, `NavHostFragment`, `Navigation Component`, `startActivity`, `startActivityForResult`
32
+
33
+ ### Resources / IDs
34
+ `R.id.*`, `R.layout.*`, `R.string.*`, `R.drawable.*`, `R.color.*`, `R.dimen.*`, `R.menu.*`, `R.xml.*`, `R.array.*`, `R.style.*`, `@+id/...`, `@string/...`, `@drawable/...`, `@color/...`
35
+
36
+ ### Coroutines / threading
37
+ `Coroutine`, `suspend`, `CoroutineScope`, `Job`, `viewModelScope`, `withContext`, `Dispatchers.*`, `async`, `await`, `launch`, `Handler`, `Looper`, `HandlerThread`, `AsyncTask`, `Executor`
38
+
39
+ ### Compose (lifecycle / state)
40
+ `@Composable`, `remember`, `derivedStateOf`, `rememberSaveable`, `MutableState`, `LaunchedEffect`, `DisposableEffect`, `SideEffect`, `CompositionLocal`, `produceState`
41
+
42
+ ### Compose Shape
43
+ `CircleShape`, `RoundedCornerShape`, `RectangleShape`, `CutCornerShape`
44
+
45
+ ### Compose Animation
46
+ `LinearEasing`, `FastOutSlowInEasing`, `EaseInOut`, `EaseOut`, `tween`, `spring`, `keyframes`, `infiniteRepeatable`, `animateXxxAsState`, `Animatable`, `AnimationSpec`
47
+
48
+ ### Compose Layout / Modifier
49
+ `ContentScale` (Fit / Crop / FillBounds / Inside / None), `Alignment`, `Arrangement`, `Modifier.clip`, `Modifier.background`, `Modifier.size`, `Modifier.padding`, `Modifier.fillMaxSize`, `Modifier.wrapContentSize`, `Modifier.aspectRatio`, `Modifier.weight`
50
+
51
+ ### Build / Manifest
52
+ `AndroidManifest`, `build.gradle`, `gradle`, `BuildConfig`, `applicationId`, `versionCode`, `minSdkVersion`, `targetSdkVersion`, `compileSdkVersion`, `ProGuard`, `R8`
53
+
54
+ ### DI
55
+ `Hilt`, `Dagger`, `@Inject`, `@Module`, `@Provides`, `@Singleton`, `Koin`, `ServiceLocator`
56
+
57
+ ### System services / media
58
+ `ContextCompat`, `getSystemService`, `NotificationManager`, `NotificationChannel`, `AlarmManager`, `PowerManager`, `ConnectivityManager`, `AudioManager`, `MediaSession`, `MediaPlayer`, `ExoPlayer`, `MediaBrowserServiceCompat`
59
+
60
+ ### Implementation constants (NEVER appear in spec)
61
+
62
+ - **Hardcoded dimensions** (`8dp`, `48.dp`, `16.sp`, `2.dp`) — strip entirely. Spec describes shape/size semantically: "圆形" / "小圆点" / "歌词字号比正文略大". 不要保留单位 ("8 dp" 也不行).
63
+ - **Hardcoded durations** (`25000ms`, `300L`, `Duration.seconds(2)`) — restate as semantic time: "约 25 秒一圈" / "短暂淡入". 不要写原始数值.
64
+ - **Persistence key literals** (`circle_playback_cover`, `karaoke_mode_compat`, `floating_lyric_enabled`) — NEVER. Describe the user-visible setting, not the storage key.
65
+
66
+ ## Critical: Chinese translations of platform concepts are ALSO forbidden
67
+
68
+ The strip list above uses English API names. But platform concepts translated into Chinese (e.g. `活动基类` for Activity / `主活动页面` for MainActivity / `媒体会话信息` for MediaSession / `短边模式` for DISPLAY_CUTOUT_MODE / `广播接收器` for BroadcastReceiver / `视图模型` for ViewModel) are STILL platform tokens — restate them in user-facing behavior language per the replacement vocabulary below. Translating a platform concept does NOT make it user-facing.
69
+
70
+ ## Replacement vocabulary (behavior-level Chinese)
71
+
72
+ | Stripped token | Spec vocabulary |
73
+ |---|---|
74
+ | Activity / Fragment / Composable | 页面 |
75
+ | Dialog / AlertDialog / BottomSheet | 弹窗 / 对话框 |
76
+ | Toast / Snackbar | toast 提示 / 浮动提示 |
77
+ | ViewModel / LiveData / StateFlow / mutableStateOf | 状态 / 状态写入 / 状态刷新 |
78
+ | Room / DAO / DataStore / SharedPreferences / MMKV | 持久化 / 数据库 / 配置存储 |
79
+ | RecyclerView + Adapter / ListView | 列表 / 列表项 |
80
+ | onClick / onLongClick / onTap | 点击 / 长按 |
81
+ | Intent / startActivity / Navigation | 跳转 / 进入<目标页> |
82
+ | BroadcastReceiver / sendBroadcast | 系统事件监听 / 广播 |
83
+ | Service / ForegroundService | 后台服务 / 前台服务 |
84
+ | Coroutine / launch / withContext | 异步 / 异步执行 |
85
+ | MediaPlayer / ExoPlayer / MediaSession | 播放器 / 播放控制 |
86
+ | Notification / NotificationManager / NotificationChannel | 通知 / 通知栏 / 通知分组 |
87
+ | ContentResolver / ContentProvider | 数据访问 / 数据共享 |
88
+ | build.gradle flag / BuildConfig | 编译开关 / 配置项 |
89
+ | ConnectivityManager | 网络状态 / 网络可达性 |
90
+ | AudioManager / audio focus | 音频焦点 / 音频通道 |
91
+ | PowerManager / WakeLock | 屏幕唤醒 / 锁屏唤醒 |
92
+ | CircleShape / RoundedCornerShape / RectangleShape / CutCornerShape | 圆形 / 圆角矩形 / 矩形 / 切角矩形 |
93
+ | LinearEasing / FastOutSlowInEasing / EaseInOut / EaseOut | 线性 / 减速 / 缓入缓出 / 减速出 |
94
+ | tween / spring / keyframes / infiniteRepeatable / Animatable | 持续N秒动画 / 弹性动画 / 关键帧动画 / 循环动画 / 动画对象 |
95
+ | ContentScale.Fit / Crop / FillBounds / Inside / None | 等比缩放适配 / 裁剪填充 / 拉伸填充 / 等比居中 / 不缩放 |
96
+ | Modifier.clip / .size / .padding / .fillMaxSize / .aspectRatio | 裁剪为X形 / 设定尺寸 / 内边距 / 填满父容器 / 宽高比 |
97
+ | Modifier.wrapContentSize / .weight / .background | 内容自适应 / 权重占比 / 背景 |
98
+ | animateXxxAsState | 动画过渡到目标值 |
99
+
100
+ ## Items to keep verbatim (do NOT strip)
101
+
102
+ - **Business entity names** (歌单, 歌曲, 专辑, 艺术家, 播放页, ...) — these are domain language, not platform tokens.
103
+ - **User-visible resource string content** (toast text, button labels, error messages) — translate the displayed content into the spec; strip the `R.string.xxx` reference but keep the message text.
104
+ - **Standard permission semantics** — describe permissions in user language ("录音权限", "通知权限", "存储访问权限"), NOT by code constant (`RECORD_AUDIO`, `POST_NOTIFICATIONS`, ...).
105
+ - **Persistence key literals** are usually internal — do NOT surface them in the spec unless they appear in user-visible UI (rare). If a key appears in the trace's `interaction` field, describe its behavior, not its name.
@@ -0,0 +1,78 @@
1
+ # Spec Sample 1 — Boundary-and-happy-path Decomposition
2
+
3
+ **Style focus**: how to slice one feature into `empty / over-length / valid / cancel` atomic scenarios on a single-entry trigger flow. Mimic the voice, scenario granularity, and structure — NOT the vocabulary or domain.
4
+
5
+ **Read when**: 3.5 Synthesize.
6
+
7
+ ---
8
+
9
+ # 新建歌单SPEC
10
+
11
+ 创建新歌单
12
+
13
+ ## 场景一
14
+
15
+ ### 场景概述
16
+
17
+ 用户点击创建歌单,但输入的歌单名称为空并且创建歌单
18
+
19
+ ### 场景逻辑步骤
20
+
21
+ - 1. 用户在"歌单页面"点击"更多菜单"中的"新建歌单按钮"或者用户在"添加到歌单弹窗"中点击"新建歌单按钮"
22
+ - 2. 弹出"新建歌单对话框"
23
+ - 3. 用户在输入框中输入空白歌单名称并点击确定按钮
24
+ - 4. 弹出toast"歌单名称不得为空"并且关闭"新建歌单对话框"
25
+
26
+ ## 场景二
27
+
28
+ ### 场景概述
29
+
30
+ 用户点击创建歌单,但输入的歌单名称超过最大长度并且创建歌单
31
+
32
+ ### 场景逻辑步骤
33
+
34
+ - 1. 用户在"歌单页面"点击"更多菜单"中的"新建歌单按钮"或者用户在"添加到歌单弹窗"中点击"新建歌单按钮"
35
+ - 2. 弹出"新建歌单对话框"
36
+ - 3. 用户在输入框中输入歌单名称并且歌单名称超过100个字符,然后点击确定按钮
37
+ - 4. 弹出toast"歌单名称过长"并且关闭"新建歌单对话框"
38
+
39
+ ## 场景三
40
+
41
+ ### 场景概述
42
+
43
+ 用户点击创建歌单,输入有效歌单名称并且创建歌单
44
+
45
+ ### 场景逻辑步骤
46
+
47
+ - 1. 用户在"歌单页面"点击"更多菜单"中的"新建歌单按钮"或者用户在"添加到歌单弹窗"中点击"新建歌单按钮"
48
+ - 2. 弹出"新建歌单对话框"
49
+ - 3. 用户在输入框中输入有效歌单名称,即用户输入到歌单名称不为空并且歌单名称没有超过100个字符,然后点击确定按钮
50
+ - 4. 去除歌单名称首尾空白字符
51
+ - 5. 把新建的歌单数据写入数据库中的歌单数据库表
52
+ - 6. 如果是在"歌单页面",那么从数据库中读取新建歌单的数据,并且在"歌单页面"创建新建歌单item,实时刷新歌单页面,在歌单页面列表中的第一个位置上显示新建的歌单
53
+ - 7. 如果是在"添加到歌单弹窗",那么从数据库中读取新建歌单的数据,并且在"添加到歌单弹窗"创建新建歌单item,实时刷新歌单页面,在添加到歌单弹窗列表中的第一个位置上显示新建的歌单
54
+
55
+ > [偏差] 需求要求歌单名为空时禁用"确定"按钮,但实际代码允许点击后弹出 toast 提示(参见场景一步骤 4)。
56
+
57
+ ## 场景四
58
+
59
+ ### 场景概述
60
+
61
+ 用户点击创建歌单,输入或者不输入歌单名称,然后点击取消按钮
62
+
63
+ ### 场景逻辑步骤
64
+
65
+ - 1. 用户在"歌单页面"点击"更多菜单"中的"新建歌单按钮"或者用户在"添加到歌单弹窗"中点击"新建歌单按钮"
66
+ - 2. 弹出"新建歌单对话框"
67
+ - 3. 无论用户是否在输入框中输入歌单名称,只要用户点击取消按钮,那么就关闭"新建歌单对话框",无需执行其他操作
68
+
69
+ ## 场景五
70
+
71
+ ### 场景概述
72
+
73
+ "新建歌单"功能的作用范围与不作用范围
74
+
75
+ ### 场景逻辑步骤
76
+
77
+ - 1. **仅作用于** 以下入口: "歌单页面"的"更多菜单 - 新建歌单"按钮; "添加到歌单弹窗"的"新建歌单"按钮
78
+ - 2. **不作用于** 以下位置: "歌单详情页"(无新建入口) / "播放页" / "首页推荐区域" / "搜索结果页" / "我的页面" — 这些位置既不显示新建歌单入口, 也不响应新建歌单事件
@@ -0,0 +1,58 @@
1
+ # Spec Sample 2 — Nested Sub-bullet Decomposition
2
+
3
+ **Style focus**: how to express per-field present/absent fallback rules as nested sub-bullets within a single scenario's flow. Mimic the structure, NOT the vocabulary or domain.
4
+
5
+ **Read when**: 3.5 Synthesize.
6
+
7
+ ---
8
+
9
+ # 歌曲信息页信息展示与信息更新SPEC
10
+
11
+ 歌曲信息页展示音频信息、出自专辑、参与创作的艺术家,以及播放界面保持屏幕唤醒、沉浸模式内容。
12
+
13
+ ## 场景一
14
+
15
+ ### 场景概述
16
+
17
+ 进入歌曲信息页后,展示当前播放歌曲的信息及相关功能入口
18
+
19
+ ### 场景逻辑步骤
20
+
21
+ - 1. 在播放页右滑进入歌曲信息页
22
+ - 2. 歌曲信息页读取信息并展示:
23
+ - 2.1 音频信息展示:
24
+ - 当当前播放歌曲的音频格式存在时,显示当前播放歌曲的音频格式
25
+ - 当当前播放歌曲的音频格式缺失时,显示当前播放歌曲的文件扩展名;若文件扩展名也为空,则显示为空白
26
+ - 当当前播放歌曲的声道数存在时,显示声道数
27
+ - 当当前播放歌曲的声道数缺失时,隐藏该字段
28
+ - 当当前播放歌曲的采样率存在时,显示采样率
29
+ - 当当前播放歌曲的采样率缺失时,隐藏该字段
30
+ - 当当前播放歌曲的比特率存在时,显示比特率
31
+ - 当当前播放歌曲的比特率缺失时,显示 0 Kbps
32
+ - 2.2 出自专辑展示:
33
+ - 当当前播放歌曲的专辑封面存在时,显示专辑封面
34
+ - 当当前播放歌曲的专辑封面缺失时,显示默认专辑封面图标
35
+ - 当当前播放歌曲的专辑标题存在时,显示专辑标题
36
+ - 当当前播放歌曲的专辑标题缺失时,显示"未知专辑标题"
37
+ - 当当前播放歌曲的专辑艺术家存在时,显示专辑艺术家
38
+ - 当当前播放歌曲的专辑艺术家缺失时,显示"未知专辑艺术家"
39
+ - 2.3 参与创作的艺术家展示:
40
+ - 当当前播放歌曲的艺术家头像存在时,显示艺术家头像
41
+ - 当当前播放歌曲的艺术家头像缺失时,显示默认歌曲封面图标
42
+ - 当当前播放歌曲的艺术家名称存在时,显示艺术家名称
43
+ - 当当前播放歌曲的艺术家名称缺失时,显示"未知艺术家"
44
+ - 当当前播放歌曲的艺术家音轨数量(歌曲数量)存在时,显示艺术家音轨数量(歌曲数量)
45
+ - 当当前播放歌曲的艺术家音轨数量(歌曲数量)缺失时,显示 0
46
+
47
+
48
+ ## 场景二
49
+
50
+ ### 场景概述
51
+
52
+ 切换播放歌曲后,歌曲信息页面同步刷新
53
+
54
+ ### 场景逻辑步骤
55
+
56
+ - 1. 在播放页右滑进入歌曲信息页
57
+ - 2. 用户通过上一首、下一首、播放队列切歌或自动切歌等方式切换当前播放歌曲
58
+ - 3. 歌曲信息页中的音频信息、专辑信息、艺术家信息同步刷新为新歌曲对应内容