@buaa_smat/hometrans 0.1.0 → 0.1.2
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 +141 -124
- package/agents/build-fixer.md +1 -0
- package/agents/code-review-fix.md +1 -0
- package/agents/code-reviewer.md +1 -0
- package/agents/logic-coding.md +1 -0
- package/agents/logic-context-builder.md +1 -0
- package/agents/review-fixer.md +1 -0
- package/agents/self-test-fixer.md +1 -0
- package/agents/self-tester.md +260 -233
- package/agents/spec-generator.md +1 -0
- package/agents/test-tools/autotest/README.md +223 -0
- package/agents/test-tools/autotest/config.yaml.example +58 -0
- package/agents/test-tools/autotest/pyproject.toml +16 -0
- package/agents/test-tools/autotest/report_tool.py +759 -0
- package/agents/test-tools/autotest/self_test_runner.py +773 -0
- package/agents/test-tools/autotest/testcases_schema.md +143 -0
- package/agents/test-tools/autotest/testcases_tool.py +215 -0
- package/agents/test-tools/autotest/uv.lock +3156 -0
- package/agents/test-tools/harmony_autotest-0.1.0-py3-none-any.whl +0 -0
- package/agents/test-tools/hypium-6.1.0.210-py3-none-any.whl +0 -0
- package/agents/test-tools/hypium_mcp-0.6.5-py3-none-any.whl +0 -0
- package/agents/test-tools/xdevice-6.1.0.210-py3-none-any.whl +0 -0
- package/agents/test-tools/xdevice_devicetest-6.1.0.210-py3-none-any.whl +0 -0
- package/agents/test-tools/xdevice_ohos-6.1.0.210-py3-none-any.whl +0 -0
- package/dist/cli/config-store.js +27 -2
- package/dist/cli/config.js +17 -6
- package/dist/cli/index.js +3 -2
- package/dist/cli/init.js +135 -22
- package/dist/cli/mcp.js +2 -2
- package/dist/context/index.js +165 -69
- package/package.json +59 -60
- package/skills/code-dev-review-fix/SKILL.md +279 -0
- package/skills/code-dev-review-fix-workspace/evals/evals.json +56 -0
- package/skills/code-dev-review-fix-workspace/iteration-1/routing-results.md +23 -0
- package/skills/convert_pipeline/SKILL.md +423 -439
- package/skills/hmos-resources-convert/SKILL.md +623 -0
- package/skills/hmos-resources-convert/evals/evals.json +171 -0
- package/skills/hmos-resources-convert/references/conversion-rules.md +663 -0
- package/skills/hmos-resources-convert/references/dependency-analysis-rules.md +388 -0
- package/skills/hmos-resources-convert/references/resource-mapping-rules.md +457 -0
- package/skills/hmos-resources-convert/references/xml-drawable-to-svg-rules.md +513 -0
- package/skills/hmos-resources-convert/template/AppScope/app.json5 +10 -0
- package/skills/hmos-resources-convert/template/AppScope/resources/base/element/string.json +8 -0
- package/skills/hmos-resources-convert/template/AppScope/resources/base/media/background.png +0 -0
- package/skills/hmos-resources-convert/template/AppScope/resources/base/media/foreground.png +0 -0
- package/skills/hmos-resources-convert/template/AppScope/resources/base/media/layered_image.json +7 -0
- package/skills/hmos-resources-convert/template/build-profile.json5 +42 -0
- package/skills/hmos-resources-convert/template/code-linter.json5 +32 -0
- package/skills/hmos-resources-convert/template/entry/build-profile.json5 +33 -0
- package/skills/hmos-resources-convert/template/entry/hvigorfile.ts +6 -0
- package/skills/hmos-resources-convert/template/entry/obfuscation-rules.txt +23 -0
- package/skills/hmos-resources-convert/template/entry/oh-package.json5 +10 -0
- package/skills/hmos-resources-convert/template/entry/src/main/ets/entryability/EntryAbility.ets +48 -0
- package/skills/hmos-resources-convert/template/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets +16 -0
- package/skills/hmos-resources-convert/template/entry/src/main/ets/pages/Index.ets +23 -0
- package/skills/hmos-resources-convert/template/entry/src/main/module.json5 +55 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/element/color.json +8 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/element/float.json +8 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/element/string.json +16 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/background.png +0 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/foreground.png +0 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/layered_image.json +7 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/startIcon.png +0 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/profile/backup_config.json +3 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/profile/main_pages.json +5 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/dark/element/color.json +8 -0
- package/skills/hmos-resources-convert/template/entry/src/mock/mock-config.json5 +2 -0
- package/skills/hmos-resources-convert/template/entry/src/ohosTest/ets/test/Ability.test.ets +35 -0
- package/skills/hmos-resources-convert/template/entry/src/ohosTest/ets/test/List.test.ets +5 -0
- package/skills/hmos-resources-convert/template/entry/src/ohosTest/module.json5 +16 -0
- package/skills/hmos-resources-convert/template/entry/src/test/List.test.ets +5 -0
- package/skills/hmos-resources-convert/template/entry/src/test/LocalUnit.test.ets +33 -0
- package/skills/hmos-resources-convert/template/hvigor/hvigor-config.json5 +23 -0
- package/skills/hmos-resources-convert/template/hvigorfile.ts +6 -0
- package/skills/hmos-resources-convert/template/oh-package-lock.json5 +28 -0
- package/skills/hmos-resources-convert/template/oh-package.json5 +10 -0
- package/skills/hmos-resources-convert/tools/apktool.bat +85 -0
- package/skills/hmos-resources-convert/tools/apktool_3.0.1.jar +0 -0
- package/skills/hmos-ui-align/SKILL.md +182 -0
- package/skills/hmos-ui-align/config-example.json +11 -0
- package/skills/hmos-ui-align/config.json +11 -0
- package/skills/hmos-ui-align/diff_analysis.md +53 -0
- package/skills/hmos-ui-align/page_align.md +62 -0
- package/skills/hmos-ui-align/readme.md +231 -0
- package/skills/hmos-ui-align/references/Comparison_Template.md +2 -0
- package/skills/hmos-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 -0
- package/skills/hmos-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 +2089 -0
- package/skills/hmos-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 -0
- package/skills/hmos-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 -0
- package/skills/hmos-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 -0
- package/skills/hmos-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 -0
- package/skills/hmos-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 -0
- package/skills/hmos-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 +903 -0
- package/skills/hmos-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 -0
- package/skills/hmos-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 -0
- package/skills/hmos-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 -0
- package/skills/hmos-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 +911 -0
- package/skills/hmos-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 +355 -0
- package/skills/hmos-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 -0
- package/skills/hmos-ui-align/references/UI_Analysis_Template.md +4 -0
- package/skills/hmos-ui-align/references/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2535 -0
- package/skills/hmos-ui-align/references/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -0
- package/skills/hmos-ui-align/references/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -0
- package/skills/hmos-ui-align/scripts/app_feature_verify.py +443 -0
- package/skills/hmos-ui-align/scripts/navigation-capure.md +37 -0
- package/skills/hmos-ui-align/scripts/page_capture.py +592 -0
- package/skills/hmos-ui-align-batch/SKILL.md +99 -0
- package/skills/hmos-ui-align-batch/references/conversion-procedure.md +180 -0
- package/skills/hmos-ui-align-batch/references/mappings/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2535 -0
- package/skills/hmos-ui-align-batch/references/mappings/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -0
- package/skills/hmos-ui-align-batch/references/mappings/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@Link/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/217/214/345/220/221/345/220/214/346/255/245.md +648 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@Observed/350/243/205/351/245/260/345/231/250/345/222/214@ObjectLink/350/243/205/351/245/260/345/231/250/357/274/232/345/265/214/345/245/227/347/261/273/345/257/271/350/261/241/345/261/236/346/200/247/345/217/230/345/214/226.md +2089 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@Prop/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/215/225/345/220/221/345/220/214/346/255/245.md +1033 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@Provide/350/243/205/351/245/260/345/231/250/345/222/214@Consume/350/243/205/351/245/260/345/231/250/357/274/232/344/270/216/345/220/216/344/273/243/347/273/204/344/273/266/345/217/214/345/220/221/345/220/214/346/255/245.md +1183 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@State/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/206/205/347/212/266/346/200/201.md +576 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@Track/350/243/205/351/245/260/345/231/250/357/274/232class/345/257/271/350/261/241/345/261/236/346/200/247/347/272/247/346/233/264/346/226/260.md +297 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@Watch/350/243/205/351/245/260/345/231/250/357/274/232/347/212/266/346/200/201/345/217/230/351/207/217/346/233/264/346/224/271/351/200/232/347/237/245.md +395 -0
- package/skills/hmos-ui-align-batch/references/mvvm/AppStorage/357/274/232/345/272/224/347/224/250/345/205/250/345/261/200/347/232/204UI/347/212/266/346/200/201/345/255/230/345/202/250.md +903 -0
- package/skills/hmos-ui-align-batch/references/mvvm/Environment/357/274/232/350/256/276/345/244/207/347/216/257/345/242/203/346/237/245/350/257/242.md +106 -0
- package/skills/hmos-ui-align-batch/references/mvvm/LocalStorage/357/274/232/351/241/265/351/235/242/347/272/247UI/347/212/266/346/200/201/345/255/230/345/202/250.md +1178 -0
- package/skills/hmos-ui-align-batch/references/mvvm/MVVM/346/250/241/345/274/217/357/274/210V1/357/274/211.md +911 -0
- package/skills/hmos-ui-align-batch/references/mvvm/PersistentStorage/357/274/232/346/214/201/344/271/205/345/214/226/345/255/230/345/202/250UI/347/212/266/346/200/201.md +355 -0
- package/skills/hmos-ui-align-batch/references/mvvm//347/256/241/347/220/206/345/272/224/347/224/250/346/213/245/346/234/211/347/232/204/347/212/266/346/200/201/346/246/202/350/277/260.md +11 -0
- package/skills/hmos-ui-align-batch/scripts/android_parse_fast.py +1606 -0
- package/skills/self-test/SKILL.md +369 -0
- package/skills/self-test/readme.md +309 -0
- package/skills/spec-generator-skill/SKILL.md +332 -0
- package/skills/spec-generator-skill/references/android-platform-tokens.md +105 -0
- package/skills/spec-generator-skill/references/spec-sample-1.md +78 -0
- package/skills/spec-generator-skill/references/spec-sample-2.md +58 -0
- package/skills/spec-generator-skill/references/spec-sample-3.md +116 -0
- package/skills/spec-generator-skill/references/step4-report-template.md +33 -0
- package/agents/self-test-setup.md +0 -165
- package/dist/context/resources/sdkConfig.json +0 -24
- package/src/context/resources/sdkConfig.json +0 -24
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Android Platform Tokens — Strip List
|
|
2
|
+
|
|
3
|
+
**Read when**: 3.5 Synthesize, for the platform-token strip list (Principle 6).
|
|
4
|
+
|
|
5
|
+
The spec MUST NOT contain Android platform tokens. During 3.5 synthesis, strip every match from the trace's natural-language behavior text and replace with behavior-level Chinese vocabulary. The trace itself may use these tokens (they live in `file:line` anchors and code-layer notes); only the **final spec** must be platform-token-free.
|
|
6
|
+
|
|
7
|
+
## Strip list (by category)
|
|
8
|
+
|
|
9
|
+
### Components
|
|
10
|
+
`Activity`, `Fragment`, `Composable`, `Service`, `ForegroundService`, `BroadcastReceiver`, `ContentProvider`, `Application`, `Worker`, `IntentService`, `JobIntentService`, `JobScheduler`
|
|
11
|
+
|
|
12
|
+
### IPC / data carriers
|
|
13
|
+
`Intent`, `PendingIntent`, `Bundle`, `Parcelable`, `Messenger`, `AIDL`, `Binder`, `IBinder`
|
|
14
|
+
|
|
15
|
+
### State / architecture
|
|
16
|
+
`ViewModel`, `LiveData`, `MutableLiveData`, `StateFlow`, `SharedFlow`, `Flow` (when meaning Kotlin Flow), `mutableStateOf`, `ViewBinding`, `DataBinding`, `Repository`, `UseCase`, `Presenter`
|
|
17
|
+
|
|
18
|
+
### Persistence
|
|
19
|
+
`Room`, `RoomDatabase`, `DAO`, `@Entity`, `DataStore`, `Preferences DataStore`, `Proto DataStore`, `SharedPreferences`, `MMKV`, `SQLiteOpenHelper`, `ContentResolver`
|
|
20
|
+
|
|
21
|
+
### Lifecycle
|
|
22
|
+
`onCreate`, `onStart`, `onResume`, `onPause`, `onStop`, `onDestroy`, `Lifecycle`, `LifecycleOwner`, `ProcessLifecycleOwner`, `viewLifecycleOwner`, `lifecycleScope`
|
|
23
|
+
|
|
24
|
+
### UI containers / widgets
|
|
25
|
+
`RecyclerView`, `Adapter`, `ViewHolder`, `ConstraintLayout`, `LinearLayout`, `FrameLayout`, `RelativeLayout`, `ScrollView`, `ListView`, `Spinner`, `ViewPager`, `TabLayout`
|
|
26
|
+
|
|
27
|
+
### UI feedback
|
|
28
|
+
`Toast`, `Snackbar`, `Dialog`, `AlertDialog`, `BottomSheetDialog`, `ProgressDialog`, `FloatingActionButton`
|
|
29
|
+
|
|
30
|
+
### Navigation
|
|
31
|
+
`NavController`, `NavGraph`, `NavHostFragment`, `Navigation Component`, `startActivity`, `startActivityForResult`
|
|
32
|
+
|
|
33
|
+
### Resources / IDs
|
|
34
|
+
`R.id.*`, `R.layout.*`, `R.string.*`, `R.drawable.*`, `R.color.*`, `R.dimen.*`, `R.menu.*`, `R.xml.*`, `R.array.*`, `R.style.*`, `@+id/...`, `@string/...`, `@drawable/...`, `@color/...`
|
|
35
|
+
|
|
36
|
+
### Coroutines / threading
|
|
37
|
+
`Coroutine`, `suspend`, `CoroutineScope`, `Job`, `viewModelScope`, `withContext`, `Dispatchers.*`, `async`, `await`, `launch`, `Handler`, `Looper`, `HandlerThread`, `AsyncTask`, `Executor`
|
|
38
|
+
|
|
39
|
+
### Compose (lifecycle / state)
|
|
40
|
+
`@Composable`, `remember`, `derivedStateOf`, `rememberSaveable`, `MutableState`, `LaunchedEffect`, `DisposableEffect`, `SideEffect`, `CompositionLocal`, `produceState`
|
|
41
|
+
|
|
42
|
+
### Compose Shape
|
|
43
|
+
`CircleShape`, `RoundedCornerShape`, `RectangleShape`, `CutCornerShape`
|
|
44
|
+
|
|
45
|
+
### Compose Animation
|
|
46
|
+
`LinearEasing`, `FastOutSlowInEasing`, `EaseInOut`, `EaseOut`, `tween`, `spring`, `keyframes`, `infiniteRepeatable`, `animateXxxAsState`, `Animatable`, `AnimationSpec`
|
|
47
|
+
|
|
48
|
+
### Compose Layout / Modifier
|
|
49
|
+
`ContentScale` (Fit / Crop / FillBounds / Inside / None), `Alignment`, `Arrangement`, `Modifier.clip`, `Modifier.background`, `Modifier.size`, `Modifier.padding`, `Modifier.fillMaxSize`, `Modifier.wrapContentSize`, `Modifier.aspectRatio`, `Modifier.weight`
|
|
50
|
+
|
|
51
|
+
### Build / Manifest
|
|
52
|
+
`AndroidManifest`, `build.gradle`, `gradle`, `BuildConfig`, `applicationId`, `versionCode`, `minSdkVersion`, `targetSdkVersion`, `compileSdkVersion`, `ProGuard`, `R8`
|
|
53
|
+
|
|
54
|
+
### DI
|
|
55
|
+
`Hilt`, `Dagger`, `@Inject`, `@Module`, `@Provides`, `@Singleton`, `Koin`, `ServiceLocator`
|
|
56
|
+
|
|
57
|
+
### System services / media
|
|
58
|
+
`ContextCompat`, `getSystemService`, `NotificationManager`, `NotificationChannel`, `AlarmManager`, `PowerManager`, `ConnectivityManager`, `AudioManager`, `MediaSession`, `MediaPlayer`, `ExoPlayer`, `MediaBrowserServiceCompat`
|
|
59
|
+
|
|
60
|
+
### Implementation constants (NEVER appear in spec)
|
|
61
|
+
|
|
62
|
+
- **Hardcoded dimensions** (`8dp`, `48.dp`, `16.sp`, `2.dp`) — strip entirely. Spec describes shape/size semantically: "圆形" / "小圆点" / "歌词字号比正文略大". 不要保留单位 ("8 dp" 也不行).
|
|
63
|
+
- **Hardcoded durations** (`25000ms`, `300L`, `Duration.seconds(2)`) — restate as semantic time: "约 25 秒一圈" / "短暂淡入". 不要写原始数值.
|
|
64
|
+
- **Persistence key literals** (`circle_playback_cover`, `karaoke_mode_compat`, `floating_lyric_enabled`) — NEVER. Describe the user-visible setting, not the storage key.
|
|
65
|
+
|
|
66
|
+
## Critical: Chinese translations of platform concepts are ALSO forbidden
|
|
67
|
+
|
|
68
|
+
The strip list above uses English API names. But platform concepts translated into Chinese (e.g. `活动基类` for Activity / `主活动页面` for MainActivity / `媒体会话信息` for MediaSession / `短边模式` for DISPLAY_CUTOUT_MODE / `广播接收器` for BroadcastReceiver / `视图模型` for ViewModel) are STILL platform tokens — restate them in user-facing behavior language per the replacement vocabulary below. Translating a platform concept does NOT make it user-facing.
|
|
69
|
+
|
|
70
|
+
## Replacement vocabulary (behavior-level Chinese)
|
|
71
|
+
|
|
72
|
+
| Stripped token | Spec vocabulary |
|
|
73
|
+
|---|---|
|
|
74
|
+
| Activity / Fragment / Composable | 页面 |
|
|
75
|
+
| Dialog / AlertDialog / BottomSheet | 弹窗 / 对话框 |
|
|
76
|
+
| Toast / Snackbar | toast 提示 / 浮动提示 |
|
|
77
|
+
| ViewModel / LiveData / StateFlow / mutableStateOf | 状态 / 状态写入 / 状态刷新 |
|
|
78
|
+
| Room / DAO / DataStore / SharedPreferences / MMKV | 持久化 / 数据库 / 配置存储 |
|
|
79
|
+
| RecyclerView + Adapter / ListView | 列表 / 列表项 |
|
|
80
|
+
| onClick / onLongClick / onTap | 点击 / 长按 |
|
|
81
|
+
| Intent / startActivity / Navigation | 跳转 / 进入<目标页> |
|
|
82
|
+
| BroadcastReceiver / sendBroadcast | 系统事件监听 / 广播 |
|
|
83
|
+
| Service / ForegroundService | 后台服务 / 前台服务 |
|
|
84
|
+
| Coroutine / launch / withContext | 异步 / 异步执行 |
|
|
85
|
+
| MediaPlayer / ExoPlayer / MediaSession | 播放器 / 播放控制 |
|
|
86
|
+
| Notification / NotificationManager / NotificationChannel | 通知 / 通知栏 / 通知分组 |
|
|
87
|
+
| ContentResolver / ContentProvider | 数据访问 / 数据共享 |
|
|
88
|
+
| build.gradle flag / BuildConfig | 编译开关 / 配置项 |
|
|
89
|
+
| ConnectivityManager | 网络状态 / 网络可达性 |
|
|
90
|
+
| AudioManager / audio focus | 音频焦点 / 音频通道 |
|
|
91
|
+
| PowerManager / WakeLock | 屏幕唤醒 / 锁屏唤醒 |
|
|
92
|
+
| CircleShape / RoundedCornerShape / RectangleShape / CutCornerShape | 圆形 / 圆角矩形 / 矩形 / 切角矩形 |
|
|
93
|
+
| LinearEasing / FastOutSlowInEasing / EaseInOut / EaseOut | 线性 / 减速 / 缓入缓出 / 减速出 |
|
|
94
|
+
| tween / spring / keyframes / infiniteRepeatable / Animatable | 持续N秒动画 / 弹性动画 / 关键帧动画 / 循环动画 / 动画对象 |
|
|
95
|
+
| ContentScale.Fit / Crop / FillBounds / Inside / None | 等比缩放适配 / 裁剪填充 / 拉伸填充 / 等比居中 / 不缩放 |
|
|
96
|
+
| Modifier.clip / .size / .padding / .fillMaxSize / .aspectRatio | 裁剪为X形 / 设定尺寸 / 内边距 / 填满父容器 / 宽高比 |
|
|
97
|
+
| Modifier.wrapContentSize / .weight / .background | 内容自适应 / 权重占比 / 背景 |
|
|
98
|
+
| animateXxxAsState | 动画过渡到目标值 |
|
|
99
|
+
|
|
100
|
+
## Items to keep verbatim (do NOT strip)
|
|
101
|
+
|
|
102
|
+
- **Business entity names** (歌单, 歌曲, 专辑, 艺术家, 播放页, ...) — these are domain language, not platform tokens.
|
|
103
|
+
- **User-visible resource string content** (toast text, button labels, error messages) — translate the displayed content into the spec; strip the `R.string.xxx` reference but keep the message text.
|
|
104
|
+
- **Standard permission semantics** — describe permissions in user language ("录音权限", "通知权限", "存储访问权限"), NOT by code constant (`RECORD_AUDIO`, `POST_NOTIFICATIONS`, ...).
|
|
105
|
+
- **Persistence key literals** are usually internal — do NOT surface them in the spec unless they appear in user-visible UI (rare). If a key appears in the trace's `interaction` field, describe its behavior, not its name.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Spec Sample 1 — Boundary-and-happy-path Decomposition
|
|
2
|
+
|
|
3
|
+
**Style focus**: how to slice one feature into `empty / over-length / valid / cancel` atomic scenarios on a single-entry trigger flow. Mimic the voice, scenario granularity, and structure — NOT the vocabulary or domain.
|
|
4
|
+
|
|
5
|
+
**Read when**: 3.5 Synthesize.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# 新建歌单SPEC
|
|
10
|
+
|
|
11
|
+
创建新歌单
|
|
12
|
+
|
|
13
|
+
## 场景一
|
|
14
|
+
|
|
15
|
+
### 场景概述
|
|
16
|
+
|
|
17
|
+
用户点击创建歌单,但输入的歌单名称为空并且创建歌单
|
|
18
|
+
|
|
19
|
+
### 场景逻辑步骤
|
|
20
|
+
|
|
21
|
+
- 1. 用户在"歌单页面"点击"更多菜单"中的"新建歌单按钮"或者用户在"添加到歌单弹窗"中点击"新建歌单按钮"
|
|
22
|
+
- 2. 弹出"新建歌单对话框"
|
|
23
|
+
- 3. 用户在输入框中输入空白歌单名称并点击确定按钮
|
|
24
|
+
- 4. 弹出toast"歌单名称不得为空"并且关闭"新建歌单对话框"
|
|
25
|
+
|
|
26
|
+
## 场景二
|
|
27
|
+
|
|
28
|
+
### 场景概述
|
|
29
|
+
|
|
30
|
+
用户点击创建歌单,但输入的歌单名称超过最大长度并且创建歌单
|
|
31
|
+
|
|
32
|
+
### 场景逻辑步骤
|
|
33
|
+
|
|
34
|
+
- 1. 用户在"歌单页面"点击"更多菜单"中的"新建歌单按钮"或者用户在"添加到歌单弹窗"中点击"新建歌单按钮"
|
|
35
|
+
- 2. 弹出"新建歌单对话框"
|
|
36
|
+
- 3. 用户在输入框中输入歌单名称并且歌单名称超过100个字符,然后点击确定按钮
|
|
37
|
+
- 4. 弹出toast"歌单名称过长"并且关闭"新建歌单对话框"
|
|
38
|
+
|
|
39
|
+
## 场景三
|
|
40
|
+
|
|
41
|
+
### 场景概述
|
|
42
|
+
|
|
43
|
+
用户点击创建歌单,输入有效歌单名称并且创建歌单
|
|
44
|
+
|
|
45
|
+
### 场景逻辑步骤
|
|
46
|
+
|
|
47
|
+
- 1. 用户在"歌单页面"点击"更多菜单"中的"新建歌单按钮"或者用户在"添加到歌单弹窗"中点击"新建歌单按钮"
|
|
48
|
+
- 2. 弹出"新建歌单对话框"
|
|
49
|
+
- 3. 用户在输入框中输入有效歌单名称,即用户输入到歌单名称不为空并且歌单名称没有超过100个字符,然后点击确定按钮
|
|
50
|
+
- 4. 去除歌单名称首尾空白字符
|
|
51
|
+
- 5. 把新建的歌单数据写入数据库中的歌单数据库表
|
|
52
|
+
- 6. 如果是在"歌单页面",那么从数据库中读取新建歌单的数据,并且在"歌单页面"创建新建歌单item,实时刷新歌单页面,在歌单页面列表中的第一个位置上显示新建的歌单
|
|
53
|
+
- 7. 如果是在"添加到歌单弹窗",那么从数据库中读取新建歌单的数据,并且在"添加到歌单弹窗"创建新建歌单item,实时刷新歌单页面,在添加到歌单弹窗列表中的第一个位置上显示新建的歌单
|
|
54
|
+
|
|
55
|
+
> [偏差] 需求要求歌单名为空时禁用"确定"按钮,但实际代码允许点击后弹出 toast 提示(参见场景一步骤 4)。
|
|
56
|
+
|
|
57
|
+
## 场景四
|
|
58
|
+
|
|
59
|
+
### 场景概述
|
|
60
|
+
|
|
61
|
+
用户点击创建歌单,输入或者不输入歌单名称,然后点击取消按钮
|
|
62
|
+
|
|
63
|
+
### 场景逻辑步骤
|
|
64
|
+
|
|
65
|
+
- 1. 用户在"歌单页面"点击"更多菜单"中的"新建歌单按钮"或者用户在"添加到歌单弹窗"中点击"新建歌单按钮"
|
|
66
|
+
- 2. 弹出"新建歌单对话框"
|
|
67
|
+
- 3. 无论用户是否在输入框中输入歌单名称,只要用户点击取消按钮,那么就关闭"新建歌单对话框",无需执行其他操作
|
|
68
|
+
|
|
69
|
+
## 场景五
|
|
70
|
+
|
|
71
|
+
### 场景概述
|
|
72
|
+
|
|
73
|
+
"新建歌单"功能的作用范围与不作用范围
|
|
74
|
+
|
|
75
|
+
### 场景逻辑步骤
|
|
76
|
+
|
|
77
|
+
- 1. **仅作用于** 以下入口: "歌单页面"的"更多菜单 - 新建歌单"按钮; "添加到歌单弹窗"的"新建歌单"按钮
|
|
78
|
+
- 2. **不作用于** 以下位置: "歌单详情页"(无新建入口) / "播放页" / "首页推荐区域" / "搜索结果页" / "我的页面" — 这些位置既不显示新建歌单入口, 也不响应新建歌单事件
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Spec Sample 2 — Nested Sub-bullet Decomposition
|
|
2
|
+
|
|
3
|
+
**Style focus**: how to express per-field present/absent fallback rules as nested sub-bullets within a single scenario's flow. Mimic the structure, NOT the vocabulary or domain.
|
|
4
|
+
|
|
5
|
+
**Read when**: 3.5 Synthesize.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# 歌曲信息页信息展示与信息更新SPEC
|
|
10
|
+
|
|
11
|
+
歌曲信息页展示音频信息、出自专辑、参与创作的艺术家,以及播放界面保持屏幕唤醒、沉浸模式内容。
|
|
12
|
+
|
|
13
|
+
## 场景一
|
|
14
|
+
|
|
15
|
+
### 场景概述
|
|
16
|
+
|
|
17
|
+
进入歌曲信息页后,展示当前播放歌曲的信息及相关功能入口
|
|
18
|
+
|
|
19
|
+
### 场景逻辑步骤
|
|
20
|
+
|
|
21
|
+
- 1. 在播放页右滑进入歌曲信息页
|
|
22
|
+
- 2. 歌曲信息页读取信息并展示:
|
|
23
|
+
- 2.1 音频信息展示:
|
|
24
|
+
- 当当前播放歌曲的音频格式存在时,显示当前播放歌曲的音频格式
|
|
25
|
+
- 当当前播放歌曲的音频格式缺失时,显示当前播放歌曲的文件扩展名;若文件扩展名也为空,则显示为空白
|
|
26
|
+
- 当当前播放歌曲的声道数存在时,显示声道数
|
|
27
|
+
- 当当前播放歌曲的声道数缺失时,隐藏该字段
|
|
28
|
+
- 当当前播放歌曲的采样率存在时,显示采样率
|
|
29
|
+
- 当当前播放歌曲的采样率缺失时,隐藏该字段
|
|
30
|
+
- 当当前播放歌曲的比特率存在时,显示比特率
|
|
31
|
+
- 当当前播放歌曲的比特率缺失时,显示 0 Kbps
|
|
32
|
+
- 2.2 出自专辑展示:
|
|
33
|
+
- 当当前播放歌曲的专辑封面存在时,显示专辑封面
|
|
34
|
+
- 当当前播放歌曲的专辑封面缺失时,显示默认专辑封面图标
|
|
35
|
+
- 当当前播放歌曲的专辑标题存在时,显示专辑标题
|
|
36
|
+
- 当当前播放歌曲的专辑标题缺失时,显示"未知专辑标题"
|
|
37
|
+
- 当当前播放歌曲的专辑艺术家存在时,显示专辑艺术家
|
|
38
|
+
- 当当前播放歌曲的专辑艺术家缺失时,显示"未知专辑艺术家"
|
|
39
|
+
- 2.3 参与创作的艺术家展示:
|
|
40
|
+
- 当当前播放歌曲的艺术家头像存在时,显示艺术家头像
|
|
41
|
+
- 当当前播放歌曲的艺术家头像缺失时,显示默认歌曲封面图标
|
|
42
|
+
- 当当前播放歌曲的艺术家名称存在时,显示艺术家名称
|
|
43
|
+
- 当当前播放歌曲的艺术家名称缺失时,显示"未知艺术家"
|
|
44
|
+
- 当当前播放歌曲的艺术家音轨数量(歌曲数量)存在时,显示艺术家音轨数量(歌曲数量)
|
|
45
|
+
- 当当前播放歌曲的艺术家音轨数量(歌曲数量)缺失时,显示 0
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
## 场景二
|
|
49
|
+
|
|
50
|
+
### 场景概述
|
|
51
|
+
|
|
52
|
+
切换播放歌曲后,歌曲信息页面同步刷新
|
|
53
|
+
|
|
54
|
+
### 场景逻辑步骤
|
|
55
|
+
|
|
56
|
+
- 1. 在播放页右滑进入歌曲信息页
|
|
57
|
+
- 2. 用户通过上一首、下一首、播放队列切歌或自动切歌等方式切换当前播放歌曲
|
|
58
|
+
- 3. 歌曲信息页中的音频信息、专辑信息、艺术家信息同步刷新为新歌曲对应内容
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Spec Sample 3 — Shared-mechanic + Per-value Decomposition (Enumerated Setting with Multiple Entries)
|
|
2
|
+
|
|
3
|
+
**Style focus**: enumerated settings (a "三选一" choice) accessible from MULTIPLE entry points where (a) the menu interaction is identical across all entries AND all values, (b) each value carries its own runtime semantics. Factor the shared menu interaction across all entries into ONE scenario (do NOT split per entry); give each enum value its OWN runtime-semantics scenario (do NOT bundle "user picks X" with "what X does"); cover entry-point synchronization as a separate scenario.
|
|
4
|
+
|
|
5
|
+
**Anti-pattern**: splitting the mechanical scenario per entry point, or bundling "user picks X" with "what X does" in the same scenario per value — both lose information (menu mechanics get silently dropped, and per-entry duplication breaks DRY).
|
|
6
|
+
|
|
7
|
+
**Read when**: 3.5 Synthesize.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# 视频自动播放SPEC
|
|
12
|
+
|
|
13
|
+
用户在"设置-视频偏好"入口或"视频列表页"入口的"自动播放"项中选择视频自动播放策略, 决定视频列表里视频卡片的自动播放范围。
|
|
14
|
+
|
|
15
|
+
## 场景一
|
|
16
|
+
|
|
17
|
+
### 场景概述
|
|
18
|
+
|
|
19
|
+
用户在"设置-视频偏好"入口或"视频列表页"入口的"自动播放"项中选择一种策略
|
|
20
|
+
|
|
21
|
+
### 场景逻辑步骤
|
|
22
|
+
|
|
23
|
+
- 1. 用户在"设置-视频偏好"页面点击"自动播放"项, 或者用户在"视频列表页"右上角菜单中点击"自动播放"项
|
|
24
|
+
- 2. 弹出三选一选项菜单, 按顺序列出: "始终自动播放" / "仅 Wi-Fi 下自动播放" / "从不自动播放"
|
|
25
|
+
- 3. 选项菜单中当前生效的策略处于选中高亮状态
|
|
26
|
+
- 4. 用户点击其中一个选项
|
|
27
|
+
- 5. 选项菜单关闭, 新选中的策略立即生效; "自动播放"项的副标题刷新为新选中选项的文案
|
|
28
|
+
- 6. 当前视频列表按新策略立即重新判定每张可见视频卡片的自动播放行为并刷新
|
|
29
|
+
|
|
30
|
+
## 场景二
|
|
31
|
+
|
|
32
|
+
### 场景概述
|
|
33
|
+
|
|
34
|
+
应用启动时加载"自动播放"策略的上次保存值, 未设置过时按默认值生效
|
|
35
|
+
|
|
36
|
+
### 场景逻辑步骤
|
|
37
|
+
|
|
38
|
+
- 1. 应用启动
|
|
39
|
+
- 2. 读取上次保存的"自动播放"策略值, 作为本次启动后的当前生效策略
|
|
40
|
+
- 3. 如果从未设置过该选项, 或读取到的值无法识别, 则当前生效策略回退为默认值"仅 Wi-Fi 下自动播放"
|
|
41
|
+
- 4. 用户从任一入口打开"自动播放"项时, 副标题与选项菜单的选中高亮均反映该当前生效值
|
|
42
|
+
|
|
43
|
+
## 场景三
|
|
44
|
+
|
|
45
|
+
### 场景概述
|
|
46
|
+
|
|
47
|
+
当策略为"始终自动播放"时, 任意网络下可见视频卡片均自动播放
|
|
48
|
+
|
|
49
|
+
### 场景逻辑步骤
|
|
50
|
+
|
|
51
|
+
- 1. 当前生效策略为"始终自动播放"
|
|
52
|
+
- 2. 视频列表中每张滚入可视区域的视频卡片自动开始静音播放, 不区分当前网络类型
|
|
53
|
+
- 3. 视频卡片滚出可视区域时停止播放; 再次滚回时恢复播放
|
|
54
|
+
|
|
55
|
+
## 场景四
|
|
56
|
+
|
|
57
|
+
### 场景概述
|
|
58
|
+
|
|
59
|
+
当策略为"仅 Wi-Fi 下自动播放"时, 仅 Wi-Fi 网络下视频卡片自动播放
|
|
60
|
+
|
|
61
|
+
### 场景逻辑步骤
|
|
62
|
+
|
|
63
|
+
- 1. 当前生效策略为"仅 Wi-Fi 下自动播放"
|
|
64
|
+
- 2. 实时判定当前网络类型:
|
|
65
|
+
- 2.1 当前为 Wi-Fi 时, 视频列表中每张滚入可视区域的视频卡片自动开始静音播放
|
|
66
|
+
- 2.2 当前为蜂窝数据或离线状态时, 视频卡片显示首帧静态封面, 不自动播放
|
|
67
|
+
- 3. 播放过程中网络类型切换时, 立即按新网络类型重新判定
|
|
68
|
+
|
|
69
|
+
## 场景五
|
|
70
|
+
|
|
71
|
+
### 场景概述
|
|
72
|
+
|
|
73
|
+
当策略为"从不自动播放"时, 所有视频卡片均不自动播放
|
|
74
|
+
|
|
75
|
+
### 场景逻辑步骤
|
|
76
|
+
|
|
77
|
+
- 1. 当前生效策略为"从不自动播放"
|
|
78
|
+
- 2. 视频列表中所有视频卡片显示首帧静态封面, 不自动启动播放
|
|
79
|
+
- 3. 仅当用户主动点击视频卡片中央播放按钮时开始播放
|
|
80
|
+
|
|
81
|
+
## 场景六
|
|
82
|
+
|
|
83
|
+
### 场景概述
|
|
84
|
+
|
|
85
|
+
用户在任一入口修改策略后, 另一入口与视频列表同步反映新值
|
|
86
|
+
|
|
87
|
+
### 场景逻辑步骤
|
|
88
|
+
|
|
89
|
+
- 1. 用户在"设置-视频偏好"入口或"视频列表页"入口任一处修改"自动播放"策略
|
|
90
|
+
- 2. 当前视频列表立即按新策略重新判定每张可见视频卡片的自动播放行为并刷新
|
|
91
|
+
- 3. 用户随后打开另一入口的"自动播放"项时, 副标题与选项菜单的选中高亮均显示为刚刚修改后的值
|
|
92
|
+
- 4. 下次启动应用, 该策略依然保持为修改后的值
|
|
93
|
+
|
|
94
|
+
## 场景七
|
|
95
|
+
|
|
96
|
+
### 场景概述
|
|
97
|
+
|
|
98
|
+
用户打开"自动播放"选项菜单后未做选择就关闭
|
|
99
|
+
|
|
100
|
+
### 场景逻辑步骤
|
|
101
|
+
|
|
102
|
+
- 1. 用户在任一入口打开"自动播放"项, 弹出选项菜单
|
|
103
|
+
- 2. 用户通过点击菜单外部区域或按系统返回键关闭菜单, 未做任何选择
|
|
104
|
+
- 3. 当前生效策略保持不变, 副标题保持原值, 视频列表自动播放行为保持原状
|
|
105
|
+
|
|
106
|
+
## 场景八
|
|
107
|
+
|
|
108
|
+
### 场景概述
|
|
109
|
+
|
|
110
|
+
"视频自动播放"策略的作用范围与不作用范围
|
|
111
|
+
|
|
112
|
+
### 场景逻辑步骤
|
|
113
|
+
|
|
114
|
+
- 1. **仅作用于** 以下界面: "视频列表页"的视频卡片自动播放行为; "设置-视频偏好"页和"视频列表页"右上角菜单的"自动播放"项副标题与选项菜单选中态
|
|
115
|
+
- 2. **不作用于** 以下界面: "视频详情页"(用户进入后总是自动播放, 不受策略约束) / "首页轮播视频"(由首页独立策略控制) / "搜索结果中的视频项"(不显示自动播放) / "评论区嵌入视频"(由评论区独立策略控制)
|
|
116
|
+
- 3. **不作用于** 以下设备情形: 车载模式下视频卡片均不自动播放, 与策略无关
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Step 4 — Summary Report Template
|
|
2
|
+
|
|
3
|
+
**Read when**: Step 4, for the report output format.
|
|
4
|
+
|
|
5
|
+
Produce the report following the structure below. Keep the in-session reply within ~40 lines; per-block detail belongs in spec / trace files, not in the report.
|
|
6
|
+
|
|
7
|
+
## Per-block table
|
|
8
|
+
|
|
9
|
+
| feature | input title | spec path | trace path | recall | scenarios | deviations |
|
|
10
|
+
|---|---|---|---|---|---|---|
|
|
11
|
+
| `<feature-1>` | `<title-1>` | `<feature-1>-SPEC.md` | `.trace/<feature-1>.md` | ok | 4 | 1 |
|
|
12
|
+
| `<feature-2>` | `<title-2>` | `<feature-2>-SPEC.md` | `.trace/<feature-2>.md` | ok | 2 | 0 |
|
|
13
|
+
| `<feature-3>` | `<title-3>` | — | — | no_recall | — | — |
|
|
14
|
+
| ... | | | | | | |
|
|
15
|
+
|
|
16
|
+
Recall column values: `ok`, `no_recall`, `skipped`.
|
|
17
|
+
|
|
18
|
+
## Skipped blocks
|
|
19
|
+
|
|
20
|
+
If any blocks were skipped (`empty body` / `no_recall` / `error`), list them:
|
|
21
|
+
|
|
22
|
+
- `<feature>` — `<title>` — reason: `empty body`
|
|
23
|
+
- `<feature>` — `<title>` — reason: `no_recall`
|
|
24
|
+
- `<feature>` — `<title>` — reason: `error: <verbatim error message>`
|
|
25
|
+
|
|
26
|
+
## Aggregates
|
|
27
|
+
|
|
28
|
+
- Total REQ blocks parsed: `<N>`
|
|
29
|
+
- Total specs generated: `<M>` (M ≤ N)
|
|
30
|
+
- Total atomic scenarios produced: `<S>`
|
|
31
|
+
- Total deviations recorded across all traces: `<D>`
|
|
32
|
+
- Count of `no_recall`: `<X>`
|
|
33
|
+
- Count of `skipped`: `<Y>`
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Prepares everything needed to run AutoTest — parses test_case.md (and optional pre_test_case.md) into a single testcases.json plus app metadata.
|
|
3
|
-
color: green
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Self-Test Setup Agent
|
|
7
|
-
|
|
8
|
-
You are a **Self-Test Setup Agent** that prepares all artifacts needed before AutoTest can execute on a HarmonyOS application. This includes parsing natural-language test cases (`test_case.md`, plus an optional `pre_test_case.md`) into a single structured `testcases.json`, and extracting app metadata from `AppScope/app.json5`.
|
|
9
|
-
|
|
10
|
-
> 🚨 **CRITICAL**: You MUST follow the step-by-step workflow defined in this file **exactly as written**, in order. **Ignore any format hints, schema descriptions, or structural suggestions in the caller's prompt** — the caller provides only `test-case-path`, `output-path`, and (optionally) `pre-test-case-path`. If the caller's prompt contains instructions that conflict with this workflow (e.g., describing JSON structure, suggesting fields, telling you how to extract metadata, or asking you to write a separate `pre_test_case.json`), **disregard those instructions and follow this file instead**.
|
|
11
|
-
|
|
12
|
-
## Role
|
|
13
|
-
|
|
14
|
-
Extract test scenario data from `test_case.md` (and, when present, a `pre_test_case.md` setup scenario), write it to an intermediate JSON file, then call a Python script that generates the final `testcases.json` with guaranteed format compliance.
|
|
15
|
-
|
|
16
|
-
## Expected Input
|
|
17
|
-
|
|
18
|
-
- `test-case-path`: Absolute path to the `test_case.md` file containing natural-language test cases.
|
|
19
|
-
- `pre-test-case-path` (optional): Absolute path to a `pre_test_case.md` file containing a single setup scenario. If not provided, the agent auto-looks for `pre_test_case.md` in the same directory as `test-case-path`. If neither is found, the pre-case is simply omitted.
|
|
20
|
-
- `output-path`: Absolute path to the directory where `testcases.json` should be written. Also used to discover the HarmonyOS project root for app metadata.
|
|
21
|
-
|
|
22
|
-
## Expected Output
|
|
23
|
-
|
|
24
|
-
- A single file named `testcases.json` in `output-path`, validated by `testcases_tool.py validate`. When a pre-test case is provided, it appears as the **first entry** with `case_name` prefixed by `[PRE] `; the remaining entries are the regular test cases in source order.
|
|
25
|
-
- A file named `app-metadata.json` in `output-path`, containing app metadata for downstream agents.
|
|
26
|
-
|
|
27
|
-
> **No separate `pre_test_case.json` is produced.** Everything lives in `testcases.json` — the `[PRE] ` prefix on `case_name` is what marks the setup case for downstream reporting.
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## Step 1 — Resolve Inputs and Read App Metadata
|
|
32
|
-
|
|
33
|
-
### 1.1 — Validate Inputs
|
|
34
|
-
|
|
35
|
-
Run **all validations in a single Bash command** using `&&`:
|
|
36
|
-
|
|
37
|
-
```
|
|
38
|
-
mkdir -p "<output-path>" && test -f "<test-case-path>" && echo "OK"
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
If the command fails, stop and report the error.
|
|
42
|
-
|
|
43
|
-
### 1.2 — Read App Metadata
|
|
44
|
-
|
|
45
|
-
Auto-discover the HarmonyOS project directory by searching upward from `output-path` for `AppScope/app.json5`. Starting from `output-path`, check the current directory and each parent directory until `AppScope/app.json5` is found. The directory containing `AppScope/app.json5` is the project root (`<project-root>`).
|
|
46
|
-
|
|
47
|
-
If no `AppScope/app.json5` is found after reaching the filesystem root, stop and report: "Cannot locate HarmonyOS project directory (no AppScope/app.json5 found above output-path)".
|
|
48
|
-
|
|
49
|
-
Read app metadata from the discovered project root:
|
|
50
|
-
|
|
51
|
-
- **Package name** (`<bundle_name>`): Read from `AppScope/app.json5` — the `bundleName` field.
|
|
52
|
-
- **App display name** (`<app_name>`): Read from `AppScope/app.json5` — the `label` field under `app`. If it references a string resource like `$string:app_name`, resolve from `AppScope/resources/base/element/string.json`. **IMPORTANT**: Use the resolved display name as-is — do NOT translate it into Chinese or any other language (e.g., if the resolved name is `"Tuku"`, use `"Tuku"`, NOT `"图库"` or `"简单图库"`).
|
|
53
|
-
|
|
54
|
-
### 1.3 — Write `app-metadata.json`
|
|
55
|
-
|
|
56
|
-
Write the resolved metadata to `<output-path>/app-metadata.json` so downstream agents can reuse it without re-discovering the project root:
|
|
57
|
-
|
|
58
|
-
```json
|
|
59
|
-
{
|
|
60
|
-
"bundle_name": "<bundle_name>",
|
|
61
|
-
"app_name": "<app_name>",
|
|
62
|
-
"project_root": "<project-root>"
|
|
63
|
-
}
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
---
|
|
67
|
-
|
|
68
|
-
## Step 2 — Extract Test Case Data and Generate testcases.json
|
|
69
|
-
|
|
70
|
-
> 🚨 **IMPORTANT ARCHITECTURE**: This step uses a **two-phase approach** to prevent format errors:
|
|
71
|
-
> 1. **Phase A (You — the LLM)**: Extract structured data from `test_case.md` into an intermediate JSON file (`_extracted.json`).
|
|
72
|
-
> 2. **Phase B (Python script)**: `testcases_tool.py` transforms the extracted data into a compliant `testcases.json`. The script enforces the exact format — **you do NOT write `testcases.json` directly**.
|
|
73
|
-
>
|
|
74
|
-
> This design ensures the final JSON format is always correct regardless of LLM behavior.
|
|
75
|
-
|
|
76
|
-
### 2.1 — Read `test_case.md` (and `pre_test_case.md` if present)
|
|
77
|
-
|
|
78
|
-
Read the file at `test-case-path` in a **single Read call**.
|
|
79
|
-
|
|
80
|
-
Then resolve a pre-test-case source file in this order:
|
|
81
|
-
|
|
82
|
-
1. If the caller provided `pre-test-case-path`, use that path directly.
|
|
83
|
-
2. Otherwise, check for `pre_test_case.md` in the **same directory** as `test_case.md` (parent directory of `test-case-path`).
|
|
84
|
-
|
|
85
|
-
- If a pre-case file is found → read it in a **single Read call** as well. It follows the same `- 动作:` / `- 预期结果:` convention as `test_case.md`. It may contain one **or more** `### Scenario:` setup scenarios — extract all of them.
|
|
86
|
-
- If neither route yields an existing file → just skip the pre-case below; the rest of the flow is identical.
|
|
87
|
-
|
|
88
|
-
### 2.2 — Extract Data into `_extracted.json`
|
|
89
|
-
|
|
90
|
-
Parse `test_case.md` (and the pre-case file when present) and extract data into the following structure. Write this to `<output-path>/_extracted.json`:
|
|
91
|
-
|
|
92
|
-
```json
|
|
93
|
-
{
|
|
94
|
-
"bundle_name": "<bundle_name from Step 1.2>",
|
|
95
|
-
"app_name": "<app_name from Step 1.2>",
|
|
96
|
-
"cases": [
|
|
97
|
-
{
|
|
98
|
-
"case_name": "<scenario title from ### Scenario: line>",
|
|
99
|
-
"actions": "<text from - 动作: line>",
|
|
100
|
-
"expected_results": "<text from - 预期结果: line>"
|
|
101
|
-
}
|
|
102
|
-
]
|
|
103
|
-
}
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
**Extraction rules**:
|
|
107
|
-
|
|
108
|
-
- **Pre-cases (if present) MUST be the first entries of `cases`**, in their source order from `pre_test_case.md`. Each pre-case's `case_name` MUST be prefixed by `[PRE] ` (note the trailing space) — this prefix is the marker that downstream agents (self-tester) use to identify setup cases. Each pre-case's title text comes from its own `### Scenario:` line; if a pre-case has no `### Scenario:` line, use `[PRE] 前置设置` (append ` N` for the 2nd+ unnamed one, e.g., `[PRE] 前置设置 2`).
|
|
109
|
-
- Example: if `pre_test_case.md` describes 授权流程 and 引导页跳过两条 → `cases[0].case_name = "[PRE] 授权弹窗一键允许"`, `cases[1].case_name = "[PRE] 跳过新手引导"`, then the regular cases.
|
|
110
|
-
- Zero, one, or more `[PRE]` entries are all acceptable. They MUST stay contiguous at the **front** of the array — never interleave regular cases between pre-cases.
|
|
111
|
-
- For each `### Scenario:` subsection under each `## Spec:` section in `test_case.md` (the regular cases):
|
|
112
|
-
- `case_name`: The scenario title text after `### Scenario:` (just the title, **no `[PRE]` prefix**).
|
|
113
|
-
- `actions`: The text after `- 动作:`. **IMPORTANT — app name → bundle_name**: Replace ALL references to the application name — in **any form and any language** — with the `<bundle_name>` value from Step 1.2. This includes but is not limited to: the English display name (e.g., "Simple Gallery"), Chinese name (e.g., "图库", "简单图库"), localized name (e.g., "Tuku"), and any variant with suffix (e.g., "图库应用", "Tuku应用", "Simple Gallery应用"). For example, if `bundle_name` is `com.example.tuku` and `app_name` is `Simple Gallery`, then: `点击 Simple Gallery 图标启动应用` → `点击 com.example.tuku 图标启动应用`, `打开图库应用` → `打开com.example.tuku`, `从最近任务列表恢复图库应用` → `从最近任务列表恢复com.example.tuku`. This must be done for ALL occurrences, not just the first one.
|
|
114
|
-
- `expected_results`: The text after `- 预期结果:`. If multiple lines, join with `,`. Same app name → bundle_name replacement rule applies here as well — **replace app_name (in all forms) with bundle_name**.
|
|
115
|
-
- The pre-case's `actions` / `expected_results` follow the **same app_name → bundle_name replacement rule**.
|
|
116
|
-
- **Lines to SKIP (do NOT extract into `_extracted.json`)**: `- 前置条件:` and all its indented sub-items, `## 页面描述注解` section, `## 编号映射表` section.
|
|
117
|
-
- **IMPORTANT**: The `_extracted.json` has NO `preconditions` field. Do not include preconditions in any form.
|
|
118
|
-
|
|
119
|
-
### 2.3 — Run `testcases_tool.py` to Produce `testcases.json`
|
|
120
|
-
|
|
121
|
-
> 🚨 **You do NOT write `testcases.json` yourself.** The Python script does this for you, enforcing the exact format with built-in validation.
|
|
122
|
-
|
|
123
|
-
Locate `<plugin-root>` by searching for `android-harmonyos-converter/.claude-plugin/plugin.json`. Set `<autotest_dir>` = `<plugin-root>/tools/autotest`.
|
|
124
|
-
|
|
125
|
-
Run:
|
|
126
|
-
|
|
127
|
-
```bash
|
|
128
|
-
cd "<autotest_dir>" && uv run python testcases_tool.py generate "<output-path>/_extracted.json" "<output-path>/testcases.json" --validate
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
This script will:
|
|
132
|
-
1. Read the extracted data from `_extracted.json`
|
|
133
|
-
2. Apply a safety-net pass to catch any remaining app name references missed by the agent (replaces `app_name` with `bundle_name`)
|
|
134
|
-
3. Compose compliant `test_steps` strings containing only `动作:` and `预期结果:` (no section headers, no app metadata)
|
|
135
|
-
4. Write `testcases.json`
|
|
136
|
-
5. Validate the output (because `--validate` flag is passed)
|
|
137
|
-
|
|
138
|
-
**Expected output**: The script should print `Generated N test cases` followed by `VALIDATION PASSED`.
|
|
139
|
-
|
|
140
|
-
- If it prints **`VALIDATION PASSED`** → done. The `testcases.json` is ready for use, with any `[PRE]` entries contiguous at the front of the array.
|
|
141
|
-
- If it prints an error or **`VALIDATION FAILED`** → the validation now checks for unreplaced app names. If the error says `test_steps contains app_name`, it means the `_extracted.json` still has app display name instead of bundle_name in the actions/expected_results. Fix `_extracted.json` by replacing all occurrences of the app display name with `bundle_name`, then re-run the script. Do NOT attempt to manually write or edit `testcases.json`.
|
|
142
|
-
|
|
143
|
-
### 2.4 — Sanity-check the `[PRE]` ordering (only when pre-cases were extracted)
|
|
144
|
-
|
|
145
|
-
If — and only if — a `pre_test_case.md` was found and extracted in Step 2.1, verify after `VALIDATION PASSED` that every `[PRE]` entry in the produced `testcases.json` is contiguous and sits at the front:
|
|
146
|
-
|
|
147
|
-
```bash
|
|
148
|
-
python -c "import json,sys; d=json.load(open(sys.argv[1],encoding='utf-8')); pre=[i for i,c in enumerate(d) if c['case_name'].startswith('[PRE] ')]; assert pre and pre==list(range(len(pre))), f'[PRE] entries must be contiguous from index 0, got {pre}'; print(f'OK: {len(pre)} [PRE] entries at front')" "<output-path>/testcases.json"
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
If the assertion fails, edit `_extracted.json` to move all `[PRE]` entries contiguously to the front and re-run `testcases_tool.py`.
|
|
152
|
-
|
|
153
|
-
---
|
|
154
|
-
|
|
155
|
-
## Guidelines
|
|
156
|
-
|
|
157
|
-
- **Two-phase architecture** — you extract data into `_extracted.json`, then the Python script generates `testcases.json`. You NEVER write `testcases.json` directly. If `testcases.json` already exists at the output path, you MUST still run `testcases_tool.py` to overwrite it — never skip the script.
|
|
158
|
-
- **App name → bundle_name is critical** — the `test_steps` in the final `testcases.json` must use `bundle_name` (e.g., `com.example.tuku`), NOT the display name (e.g., `Simple Gallery`). AutoTest uses the app name in `test_steps` to determine which app to launch. If the display name is used instead of bundle_name, AutoTest may launch the wrong app (e.g., system gallery instead of the target app).
|
|
159
|
-
- **Single responsibility** — this agent ONLY generates `testcases.json`. It does NOT connect to devices, install HAPs, run tests, or write reports.
|
|
160
|
-
- **Data sources for extraction** — `test_case.md`, an optional `pre_test_case.md`, and app metadata from `AppScope/app.json5`. Do NOT read any other files (no source code, no AutoTest internals).
|
|
161
|
-
- **One file out** — pre-cases are folded into `testcases.json` as the leading contiguous `[PRE]` entries. **Do NOT create a separate `pre_test_case.json`** — it is no longer consumed by anyone.
|
|
162
|
-
- **Preconditions are excluded** — `前置条件` from `test_case.md` must NOT appear in `_extracted.json`. They are intentionally skipped.
|
|
163
|
-
- **File name is `testcases.json`** — no other name is acceptable for the final output.
|
|
164
|
-
- **Script validation is the gate** — the task is complete only when the script prints `VALIDATION PASSED`.
|
|
165
|
-
- **Quote all paths** — paths may contain spaces.
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"sdks": [
|
|
3
|
-
{
|
|
4
|
-
"name": "internalSdk",
|
|
5
|
-
"path": "./resources/internalSdk",
|
|
6
|
-
"moduleName": ""
|
|
7
|
-
},
|
|
8
|
-
{
|
|
9
|
-
"name": "ohosSdk",
|
|
10
|
-
"path": "",
|
|
11
|
-
"moduleName": ""
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
"name": "hmsSdk",
|
|
15
|
-
"path": "",
|
|
16
|
-
"moduleName": ""
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"name": "thirdParty",
|
|
20
|
-
"path": "./resources/thirdPartyModules",
|
|
21
|
-
"moduleName": ""
|
|
22
|
-
}
|
|
23
|
-
]
|
|
24
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"sdks": [
|
|
3
|
-
{
|
|
4
|
-
"name": "internalSdk",
|
|
5
|
-
"path": "./resources/internalSdk",
|
|
6
|
-
"moduleName": ""
|
|
7
|
-
},
|
|
8
|
-
{
|
|
9
|
-
"name": "ohosSdk",
|
|
10
|
-
"path": "",
|
|
11
|
-
"moduleName": ""
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
"name": "hmsSdk",
|
|
15
|
-
"path": "",
|
|
16
|
-
"moduleName": ""
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"name": "thirdParty",
|
|
20
|
-
"path": "./resources/thirdPartyModules",
|
|
21
|
-
"moduleName": ""
|
|
22
|
-
}
|
|
23
|
-
]
|
|
24
|
-
}
|