@buaa_smat/hometrans 0.1.13 → 0.1.15
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.
- package/README.md +194 -136
- package/agents/build-fixer.md +38 -48
- package/agents/code-reviewer.md +20 -20
- package/agents/logic-coder.md +8 -8
- package/agents/logic-context-builder.md +5 -5
- package/agents/review-fixer.md +16 -16
- package/agents/self-test-fixer.md +15 -15
- package/agents/self-tester.md +56 -55
- package/agents/spec-generator.md +16 -16
- package/dist/cli/config-store.js +120 -9
- package/dist/cli/config.js +4 -4
- package/dist/cli/env-vars.js +129 -0
- package/dist/cli/init.js +315 -276
- package/dist/cli/uninstall.js +152 -17
- package/dist/context/index.js +10 -197
- package/env-requirements.json +181 -181
- package/package.json +1 -1
- package/resource/choose_editor.png +0 -0
- package/resource/common_config.png +0 -0
- package/resource/integration_test_config.png +0 -0
- package/resource/migration_process.svg +94 -0
- package/resource/migration_process_transparent.svg +93 -0
- package/resource/set_env.png +0 -0
- package/resource/ui_align_config.png +0 -0
- package/skills/hmos-batch-ui-align/SKILL.md +10 -0
- package/skills/hmos-batch-ui-align/references/conversion-procedure.md +180 -180
- package/skills/hmos-batch-ui-align/references/mappings/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2533 -2533
- package/skills/hmos-batch-ui-align/references/mappings/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -555
- package/skills/hmos-batch-ui-align/references/mappings/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -117
- 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 -648
- 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 +2088 -2088
- 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 -1033
- 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 -1183
- 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 -576
- 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 -297
- 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 -395
- 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 +902 -902
- 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 -106
- 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 -1178
- package/skills/hmos-batch-ui-align/references/mvvm/MVVM/346/250/241/345/274/217/357/274/210V1/357/274/211.md +911 -911
- 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 +354 -354
- 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 -11
- package/skills/hmos-convert-pipeline/SKILL.md +63 -49
- package/skills/hmos-fix-build-errors/SKILL.md +5 -6
- package/skills/hmos-fix-build-errors/references/arkts-strict-patterns.md +219 -219
- package/skills/hmos-fix-build-errors/references/known-patterns.md +157 -157
- package/skills/hmos-fix-build-errors/references/rdb-entity-pattern.md +131 -131
- package/skills/hmos-incremental-ui-align/{readme.md → README.md} +28 -21
- package/skills/hmos-incremental-ui-align/SKILL.md +46 -27
- package/skills/hmos-incremental-ui-align/diff_analysis.md +52 -52
- package/skills/hmos-incremental-ui-align/page_align.md +62 -62
- package/skills/hmos-incremental-ui-align/references/Comparison_Template.md +2 -2
- package/skills/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 +648 -648
- package/skills/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 +2088 -2088
- package/skills/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 +1033 -1033
- package/skills/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 +1183 -1183
- package/skills/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 +576 -576
- package/skills/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 +297 -297
- package/skills/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 +395 -395
- package/skills/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 +902 -902
- package/skills/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 +106 -106
- package/skills/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 +1178 -1178
- package/skills/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 +911 -911
- package/skills/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 +354 -354
- package/skills/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 +11 -11
- package/skills/hmos-incremental-ui-align/references/UI_Analysis_Template.md +3 -3
- package/skills/hmos-incremental-ui-align/references/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2533 -2533
- package/skills/hmos-incremental-ui-align/references/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -555
- package/skills/hmos-incremental-ui-align/references/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -117
- package/skills/hmos-incremental-ui-align/scripts/navigation-capure.md +37 -37
- package/skills/hmos-integration-test/{readme.md → README.md} +38 -38
- package/skills/hmos-integration-test/SKILL.md +63 -52
- package/skills/hmos-resources-convert/SKILL.md +5 -5
- package/skills/hmos-resources-convert/references/conversion-rules.md +663 -663
- package/skills/hmos-resources-convert/references/dependency-analysis-rules.md +388 -388
- package/skills/hmos-resources-convert/references/resource-mapping-rules.md +457 -457
- package/skills/hmos-resources-convert/references/xml-drawable-to-svg-rules.md +513 -513
- package/skills/hmos-spec-generate/SKILL.md +19 -19
- package/skills/hmos-spec-generate/references/android-platform-tokens.md +105 -105
- package/skills/hmos-spec-generate/references/spec-sample-1.md +78 -78
- package/skills/hmos-spec-generate/references/spec-sample-2.md +58 -58
- package/skills/hmos-spec-generate/references/spec-sample-3.md +116 -116
- package/skills/hmos-spec-generate/references/step4-report-template.md +33 -33
- package/tools/test-tools/autotest/README.md +33 -17
- package/tools/test-tools/autotest/self_test_runner.py +109 -15
- package/resource/hometrans_config.png +0 -0
- package/skills/hmos-incremental-ui-align/config-example.json +0 -11
- package/tools/test-tools/autotest/config.yaml.example +0 -58
|
@@ -1,157 +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`).
|
|
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`).
|
|
@@ -1,131 +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
|
+
# 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
|
+
```
|
|
@@ -36,39 +36,47 @@ HarmonyOS-Android UI 自动对齐流水线。
|
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
3. **智谱 GLM API Key**(phone-agent 调用的模型)
|
|
39
|
-
到 https://open.bigmodel.cn/
|
|
39
|
+
到 https://open.bigmodel.cn/ 申请,有免费额度。设为 OS 环境变量 `GLM_API_KEY`(`ht init` 可帮你写入机器环境变量)。
|
|
40
40
|
|
|
41
41
|
4. **鸿蒙 SDK 路径**(给改码阶段查 API 用)
|
|
42
|
-
|
|
42
|
+
取自 OS 环境变量 `OHOS_SDK_PATH` / `HMS_SDK_PATH`(为空时由 `DEVECO_SDK_HOME` 派生),由 `ht init` 写入机器环境变量;例如 DevEco Studio 自带的 `E:\DevEco Studio\sdk\default\openharmony\ets`。
|
|
43
43
|
|
|
44
44
|
---
|
|
45
45
|
|
|
46
|
-
##
|
|
46
|
+
## 入参与配置
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
本 skill 需要两类信息:
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|---|---|---|
|
|
52
|
-
| `android.app_name` | 安卓端 App 显示名(桌面上看到的名字,phone-agent 打开 app 时用) | `"Salt Player"` |
|
|
53
|
-
| `android.package` | 安卓包名 | `"com.salt.music"` |
|
|
54
|
-
| `android.project_dir` | 安卓源码根目录 | `"E:\\SaltPlayerAndroid-main\\SuvineMusicX"` |
|
|
55
|
-
| `harmony.app_name` | 鸿蒙端 App 显示名 | `"Salt Player"` |
|
|
56
|
-
| `harmony.package` | 鸿蒙包名 | `"com.xuncorp.sp2"` |
|
|
57
|
-
| `harmony.project_dir` | 鸿蒙工程根目录(会被直接修改) | `"E:\\SPH"` |
|
|
58
|
-
| `hmos_sdk_dir` | 鸿蒙 SDK 路径 | `"E:\\DevEco Studio\\sdk\\default"` |
|
|
59
|
-
| `glm_api_key` | 智谱 GLM API Key | `"xxx.yyy"` |
|
|
60
|
-
| `capture_output_dir` | 采集产物输出目录(截图/view tree/分析报告都在这) | `"./tmp_saltplayer"` |
|
|
50
|
+
**① 调用时传入的入参**(每次按需提供):
|
|
61
51
|
|
|
62
|
-
|
|
52
|
+
| 入参 | 必填 | 说明 |
|
|
53
|
+
|---|---|--------------------------------------------------------------------|
|
|
54
|
+
| `android_project_dir` | 是 | 安卓源码根目录 |
|
|
55
|
+
| `harmony_project_dir` | 是 | 鸿蒙工程根目录(会被直接修改) |
|
|
56
|
+
| `capture_output_dir` | 否 | 采集产物输出目录(截图/view tree/分析报告)。默认 `<harmony_project_dir>/.hometrans/capture_output` |
|
|
57
|
+
|
|
58
|
+
**② 从 OS 环境变量直接读取的全局配置**(由 `ht init` 写入机器环境变量,无需每次传):
|
|
59
|
+
|
|
60
|
+
- GLM key ← 环境变量 `GLM_API_KEY`
|
|
61
|
+
- 鸿蒙 SDK ETS API 目录 ← 环境变量 `OHOS_SDK_PATH` / `HMS_SDK_PATH`(为空时由 `DEVECO_SDK_HOME` 派生为 `<DEVECO_SDK_HOME>/default/openharmony/ets`、`.../hms/ets`)
|
|
62
|
+
|
|
63
|
+
> **Step 0.0** 会在执行前检查这些环境变量是否存在;缺失时会要求用户输入。
|
|
64
|
+
|
|
65
|
+
> 安卓/鸿蒙两端的 **App 显示名**(`android.app_name` / `harmony.app_name`)和 **包名**(`android.package` / `harmony.package`)也无需提供——skill 的 **Step 0.1** 会按 `android_project_dir` / `harmony_project_dir` 自动解析:
|
|
66
|
+
> - 安卓包名取自 app 模块 `build.gradle(.kts)` 的 `applicationId`(兜底 `AndroidManifest.xml` 的 `package`);App 名取自启动 Activity / `<application>` 的 `android:label`(`@string/xxx` 会去 `res/values*/strings.xml` 解析,优先中文)。
|
|
67
|
+
> - 鸿蒙包名取自 `AppScope/app.json5` 的 `bundleName`;App 名取自 `app.json5` 的 `label`(`$string:xxx` 会去 `AppScope/resources/**/element/string.json` 解析,优先中文)。
|
|
68
|
+
>
|
|
69
|
+
> 若某项无法从工程目录解析,skill 会回到询问用户。
|
|
63
70
|
|
|
64
71
|
---
|
|
65
72
|
|
|
66
73
|
## 使用方式
|
|
67
74
|
|
|
68
|
-
在 Claude Code 里直接调用 skill
|
|
75
|
+
在 Claude Code 里直接调用 skill,**把两个工程目录附在需求里**(可作为命名参数,也可在自然语言里说明):
|
|
69
76
|
|
|
70
77
|
```
|
|
71
|
-
/hmos-ui-align
|
|
78
|
+
/hmos-ui-align android_project_dir: <安卓工程绝对路径> harmony_project_dir: <鸿蒙工程绝对路径>
|
|
79
|
+
<自然语言需求,描述要对齐的页面+点击路径>
|
|
72
80
|
```
|
|
73
81
|
|
|
74
82
|
### 写需求的三个要点
|
|
@@ -111,8 +119,8 @@ HarmonyOS-Android UI 自动对齐流水线。
|
|
|
111
119
|
|
|
112
120
|
skill 会严格按 `SKILL.md` 里的 5 步流水线跑:
|
|
113
121
|
|
|
114
|
-
### Step 0 ·
|
|
115
|
-
|
|
122
|
+
### Step 0 · 解析入参
|
|
123
|
+
读取调用入参 `android_project_dir` / `harmony_project_dir` / `capture_output_dir`,并从 OS 环境变量直接读取 `GLM_API_KEY` 与 `OHOS_SDK_PATH` / `HMS_SDK_PATH`(**Step 0.0** 会先做存在性检查,缺失则要求用户输入)。随后 **Step 0.1** 按两个工程目录自动解析两端的 App 显示名与包名(无需手动配置)。
|
|
116
124
|
|
|
117
125
|
### Step 1 · 双端页面采集
|
|
118
126
|
1.1 解析你的需求,拆成一组「基础页」,每个基础页有 `android_nav_path` 和 `hmos_nav_path`
|
|
@@ -161,7 +169,6 @@ skill 会严格按 `SKILL.md` 里的 5 步流水线跑:
|
|
|
161
169
|
Agents/hmos-ui-align/
|
|
162
170
|
├── SKILL.md # 流水线定义(主 agent 执行逻辑)
|
|
163
171
|
├── readme.md # 本文档
|
|
164
|
-
├── config-example.json # 配置样例(实际使用的 config.json 由用户自备并显式传路径)
|
|
165
172
|
├── page_align.md # Step 3 的转换规则
|
|
166
173
|
├── diff_analysis.md # 内部说明
|
|
167
174
|
├── scripts/
|