@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.
Files changed (88) hide show
  1. package/README.md +194 -136
  2. package/agents/build-fixer.md +38 -48
  3. package/agents/code-reviewer.md +20 -20
  4. package/agents/logic-coder.md +8 -8
  5. package/agents/logic-context-builder.md +5 -5
  6. package/agents/review-fixer.md +16 -16
  7. package/agents/self-test-fixer.md +15 -15
  8. package/agents/self-tester.md +56 -55
  9. package/agents/spec-generator.md +16 -16
  10. package/dist/cli/config-store.js +120 -9
  11. package/dist/cli/config.js +4 -4
  12. package/dist/cli/env-vars.js +129 -0
  13. package/dist/cli/init.js +315 -276
  14. package/dist/cli/uninstall.js +152 -17
  15. package/dist/context/index.js +10 -197
  16. package/env-requirements.json +181 -181
  17. package/package.json +1 -1
  18. package/resource/choose_editor.png +0 -0
  19. package/resource/common_config.png +0 -0
  20. package/resource/integration_test_config.png +0 -0
  21. package/resource/migration_process.svg +94 -0
  22. package/resource/migration_process_transparent.svg +93 -0
  23. package/resource/set_env.png +0 -0
  24. package/resource/ui_align_config.png +0 -0
  25. package/skills/hmos-batch-ui-align/SKILL.md +10 -0
  26. package/skills/hmos-batch-ui-align/references/conversion-procedure.md +180 -180
  27. package/skills/hmos-batch-ui-align/references/mappings/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2533 -2533
  28. package/skills/hmos-batch-ui-align/references/mappings/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -555
  29. package/skills/hmos-batch-ui-align/references/mappings/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -117
  30. 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
  31. 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
  32. 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
  33. 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
  34. 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
  35. 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
  36. 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
  37. 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
  38. 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
  39. 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
  40. package/skills/hmos-batch-ui-align/references/mvvm/MVVM/346/250/241/345/274/217/357/274/210V1/357/274/211.md +911 -911
  41. 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
  42. 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
  43. package/skills/hmos-convert-pipeline/SKILL.md +63 -49
  44. package/skills/hmos-fix-build-errors/SKILL.md +5 -6
  45. package/skills/hmos-fix-build-errors/references/arkts-strict-patterns.md +219 -219
  46. package/skills/hmos-fix-build-errors/references/known-patterns.md +157 -157
  47. package/skills/hmos-fix-build-errors/references/rdb-entity-pattern.md +131 -131
  48. package/skills/hmos-incremental-ui-align/{readme.md → README.md} +28 -21
  49. package/skills/hmos-incremental-ui-align/SKILL.md +46 -27
  50. package/skills/hmos-incremental-ui-align/diff_analysis.md +52 -52
  51. package/skills/hmos-incremental-ui-align/page_align.md +62 -62
  52. package/skills/hmos-incremental-ui-align/references/Comparison_Template.md +2 -2
  53. 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
  54. 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
  55. 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
  56. 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
  57. 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
  58. 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
  59. 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
  60. 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
  61. 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
  62. 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
  63. 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
  64. 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
  65. 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
  66. package/skills/hmos-incremental-ui-align/references/UI_Analysis_Template.md +3 -3
  67. package/skills/hmos-incremental-ui-align/references/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2533 -2533
  68. package/skills/hmos-incremental-ui-align/references/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -555
  69. package/skills/hmos-incremental-ui-align/references/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -117
  70. package/skills/hmos-incremental-ui-align/scripts/navigation-capure.md +37 -37
  71. package/skills/hmos-integration-test/{readme.md → README.md} +38 -38
  72. package/skills/hmos-integration-test/SKILL.md +63 -52
  73. package/skills/hmos-resources-convert/SKILL.md +5 -5
  74. package/skills/hmos-resources-convert/references/conversion-rules.md +663 -663
  75. package/skills/hmos-resources-convert/references/dependency-analysis-rules.md +388 -388
  76. package/skills/hmos-resources-convert/references/resource-mapping-rules.md +457 -457
  77. package/skills/hmos-resources-convert/references/xml-drawable-to-svg-rules.md +513 -513
  78. package/skills/hmos-spec-generate/SKILL.md +19 -19
  79. package/skills/hmos-spec-generate/references/android-platform-tokens.md +105 -105
  80. package/skills/hmos-spec-generate/references/spec-sample-1.md +78 -78
  81. package/skills/hmos-spec-generate/references/spec-sample-2.md +58 -58
  82. package/skills/hmos-spec-generate/references/spec-sample-3.md +116 -116
  83. package/skills/hmos-spec-generate/references/step4-report-template.md +33 -33
  84. package/tools/test-tools/autotest/README.md +33 -17
  85. package/tools/test-tools/autotest/self_test_runner.py +109 -15
  86. package/resource/hometrans_config.png +0 -0
  87. package/skills/hmos-incremental-ui-align/config-example.json +0 -11
  88. 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/ 申请,有免费额度,填到 `config.json` 的 `glm_api_key`。
39
+ 到 https://open.bigmodel.cn/ 申请,有免费额度。设为 OS 环境变量 `GLM_API_KEY`(`ht init` 可帮你写入机器环境变量)。
40
40
 
41
41
  4. **鸿蒙 SDK 路径**(给改码阶段查 API 用)
42
- 例如 DevEco Studio 自带的 `E:\DevEco Studio\sdk\default`。
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
- ## 配置 `config.json`
46
+ ## 入参与配置
47
47
 
48
- 首次使用前,自行准备一份 `config.json`(放任何位置都可以),调用 skill 时把它的**绝对路径**作为参数传给 skill。可复制同目录下的 `config-example.json` 作为模板。字段说明:
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
- 可以直接参考同目录下的 `config-example.json`。
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,**必须把准备好的 `config.json` 的绝对路径附在需求里**:
75
+ 在 Claude Code 里直接调用 skill,**把两个工程目录附在需求里**(可作为命名参数,也可在自然语言里说明):
69
76
 
70
77
  ```
71
- /hmos-ui-align config: <绝对路径/config.json> <自然语言需求,描述要对齐的页面+点击路径>
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 · 加载 config
115
- 读用户指定路径下的 `config.json`,解析出所有路径和 API Key。
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/