@buaa_smat/hometrans 0.1.5 → 0.1.7

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 (87) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +112 -55
  3. package/agents/{logic-coding.md → logic-coder.md} +2 -2
  4. package/agents/logic-context-builder.md +1 -1
  5. package/package.json +1 -1
  6. package/skills/{hmos-ui-align-batch → hmos-batch-ui-align}/SKILL.md +3 -3
  7. package/skills/{hmos-ui-align-batch → hmos-batch-ui-align}/references/conversion-procedure.md +2 -2
  8. package/skills/{hmos-ui-align-batch → hmos-batch-ui-align}/references/mappings/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +3 -5
  9. package/skills/{convert_pipeline → hmos-convert-pipeline}/SKILL.md +4 -4
  10. package/skills/hmos-fix-build-errors/SKILL.md +265 -0
  11. package/skills/hmos-fix-build-errors/references/arkts-strict-patterns.md +219 -0
  12. package/skills/hmos-fix-build-errors/references/known-patterns.md +157 -0
  13. package/skills/hmos-fix-build-errors/references/rdb-entity-pattern.md +131 -0
  14. package/skills/{hmos-ui-align → hmos-incremental-ui-align}/SKILL.md +20 -16
  15. package/skills/{hmos-ui-align → hmos-incremental-ui-align}/readme.md +5 -6
  16. package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +3 -5
  17. package/skills/{self-test → hmos-integration-test}/SKILL.md +1 -1
  18. package/skills/{spec-generator-skill → hmos-spec-generate}/SKILL.md +1 -1
  19. package/skills/skill-quality-evaluator/SKILL.md +138 -0
  20. package/skills/skill-quality-evaluator/assets/SKILL_TEMPLATE.md +77 -0
  21. package/skills/skill-quality-evaluator/references/Best-practices-for-skill-creators.md +277 -0
  22. package/skills/skill-quality-evaluator/references/Evaluating-skill-output-quality.md +300 -0
  23. package/skills/skill-quality-evaluator/references/Optimizing-skill-descriptions.md +196 -0
  24. package/skills/skill-quality-evaluator/references/Specification.md +272 -0
  25. package/skills/skill-quality-evaluator/references/Using-scripts-in-skills.md +308 -0
  26. package/skills/skill-quality-evaluator/references/report-template.md +163 -0
  27. package/skills/skill-quality-evaluator/references/scoring-rubric.md +269 -0
  28. package/agents/code-review-fix.md +0 -356
  29. package/dist/cli/config-store.js +0 -148
  30. package/dist/cli/config.js +0 -40
  31. package/dist/cli/index.js +0 -43
  32. package/dist/cli/init.js +0 -378
  33. package/dist/cli/mcp-setup.js +0 -262
  34. package/dist/cli/mcp.js +0 -94
  35. package/dist/cli/uninstall.js +0 -310
  36. package/dist/context/index.js +0 -792
  37. package/skills/code-dev-review-fix/SKILL.md +0 -279
  38. package/skills/code-dev-review-fix-workspace/evals/evals.json +0 -56
  39. package/skills/code-dev-review-fix-workspace/iteration-1/routing-results.md +0 -23
  40. package/skills/hmos-ui-align/config.json +0 -11
  41. /package/agents/{logic-coding → logic-coder}/scripts/platform_context_query.py +0 -0
  42. /package/skills/{hmos-ui-align-batch → hmos-batch-ui-align}/references/mappings/android-to-harmonyOS-ui-interaction-mapping-reference.md +0 -0
  43. /package/skills/{hmos-ui-align-batch → hmos-batch-ui-align}/references/mappings/android-to-harmonyOS-ui-layout-mapping-reference.md +0 -0
  44. /package/skills/{hmos-ui-align-batch → 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" +0 -0
  45. /package/skills/{hmos-ui-align-batch → 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" +0 -0
  46. /package/skills/{hmos-ui-align-batch → 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" +0 -0
  47. /package/skills/{hmos-ui-align-batch → 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" +0 -0
  48. /package/skills/{hmos-ui-align-batch → 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" +0 -0
  49. /package/skills/{hmos-ui-align-batch → 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" +0 -0
  50. /package/skills/{hmos-ui-align-batch → 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" +0 -0
  51. /package/skills/{hmos-ui-align-batch → 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" +0 -0
  52. /package/skills/{hmos-ui-align-batch → 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" +0 -0
  53. /package/skills/{hmos-ui-align-batch → 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" +0 -0
  54. /package/skills/{hmos-ui-align-batch → hmos-batch-ui-align}/references/mvvm/MVVM/346/250/241/345/274/217/357/274/210V1/357/274/211.md" +0 -0
  55. /package/skills/{hmos-ui-align-batch → 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" +0 -0
  56. /package/skills/{hmos-ui-align-batch → 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" +0 -0
  57. /package/skills/{hmos-ui-align-batch → hmos-batch-ui-align}/scripts/android_parse_fast.py +0 -0
  58. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/config-example.json +0 -0
  59. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/diff_analysis.md +0 -0
  60. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/page_align.md +0 -0
  61. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/Comparison_Template.md +0 -0
  62. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@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" +0 -0
  63. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@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" +0 -0
  64. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@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" +0 -0
  65. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@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" +0 -0
  66. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@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" +0 -0
  67. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@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" +0 -0
  68. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@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" +0 -0
  69. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/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" +0 -0
  70. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/Environment/357/274/232/350/256/276/345/244/207/347/216/257/345/242/203/346/237/245/350/257/242.md" +0 -0
  71. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/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" +0 -0
  72. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/MVVM/346/250/241/345/274/217V1.md" +0 -0
  73. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/MVVM/346/250/241/345/274/217/357/274/210V1/357/274/211.md" +0 -0
  74. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/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" +0 -0
  75. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243//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" +0 -0
  76. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/UI_Analysis_Template.md +0 -0
  77. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/android-to-harmonyOS-ui-interaction-mapping-reference.md +0 -0
  78. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/android-to-harmonyOS-ui-layout-mapping-reference.md +0 -0
  79. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/scripts/app_feature_verify.py +0 -0
  80. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/scripts/navigation-capure.md +0 -0
  81. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/scripts/page_capture.py +0 -0
  82. /package/skills/{self-test → hmos-integration-test}/readme.md +0 -0
  83. /package/skills/{spec-generator-skill → hmos-spec-generate}/references/android-platform-tokens.md +0 -0
  84. /package/skills/{spec-generator-skill → hmos-spec-generate}/references/spec-sample-1.md +0 -0
  85. /package/skills/{spec-generator-skill → hmos-spec-generate}/references/spec-sample-2.md +0 -0
  86. /package/skills/{spec-generator-skill → hmos-spec-generate}/references/spec-sample-3.md +0 -0
  87. /package/skills/{spec-generator-skill → hmos-spec-generate}/references/step4-report-template.md +0 -0
@@ -0,0 +1,219 @@
1
+ # ArkTS 严格模式确定性修复 Pattern
2
+ # 适用于: ArkTS 严格模式编译错误
3
+ # 触发场景: 编译报错 arkts-no-xxx 系列
4
+ # 经验来源: EinkBro 迁移 (2026-03-26)
5
+
6
+ ---
7
+
8
+ ## Pattern 1: throw 语句
9
+
10
+ ### 错误写法
11
+ ```typescript
12
+ throw err; // ERROR: arkts-limited-throw
13
+ throw 'error string'; // ERROR: arkts-limited-throw
14
+ throw unknownVariable; // ERROR: arkts-limited-throw
15
+ ```
16
+
17
+ ### 正确写法
18
+ ```typescript
19
+ throw new Error(String(error));
20
+ ```
21
+
22
+ ### 不需要修改的情况
23
+ ```typescript
24
+ throw new Error('specific message'); // OK - 已经是 Error 实例
25
+ ```
26
+
27
+ ---
28
+
29
+ ## Pattern 2: 对象字面量作为参数 (arkts-no-untyped-obj-literals)
30
+
31
+ ### 错误写法
32
+ ```typescript
33
+ // ERROR: Object literal must correspond to some explicitly declared class or interface
34
+ const response = await this.sendRequest(url, { contents });
35
+ ```
36
+
37
+ ### 正确写法 — 先声明变量
38
+ ```typescript
39
+ interface GeminiRequestBody {
40
+ contents: GeminiContent[];
41
+ }
42
+
43
+ const requestBody: GeminiRequestBody = { contents };
44
+ const response = await this.sendRequest(url, requestBody);
45
+ ```
46
+
47
+ ### 内联参数场景
48
+ ```typescript
49
+ // 方法参数也是对象字面量,同样需要处理
50
+ httpRequest.request(url, {
51
+ method: http.RequestMethod.POST,
52
+ header: { 'Content-Type': 'application/json' },
53
+ extraData: JSON.stringify(body),
54
+ connectTimeout: 30000,
55
+ readTimeout: 30000
56
+ });
57
+ // ^ 这种场景 SDK 方法签名本身接受 object 类型,通常 OK
58
+ // 但自定义方法调用时必须用已声明接口的变量
59
+ ```
60
+
61
+ ---
62
+
63
+ ## Pattern 3: Margin vertical 简写不支持
64
+
65
+ ### 错误写法
66
+ ```typescript
67
+ .margin({ vertical: 8 }); // ERROR: 'vertical' does not exist in type
68
+ ```
69
+
70
+ ### 正确写法
71
+ ```typescript
72
+ .margin({ top: 8, bottom: 8 });
73
+ ```
74
+
75
+ ### 常见场景
76
+ | 错误 | 正确 |
77
+ |------|------|
78
+ | `.margin({ vertical: 8 })` | `.margin({ top: 8, bottom: 8 })` |
79
+ | `.margin({ horizontal: 16 })` | `.margin({ left: 16, right: 16 })` |
80
+
81
+ ---
82
+
83
+ ## Pattern 4: List 内不能直接放 Divider
84
+
85
+ ### 错误写法
86
+ ```typescript
87
+ List() {
88
+ ForEach(items, (item) => {
89
+ ListItem() { /* ... */ }
90
+ })
91
+ Divider() // ERROR: List children must be ListItem only
92
+ }
93
+ ```
94
+
95
+ ### 正确写法 — 用 ListItem + border
96
+ ```typescript
97
+ List() {
98
+ ForEach(items, (item) => {
99
+ ListItem() {
100
+ Column() {
101
+ Text(item.name)
102
+ }
103
+ .width('100%')
104
+ .padding(12)
105
+ .border({ width: { bottom: 1 }, color: '#E0E0E0' }) // 替代 Divider 分隔线
106
+ }
107
+ })
108
+ }
109
+ ```
110
+
111
+ ### 另一种方案 — border 直接在 ListItem 上
112
+ ```typescript
113
+ ListItem() {
114
+ // content
115
+ }
116
+ .border({ width: { bottom: 1 }, color: '#E0E0E0' })
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Pattern 5: 数组字面量类型推断 (arkts-no-noninferrable-arr-literals)
122
+
123
+ ### 错误写法
124
+ ```typescript
125
+ const arr = [1, 2, 3].map(x => ({ val: x }));
126
+ // ERROR: Array literals must contain elements of only inferrable types
127
+ ```
128
+
129
+ ### 正确写法 — 显式类型
130
+ ```typescript
131
+ interface Item { val: number; }
132
+ const arr: Item[] = [1, 2, 3].map((x): Item => ({ val: x }));
133
+ ```
134
+
135
+ ---
136
+
137
+ ## Pattern 6: TextDecoder 不存在
138
+
139
+ ### 错误写法
140
+ ```typescript
141
+ const decoder = new TextDecoder(); // ERROR: Cannot find name 'TextDecoder'
142
+ const str = decoder.decode(data);
143
+ ```
144
+
145
+ ### 正确写法
146
+ ```typescript
147
+ const bytes = new Uint8Array(data);
148
+ let chunk = '';
149
+ for (let i = 0; i < bytes.length; i++) {
150
+ chunk += String.fromCharCode(bytes[i]);
151
+ }
152
+ ```
153
+
154
+ ---
155
+
156
+ ## Pattern 7: HTTP 组件事件名
157
+
158
+ | 错误事件 | 正确事件 | 说明 |
159
+ |---------|---------|------|
160
+ | `request.on('requestEnd', ...)` | `request.on('dataEnd', ...)` | 请求结束事件 |
161
+ | `request.on('error', ...)` | 改用 Promise 的 catch | HTTP 组件 error 事件签名不标准 |
162
+
163
+ ---
164
+
165
+ ## Pattern 8: GeminiService 等自定义类缺少成员
166
+
167
+ ### 错误场景
168
+ ```typescript
169
+ class GeminiService {
170
+ private async sendRequest(url: string, body: object): Promise<Object> {
171
+ httpRequest.request(url, { extraData: JSON.stringify(body),
172
+ connectTimeout: this.timeout, // ERROR: Property 'timeout' does not exist
173
+ readTimeout: this.timeout
174
+ });
175
+ }
176
+ // timeout 属性忘记声明
177
+ }
178
+ ```
179
+
180
+ ### 正确 — 确保所有成员都在类体内声明
181
+ ```typescript
182
+ class GeminiService {
183
+ private timeout: number = 30000; // 在类体内声明
184
+ private async sendRequest(...) { ... }
185
+ }
186
+ ```
187
+
188
+ ---
189
+
190
+ ## Pattern 9: Button 不支持 emoji
191
+
192
+ ### 错误写法
193
+ ```typescript
194
+ Button('X') // 有时 emoji 渲染异常
195
+ Button('🗑')
196
+ ```
197
+
198
+ ### 正确写法
199
+ ```typescript
200
+ Button('Del') // 纯文本
201
+ Button('Copy')
202
+ Button('Back')
203
+ ```
204
+
205
+ ---
206
+
207
+ ## 快速检查清单
208
+
209
+ 遇到 ArkTS 编译错误时,按序检查:
210
+
211
+ 1. throw → `throw new Error(String(x))`
212
+ 2. 对象字面量作为参数 → 先赋值给显式类型变量
213
+ 3. any / unknown → `Object` + `as Function` / `as SomeType`
214
+ 4. // @ts-ignore → 禁止,必须用类型操作替代
215
+ 5. ValuesBucket → 普通对象字面量 `{}`
216
+ 6. margin { vertical } → `{ top, bottom }`
217
+ 7. List 内 Divider → ListItem + border
218
+ 8. TextDecoder → Uint8Array 遍历
219
+ 9. `new SomeType()` 报错 → 检查是否是 type alias 而非 class
@@ -0,0 +1,157 @@
1
+ # Known Compile Error Patterns
2
+
3
+ > **This file is auto-maintained by `a2h-retrospect`.**
4
+ > Manual edits are allowed but may be overwritten when retrospect detects updated patterns.
5
+ > Last updated: 2026-03-27
6
+
7
+ ---
8
+
9
+ ## Pattern Index
10
+
11
+ | # | Error Code / Type | Frequency | Short Description |
12
+ |---|-------------------|-----------|-------------------|
13
+ | 1 | arkts-identifiers-as-prop-names | 85 | ValuesBucket computed property name |
14
+ | 2 | type mismatch (EventData) | 16 | EventData double type cast |
15
+ | 3 | arkts-no-untyped-obj-literals | 9 | Untyped object literal |
16
+ | 4 | type mismatch (promptAction) | 8 | promptAction button color type |
17
+ | 5 | type error (@Prop) | 3 | @Prop naming conflict |
18
+
19
+ ---
20
+
21
+ ## 1. ValuesBucket Computed Property Name
22
+
23
+ - **Date**: 2026-03-27
24
+ - **Error code**: `arkts-identifiers-as-prop-names`
25
+ - **Frequency**: 85 occurrences
26
+ - **Source**: AntennaPod V1 migration (a2h-retrospect-report-2026-03-27)
27
+
28
+ **Error code**:
29
+ ```typescript
30
+ const bucket: ValuesBucket = {
31
+ [ColumnName.TITLE]: title, // ERROR: computed property name not allowed
32
+ [ColumnName.URL]: url,
33
+ };
34
+ ```
35
+
36
+ **Correct code**:
37
+ ```typescript
38
+ const bucket: ValuesBucket = {};
39
+ bucket[ColumnName.TITLE] = title;
40
+ bucket[ColumnName.URL] = url;
41
+ ```
42
+
43
+ **Rule**: ArkTS forbids computed property names (`[expr]: value`) in object literals. Build the object first, then assign properties via bracket notation.
44
+
45
+ ---
46
+
47
+ ## 2. EventData Double Type Cast
48
+
49
+ - **Date**: 2026-03-27
50
+ - **Error code**: type mismatch
51
+ - **Frequency**: 16 occurrences
52
+ - **Source**: AntennaPod V1 migration (a2h-retrospect-report-2026-03-27)
53
+
54
+ **Error code**:
55
+ ```typescript
56
+ emitter.on({ eventId: 1 }, (data: emitter.EventData) => {
57
+ const value = data.data?.['key'] as string; // ERROR: data.data is optional Record, direct cast fails
58
+ });
59
+ ```
60
+
61
+ **Correct code**:
62
+ ```typescript
63
+ emitter.on({ eventId: 1 }, (data: emitter.EventData) => {
64
+ const raw = data.data as Record<string, Object>;
65
+ const value = raw['key'] as string;
66
+ });
67
+ ```
68
+
69
+ **Rule**: `EventData.data` is typed `Record<string, Object> | undefined`. Access requires two steps: (1) cast to `Record<string, Object>`, (2) cast the extracted value to the target type.
70
+
71
+ ---
72
+
73
+ ## 3. Untyped Object Literal
74
+
75
+ - **Date**: 2026-03-27
76
+ - **Error code**: `arkts-no-untyped-obj-literals`
77
+ - **Frequency**: 9 occurrences
78
+ - **Source**: AntennaPod V1 migration (a2h-retrospect-report-2026-03-27)
79
+
80
+ **Error code**:
81
+ ```typescript
82
+ const options = {
83
+ title: 'Hello',
84
+ message: 'World',
85
+ }; // ERROR: object literal without explicit type annotation
86
+ ```
87
+
88
+ **Correct code**:
89
+ ```typescript
90
+ interface DialogOptions {
91
+ title: string;
92
+ message: string;
93
+ }
94
+ const options: DialogOptions = {
95
+ title: 'Hello',
96
+ message: 'World',
97
+ };
98
+ ```
99
+
100
+ **Rule**: ArkTS requires all object literals to have an explicit type. Define an `interface` or `class` and annotate the variable.
101
+
102
+ ---
103
+
104
+ ## 4. promptAction Button Color Type
105
+
106
+ - **Date**: 2026-03-27
107
+ - **Error code**: type mismatch
108
+ - **Frequency**: 8 occurrences
109
+ - **Source**: AntennaPod V1 migration (a2h-retrospect-report-2026-03-27)
110
+
111
+ **Error code**:
112
+ ```typescript
113
+ promptAction.showDialog({
114
+ buttons: [
115
+ { text: 'OK', color: '#ff0000' } // ERROR: color expects ResourceColor, not string
116
+ ]
117
+ });
118
+ ```
119
+
120
+ **Correct code**:
121
+ ```typescript
122
+ promptAction.showDialog({
123
+ buttons: [
124
+ { text: 'OK', color: Color.Red }
125
+ ]
126
+ });
127
+ // Or use $r('app.color.xxx') for resource reference
128
+ ```
129
+
130
+ **Rule**: `promptAction.showDialog` button `color` property expects `ResourceColor` type (Color enum or `$r()` resource reference), not a raw hex string.
131
+
132
+ ---
133
+
134
+ ## 5. @Prop Naming Conflict
135
+
136
+ - **Date**: 2026-03-27
137
+ - **Error code**: type error
138
+ - **Frequency**: 3 occurrences
139
+ - **Source**: AntennaPod V1 migration (a2h-retrospect-report-2026-03-27)
140
+
141
+ **Error code**:
142
+ ```typescript
143
+ @Component
144
+ struct MyComponent {
145
+ @Prop title: string = ''; // ERROR: 'title' conflicts with built-in component property
146
+ }
147
+ ```
148
+
149
+ **Correct code**:
150
+ ```typescript
151
+ @Component
152
+ struct MyComponent {
153
+ @Prop itemTitle: string = ''; // Renamed to avoid conflict
154
+ }
155
+ ```
156
+
157
+ **Rule**: Certain property names (`title`, `content`, `action`, etc.) conflict with built-in component attributes. Prefix with a domain-specific qualifier (e.g., `itemTitle`, `feedTitle`).
@@ -0,0 +1,131 @@
1
+ # RDB Entity 确定性修复 Pattern
2
+ # 适用于: ArkTS 严格模式 + @kit.ArkData relationalStore
3
+ # 触发场景: 迁移 Android RDB 实体类到 ArkTS 时
4
+ # 经验来源: EinkBro 迁移 (2026-03-26)
5
+
6
+ ---
7
+
8
+ ## Pattern 1: ValuesBucket 正确用法
9
+
10
+ ### 错误写法 (编译报错)
11
+ ```typescript
12
+ import { relationalStore, ValuesBucket } from '@kit.ArkData';
13
+
14
+ toValuesBucket(): ValuesBucket {
15
+ const bucket = new ValuesBucket(); // ERROR: 'ValuesBucket' only refers to a type
16
+ bucket.put('key', value); // ERROR: ValuesBucket has no .put() method
17
+ return bucket;
18
+ }
19
+ ```
20
+
21
+ ### 正确写法
22
+ ```typescript
23
+ type EntityValuesBucket = Record<string, number | string | boolean | Uint8Array | null>;
24
+
25
+ toValuesBucket(): EntityValuesBucket {
26
+ const bucket: EntityValuesBucket = {};
27
+ bucket['key'] = value;
28
+ return bucket;
29
+ }
30
+ ```
31
+
32
+ **原因**: `ValuesBucket` 在 SDK 中是 type alias (`Record<string, ValueType>`),不是可实例化的类。
33
+
34
+ ---
35
+
36
+ ## Pattern 2: fromResultSet 参数类型 (禁止 any)
37
+
38
+ ### 错误写法 (编译报错)
39
+ ```typescript
40
+ // ArkTS 严格模式禁止 any
41
+ static fromResultSet(resultSet: any): EntityName { // ERROR: arkts-no-any-unknown
42
+ ```
43
+
44
+ ### 正确写法
45
+ ```typescript
46
+ static fromResultSet(resultSet: Object): EntityName {
47
+ const rs = resultSet as Record<string, Object>;
48
+ const colIndex = (name: string): number =>
49
+ (rs['getColumnIndex'] as Function)(name) as number;
50
+
51
+ entity.field = (rs['getLong'] as Function)(colIndex('field_name')) as number;
52
+ entity.name = (rs['getString'] as Function)(colIndex('name')) as string;
53
+ return entity;
54
+ }
55
+ ```
56
+
57
+ **替代方案** (更简洁但运行时开销略高):
58
+ ```typescript
59
+ // 使用类型断言避免 any,运行时通过 Record<string, Function> 调用
60
+ static fromResultSet(resultSet: Object): EntityName {
61
+ const getCol = (name: string): number =>
62
+ (resultSet as Record<string, Function>)['getColumnIndex'](name) as number;
63
+ const getLong = (name: string): number =>
64
+ (resultSet as Record<string, Function>)['getLong'](getCol(name)) as number;
65
+ const getStr = (name: string): string =>
66
+ (resultSet as Record<string, Function>)['getString'](getCol(name)) as string;
67
+
68
+ const entity = new EntityName();
69
+ entity.id = getLong('id');
70
+ entity.name = getStr('name');
71
+ return entity;
72
+ }
73
+ ```
74
+
75
+ ---
76
+
77
+ ## Pattern 3: // @ts-ignore 不可用
78
+
79
+ ### 错误尝试
80
+ ```typescript
81
+ // @ts-ignore // ERROR: Switching off type checks with in-place comments is not allowed
82
+ static fromResultSet(resultSet: any): EntityName {
83
+ ```
84
+
85
+ ### 必须用 Pattern 2 替代
86
+
87
+ ---
88
+
89
+ ## Pattern 4: toValuesBucket() 返回类型注解
90
+
91
+ ```typescript
92
+ type EntityValuesBucket = Record<string, number | string | boolean | Uint8Array | null>;
93
+
94
+ toValuesBucket(): EntityValuesBucket {
95
+ const bucket: EntityValuesBucket = {} as EntityValuesBucket;
96
+ // ...
97
+ return bucket;
98
+ }
99
+ ```
100
+
101
+ ---
102
+
103
+ ## 完整 Entity 模板
104
+
105
+ ```typescript
106
+ type EntityValuesBucket = Record<string, number | string | boolean | Uint8Array | null>;
107
+
108
+ export class MyEntity {
109
+ id: number = 0;
110
+ name: string = '';
111
+ value: number = 0;
112
+
113
+ static fromResultSet(resultSet: Object): MyEntity {
114
+ const rs = resultSet as Record<string, Object>;
115
+ const col = (n: string): number => (rs['getColumnIndex'] as Function)(n) as number;
116
+ const entity = new MyEntity();
117
+ entity.id = (rs['getLong'] as Function)(col('id')) as number;
118
+ entity.name = (rs['getString'] as Function)(col('name')) as string;
119
+ entity.value = (rs['getLong'] as Function)(col('value')) as number;
120
+ return entity;
121
+ }
122
+
123
+ toValuesBucket(): EntityValuesBucket {
124
+ const bucket: EntityValuesBucket = {} as EntityValuesBucket;
125
+ if (this.id > 0) { bucket['id'] = this.id; }
126
+ bucket['name'] = this.name;
127
+ bucket['value'] = this.value;
128
+ return bucket;
129
+ }
130
+ }
131
+ ```
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: hmos-ui-align
2
+ name: hmos-incremental-ui-align
3
3
  description: "Automated HarmonyOS-Android UI alignment pipeline. Takes a natural language task description, automatically navigates to the target pages on both Android and HarmonyOS devices, captures view trees and screenshots, then aligns HarmonyOS code to match Android. Use this skill whenever the user wants to align a HarmonyOS page with its Android counterpart, fix visual differences between Android and HarmonyOS, add missing HarmonyOS pages based on Android, or describes a page path like '首页-设置-关于' that needs UI alignment. Also trigger on phrases like 'UI对齐', '页面对齐', '和安卓对齐', '鸿蒙页面修复','UI增量开发','align HarmonyOS with Android', or any request involving comparing and fixing HarmonyOS UI to match Android."
4
4
  ---
5
5
 
@@ -17,21 +17,25 @@ You are writing ArkTS codes.
17
17
  - 不要做和用户需求无关的其他修改
18
18
  -
19
19
  ## Step 0: Load Config
20
- Read `config.json` from this skill's directory. The config provides all fixed paths so the user only describes what needs to be aligned.
21
- Key config fields:
22
- - `android.app_name`, `android.package` — Android app info for navigation
23
- - `android.project_dir` — Android source code root
24
- - `harmony.app_name`, `harmony.package` HarmonyOS app info for navigation
25
- - `harmony.project_dir` — HarmonyOS project root
26
- - `hmos_sdk_dir` HarmonyOS SDK path for API reference
27
- - `glm_api_key` Zhipu GLM API key for phone-agent
28
- - `capture_output_dir` base directory for captured page data
29
- - `navigation_tool` = `scripts/app_feature_verify.py`
30
- - `capture_tool` = `scripts/page_capture.py`
20
+ The user MUST provide a `config-path` when invoking this skill (e.g., `config-path: D:\path\to\config.json`). The config file must exist before running — verify with a Read, and if it's missing or unreadable, ask the user for a valid path. Refer to `config-example.json` in this skill's directory for the expected schema.
21
+
22
+ Config fields:
23
+
24
+ | Field | Description |
25
+ |---|---|
26
+ | `android.app_name` | Android app name for navigation |
27
+ | `android.package` | Android app package name |
28
+ | `android.project_dir` | Android source code root path |
29
+ | `harmony.app_name` | HarmonyOS app name for navigation |
30
+ | `harmony.package` | HarmonyOS app package name |
31
+ | `harmony.project_dir` | HarmonyOS project root path |
32
+ | `hmos_sdk_dir` | HarmonyOS SDK path (ETS API reference) |
33
+ | `glm_api_key` | Zhipu GLM API key for phone-agent |
34
+ | `capture_output_dir` | Base directory for captured page data |
31
35
 
32
36
  ## Step 1: Capture All Related Pages on Android & HarmonyOS Devices
33
37
 
34
- Read `scripts/navigation-capure.md` to learn the usage of `navigation_tool` and `capture_tool`.
38
+ Read `scripts/navigation-capure.md` to learn the usage of `scripts/app_feature_verify.py` (navigation) and `scripts/page_capture.py` (capture).
35
39
 
36
40
  ### Step 1.1: Parse User Request and Build Capture Plan
37
41
  Analyze the user's description and build a list of **base pages** to capture.
@@ -46,8 +50,8 @@ Create the timestamped output directory and per-page sub-directories following t
46
50
 
47
51
  ### Step 1.2: Capture Base Pages
48
52
  For each base page in the plan, on **both** Android and HarmonyOS devices:
49
- 1. Use `navigation_tool` to navigate to the page.
50
- 2. On success, use `capture_tool` to capture the view tree and screenshot.
53
+ 1. Use `scripts/app_feature_verify.py` to navigate to the page.
54
+ 2. On success, use `scripts/page_capture.py` to capture the view tree and screenshot.
51
55
  3. For HarmonyOS pages that don't exist yet, navigation will fail — leave the directory empty (expected).
52
56
 
53
57
  ### Step 1.3: Discover and Capture Interactive States
@@ -59,7 +63,7 @@ After capturing each base page, scan its view tree for **interactive elements th
59
63
 
60
64
  **For each interactive element found:**
61
65
  1. Create a separate capture directory: `{platform}_page_{i}_{base_name}_{state_type}_{state_name}` (e.g., `android_page_1_detail_tab_city`, `android_page_1_detail_popup_filter_identity`).
62
- 2. Navigate to the base page (reuse the same nav path), then append the click action to trigger the state change. Capture with `capture_tool`.
66
+ 2. Navigate to the base page (reuse the same nav path), then append the click action to trigger the state change. Capture with `scripts/page_capture.py`.
63
67
  3. Repeat for **both** Android and HarmonyOS devices.
64
68
  4. Each captured state is treated as a separate page pair in Step 2 and Step 3.
65
69
 
@@ -45,7 +45,7 @@ HarmonyOS-Android UI 自动对齐流水线。
45
45
 
46
46
  ## 配置 `config.json`
47
47
 
48
- 首次使用前必须改 `Agents/hmos-ui-align/config.json`。字段说明:
48
+ 首次使用前,自行准备一份 `config.json`(放任何位置都可以),调用 skill 时把它的**绝对路径**作为参数传给 skill。可复制同目录下的 `config-example.json` 作为模板。字段说明:
49
49
 
50
50
  | 字段 | 说明 | 示例 |
51
51
  |---|---|---|
@@ -65,10 +65,10 @@ HarmonyOS-Android UI 自动对齐流水线。
65
65
 
66
66
  ## 使用方式
67
67
 
68
- 在 Claude Code 里直接调用 skill
68
+ 在 Claude Code 里直接调用 skill,**必须把准备好的 `config.json` 的绝对路径附在需求里**:
69
69
 
70
70
  ```
71
- /hmos-ui-align <自然语言需求,描述要对齐的页面+点击路径>
71
+ /hmos-ui-align config: <绝对路径/config.json> <自然语言需求,描述要对齐的页面+点击路径>
72
72
  ```
73
73
 
74
74
  ### 写需求的三个要点
@@ -112,7 +112,7 @@ HarmonyOS-Android UI 自动对齐流水线。
112
112
  skill 会严格按 `SKILL.md` 里的 5 步流水线跑:
113
113
 
114
114
  ### Step 0 · 加载 config
115
- `config.json`,解析出所有路径和 API Key。
115
+ 读用户指定路径下的 `config.json`,解析出所有路径和 API Key。
116
116
 
117
117
  ### Step 1 · 双端页面采集
118
118
  1.1 解析你的需求,拆成一组「基础页」,每个基础页有 `android_nav_path` 和 `hmos_nav_path`
@@ -161,8 +161,7 @@ skill 会严格按 `SKILL.md` 里的 5 步流水线跑:
161
161
  Agents/hmos-ui-align/
162
162
  ├── SKILL.md # 流水线定义(主 agent 执行逻辑)
163
163
  ├── readme.md # 本文档
164
- ├── config.json # 用户配置
165
- ├── config-example.json # 配置样例
164
+ ├── config-example.json # 配置样例(实际使用的 config.json 由用户自备并显式传路径)
166
165
  ├── page_align.md # Step 3 的转换规则
167
166
  ├── diff_analysis.md # 内部说明
168
167
  ├── scripts/
@@ -2524,11 +2524,9 @@ Column() {
2524
2524
 
2525
2525
  ## 参考链接
2526
2526
 
2527
- 1. **Android UI 组件全量清单**: `/docs/android-ui-components-full-list.md`
2528
- 2. **HarmonyOS ArkUI 组件全量清单**: `/docs/harmonyos-arkui-components-full-list.md`
2529
- 3. **HarmonyOS 开发者文档**: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/
2530
- 4. **Android UI 组件总览**: https://developer.android.com/develop/ui
2531
- 5. **Material Design 3 规范**: https://m3.material.io/components
2527
+ 1. **HarmonyOS 开发者文档**: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/
2528
+ 2. **Android UI 组件总览**: https://developer.android.com/develop/ui
2529
+ 3. **Material Design 3 规范**: https://m3.material.io/components
2532
2530
 
2533
2531
  ---
2534
2532
 
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: self-test
2
+ name: hmos-integration-test
3
3
  description: "Run on-device self-test for a HarmonyOS app. Parse test_case.md, install the HAP, execute AutoTest, and produce a verification report. Optionally enters a test-and-fix loop. Triggers on phrases like '跑自测', '运行自测', '执行自测', '自动测试', '设备测试', '跑用例', '跑自动化测试', 'self test', 'run autotest'."
4
4
  allowed-tools:
5
5
  - Read
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: spec-generator-skill
2
+ name: hmos-spec-generate
3
3
  description: "Generate atomic-scenario requirement specs (markdown) from raw .txt requirement batches for Android-to-HarmonyOS migration. Reads a single .txt holding multiple REQ blocks (blank-line separated), explores the Android code graph via GitNexus, writes per-REQ trace files first then synthesizes specs from the trace. Triggers: spec generation, generate spec, requirement to spec, atomic scenarios, scenario decomposition, decompose scenarios, req to spec, code-trace-first, batch req txt."
4
4
  license: MIT
5
5
  allowed-tools: