@buaa_smat/hometrans 0.1.0 → 0.1.1

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 (128) hide show
  1. package/README.md +141 -124
  2. package/agents/self-tester.md +259 -233
  3. package/agents/test-tools/autotest/README.md +223 -0
  4. package/agents/test-tools/autotest/config.yaml.example +58 -0
  5. package/agents/test-tools/autotest/pyproject.toml +16 -0
  6. package/agents/test-tools/autotest/report_tool.py +759 -0
  7. package/agents/test-tools/autotest/self_test_runner.py +773 -0
  8. package/agents/test-tools/autotest/testcases_schema.md +143 -0
  9. package/agents/test-tools/autotest/testcases_tool.py +215 -0
  10. package/agents/test-tools/autotest/uv.lock +3156 -0
  11. package/agents/test-tools/harmony_autotest-0.1.0-py3-none-any.whl +0 -0
  12. package/agents/test-tools/hypium-6.1.0.210-py3-none-any.whl +0 -0
  13. package/agents/test-tools/hypium_mcp-0.6.5-py3-none-any.whl +0 -0
  14. package/agents/test-tools/xdevice-6.1.0.210-py3-none-any.whl +0 -0
  15. package/agents/test-tools/xdevice_devicetest-6.1.0.210-py3-none-any.whl +0 -0
  16. package/agents/test-tools/xdevice_ohos-6.1.0.210-py3-none-any.whl +0 -0
  17. package/dist/cli/config-store.js +27 -2
  18. package/dist/cli/config.js +17 -6
  19. package/dist/cli/index.js +3 -2
  20. package/dist/cli/init.js +135 -22
  21. package/dist/cli/mcp.js +2 -2
  22. package/dist/context/index.js +165 -69
  23. package/package.json +59 -60
  24. package/skills/code-dev-review-fix/SKILL.md +279 -0
  25. package/skills/code-dev-review-fix-workspace/evals/evals.json +56 -0
  26. package/skills/code-dev-review-fix-workspace/iteration-1/routing-results.md +23 -0
  27. package/skills/convert_pipeline/SKILL.md +423 -439
  28. package/skills/hmos-resources-convert/SKILL.md +623 -0
  29. package/skills/hmos-resources-convert/evals/evals.json +171 -0
  30. package/skills/hmos-resources-convert/references/conversion-rules.md +663 -0
  31. package/skills/hmos-resources-convert/references/dependency-analysis-rules.md +388 -0
  32. package/skills/hmos-resources-convert/references/resource-mapping-rules.md +457 -0
  33. package/skills/hmos-resources-convert/references/xml-drawable-to-svg-rules.md +513 -0
  34. package/skills/hmos-resources-convert/template/AppScope/app.json5 +10 -0
  35. package/skills/hmos-resources-convert/template/AppScope/resources/base/element/string.json +8 -0
  36. package/skills/hmos-resources-convert/template/AppScope/resources/base/media/background.png +0 -0
  37. package/skills/hmos-resources-convert/template/AppScope/resources/base/media/foreground.png +0 -0
  38. package/skills/hmos-resources-convert/template/AppScope/resources/base/media/layered_image.json +7 -0
  39. package/skills/hmos-resources-convert/template/build-profile.json5 +42 -0
  40. package/skills/hmos-resources-convert/template/code-linter.json5 +32 -0
  41. package/skills/hmos-resources-convert/template/entry/build-profile.json5 +33 -0
  42. package/skills/hmos-resources-convert/template/entry/hvigorfile.ts +6 -0
  43. package/skills/hmos-resources-convert/template/entry/obfuscation-rules.txt +23 -0
  44. package/skills/hmos-resources-convert/template/entry/oh-package.json5 +10 -0
  45. package/skills/hmos-resources-convert/template/entry/src/main/ets/entryability/EntryAbility.ets +48 -0
  46. package/skills/hmos-resources-convert/template/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets +16 -0
  47. package/skills/hmos-resources-convert/template/entry/src/main/ets/pages/Index.ets +23 -0
  48. package/skills/hmos-resources-convert/template/entry/src/main/module.json5 +55 -0
  49. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/element/color.json +8 -0
  50. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/element/float.json +8 -0
  51. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/element/string.json +16 -0
  52. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/background.png +0 -0
  53. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/foreground.png +0 -0
  54. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/layered_image.json +7 -0
  55. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/startIcon.png +0 -0
  56. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/profile/backup_config.json +3 -0
  57. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/profile/main_pages.json +5 -0
  58. package/skills/hmos-resources-convert/template/entry/src/main/resources/dark/element/color.json +8 -0
  59. package/skills/hmos-resources-convert/template/entry/src/mock/mock-config.json5 +2 -0
  60. package/skills/hmos-resources-convert/template/entry/src/ohosTest/ets/test/Ability.test.ets +35 -0
  61. package/skills/hmos-resources-convert/template/entry/src/ohosTest/ets/test/List.test.ets +5 -0
  62. package/skills/hmos-resources-convert/template/entry/src/ohosTest/module.json5 +16 -0
  63. package/skills/hmos-resources-convert/template/entry/src/test/List.test.ets +5 -0
  64. package/skills/hmos-resources-convert/template/entry/src/test/LocalUnit.test.ets +33 -0
  65. package/skills/hmos-resources-convert/template/hvigor/hvigor-config.json5 +23 -0
  66. package/skills/hmos-resources-convert/template/hvigorfile.ts +6 -0
  67. package/skills/hmos-resources-convert/template/oh-package-lock.json5 +28 -0
  68. package/skills/hmos-resources-convert/template/oh-package.json5 +10 -0
  69. package/skills/hmos-resources-convert/tools/apktool.bat +85 -0
  70. package/skills/hmos-resources-convert/tools/apktool_3.0.1.jar +0 -0
  71. package/skills/hmos-ui-align/SKILL.md +182 -0
  72. package/skills/hmos-ui-align/config-example.json +11 -0
  73. package/skills/hmos-ui-align/config.json +11 -0
  74. package/skills/hmos-ui-align/diff_analysis.md +53 -0
  75. package/skills/hmos-ui-align/page_align.md +62 -0
  76. package/skills/hmos-ui-align/readme.md +231 -0
  77. package/skills/hmos-ui-align/references/Comparison_Template.md +2 -0
  78. 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
  79. 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
  80. 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
  81. 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
  82. 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
  83. 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
  84. 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
  85. 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
  86. 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
  87. 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
  88. 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
  89. 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
  90. 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
  91. 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
  92. package/skills/hmos-ui-align/references/UI_Analysis_Template.md +4 -0
  93. package/skills/hmos-ui-align/references/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2535 -0
  94. package/skills/hmos-ui-align/references/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -0
  95. package/skills/hmos-ui-align/references/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -0
  96. package/skills/hmos-ui-align/scripts/app_feature_verify.py +443 -0
  97. package/skills/hmos-ui-align/scripts/navigation-capure.md +37 -0
  98. package/skills/hmos-ui-align/scripts/page_capture.py +592 -0
  99. package/skills/hmos-ui-align-batch/SKILL.md +99 -0
  100. package/skills/hmos-ui-align-batch/references/conversion-procedure.md +180 -0
  101. package/skills/hmos-ui-align-batch/references/mappings/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2535 -0
  102. package/skills/hmos-ui-align-batch/references/mappings/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -0
  103. package/skills/hmos-ui-align-batch/references/mappings/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -0
  104. 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
  105. 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
  106. 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
  107. 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
  108. 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
  109. 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
  110. 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
  111. 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
  112. 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
  113. 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
  114. package/skills/hmos-ui-align-batch/references/mvvm/MVVM/346/250/241/345/274/217/357/274/210V1/357/274/211.md +911 -0
  115. 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
  116. 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
  117. package/skills/hmos-ui-align-batch/scripts/android_parse_fast.py +1606 -0
  118. package/skills/self-test/SKILL.md +369 -0
  119. package/skills/self-test/readme.md +309 -0
  120. package/skills/spec-generator-skill/SKILL.md +332 -0
  121. package/skills/spec-generator-skill/references/android-platform-tokens.md +105 -0
  122. package/skills/spec-generator-skill/references/spec-sample-1.md +78 -0
  123. package/skills/spec-generator-skill/references/spec-sample-2.md +58 -0
  124. package/skills/spec-generator-skill/references/spec-sample-3.md +116 -0
  125. package/skills/spec-generator-skill/references/step4-report-template.md +33 -0
  126. package/agents/self-test-setup.md +0 -165
  127. package/dist/context/resources/sdkConfig.json +0 -24
  128. package/src/context/resources/sdkConfig.json +0 -24
@@ -0,0 +1,369 @@
1
+ ---
2
+ name: self-test
3
+ description: "Run on-device self-test for a HarmonyOS app. Parse test_case.md, install the HAP, execute AutoTest, and produce a verification report. Optionally enters a test-and-fix loop. Triggers on phrases like '跑自测', '运行自测', '执行自测', '自动测试', '设备测试', '跑用例', '跑自动化测试', 'self test', 'run autotest'."
4
+ allowed-tools:
5
+ - Read
6
+ - Bash
7
+ - Agent
8
+ - Glob
9
+ - AskUserQuestion
10
+ ---
11
+
12
+ # Self-Test Skill
13
+
14
+ You are a **Self-Test Runner**. Your job is to invoke the `self-tester` with the correct parameters, optionally drive a test-and-fix loop (test → fix → build → retest, default up to 3 rounds, configurable via `max-rounds`), and surface results to the user. You do NOT run test tools directly — you delegate all test work to `self-tester`.
15
+
16
+ ---
17
+
18
+ ## Prerequisites
19
+
20
+ The skill requires two user inputs: `test-case-path` and `hap-path`. `output-path` is optional — if omitted, it defaults to the directory containing `test-case-path`. After the initial test the skill can optionally enter a test-and-fix loop. Each round writes outputs into `<output-path>/round-{n}/` as a snapshot for history; the canonical "latest" copies live at `<output-path>/` root.
21
+
22
+ A signed `.hap` file is required (this is a device test — the HAP will be installed on a real HarmonyOS device). Confirm the HAP source with the user before proceeding.
23
+
24
+ ---
25
+
26
+ ## Step 1 — Parse Inputs
27
+
28
+ Extract the following from the user's message. If any required input is missing, use `AskUserQuestion` with the template below — do not guess and do not invent paths.
29
+
30
+ | Variable | Required | Meaning | Typical Phrasing |
31
+ |----------|----------|---------|------------------|
32
+ | `test-case-path` | yes | Path to test_case.md | "测试用例在...", "用例文件...", "test case path" |
33
+ | `output-path` | no (default: directory of `test-case-path`) | Directory for all output artifacts | "输出到...", "产物目录...", "output to..." |
34
+ | `hap-path` | yes | Path to the signed .hap file | "HAP路径...", "安装包在...", "hap file..." |
35
+ | `pre-test-case-path` | optional | Path to pre_test_case.md | "前置用例...", "pre test case..." |
36
+ | `android-project-path` | optional (for fix loop) | Path to Android source project for reference-based fixing | "Android路径...", "android project..." |
37
+ | `max-rounds` | optional, default `3` | Max iterations for the test-and-fix loop. Must be a positive integer (`>= 1`). Only meaningful when the fix loop is enabled. | "最多 X 轮", "max rounds X", "迭代 X 次" |
38
+
39
+ **AskUserQuestion template (use this exact shape — do NOT ad-lib free-form questions):**
40
+
41
+ ```
42
+ question: "缺少必填参数 <param>。请提供具体路径。"
43
+ choices:
44
+ - { value: "<typed_path>", label: "提供具体路径(在补充消息里给出绝对路径)" }
45
+ ```
46
+
47
+ Map the user's reply back to the variable.
48
+
49
+ **Default `output-path`**: If the user did not provide `output-path`, set it to the parent directory of `test-case-path` (the directory portion, without the filename). Use this resolved value everywhere downstream.
50
+
51
+ **Validation command** (platform-agnostic — adapt to OS):
52
+
53
+ Verify that `test-case-path` and `hap-path` point to readable files and `output-path` is an existing directory (create if missing).
54
+
55
+ | OS | Example check |
56
+ |----|---------------|
57
+ | macOS / Linux / bash on Windows | `test -f "<path>" && echo OK` |
58
+ | Native PowerShell on Windows | `Test-Path -LiteralPath "<path>" -PathType Leaf` |
59
+
60
+ Pick whichever shell is available — the operation, not the syntax, is what matters.
61
+
62
+ ---
63
+
64
+ ## Step 2 — Test-and-Fix Loop
65
+
66
+ ### Entry — Ask User (Opt-In for Fix Loop)
67
+
68
+ Before entering the loop, if the user did NOT already say "自动修复" / "fix and retest" / "自动修", ask:
69
+
70
+ > 检测到将进入测试修复循环。是否启用自动修复和重测?(最多 `<MAX_ROUNDS>` 轮,每轮测试失败后自动修代码、重建 HAP、重新测试)
71
+
72
+ Substitute `<MAX_ROUNDS>` in the question text with the parsed value (default `3`).
73
+
74
+ - User says yes / "是" / "好" / "修" → proceed with the full loop below (2.0 → 2A → 2B → 2C → 2D).
75
+ - User says no / "不用" / "skip" → run **2A only** (single test round), skip 2B–2D, snapshot the round directory (2.5), then go to Step 3.
76
+
77
+ > If the user explicitly said "自动修复" / "fix and retest" in the original message, skip the question and enter the full loop directly.
78
+
79
+ ---
80
+
81
+ ### 2.0 — Loop Setup
82
+
83
+ 1. Record `CURRENT_HAP = <hap-path>`.
84
+ 2. Initialize `round = 1`, `MAX_ROUNDS = <max-rounds from Step 1, default 3>`. If the parsed value is missing or not a positive integer, use `3`.
85
+ 3. Set `ROUND_DIR = <output-path>/round-1`. Create the directory.
86
+ 4. `PROJECT_ROOT` is **unset** at this point — it will be read after round 1's agent invocation produces `<output-path>/app-metadata.json`.
87
+ 5. Mark step description with round info (e.g., "**Round 1/<MAX_ROUNDS>**").
88
+
89
+ ---
90
+
91
+ ### 2A — Test (per round)
92
+
93
+ **Round 1 invocation** — runs the parse phase plus the test phase:
94
+
95
+ ```
96
+ Agent(
97
+ subagent_type="self-tester",
98
+ description="Run Device Tests (Round 1)",
99
+ prompt="<assembled prompt>"
100
+ )
101
+ ```
102
+
103
+ Assemble the prompt by joining these lines with `\n`, skipping any line whose value is unset:
104
+
105
+ - `hap-path: <CURRENT_HAP>`
106
+ - `output-path: <output-path>` (the ROOT — the agent always writes here)
107
+ - `test-case-path: <test-case-path>`
108
+ - `pre-test-case-path: <pre-test-case-path>` (only if provided / resolved)
109
+ - `setup: true`
110
+
111
+ After the agent returns, read `<output-path>/app-metadata.json` and extract `project_root` → store as `PROJECT_ROOT`. This is the canonical source from now on.
112
+
113
+ **Round 2+ invocation** — skips the parse phase and reuses the JSONs round 1 produced:
114
+
115
+ ```
116
+ Agent(
117
+ subagent_type="self-tester",
118
+ description="Run Device Tests (Round {round})",
119
+ prompt="hap-path: <CURRENT_HAP>\noutput-path: <output-path>\nsetup: false"
120
+ )
121
+ ```
122
+
123
+ Before each round 2+ invocation, apply the **PROJECT_ROOT refresh rule**: re-read `<output-path>/app-metadata.json` (canonical source). If the previous round's `<PREV_ROUND_DIR>/app-metadata.json` exists (build-fixer may have written one for a relocated project root), the round-dir copy overrides the root copy for this round.
124
+
125
+ ---
126
+
127
+ ### 2A.1 — Detect early-exit (sentinel) reports first
128
+
129
+ The agent writes a degraded sentinel report when T1 / T3 / T4 / T7 fail before the case table is rendered. Look at the first two non-frontmatter lines of `<output-path>/self-test-report.md`:
130
+
131
+ ```bash
132
+ grep -m1 -E '^status:' "<output-path>/self-test-report.md"
133
+ grep -m1 -E '^reason:' "<output-path>/self-test-report.md"
134
+ ```
135
+
136
+ - If the first line matches `status: FAIL` → this is a sentinel report. Set `stop_reason = agent_early_exit`, capture the `reason:` line for the user (`early_exit_reason = <reason>`), snapshot the round (2.5), and exit the loop. Do NOT enter 2B (the fixer cannot fix an environment / connectivity / config issue).
137
+ - Otherwise → proceed to 2A.2 below.
138
+
139
+ ---
140
+
141
+ ### 2A.2 — Parse the normal case table
142
+
143
+ Read `<output-path>/self-test-report.md` (first 80 lines). Extract:
144
+ - `total` — total test cases
145
+ - `passed` — passed count
146
+ - `failed` — failed count
147
+
148
+ **Empty-suite guard**: If `total == 0` (e.g., `testcases.json` happened to be empty), set `stop_reason = no_testcases`, surface a clear message to the user (`<output-path>/testcases.json contains 0 cases — nothing to run`), snapshot the round (2.5), and exit the loop. Do NOT enter the fix loop.
149
+
150
+ Otherwise: Set `round_all_passed = true` if `failed == 0` and `passed == total` (and `total > 0`, which the guard above ensures).
151
+
152
+ ---
153
+
154
+ ### 2B — Fix (if failed > 0)
155
+
156
+ If `round_all_passed`:
157
+ - Skip 2B and 2C.
158
+ - Set `stop_reason = all_passed`.
159
+ - Snapshot the round (2.5) and exit the loop.
160
+
161
+ If `failed > 0`:
162
+
163
+ Launch `self-test-fixer`. Use `PROJECT_ROOT`:
164
+
165
+ ```
166
+ Agent(
167
+ subagent_type="self-test-fixer",
168
+ description="Fix Self-Test Failures (Round {round})",
169
+ prompt="self-test-report-path: <output-path>/self-test-report.md\nharmonyos-project-path: <PROJECT_ROOT>\noutput-path: <ROUND_DIR>"
170
+ )
171
+ ```
172
+
173
+ > `android-project-path` is optional — if the user mentioned an Android source path, add the line `android-project-path: <android-project-path>` to the prompt. Omit otherwise.
174
+
175
+ After completion, read `<ROUND_DIR>/self-test-fix-report.md` (first 60 lines). Extract:
176
+ - `confirmed` — white-box confirmed defect count
177
+ - `false_positives` — false positive count
178
+ - `fixed` — successfully fixed count
179
+ - `failed_to_fix` — failed to fix count
180
+
181
+ Set `round_no_confirmed_defects = true` if `confirmed == 0` (all failures are false positives).
182
+
183
+ Surface a one-line summary:
184
+
185
+ > Round N: test=<passed>/<total>, confirmed=X, fixed=Y, false_positives=Z
186
+
187
+ ---
188
+
189
+ ### 2C — Build (if defects were confirmed)
190
+
191
+ If `round_no_confirmed_defects`:
192
+ - Skip 2C.
193
+ - Set `stop_reason = no_confirmed_defects`.
194
+ - Snapshot the round (2.5) and exit the loop.
195
+
196
+ If `confirmed > 0`:
197
+
198
+ Launch `build-fixer` with `--signed`:
199
+
200
+ ```
201
+ Agent(
202
+ subagent_type="build-fixer",
203
+ description="Rebuild Signed HAP After Fix (Round {round})",
204
+ prompt="harmonyos-project-path: <PROJECT_ROOT>\noutput-path: <ROUND_DIR>\n--signed"
205
+ )
206
+ ```
207
+
208
+ After completion, find the new signed HAP in `ROUND_DIR`:
209
+
210
+ 1. `<ROUND_DIR>/entry-default-signed.hap`
211
+ 2. First `<ROUND_DIR>/*-signed.hap`
212
+
213
+ If no HAP found → report "Build did not produce a signed HAP — cannot re-test." Set `stop_reason = no_signed_hap`. Snapshot the round (2.5) and exit the loop.
214
+
215
+ Update `CURRENT_HAP` to the new HAP path.
216
+
217
+ ---
218
+
219
+ ### 2D — Loop Control
220
+
221
+ ```
222
+ # stop_reason may already be set by 2A.1 (agent_early_exit), 2A.2 (no_testcases),
223
+ # 2B (all_passed / no_confirmed_defects), or 2C (no_signed_hap).
224
+ if stop_reason is set: snapshot (2.5) and exit loop
225
+ elif round >= MAX_ROUNDS: stop_reason = max_rounds_reached; snapshot (2.5); exit loop
226
+ else:
227
+ snapshot (2.5) # snapshot the just-completed round
228
+ round += 1
229
+ ROUND_DIR = <output-path>/round-{round}
230
+ create ROUND_DIR
231
+ go to 2A
232
+ ```
233
+
234
+ ---
235
+
236
+ ### 2.5 — Per-round Snapshot
237
+
238
+ After every round's 2A returns (round 1 and rounds 2+), snapshot these files from `<output-path>/` to `<ROUND_DIR>`. Each copy follows the rule **"skip if source missing"**.
239
+
240
+ | Source | Destination | Notes |
241
+ |--------|-------------|-------|
242
+ | `<output-path>/self-test-report.md` | `<ROUND_DIR>/self-test-report.md` | Always expected after a successful T9. If missing, sentinel-FAIL detection in 2A.1 already routed via `agent_early_exit`. |
243
+ | `<output-path>/task/` | `<ROUND_DIR>/task/` | Per-round runner artifacts. Skip if missing (e.g., agent FAILed before T6 created the dir). |
244
+ | `<output-path>/_extracted.json` | `<ROUND_DIR>/_extracted.json` | Only present after round 1 (S4.2 wrote it). Skip in rounds 2+. |
245
+
246
+ **NOT snapshotted** (these stay at root only as the canonical, cross-round artifacts):
247
+ - `<output-path>/testcases.json` — written once by round 1; rounds 2+ read it in place.
248
+ - `<output-path>/app-metadata.json` — written once by round 1; rounds 2+ read it in place.
249
+
250
+ **`task/` cleanup ordering**: T5 (inside the agent) cleans `<output-path>/task/` at the start of each test invocation. The invariant: by the time T5 wipes the root `task/` at the start of round N, the previous round's `task/` has already been snapshotted into `<output-path>/round-{N-1}/task/`.
251
+
252
+ **Cross-platform copy syntax**:
253
+
254
+ | Shell | Example |
255
+ |-------|---------|
256
+ | bash / sh | `cp -fr "<source>" "<destination>"` |
257
+ | PowerShell | `Copy-Item -LiteralPath "<source>" -Destination "<destination>" -Recurse -Force` |
258
+
259
+ Use forward slashes for cross-platform safety; both shells accept them.
260
+
261
+ ---
262
+
263
+ ### 2.6 — Loop Finalization (HAP mirror only)
264
+
265
+ When the loop exits, mirror the final HAP from `CURRENT_HAP` (which may live under the last `<ROUND_DIR>`) to `<output-path>/entry-default-signed.hap`. This is the only "latest" artifact whose primary location is a round dir; `self-test-report.md`, `testcases.json`, `app-metadata.json`, and `task/` already live at `<output-path>/` as canonical copies.
266
+
267
+ Copy `CURRENT_HAP` → `<output-path>/entry-default-signed.hap` using the same cross-platform syntax above. Skip if `CURRENT_HAP` is already at `<output-path>/entry-default-signed.hap`.
268
+
269
+ ---
270
+
271
+ ## Step 3 — Surface Results
272
+
273
+ Read `<output-path>/self-test-report.md` (first 80 lines) and extract the overview section:
274
+
275
+ ```
276
+ ## 自测报告
277
+
278
+ | 指标 | 值 |
279
+ |------|-----|
280
+ | 设备 | <device-serial> |
281
+ | HAP | <hap-basename> |
282
+ | 测试套件 | <suite-name> |
283
+ | 总用例 | <total> |
284
+ | 通过 | <passed> |
285
+ | 失败 | <failed> |
286
+ | 常规通过率 | <pass-rate>% |
287
+ ```
288
+
289
+ > If the report file is missing or malformed, report the error to the user with the agent's output path — do NOT fabricate results. If the report exists but is truncated or unexpectedly formatted, read up to the first 80 lines for the overview section, and point the user to the full file at `<output-path>/self-test-report.md`.
290
+
291
+ **Pre-case reminder**: If pre-cases failed, note that these are environment/setup issues (permissions, media imports, tutorial skipping), NOT application defects. The regular pass rate (常规通过率) is the primary quality metric.
292
+
293
+ **Point the user to the full report**: `<output-path>/self-test-report.md` and per-round artifacts at `<output-path>/round-{N}/`.
294
+
295
+ ### Loop Summary (if loop ran)
296
+
297
+ After the report, present:
298
+
299
+ ```
300
+ ## 自测修复循环完成
301
+
302
+ | 指标 | 值 |
303
+ |------|-----|
304
+ | 迭代次数 | <round>/<MAX_ROUNDS> |
305
+ | 最终状态 | <passed>/<total> 通过(<pass-rate>%) |
306
+ | 停止原因 | <stop_reason> |
307
+ ```
308
+
309
+ `<stop_reason>` is one of:
310
+ - `all_passed` — all cases passed, loop exited successfully.
311
+ - `no_confirmed_defects` — failures exist but fixer judged them all as false positives.
312
+ - `no_signed_hap` — build-fixer did not produce a signed HAP, loop cannot continue.
313
+ - `max_rounds_reached` — hit the configured `MAX_ROUNDS` cap (default 3) with failures remaining.
314
+ - `no_testcases` — `<output-path>/testcases.json` contained 0 cases; nothing to run. Surface the path so the user can inspect.
315
+ - `agent_early_exit` — `self-tester` wrote a sentinel FAIL report (config / device / autotest-dir / batch crash / `setup: false` precondition failure). Surface the captured `early_exit_reason` so the user knows what to fix manually.
316
+
317
+ If failures remain (for `max_rounds_reached`), list them briefly (scenario names from the report overview). Also surface paths to `<ROUND_DIR>/self-test-fix-report.md` and `<ROUND_DIR>/build-fix-report.md` (from the final round, when those reports exist).
318
+
319
+ ---
320
+
321
+ ## Error Handling
322
+
323
+ | Scenario | Action |
324
+ |----------|--------|
325
+ | `test-case-path` does not exist | Ask user for correct path, do not proceed |
326
+ | `hap-path` does not exist | Ask user for correct HAP path, do not proceed |
327
+ | `output-path` parent does not exist | Create it, proceed |
328
+ | Agent returns error / times out | Report the error to user. Suggest: check device connection (`hdc list targets`), verify HAP is valid, check `config.yaml` has real api_key |
329
+ | `<output-path>/self-test-report.md` missing after agent completes | Report: "Agent completed but no report was generated. Check agent output at <output-path>." |
330
+ | `self-test-report.md` exists but format is unrecognizable | Show the file path, report the first 80 lines as context, let user investigate |
331
+ | Device not found (agent reports "No device") | Remind user: connect device via USB, verify `hdc list targets` shows the device |
332
+ | Pre-case failures in report | Note: these are environment issues, not app defects. Highlight regular pass rate |
333
+ | `<output-path>/testcases.json` or `app-metadata.json` missing after round 1 | Round 1 setup may have failed; inspect agent output at `<output-path>/` |
334
+ | `<output-path>/testcases.json` is empty (`total == 0` in 2A) | Report: "testcases.json contains 0 cases — nothing to run." Exit loop with `stop_reason = no_testcases`. Do NOT enter the fix loop. |
335
+ | `self-tester` writes a sentinel FAIL report (first line `status: FAIL`) | Capture the `reason:` line. Exit loop with `stop_reason = agent_early_exit` and surface the captured reason. Do NOT enter the fix loop — these failures (config / device / autotest-dir / crash / timeout / setup=false preconditions) are not application defects. |
336
+ | Fixer returns `confirmed == 0` (all false positives) | Exit loop with `stop_reason = no_confirmed_defects`. Surface the fix report summary. |
337
+ | Build-fixer produces no signed HAP in ROUND_DIR | Report: "Build did not produce a signed HAP — cannot re-test." Exit loop with `stop_reason = no_signed_hap`. |
338
+ | Loop reaches `MAX_ROUNDS` (default 3) with failures remaining | Report `stop_reason = max_rounds_reached`. Surface final pass rate and remaining failures. |
339
+ | `app-metadata.json` missing after round 1 (PROJECT_ROOT unknown) | Surface agent error; PROJECT_ROOT cannot be resolved. Do NOT enter 2B. |
340
+ | Signing config missing in `build-profile.json5` before build | Report: "Signing configuration not found. Please open project in DevEco Studio, go to File → Project Structure → Signing Configs, enable Automatically generate signature, then re-run." Exit loop. |
341
+
342
+ ---
343
+
344
+ ## Key Constraints
345
+
346
+ - **Delegation only**: Do NOT run test tools directly. Never call `hdc`, `self_test_runner.py`, `AutoTest.batch`, or `report_tool.py` yourself. All test work goes through `self-tester`.
347
+ - **Parameter purity**: Pass only parameter values to the agent's prompt in `key: value` format. Do NOT add extra instructions, format descriptions, schema hints, or implementation suggestions. The agent has its own built-in workflow.
348
+ - **Do NOT read full reports**: Self-test reports can be very large (10KB–200KB). Only read the overview (first 80 lines for test report, first 60 lines for fix report). Point the user to the full file.
349
+ - **Quote all paths**: Paths may contain spaces. Always wrap paths in double quotes in commands.
350
+ - **Pre-cases are environment scripts**: Their failures indicate testing-environment issues, not app bugs. The regular pass rate is the primary quality metric.
351
+ - **Fix-and-retest loop is opt-in**: Follow Step 2 Entry — ask the user unless they already opted in with "自动修复".
352
+ - **Test → Fix → Build is the mandatory order**: Never re-test without rebuilding after a fix (would test old code). Never skip the build step in the loop.
353
+ - **`CURRENT_HAP` must track the latest build**: After each 2C rebuild, update `CURRENT_HAP` to the new signed HAP from `ROUND_DIR`. Never re-test with the old HAP.
354
+ - **Per-round snapshots**: Each round writes its latest artifacts to `<output-path>/` (root), then the SKILL snapshots per-round outputs to `<output-path>/round-{N}/`. The persistent JSONs (`testcases.json`, `app-metadata.json`) are written exactly once by round 1 and consumed unchanged by rounds 2+.
355
+ - **Loop stop conditions**: Normal exits (3) — `all_passed`, `no_confirmed_defects`, `max_rounds_reached`. Error exits (3) — `no_signed_hap` (build did not produce HAP), `no_testcases` (empty testcases.json), `agent_early_exit` (self-tester sentinel FAIL: config / device / autotest-dir / crash / timeout / `setup: false` precondition failure).
356
+ - **Loop iterations are strictly sequential**: Never launch more than one fixer or tester at a time.
357
+
358
+ ## Forbidden
359
+
360
+ - ❌ Running `hdc list targets`, `hdc install`, or any `hdc` command directly
361
+ - ❌ Calling `self_test_runner.py` or `report_tool.py` directly
362
+ - ❌ Reading `test_case.md` or modifying test cases — the agent handles this
363
+ - ❌ Reading the full `self-test-report.md` (read only first 80 lines for summary)
364
+ - ❌ Reading the full `self-test-fix-report.md` (read only first 60 lines for summary)
365
+ - ❌ Fabricating results when the report is missing or unreadable
366
+ - ❌ Passing `output-path: <output-path>/round-N` to the agent — the agent always writes to `<output-path>/` root; per-round directories are populated by the SKILL's snapshot step
367
+ - ❌ Skipping the build step in the loop (rebuild is mandatory after each confirmed fix)
368
+ - ❌ Re-testing with an old HAP after a build
369
+ - ❌ Launching more than one fixer or tester at a time — loop rounds are strictly sequential