@buaa_smat/hometrans 0.1.4 → 0.1.6

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 (80) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +17 -18
  3. package/agents/build-fixer.md +6 -5
  4. package/agents/{logic-coding.md → logic-coder.md} +2 -2
  5. package/agents/logic-context-builder.md +1 -1
  6. package/agents/self-tester.md +19 -8
  7. package/package.json +1 -1
  8. package/skills/{hmos-ui-align-batch → hmos-batch-ui-align}/SKILL.md +3 -3
  9. package/skills/{hmos-ui-align-batch → hmos-batch-ui-align}/references/conversion-procedure.md +2 -2
  10. package/skills/{hmos-ui-align-batch → hmos-batch-ui-align}/references/mappings/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +3 -5
  11. package/skills/{convert_pipeline → hmos-convert-pipeline}/SKILL.md +4 -4
  12. package/skills/hmos-fix-build-errors/SKILL.md +265 -0
  13. package/skills/hmos-fix-build-errors/references/arkts-strict-patterns.md +219 -0
  14. package/skills/hmos-fix-build-errors/references/known-patterns.md +157 -0
  15. package/skills/hmos-fix-build-errors/references/rdb-entity-pattern.md +131 -0
  16. package/skills/{hmos-ui-align → hmos-incremental-ui-align}/SKILL.md +4 -2
  17. package/skills/{hmos-ui-align → hmos-incremental-ui-align}/readme.md +5 -6
  18. package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +3 -5
  19. package/skills/{self-test → hmos-integration-test}/SKILL.md +1 -1
  20. package/skills/{self-test → hmos-integration-test}/readme.md +3 -3
  21. package/skills/{spec-generator-skill → hmos-spec-generate}/SKILL.md +1 -1
  22. package/agents/code-review-fix.md +0 -356
  23. package/dist/cli/config-store.js +0 -143
  24. package/dist/cli/config.js +0 -40
  25. package/dist/cli/index.js +0 -43
  26. package/dist/cli/init.js +0 -366
  27. package/dist/cli/mcp-setup.js +0 -262
  28. package/dist/cli/mcp.js +0 -94
  29. package/dist/cli/uninstall.js +0 -310
  30. package/dist/context/index.js +0 -788
  31. package/skills/code-dev-review-fix/SKILL.md +0 -279
  32. package/skills/code-dev-review-fix-workspace/evals/evals.json +0 -56
  33. package/skills/code-dev-review-fix-workspace/iteration-1/routing-results.md +0 -23
  34. package/skills/hmos-ui-align/config.json +0 -11
  35. /package/agents/{logic-coding → logic-coder}/scripts/platform_context_query.py +0 -0
  36. /package/skills/{hmos-ui-align-batch → hmos-batch-ui-align}/references/mappings/android-to-harmonyOS-ui-interaction-mapping-reference.md +0 -0
  37. /package/skills/{hmos-ui-align-batch → hmos-batch-ui-align}/references/mappings/android-to-harmonyOS-ui-layout-mapping-reference.md +0 -0
  38. /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
  39. /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
  40. /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
  41. /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
  42. /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
  43. /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
  44. /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
  45. /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
  46. /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
  47. /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
  48. /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
  49. /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
  50. /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
  51. /package/skills/{hmos-ui-align-batch → hmos-batch-ui-align}/scripts/android_parse_fast.py +0 -0
  52. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/config-example.json +0 -0
  53. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/diff_analysis.md +0 -0
  54. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/page_align.md +0 -0
  55. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/Comparison_Template.md +0 -0
  56. /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
  57. /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
  58. /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
  59. /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
  60. /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
  61. /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
  62. /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
  63. /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
  64. /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
  65. /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
  66. /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
  67. /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
  68. /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
  69. /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
  70. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/UI_Analysis_Template.md +0 -0
  71. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/android-to-harmonyOS-ui-interaction-mapping-reference.md +0 -0
  72. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/references/android-to-harmonyOS-ui-layout-mapping-reference.md +0 -0
  73. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/scripts/app_feature_verify.py +0 -0
  74. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/scripts/navigation-capure.md +0 -0
  75. /package/skills/{hmos-ui-align → hmos-incremental-ui-align}/scripts/page_capture.py +0 -0
  76. /package/skills/{spec-generator-skill → hmos-spec-generate}/references/android-platform-tokens.md +0 -0
  77. /package/skills/{spec-generator-skill → hmos-spec-generate}/references/spec-sample-1.md +0 -0
  78. /package/skills/{spec-generator-skill → hmos-spec-generate}/references/spec-sample-2.md +0 -0
  79. /package/skills/{spec-generator-skill → hmos-spec-generate}/references/spec-sample-3.md +0 -0
  80. /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,7 +17,9 @@ 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.
20
+ The user MUST specify the path to a `config.json` file when invoking this skill (e.g., as part of the request: "config: D:\path\to\config.json"). Read that file from the user-provided path. If the user did not provide a path, ask them for it before proceeding. See `config-example.json` in this skill's directory for the expected schema.
21
+
22
+ The config provides all fixed paths so the user only describes what needs to be aligned.
21
23
  Key config fields:
22
24
  - `android.app_name`, `android.package` — Android app info for navigation
23
25
  - `android.project_dir` — Android source code root
@@ -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
@@ -159,7 +159,7 @@
159
159
  | 达到最大轮数 | `max_rounds_reached` | 已完成配置的最大轮数循环(`max-rounds`,默认 3),仍有失败未解决 |
160
160
  | 编译未产出 HAP(异常) | `no_signed_hap` | build-fixer 未产出签名 HAP,无法继续测试 |
161
161
  | 用例列表为空(异常) | `no_testcases` | `testcases.json` 里 0 条用例,没有可跑的内容。常见原因:解析阶段没识别到 `### Scenario:` 区块 |
162
- | 自测 agent 早退(异常) | `agent_early_exit` | `self-tester` 在跑用例之前就退出了(设备没连、`config.yaml` 没填、`agents/test-tools/autotest` 目录找不到、batch 启动失败 / 超时 / 崩溃、`setup=false` 但所需 JSON 缺失等)。报告首行会是 `status: FAIL`,第二行 `reason: <原因>`。**这种情况下不会进入 fix 循环**——这些是环境/前置条件问题,不是应用缺陷 |
162
+ | 自测 agent 早退(异常) | `agent_early_exit` | `self-tester` 在跑用例之前就退出了(设备没连、`config.yaml` 没填、`test-tools/autotest` 目录找不到(`env.TOOL_PATH` 未配置或失效)、batch 启动失败 / 超时 / 崩溃、`setup=false` 但所需 JSON 缺失等)。报告首行会是 `status: FAIL`,第二行 `reason: <原因>`。**这种情况下不会进入 fix 循环**——这些是环境/前置条件问题,不是应用缺陷 |
163
163
 
164
164
  ---
165
165
 
@@ -242,7 +242,7 @@ build-fixer 的输出摘要:编译状态、签名类型、迭代次数、修
242
242
  - 操作系统:**Windows** 是主要测试目标;macOS/Linux 上的核心命令(`hdc`、`uv`、POSIX 工具链)也能跑,Skill 里涉及到的复制操作会按可用 shell 自适应
243
243
  - `hdc` 已安装并在 PATH 中
244
244
  - `uv` 已安装(Python 包管理)
245
- - `agents/test-tools/autotest/config.yaml` 已配置真实 api_key
245
+ - `<TOOL_PATH>/test-tools/autotest/config.yaml` 已配置真实 api_key(`TOOL_PATH` 取自 `~/.hometrans/config.json` 的 `env.TOOL_PATH`,默认即 `~/.hometrans/tools`;`ht init` 填好 `TEST_API_KEY` 后会自动写入)
246
246
  - 鸿蒙真机通过 USB 连接,`hdc list targets` 能看到设备
247
247
  - 签名后的 `.hap` 文件
248
248
 
@@ -262,7 +262,7 @@ A: 检查 USB 连接,跑 `hdc list targets` 看看有没有设备 SN。重新
262
262
 
263
263
  **Q: 报 config.yaml missing 或 api_key 没填?**
264
264
 
265
- A: 复制 `agents/test-tools/autotest/config.yaml.example` 为 `config.yaml`,把 `YOUR_API_KEY_HERE` 替换成真实的 API Key
265
+ A: AutoTest 目录 `<TOOL_PATH>/test-tools/autotest`(`TOOL_PATH` 取自 `~/.hometrans/config.json` 的 `env.TOOL_PATH`,默认 `~/.hometrans/tools`)下,复制 `config.yaml.example` 为 `config.yaml`,把 `YOUR_API_KEY_HERE` 替换成真实的 API Key。或者重新跑 `ht init` 并填入 `TEST_API_KEY`,它会自动生成。
266
266
 
267
267
  **Q: 前置用例失败了要不要修代码?**
268
268
 
@@ -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: