@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.
- package/README.md +141 -124
- package/agents/self-tester.md +259 -233
- 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,309 @@
|
|
|
1
|
+
# Self-Test 使用文档
|
|
2
|
+
|
|
3
|
+
## 简介
|
|
4
|
+
|
|
5
|
+
**Self-Test** 是 HomeTrans 的端到端真机自测能力——你把一份 Markdown 测试用例和一个 HAP 交给我,我帮你把用例跑在鸿蒙真机上,产出可读的测试报告。如果测试失败,我还能**自动分析原因、修改代码、重建签名 HAP、重新测试**,直到全部通过。测试和修复不是两个功能拼在一起,而是一条统一的工作流:你只需要说一句话,剩下的事情系统自动完成。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 我能做什么
|
|
10
|
+
|
|
11
|
+
- **把 Markdown 测试用例变成机器可读的 JSON**:解析你写的 `test_case.md`,自动提取包名、替换应用名,生成 AutoTest 可执行的 `testcases.json`。
|
|
12
|
+
- **在鸿蒙真机上跑自动化测试**:连接 USB 设备,安装 HAP,逐条执行用例,生成带通过率和失败详情的报告。
|
|
13
|
+
- **测试失败后自动修复并重测**:读到失败报告 → 白盒审查源码 → 修改代码 → 重新编译签名 HAP → 重新测试 → 如果还有失败则继续循环,默认最多 3 轮(可通过 `max-rounds` 参数配置)。
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 快速开始
|
|
18
|
+
|
|
19
|
+
你说一句话,系统跑完全程。最简写法:
|
|
20
|
+
|
|
21
|
+
> 跑自测,自动修复
|
|
22
|
+
|
|
23
|
+
更完整的写法(指定所有路径):
|
|
24
|
+
|
|
25
|
+
> 跑自测,测试用例在 `D:\project\test_case.md`,HAP 在 `D:\project\entry-default-signed.hap`,输出到 `D:\project\output`
|
|
26
|
+
|
|
27
|
+
**然后会发生什么:**
|
|
28
|
+
|
|
29
|
+
1. **测试与修复循环** — 默认最多 3 轮(可通过 `max-rounds` 参数配置),每轮跑完后产物快照到 `output-path/round-{n}/`:
|
|
30
|
+
- 首轮:解析 `test_case.md` → 写出 `output-path/testcases.json` 与 `app-metadata.json` → 连接真机、安装 HAP、跑 AutoTest → 产出 `output-path/self-test-report.md`
|
|
31
|
+
- 测试完成后,SKILL 把当轮的 `self-test-report.md`、`task/`、`_extracted.json`(若有)快照到 `output-path/round-{n}/`
|
|
32
|
+
- Fix:白盒审查代码 → 修改源码 → 产出 `round-{n}/self-test-fix-report.md`
|
|
33
|
+
- Build:重新编译 → 产出 `round-{n}/entry-default-signed.hap` 和 `build-fix-report.md`
|
|
34
|
+
- 后续轮:跳过解析阶段,直接读首轮已生成的 `testcases.json` + `app-metadata.json`,用新 HAP 跑测试 → 同样快照到对应轮 `round-{n}/`
|
|
35
|
+
2. **HAP 镜像** — 循环结束后,最后一轮的签名 HAP 复制到 `output-path/entry-default-signed.hap`,方便直接取用
|
|
36
|
+
|
|
37
|
+
**最终产物**(在 `output-path` 下):
|
|
38
|
+
|
|
39
|
+
| 文件 | 位置 | 内容 |
|
|
40
|
+
|------|------|------|
|
|
41
|
+
| `testcases.json` | 根目录 | 结构化用例,首轮生成后所有轮共享 |
|
|
42
|
+
| `app-metadata.json` | 根目录 | 包名、应用名、项目路径,首轮生成后所有轮共享 |
|
|
43
|
+
| `self-test-report.md` | 根目录(每轮覆盖,最终为最后一轮) | 测试报告 |
|
|
44
|
+
| `task/` | 根目录(每轮覆盖,最终为最后一轮) | AutoTest 原始产物 |
|
|
45
|
+
| `entry-default-signed.hap` | 根目录(循环结束后镜像) | 最后一轮编译的签名 HAP |
|
|
46
|
+
| `round-{n}/` | 子目录(每轮历史快照) | 每轮跑完后的 `self-test-report.md`、`task/`、`self-test-fix-report.md`、`build-fix-report.md`、`entry-default-signed.hap` 等 |
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 输入参数
|
|
51
|
+
|
|
52
|
+
### 测试参数
|
|
53
|
+
|
|
54
|
+
| 参数 | 是否必填 | 说明 |
|
|
55
|
+
|------|----------|------|
|
|
56
|
+
| `hap-path` | 必填 | 签名后的 `.hap` 安装包路径 |
|
|
57
|
+
| `output-path` | 可选,默认 = `test-case-path` 所在目录 | 所有产物输出到这个目录(`testcases.json`、`app-metadata.json`、`self-test-report.md`、`task/` 都写在此根目录)。不指定时直接写在用例文件同目录 |
|
|
58
|
+
| `test-case-path` | `setup=true` 时必填 | `test_case.md` 的路径 |
|
|
59
|
+
| `pre-test-case-path` | 可选 | 前置用例 `pre_test_case.md` 的路径。不传会自动在同目录查找 |
|
|
60
|
+
| `setup` | 可选,默认 `true` | `true` = 解析 `test_case.md` 写出 JSON,再跑测试;`false` = 跳过解析阶段,直接读取 `<output-path>/testcases.json` 与 `<output-path>/app-metadata.json` 跑测试。两个 JSON 都不存在或为空时硬失败,需要重跑一次 `setup=true` |
|
|
61
|
+
|
|
62
|
+
### 自动修复参数
|
|
63
|
+
|
|
64
|
+
以下参数仅在进入修复循环时使用,由 Skill 自动从 `app-metadata.json` 获取,你通常不需要手动指定:
|
|
65
|
+
|
|
66
|
+
| 参数 | 必填 | 说明 |
|
|
67
|
+
|------|------|------|
|
|
68
|
+
| `harmonyos-project-path` | 是 | 自动从 `app-metadata.json` 的 `project_root` 字段读取 |
|
|
69
|
+
| `android-project-path` | 否 | Android 参考项目路径。提供后 fixer 会参考 Android 实现来修 bug,质量更高 |
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 输出产物
|
|
74
|
+
|
|
75
|
+
`testcases.json` 和 `app-metadata.json` 在首轮(`setup=true`)写入 `output-path/` 根目录,后续轮直接复用,不再重新生成。`self-test-report.md` 与 `task/` 每轮都会在根目录覆盖更新,跑完每轮后由 SKILL 快照到 `output-path/round-{n}/`。循环结束后,最后一轮的签名 HAP 镜像到根目录。
|
|
76
|
+
|
|
77
|
+
| 文件 | 写入位置 | 内容 |
|
|
78
|
+
|------|----------|------|
|
|
79
|
+
| `testcases.json` | `output-path/` 根目录(首轮写入,跨轮共享) | 结构化的用例列表,供 AutoTest 逐条执行 |
|
|
80
|
+
| `app-metadata.json` | `output-path/` 根目录(首轮写入,跨轮共享) | `{ bundle_name, app_name, project_root }` |
|
|
81
|
+
| `_extracted.json` | `output-path/` 根目录(首轮写入,跨轮快照保留) | 用例提取的中间文件,排查问题时有用,通常不需要关注 |
|
|
82
|
+
| `self-test-report.md` | `output-path/` 根目录(每轮覆盖,跨轮快照保留) | 可读的测试报告,含通过率、失败原因、每条用例的 AutoTest 任务路径 |
|
|
83
|
+
| `task/task_<时间戳>/` | `output-path/task/`(每轮覆盖,跨轮快照保留) | 每条用例的 HTML 报告、截图、Agent 日志 |
|
|
84
|
+
| `self-test-fix-report.md` | `output-path/round-{n}/`(Fix 步骤,有失败的轮次) | 白盒审查结论、根因分析、修改内容、修复结果 |
|
|
85
|
+
| `self-test-fix-commit-info.md` | `output-path/round-{n}/`(Fix 步骤) | `commit-id: <hash>` 或 `commit-id: none` |
|
|
86
|
+
| `build-fix-report.md` | `output-path/round-{n}/`(Build 步骤) | 编译是否成功、修复了哪些编译问题 |
|
|
87
|
+
| `build-fix-commit-info.md` | `output-path/round-{n}/`(Build 步骤) | `commit-id: <hash>` 或 `commit-id: none` |
|
|
88
|
+
| `entry-default-signed.hap` | `output-path/round-{n}/`(Build 步骤);循环结束后镜像到 `output-path/` 根目录 | 修复后重新编译的签名 HAP |
|
|
89
|
+
|
|
90
|
+
> **提示**:`output-path/` 根目录下的报告和 task 始终是最近一轮的最新产物;要查看某一轮的历史快照,进入对应的 `round-{n}/` 目录即可。
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## 工作流程
|
|
95
|
+
|
|
96
|
+
一次完整的 Self-Test 跑下来会经历下面这些阶段,简化的流程示意:
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
你提供: test_case.md + HAP
|
|
100
|
+
│
|
|
101
|
+
▼
|
|
102
|
+
┌─ 解析阶段(仅首轮)─────────────────────────────────────────┐
|
|
103
|
+
│ │
|
|
104
|
+
│ 读取 test_case.md → LLM 提取动作/预期结果 → 替换应用名为包名 │
|
|
105
|
+
│ → Python 脚本生成 testcases.json + 写入 app-metadata.json │
|
|
106
|
+
│ │
|
|
107
|
+
└──────────────────────────────┬───────────────────────────────┘
|
|
108
|
+
│
|
|
109
|
+
▼
|
|
110
|
+
┌─ 测试与修复循环(每轮跑完后快照到 output-path/round-{n}/)──┐
|
|
111
|
+
│ │
|
|
112
|
+
│ ┌── Test ─────────────────────────────────────────────┐ │
|
|
113
|
+
│ │ 检测真机连接 → 安装 HAP → AutoTest 批量执行用例 │ │
|
|
114
|
+
│ │ → 每 60 秒轮询一次 → 产出 round-{n}/self-test-report │ │
|
|
115
|
+
│ └──────────────────────┬──────────────────────────────┘ │
|
|
116
|
+
│ │ │
|
|
117
|
+
│ 全部通过? │
|
|
118
|
+
│ ┌──────┴──────┐ │
|
|
119
|
+
│ ▼ ▼ │
|
|
120
|
+
│ 是(退出循环) 否(进入修复) │
|
|
121
|
+
│ │ │
|
|
122
|
+
│ ┌── Fix ──────────────────────────────────────────────┐ │
|
|
123
|
+
│ │ self-test-fixer 读报告 → 白盒审查代码 │ │
|
|
124
|
+
│ │ → 区分 confirmed(真bug) / false_positive(误报) │ │
|
|
125
|
+
│ │ → 只修改 confirmed → git commit │ │
|
|
126
|
+
│ │ → 产出 round-{n}/self-test-fix-report.md │ │
|
|
127
|
+
│ └──────────────────────┬──────────────────────────────┘ │
|
|
128
|
+
│ │ │
|
|
129
|
+
│ 有确认缺陷? │
|
|
130
|
+
│ ┌──────┴──────┐ │
|
|
131
|
+
│ ▼ ▼ │
|
|
132
|
+
│ 否(退出循环) 是(进入编译) │
|
|
133
|
+
│ │ │
|
|
134
|
+
│ ┌── Build ────────────────────────────────────────────┐ │
|
|
135
|
+
│ │ build-fixer --signed 重新编译 → 产出签名 HAP │ │
|
|
136
|
+
│ │ → 产出 round-{n}/build-fix-report.md │ │
|
|
137
|
+
│ │ → 产出 round-{n}/entry-default-signed.hap │ │
|
|
138
|
+
│ └──────────────────────┬──────────────────────────────┘ │
|
|
139
|
+
│ │ │
|
|
140
|
+
│ 未达上限? n++; 回到 Test │
|
|
141
|
+
│ ┌──────┴──────┐ │
|
|
142
|
+
│ ▼ ▼ │
|
|
143
|
+
│ 是(下一轮) 否(退出循环) │
|
|
144
|
+
│ │
|
|
145
|
+
└──────────────────────────────────────────────────────────────┘
|
|
146
|
+
│
|
|
147
|
+
▼
|
|
148
|
+
循环结束 → 镜像最终轮报告和 HAP 到 output-path/
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### 循环停止条件
|
|
152
|
+
|
|
153
|
+
满足以下任一条件,循环立即停止:
|
|
154
|
+
|
|
155
|
+
| 条件 | stop_reason | 说明 |
|
|
156
|
+
|------|-------------|------|
|
|
157
|
+
| 全部通过 | `all_passed` | 报告 `failed == 0`,所有用例通过 |
|
|
158
|
+
| 无确认缺陷 | `no_confirmed_defects` | fixer 判定所有失败都是测试误报(false positive),没有需要修改的代码缺陷 |
|
|
159
|
+
| 达到最大轮数 | `max_rounds_reached` | 已完成配置的最大轮数循环(`max-rounds`,默认 3),仍有失败未解决 |
|
|
160
|
+
| 编译未产出 HAP(异常) | `no_signed_hap` | build-fixer 未产出签名 HAP,无法继续测试 |
|
|
161
|
+
| 用例列表为空(异常) | `no_testcases` | `testcases.json` 里 0 条用例,没有可跑的内容。常见原因:解析阶段没识别到 `### Scenario:` 区块 |
|
|
162
|
+
| 自测 agent 早退(异常) | `agent_early_exit` | `self-tester` 在跑用例之前就退出了(设备没连、`config.yaml` 没填、`agents/test-tools/autotest` 目录找不到、batch 启动失败 / 超时 / 崩溃、`setup=false` 但所需 JSON 缺失等)。报告首行会是 `status: FAIL`,第二行 `reason: <原因>`。**这种情况下不会进入 fix 循环**——这些是环境/前置条件问题,不是应用缺陷 |
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## 前置用例(Pre-Cases)
|
|
167
|
+
|
|
168
|
+
如果 `test_case.md` 同目录下有 `pre_test_case.md`,系统会自动把它作为前置用例合并进去。前置用例是一些**环境准备操作**——比如授权弹窗、跳过引导、导入素材、授予权限。
|
|
169
|
+
|
|
170
|
+
- 前置用例在 `testcases.json` 中排在最前面,`case_name` 会自动加 `[PRE] ` 前缀
|
|
171
|
+
- 跑测试时最先执行,为后续用例准备环境
|
|
172
|
+
- **前置用例失败不代表应用有 bug**——通常是没素材、没权限、系统弹窗没弹等环境问题
|
|
173
|
+
- 测试报告会单独标注**常规通过率**(排除前置用例),这才是衡量应用质量的主要指标
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## 报告解读
|
|
178
|
+
|
|
179
|
+
### 测试报告(self-test-report.md)
|
|
180
|
+
|
|
181
|
+
每份报告包含以下部分:
|
|
182
|
+
|
|
183
|
+
- **测试概览**:设备序列号、HAP 文件名、测试套件名、总用例数、通过/失败数、通过率、常规通过率
|
|
184
|
+
- **前置用例**:`[PRE]` 开头的用例,与常规用例分开列出,各自从 1 开始编号(Pre 1、Pre 2... / Case 1、Case 2...)
|
|
185
|
+
- **用例详情**:每条用例的动作、预期结果、AutoTest 判定结果、失败原因
|
|
186
|
+
- **每条用例都标注了 `**AutoTest 任务路径**`**:指向该用例的原始执行目录(HTML 报告、截图、日志)
|
|
187
|
+
|
|
188
|
+
**PASS / FAIL / UNKNOWN 的含义:**
|
|
189
|
+
|
|
190
|
+
- `PASS` — 测试通过
|
|
191
|
+
- `FAIL` — 测试失败或超时/崩溃,`reason` 字段说明原因
|
|
192
|
+
- `UNKNOWN` — 有产出报告但无法明确判定结果
|
|
193
|
+
|
|
194
|
+
`FAIL` 和 `UNKNOWN` 都应视为未通过。
|
|
195
|
+
|
|
196
|
+
### 修复报告(self-test-fix-report.md)
|
|
197
|
+
|
|
198
|
+
- **概览**:失败数 → 确认 bug 数 → 误报数 → 修复成功/失败数
|
|
199
|
+
- **白盒审查结果**:每条失败用例逐一分析,结论为 `confirmed`(代码真有问题)或 `false_positive`(测试误判)
|
|
200
|
+
- **修复计划**:按依赖关系排序的修复列表
|
|
201
|
+
- **修复详情**:每条修复的 Android 参考、根因、具体修改、有效尝试次数、结果
|
|
202
|
+
- **误报说明**:为什么判定为误报,测试 agent 出了什么问题
|
|
203
|
+
- **编译验证**:编译结果及 build-fixer 修复的编译问题
|
|
204
|
+
|
|
205
|
+
### 编译报告(build-fix-report.md)
|
|
206
|
+
|
|
207
|
+
build-fixer 的输出摘要:编译状态、签名类型、迭代次数、修复的编译错误数、文件修改汇总。
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## test_case.md 怎么写
|
|
212
|
+
|
|
213
|
+
用 Markdown 写,结构如下:
|
|
214
|
+
|
|
215
|
+
```markdown
|
|
216
|
+
# 测试套件名
|
|
217
|
+
|
|
218
|
+
## Spec: 功能模块
|
|
219
|
+
### Scenario: 新建歌单
|
|
220
|
+
- 动作:点击新建歌单按钮
|
|
221
|
+
- 预期结果:弹出新建歌单对话框
|
|
222
|
+
- 动作:输入歌单名称"测试歌单"
|
|
223
|
+
- 预期结果:歌单创建成功,出现在列表顶部
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
- `# 标题` → 测试套件名,会出现在报告里
|
|
227
|
+
- `## Spec:` → 功能模块,纯逻辑分组,不影响执行
|
|
228
|
+
- `### Scenario:` → 一条用例
|
|
229
|
+
- `- 动作:` → 测试操作
|
|
230
|
+
- `- 预期结果:` → 期望结果(多行用中文逗号连接)
|
|
231
|
+
|
|
232
|
+
**不需要手动替换应用名**。动作里写的显示名称(如"简单图库"、"Tuku")系统会自动替换成包名(如 `com.example.tuku`),确保 AutoTest 能正确识别目标应用。
|
|
233
|
+
|
|
234
|
+
**以下内容会被自动忽略**:`- 前置条件:`、`## 页面描述注解`、`## 编号映射表`。
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## 环境要求
|
|
239
|
+
|
|
240
|
+
### 基础环境
|
|
241
|
+
|
|
242
|
+
- 操作系统:**Windows** 是主要测试目标;macOS/Linux 上的核心命令(`hdc`、`uv`、POSIX 工具链)也能跑,Skill 里涉及到的复制操作会按可用 shell 自适应
|
|
243
|
+
- `hdc` 已安装并在 PATH 中
|
|
244
|
+
- `uv` 已安装(Python 包管理)
|
|
245
|
+
- `agents/test-tools/autotest/config.yaml` 已配置真实 api_key
|
|
246
|
+
- 鸿蒙真机通过 USB 连接,`hdc list targets` 能看到设备
|
|
247
|
+
- 签名后的 `.hap` 文件
|
|
248
|
+
|
|
249
|
+
### 自动修复附加条件
|
|
250
|
+
|
|
251
|
+
- `app-metadata.json` 存在(setup 阶段自动产出,内含 `project_root`)
|
|
252
|
+
- 建议项目在 Git 仓库中(不在也可以修复,但不会自动 commit;`commit-id: none`)
|
|
253
|
+
- 签名配置已存在于 `build-profile.json5`(DevEco Studio → File → Project Structure → Signing Configs → Automatically generate signature)
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## 常见问题
|
|
258
|
+
|
|
259
|
+
**Q: 报 "No HarmonyOS device connected"?**
|
|
260
|
+
|
|
261
|
+
A: 检查 USB 连接,跑 `hdc list targets` 看看有没有设备 SN。重新插拔 USB,在设备上重新授权 USB 调试。
|
|
262
|
+
|
|
263
|
+
**Q: 报 config.yaml missing 或 api_key 没填?**
|
|
264
|
+
|
|
265
|
+
A: 复制 `agents/test-tools/autotest/config.yaml.example` 为 `config.yaml`,把 `YOUR_API_KEY_HERE` 替换成真实的 API Key。
|
|
266
|
+
|
|
267
|
+
**Q: 前置用例失败了要不要修代码?**
|
|
268
|
+
|
|
269
|
+
A: 不用。前置用例是环境准备脚本,失败意味着环境条件不满足(没素材、没权限、引导弹窗等),不影响应用的常规通过率。
|
|
270
|
+
|
|
271
|
+
**Q: PASS / FAIL / UNKNOWN 有什么区别?**
|
|
272
|
+
|
|
273
|
+
A: `PASS` — 通过;`FAIL` — 失败/超时/崩溃,有原因说明;`UNKNOWN` — 有报告但无法判定。后面两个都算未通过。
|
|
274
|
+
|
|
275
|
+
**Q: 测试跑多久?**
|
|
276
|
+
|
|
277
|
+
A: 每条用例大约 6 分钟(含 Agent 决策和执行时间)。整体超时上限 = 用例数 × 6 分钟,超过后自动终止并产出部分报告。
|
|
278
|
+
|
|
279
|
+
**Q: 怎么只重跑失败的用例?**
|
|
280
|
+
|
|
281
|
+
A: 目前每次都跑 `testcases.json` 的全部用例。你可以手动删掉已通过的条目,只保留失败的,然后用 `setup=false` 重新跑(会跳过解析阶段,直接读取 `<output-path>/testcases.json`)。
|
|
282
|
+
|
|
283
|
+
**Q: 产物在哪个目录?**
|
|
284
|
+
|
|
285
|
+
A: `testcases.json` 和 `app-metadata.json` 在 `output-path/` 根目录。测试和修复的每轮产物在 `output-path/round-1/`、`output-path/round-2/`... 子目录中。循环结束后,最终轮的关键文件(报告、HAP)会镜像到 `output-path/` 根目录,方便直接查看。
|
|
286
|
+
|
|
287
|
+
**Q: 怎么启用自动修复?**
|
|
288
|
+
|
|
289
|
+
A: 说"跑自测,自动修复";或者跑完测试后看到有失败,Skill 会主动问你要不要启用,回复"是"就进去了。默认最多 3 轮,需要更多/更少可以加一句"最多 N 轮"(对应 `max-rounds` 参数)。
|
|
290
|
+
|
|
291
|
+
**Q: 自动修复会改我的代码吗?**
|
|
292
|
+
|
|
293
|
+
A: 会修改鸿蒙源码来修 bug,但只在**白盒审查确认是真问题**(`confirmed`)的情况下才会改。误报(`false_positive`)不改,测试用例不改。所有修改会 git commit,可随时 revert。如果不在 Git 仓库中,修改照常进行但不 commit。
|
|
294
|
+
|
|
295
|
+
**Q: 自动修复一轮多久?**
|
|
296
|
+
|
|
297
|
+
A: Fix(白盒分析 + 改代码)约 5-10 分钟,Build(编译)约 2-5 分钟,Retest(重新跑用例)约 N×6 分钟。可以随时中断。
|
|
298
|
+
|
|
299
|
+
**Q: 什么情况下循环会停?**
|
|
300
|
+
|
|
301
|
+
A: 正常退出 3 种:① 全部通过(`all_passed`);② 所有失败都是误报,无代码缺陷需要修复(`no_confirmed_defects`);③ 跑满 `max-rounds` 轮(默认 3)仍有失败(`max_rounds_reached`)。异常退出 3 种:编译未产出签名 HAP(`no_signed_hap`);`testcases.json` 为空(`no_testcases`);自测 agent 早退,写出首行 `status: FAIL` 的 sentinel 报告(`agent_early_exit`,常见原因:设备没连、api_key 没填、batch 崩溃 / 超时)。异常退出不会进入 fix 循环——那些是环境问题,不是代码缺陷。
|
|
302
|
+
|
|
303
|
+
**Q: 需要提供 Android 项目路径吗?**
|
|
304
|
+
|
|
305
|
+
A: 不必须。提供了 fixer 会参考 Android 实现来修 bug,质量更高。不提供也能独立完成,基于白盒代码分析和 HarmonyOS API 文档修复。
|
|
306
|
+
|
|
307
|
+
**Q: 报 "Build did not produce a signed HAP"?**
|
|
308
|
+
|
|
309
|
+
A: 通常是因为 `build-profile.json5` 中的签名配置被清掉了。去 DevEco Studio 重新生成(File → Project Structure → Signing Configs → Automatically generate signature),然后继续循环。
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-generator-skill
|
|
3
|
+
description: "Generate atomic-scenario requirement specs (markdown) from raw .txt requirement batches for Android-to-HarmonyOS migration. Reads a single .txt holding multiple REQ blocks (blank-line separated), explores the Android code graph via GitNexus, writes per-REQ trace files first then synthesizes specs from the trace. Triggers: spec generation, generate spec, requirement to spec, atomic scenarios, scenario decomposition, decompose scenarios, req to spec, code-trace-first, batch req txt."
|
|
4
|
+
license: MIT
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Write
|
|
8
|
+
- Edit
|
|
9
|
+
- Bash
|
|
10
|
+
- Glob
|
|
11
|
+
- Grep
|
|
12
|
+
- Skill
|
|
13
|
+
- AskUserQuestion
|
|
14
|
+
- TaskCreate
|
|
15
|
+
- TaskList
|
|
16
|
+
- TaskUpdate
|
|
17
|
+
- mcp__gitnexus__query
|
|
18
|
+
- mcp__gitnexus__context
|
|
19
|
+
- mcp__gitnexus__impact
|
|
20
|
+
- mcp__gitnexus__cypher
|
|
21
|
+
- mcp__gitnexus__list_repos
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# Spec Generator Skill
|
|
25
|
+
|
|
26
|
+
Produce atomic-scenario requirement specs from Android source code for Android-to-HarmonyOS migration. The input is a single `.txt` carrying multiple REQ blocks (blank-line separated); each block is processed end-to-end (3.1 → 3.5) before the next block starts.
|
|
27
|
+
|
|
28
|
+
This skill uses GitNexus as the code-graph backend: the `gitnexus-cli` skill for index management, and `mcp__gitnexus__*` tools for code queries. Spec synthesis MUST go through a trace file written in 3.3 — never synthesize from conversation context.
|
|
29
|
+
|
|
30
|
+
## Expected Input
|
|
31
|
+
|
|
32
|
+
- `requirement-description-file`: absolute path to a single `.txt` file containing one or more REQ blocks separated by blank lines. Within each block, the first line is the REQ title (often a dash-separated settings path like `Settings-UserInterface-ImmersionMode`), and the remaining lines are the body (behavior, default values, toggles). Required.
|
|
33
|
+
- `android-project-path`: absolute path to the Android project root (must be inside a Git repo). Required.
|
|
34
|
+
- `spec-output-dir`: absolute path to the directory where spec files will be written (will be created if missing). Required.
|
|
35
|
+
|
|
36
|
+
**Caller example**:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
requirement-description-file: C:\proj\reqs\req-batch2-zh.txt
|
|
40
|
+
android-project-path: C:\proj\SaltPlayer\
|
|
41
|
+
spec-output-dir: C:\proj\specs-out\
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Expected Output
|
|
45
|
+
|
|
46
|
+
- One markdown spec per REQ block, written to `<spec-output-dir>/<feature>-SPEC.md`. `<feature>` is the ≤ 20-character slug distilled in 3.1 (use the REQ's own language for the slug; ASCII / kebab-case acceptable when shorter).
|
|
47
|
+
- One intermediate code-trace file per REQ block, written to `<spec-output-dir>/.trace/<feature>.md` (same slug). 3.5 synthesis MUST `Read` this file rather than recalling from conversation context.
|
|
48
|
+
- Both files overwrite if they already exist.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Principles
|
|
53
|
+
|
|
54
|
+
Rules the final spec MUST obey:
|
|
55
|
+
|
|
56
|
+
1. Decompose the requirement into atomic scenarios — their union reconstitutes the full requirement.
|
|
57
|
+
2. Each atomic scenario corresponds to one happy path OR one boundary / exception path.
|
|
58
|
+
3. Atomic scenarios MUST be exhaustive and mutually non-redundant.
|
|
59
|
+
4. The spec MUST contain a requirement-level semantic description, scenario-level semantic descriptions, and scenario flow descriptions.
|
|
60
|
+
5. Scenario flow descriptions MUST contain both a trigger action sequence and the corresponding logical execution steps.
|
|
61
|
+
6. The spec MUST NOT contain any Android-related knowledge, design, or code-level description. See `references/android-platform-tokens.md` for the full strip list and Chinese replacement vocabulary.
|
|
62
|
+
7. When `REQ_DESC` disagrees with the Android code implementation, the spec follows `REQ_DESC`; discrepancies are summarized at the end of the spec in user-facing language.
|
|
63
|
+
8. **Coverage rule** — scenarios MUST cover ALL UI entries discovered in code, not just those explicitly mentioned in `REQ_DESC`. If the trace's Scope / Boundary section enumerates N entries and `REQ_DESC` only mentions M < N, the spec still produces scenarios for all N. Missing entries here = missing scenarios in the spec.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Method Discipline
|
|
68
|
+
|
|
69
|
+
Cross-cutting disciplines for trace exploration (3.1 → 3.3), verified in 3.4 Review.
|
|
70
|
+
|
|
71
|
+
### Multi-layer claim
|
|
72
|
+
|
|
73
|
+
**Rule**: A user-observable behavior on Android is typically carried by multiple source layers. Every claim in the trace MUST enumerate each relevant layer's state — either a `file:line` hit, or an explicit `N/A: <reason>` saying why that layer does not carry it. This applies to both positive claims ("this behavior is wired at X") and negative ones ("Y does not exist"). Omitting a layer = layer not checked, never = layer not present.
|
|
74
|
+
|
|
75
|
+
Android source layers:
|
|
76
|
+
|
|
77
|
+
| Layer | Examples |
|
|
78
|
+
|---|---|
|
|
79
|
+
| **code** | Java / Kotlin / Compose source (`.java`, `.kt`) — click handlers, ViewModels, Services, Repositories, DAOs, Workers |
|
|
80
|
+
| **resource** | `res/layout/*.xml`, `res/menu/*.xml`, `res/drawable/*.xml`, `res/values/*.xml`, `res/xml/*.xml` (preference screens), `res/navigation/*.xml` |
|
|
81
|
+
| **manifest** | `AndroidManifest.xml` (activity / service / receiver / provider / permission / intent-filter / foreground-service-type declarations); `build.gradle` flavor or `buildConfig` flags when behavior is build-gated |
|
|
82
|
+
|
|
83
|
+
### Replayable fact
|
|
84
|
+
|
|
85
|
+
**Rule**: Every fact in the trace MUST be **replayable verbatim** from a tool response. `file:line` anchors come from `mcp__gitnexus__context` / `cypher` results or the line-number prefix of a `Read` output. Phrases with counts or ordering ("called N times", "first X then Y", "synchronously then asynchronously", "again") MUST be derivable from precise tool-driven counting and sequencing (e.g. `mcp__gitnexus__cypher` aggregating callers, or repeated `mcp__gitnexus__impact` calls). Delete any fact that cannot be replayed.
|
|
86
|
+
|
|
87
|
+
**Common failure mode**: Hallucinate detail by analogy with common patterns ("synchronous write then asynchronous overwrite", "set X again"); estimate a line number from a `mcp__gitnexus__context` snippet and drift to a neighbouring symbol; make negative assertions from intuition instead of reverse-lookup with `mcp__gitnexus__impact` / `cypher` / `Grep`.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## References
|
|
92
|
+
|
|
93
|
+
External resources Read on demand (not pre-loaded). Loading these too early wastes context budget; load each only at the step that needs it.
|
|
94
|
+
|
|
95
|
+
| File | When to read |
|
|
96
|
+
|---|---|
|
|
97
|
+
| `references/spec-sample-1.md` | 3.5 Synthesize — boundary-and-happy-path decomposition style |
|
|
98
|
+
| `references/spec-sample-2.md` | 3.5 Synthesize — nested sub-bullet decomposition style |
|
|
99
|
+
| `references/spec-sample-3.md` | 3.5 Synthesize — shared-mechanic + per-value decomposition for enumerated multi-entry settings |
|
|
100
|
+
| `references/android-platform-tokens.md` | 3.5 Synthesize — platform-token strip list + Chinese replacement vocabulary |
|
|
101
|
+
| `references/step4-report-template.md` | Step 4 — summary report output format |
|
|
102
|
+
|
|
103
|
+
Mimic the samples' voice, scenario granularity, and structure — NOT their vocabulary or domain. The samples happen to use consumer-app domains (music / video); this skill applies to any Android application domain.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Workflow
|
|
108
|
+
|
|
109
|
+
### Step 0 — Validate inputs and parse REQ blocks
|
|
110
|
+
|
|
111
|
+
1. Verify `requirement-description-file` exists and is a file. If not, stop and report.
|
|
112
|
+
2. Verify `android-project-path` exists and is a directory. If not, stop and report.
|
|
113
|
+
3. Ensure `spec-output-dir` exists (create if missing). Ensure `<spec-output-dir>/.trace/` exists (create if missing).
|
|
114
|
+
4. **Parse the input `.txt`** (UTF-8):
|
|
115
|
+
- Split into REQ blocks by blank lines. Each block: first non-blank line = `title`, remaining non-blank lines = `body`.
|
|
116
|
+
- If a block has empty `body`, mark it for skip with reason `empty body`; do not abort the whole batch.
|
|
117
|
+
- If the file yields zero blocks, stop and report.
|
|
118
|
+
5. **Distill a feature slug** for each block:
|
|
119
|
+
- Summarize the REQ into a `<feature>` phrase. **≤ 20 characters, in the REQ's own language.**
|
|
120
|
+
- Sanitize illegal filesystem characters (`< > : " / \ | ? *` and ASCII control chars) by replacing each with `-`.
|
|
121
|
+
- Different REQ blocks should produce different features. Titles already encode the top-level category (e.g. `Settings-UI-...` vs `Settings-Lyrics-...`); retain enough category context in the slug to keep distinct.
|
|
122
|
+
- The slug is the filename stem for both the trace (`.trace/<feature>.md`) and the spec (`<feature>-SPEC.md`).
|
|
123
|
+
|
|
124
|
+
Step 0 output: an ordered list of `(title, body, feature)` tuples plus a skip list. Proceed directly to Step 1.
|
|
125
|
+
|
|
126
|
+
### Step 1 — Confirm the Android project is a Git repo
|
|
127
|
+
|
|
128
|
+
Run `git rev-parse --is-inside-work-tree` inside `android-project-path`.
|
|
129
|
+
|
|
130
|
+
- Output is `true` → proceed to Step 2.
|
|
131
|
+
- Otherwise → STOP. Tell the user:
|
|
132
|
+
|
|
133
|
+
> `android-project-path` is not a Git repository. GitNexus indexes by Git identity. Please run:
|
|
134
|
+
>
|
|
135
|
+
> ```
|
|
136
|
+
> cd <android-project-path>
|
|
137
|
+
> git init && git add . && git commit -m "init"
|
|
138
|
+
> ```
|
|
139
|
+
>
|
|
140
|
+
> then re-invoke this skill.
|
|
141
|
+
|
|
142
|
+
Do NOT auto-`init` / `add` / `commit` the user's project. Do NOT modify `git config`.
|
|
143
|
+
|
|
144
|
+
### Step 2 — Ensure GitNexus has a fresh index for the project
|
|
145
|
+
|
|
146
|
+
GitNexus exposes two surfaces:
|
|
147
|
+
|
|
148
|
+
- **Index management** (`status`, `analyze`) → invoke the `gitnexus-cli` skill (CLI wrapper, returns text).
|
|
149
|
+
- **Code queries** (`query`, `context`, `impact`, `cypher`, `list_repos`) → call `mcp__gitnexus__*` tools directly.
|
|
150
|
+
|
|
151
|
+
Procedure:
|
|
152
|
+
|
|
153
|
+
1. Invoke `gitnexus-cli` skill with `status` against `android-project-path`.
|
|
154
|
+
2. Decide based on the output:
|
|
155
|
+
- **Not registered** or **stale** → invoke `gitnexus-cli` with `analyze`, wait for completion.
|
|
156
|
+
- **Fresh** → proceed.
|
|
157
|
+
3. Obtain `<repo-id>` via `mcp__gitnexus__list_repos()`; find the entry whose `path` matches `android-project-path`; take its `repo` (or equivalent identifier) field.
|
|
158
|
+
|
|
159
|
+
**Hard fail policy** — any of the following stops the skill and surfaces the error to the user; do NOT degrade to `Read` + `Grep`:
|
|
160
|
+
|
|
161
|
+
- `gitnexus-cli` skill is unavailable → ask the user to run `/setup` first.
|
|
162
|
+
- `gitnexus-cli status` or `analyze` returns an error → surface the error verbatim.
|
|
163
|
+
- `mcp__gitnexus__list_repos` returns no matching entry → ask the user to verify that `analyze` registered the project.
|
|
164
|
+
- Any `mcp__gitnexus__*` call in Step 3 fails unexpectedly → surface the error; stop the skill.
|
|
165
|
+
|
|
166
|
+
> All `mcp__gitnexus__*` calls in Step 3 MUST carry `repo=<repo-id>` (or equivalent scope parameter). Cross-repo results poison the trace.
|
|
167
|
+
|
|
168
|
+
### Step 3 — Process each REQ block end-to-end
|
|
169
|
+
|
|
170
|
+
Iterate the `(title, body, feature)` tuples from Step 0 in order. For each tuple, run **3.1 → 3.5** in full before starting the next. Do NOT batch code exploration across REQ blocks.
|
|
171
|
+
|
|
172
|
+
Order matters: build the trace from Android source first, then synthesize the spec from the trace. Spec synthesis (3.5) MUST `Read` the trace written in 3.3 / 3.4 — recalling from conversation context causes scenario drift and `file:line` fabrication.
|
|
173
|
+
|
|
174
|
+
#### 3.1 Read
|
|
175
|
+
|
|
176
|
+
- Use the parsed `body` directly (already loaded in Step 0). If the tuple is marked `skip: empty body`, skip to the next tuple and record in Step 4 report.
|
|
177
|
+
- Extract from `body`: UI path / page anchors (if any), primary user intent, key entities (data models, persistence key names, setting names), explicit boundary conditions (default values, toggle states, error messages, length limits).
|
|
178
|
+
- For dependent REQs (body mentions "depends on X" or similar), note the dependency for the 3.3 trace's `Core business entities` section.
|
|
179
|
+
|
|
180
|
+
#### 3.2 Recall — Locate entry points (dual-path union)
|
|
181
|
+
|
|
182
|
+
Run both paths in parallel within the same turn (emit all mcp calls together); the deduplicated union is the recall result. All mcp calls MUST carry `repo=<repo-id>`.
|
|
183
|
+
|
|
184
|
+
| Path | Approach | Value |
|
|
185
|
+
|---|---|---|
|
|
186
|
+
| **Path 1 · By-concept lookup** | For each entity / UI anchor / intent verb from 3.1, call `mcp__gitnexus__query({ query: "<concept>", repo: "<repo-id>" })` and `mcp__gitnexus__context({ name: "<symbol>", repo: "<repo-id>" })` to find candidate symbols (Activities / Fragments / Composables / ViewModels / Services / Repositories / DAOs). Cross-validate symbol name, file path, and context against `REQ_DESC`. | Direct hits: pages obviously implementing the REQ; data models named after REQ entities. |
|
|
187
|
+
| **Path 2 · Reverse-by-usage** | Take the most discriminative keyword (a settings key literal, a persistence column / preference key, a unique business term). `query` → candidate symbol → `mcp__gitnexus__impact({ name: "<symbol>", repo: "<repo-id>" })` returns callers (nested). Walk callers upward until hitting an `Activity` / `Fragment` / `@Composable` host. That host is an entry point. If the walk passes through intermediate dialog / popup / bottom-sheet / inner-composable components that directly reference the target key, record each as a **separate entry point** — these represent distinct user-facing surfaces within the host. | Covers structural blind spots Path 1 misses: deeply nested consumers, pass-through navigation pages, manifest-declared receivers. |
|
|
188
|
+
|
|
189
|
+
**Behavioral REQ anchor extraction**: when `REQ_DESC` has no explicit literal keyword (e.g. "after track-change X refreshes synchronously"), extract anchors as `(action verb, affected entity)` tuples — e.g. `(track-change, X)` — and feed both into Path 1's `query` and Path 2's seed symbol search.
|
|
190
|
+
|
|
191
|
+
**Both paths hit zero** → ask the user via `AskUserQuestion` whether to manually specify an entry point. If declined → write `status: no_recall` in the trace, skip 3.3 / 3.4 / 3.5, flag in Step 4 report. Do NOT fabricate entry points.
|
|
192
|
+
|
|
193
|
+
**Terse REQ handling** — if the REQ body has fewer than ~20 substantive characters, OR contains only topical keywords (e.g. "multi-device", "landscape/portrait") with no concrete action verb / entity:
|
|
194
|
+
|
|
195
|
+
1. **MUST** run two broad enumeration passes (both mandatory, not optional):
|
|
196
|
+
- **Pass A · Feature code**: `mcp__gitnexus__cypher` enumeration — find all Activity / Fragment / Composable hosts whose `configChanges` manifest attribute is non-default (for orientation / resize cases) or whose layout has a resource qualifier matching the REQ topic (e.g. `-land`, `-sw600dp`, `-night`).
|
|
197
|
+
- **Pass B · Settings breadth**: For EACH distinct keyword in the REQ body, run `mcp__gitnexus__query` + `Grep` to enumerate ALL settings / configuration screens that reference that keyword or a semantically related term. Terse REQs frequently span multiple unrelated settings pages; anchoring on the single most obvious page is the primary failure mode. The union of Pass A and Pass B is the recall result.
|
|
198
|
+
2. If ≥3 plausible candidates → list them in the trace's `Status` section as `candidate_hosts: [...]` and proceed normally.
|
|
199
|
+
3. If <3 candidates → invoke `AskUserQuestion`: show the candidate list, ask which are in-scope for this REQ. Do NOT silently guess.
|
|
200
|
+
4. Mark in trace `Status` block: `terse_req: true` (this signal feeds 3.4 review).
|
|
201
|
+
5. **3.4 Review MUST verify**: every settings screen discovered in Pass B has at least one Entry or Touched-entry in the trace. A discovered-but-untraced screen → fail review, return to 3.3.
|
|
202
|
+
|
|
203
|
+
**Clarification triggers** (interrupt 3.2 / 3.3 with `AskUserQuestion`):
|
|
204
|
+
|
|
205
|
+
- `REQ_DESC` contains ambiguous phrases ("any entry point", "related pages", "all related locations") AND the trace cannot map them to a unique set of components.
|
|
206
|
+
- Path 1 + Path 2 both return zero, before writing `no_recall`.
|
|
207
|
+
- Deviations from `REQ_DESC` exceed five AND touch core behavior (REQ may be stale; confirm before proceeding).
|
|
208
|
+
|
|
209
|
+
#### 3.3 Trace — Explore code and write `<spec-output-dir>/.trace/<feature>.md`
|
|
210
|
+
|
|
211
|
+
The trace file is the sole machine-readable contract delivered to 3.5. Exploration and writing form a single unit.
|
|
212
|
+
|
|
213
|
+
**Exploration checklist — execution order** (all mcp calls carry `repo: "<repo-id>"`):
|
|
214
|
+
|
|
215
|
+
| Step | Action | Tool |
|
|
216
|
+
|---|---|---|
|
|
217
|
+
| 1 | Survey candidate symbols for each anchor from 3.1 | `mcp__gitnexus__query` / `context` |
|
|
218
|
+
| 2 | Full call chain (callers / callees, up and down) | `mcp__gitnexus__impact` |
|
|
219
|
+
| 3 | Cross-class graph traversal / reverse-lookup state writers / aggregation | `mcp__gitnexus__cypher` |
|
|
220
|
+
| 4 | Exact literal positioning (settings keys, DAO columns, intent actions, preference `android:key`) | `Grep` |
|
|
221
|
+
| 5 | Final `file:line` verification / zero-hit counter-evidence | `Read` (small window) / `Grep` |
|
|
222
|
+
|
|
223
|
+
**Exploration dimensions — information coverage** (orthogonal to the checklist; checklist = order, dimensions = what to capture). Apply each to every recall entry:
|
|
224
|
+
|
|
225
|
+
- **Trigger code** — UI control + event callback (click / long-press / swipe / lifecycle / broadcast receiver) invoking the REQ behavior. Fill Entry's `code` and `resource` layer fields.
|
|
226
|
+
- **End-to-end call chain** — trigger → ViewModel / UseCase → Service / Repository → data source. Fill Entry's `data_flow`; each hop carries `file:line`.
|
|
227
|
+
- **State writes & persistence** — every state mutation (state holders, DAO inserts, preference / DataStore / MMKV puts, file writes). Record key / column names verbatim.
|
|
228
|
+
- **Side effects / cross-boundary** — broadcasts, bound services, notifications, App Widget IPC, content providers, accessibility events.
|
|
229
|
+
- **Manifest declarations / build flags** — activity / service / receiver registration, intent filters, permissions, foreground service types, build flavor / `buildConfig` gates. Fill Entry's `manifest` field — `N/A: <reason>` if none.
|
|
230
|
+
- **Deviations from `REQ_DESC`** — every gap (default values, copy strings, behavior, hidden entries, validation rules). Feeds Principle 7.
|
|
231
|
+
- **Application scope / boundary · Exhaustive entry enumeration** — ALL UI paths touching this feature / state, beyond REQ text. For state keys: reverse-lookup writers + lift to UI hosts. For readers: enumerate consumers + non-consumers. One field block per entry; omitted here = scenario omitted in spec.
|
|
232
|
+
- **Consumer list & non-consumers** — who reads this state, plus which UI surfaces explicitly do NOT. Non-consumer claims use the structured field block (`claim` / `closure_layers` / `tools` / `zero_hits`).
|
|
233
|
+
|
|
234
|
+
**Trace file template** (write to `<spec-output-dir>/.trace/<feature>.md`):
|
|
235
|
+
|
|
236
|
+
```markdown
|
|
237
|
+
# Code trace · <feature>
|
|
238
|
+
|
|
239
|
+
## Status
|
|
240
|
+
status: ok | no_recall | error
|
|
241
|
+
repo-id: <repo-id>
|
|
242
|
+
backend: gitnexus
|
|
243
|
+
|
|
244
|
+
## Recalled entry points (Path 1 + Path 2 union, deduplicated)
|
|
245
|
+
- Entry 1: <UI path / page name> — file:line — recalled by: path 1 | path 2 | both
|
|
246
|
+
- ...
|
|
247
|
+
|
|
248
|
+
## Entry · <name>
|
|
249
|
+
- claim: <user-observable behavior in one sentence>
|
|
250
|
+
- layers:
|
|
251
|
+
- code: <file:line> # required; hit or `N/A: <reason>`
|
|
252
|
+
- resource: <file:line> | N/A: <reason> # layout / menu / drawable / values / xml-preferences / navigation
|
|
253
|
+
- manifest: <file:line> | N/A: <reason> # AndroidManifest entry / build.gradle flag
|
|
254
|
+
- interaction: <state writes, persistence keys (verbatim), in-memory mutations>
|
|
255
|
+
- data_flow: <trigger → ViewModel / Service / Repo → data source, each hop with file:line>
|
|
256
|
+
|
|
257
|
+
## Entry · <name 2> ... Entry · <name N>
|
|
258
|
+
(each entry repeats the claim / layers / interaction / data_flow field block)
|
|
259
|
+
|
|
260
|
+
## Implicit triggers (non-UI state changes that activate this feature)
|
|
261
|
+
- Trigger: <track-change / Pro status change / permission change / foreground-background switch / network change / lyrics document change / current track is null> — <file:line> — behavior: <one sentence>
|
|
262
|
+
- (write "None" if no implicit trigger applies)
|
|
263
|
+
|
|
264
|
+
## Core business entities (data model / persistence key / state machine)
|
|
265
|
+
- Entity X: <file:line + field list + semantics>
|
|
266
|
+
- For dependent REQs: <dependency-key-name> sourced from feature `<depended-feature>` at file:line
|
|
267
|
+
- ...
|
|
268
|
+
|
|
269
|
+
## Cross-entry shared declarations
|
|
270
|
+
- <AndroidManifest.xml / build.gradle entries with file:line, shared across multiple entries>
|
|
271
|
+
- ... (write "None" explicitly if no cross-entry declaration applies; per-entry manifest facts live in each Entry's `manifest` layer field)
|
|
272
|
+
|
|
273
|
+
## Deviations from REQ_DESC
|
|
274
|
+
1. <REQ says A; but code at file:line behaves as B>
|
|
275
|
+
2. ...
|
|
276
|
+
(empty → write "None" explicitly to confirm the check was performed)
|
|
277
|
+
|
|
278
|
+
## Scope / Boundary — Exhaustive entry enumeration
|
|
279
|
+
### Touched entries (all UI paths, not limited to REQ_DESC mentions)
|
|
280
|
+
(each touched entry uses the same `claim` / `layers` / `interaction` / `data_flow` field block as the Entry template above)
|
|
281
|
+
|
|
282
|
+
### Consumers (who reads this state / data)
|
|
283
|
+
- Consumer: <component name> — file:line
|
|
284
|
+
|
|
285
|
+
### Non-consumers (boundary counter-examples with evidence)
|
|
286
|
+
- claim: <e.g. "App widget does not read this key">
|
|
287
|
+
closure_layers: [code, resource, manifest]
|
|
288
|
+
tools: [Grep "<pattern>", mcp__gitnexus__cypher "<...>", Read "<path>"]
|
|
289
|
+
zero_hits: <verbatim zero-hit evidence — file globs searched, regex used, hit count>
|
|
290
|
+
|
|
291
|
+
## Same-source cross-reference (if applicable)
|
|
292
|
+
- This REQ shares behavior with feature `<other-feature>` (e.g. the same setting exposed under multiple settings paths).
|
|
293
|
+
Both specs are generated independently and reference each other in their deviation sections.
|
|
294
|
+
- (write "None" if not applicable)
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
#### 3.4 Review — No fabrication, no omission, method-discipline compliant
|
|
298
|
+
|
|
299
|
+
Run the checks below against the trace from 3.3; every check must pass before proceeding to 3.5.
|
|
300
|
+
|
|
301
|
+
- **No fabrication** — every declared `file:line` actually exists (sample-verify via `mcp__gitnexus__context` or `Read`); every behavioral claim is source-supported; every boundary claim has tool evidence.
|
|
302
|
+
- **No omission** — every detail in `REQ_DESC` has a counterpart in the trace (Entry / behavior / deviation). If REQ mentions a feature code does not implement, record as deviation, not omission.
|
|
303
|
+
- **Method-discipline compliance** (Multi-layer claim + Replayable fact) — sample-verify random `file:line` anchors via `mcp__gitnexus__context` / `Read` (≥1 line drift → fail); sample-verify every count / ordering phrase against source (unreplayable → fail); every Entry / Touched-entry has all three layer fields filled (hit or `N/A: <reason>`); every Non-consumer claim has all four structured fields (`claim` / `closure_layers` / `tools` / `zero_hits`).
|
|
304
|
+
- **Implicit triggers coverage** — the trace's `Implicit triggers` section is present and explicitly filled (≥1 trigger OR `None`). Absence of the section = fail review.
|
|
305
|
+
- **Trace section presence audit** — every trace MUST contain these H2 sections (with `None` if truly empty; absence = fail): `Status` / `Recalled entry points` / per `Entry` (all 4 fields: `claim` / `layers` / `interaction` / `data_flow`) / `Implicit triggers` / `Core business entities` / `Cross-entry shared declarations` / `Deviations from REQ_DESC` / `Scope / Boundary` / `Same-source cross-reference`.
|
|
306
|
+
|
|
307
|
+
Any check failing → return to 3.3 (rewrite / supplement / fix). Judge convergence yourself; no external iteration cap. All checks pass → proceed to 3.5.
|
|
308
|
+
|
|
309
|
+
#### 3.5 Synthesize — Write the final spec
|
|
310
|
+
|
|
311
|
+
`Read` the trace from 3.3 / 3.4, then synthesize the spec following `## Principles` and the style references under `references/`. Write to `<spec-output-dir>/<feature>-SPEC.md` (overwrite if exists).
|
|
312
|
+
|
|
313
|
+
**Synthesis discipline**:
|
|
314
|
+
|
|
315
|
+
- **Implicit triggers coverage** — every entry in the trace's `Implicit triggers` section MUST appear in the spec as an independent scenario OR as a main step within an existing scenario. Listed in trace but absent from spec = scenario omission. (Extends Principle 8 to non-UI triggers.)
|
|
316
|
+
- **Shared-mechanic factoring** — for enumerated-value settings (three-way / four-way / radio-group) accessible from multiple entry points, factor the shared menu interaction across all entries into ONE scenario; give each enum value its OWN runtime-semantics scenario. Do NOT split the mechanical scenario per entry point, and do NOT bundle "user picks X" with "what X does" in the same scenario per value.
|
|
317
|
+
- **Binary-toggle anti-pattern** — a binary on/off switch is ONE trigger; write ONE scenario for the toggle (both directions), with linked-control side-effects as sub-bullets. Write SEPARATE scenarios for each state's runtime rendering (e.g. "when ON, cover rotates" / "when OFF, cover is static"). Do NOT split "turn on" / "turn off" into independent scenes.
|
|
318
|
+
- **Same-source cross-reference** — if the trace's `Same-source cross-reference` section is non-empty, append a short note at the end of the spec referencing the other `<feature>-SPEC.md` (e.g. "This setting also exists under `<other-feature>-SPEC.md` with identical behavior").
|
|
319
|
+
- **REQ-vs-code-string arbitration** — code's user-facing strings (toast / notification / dialog / snackbar / error) that conflict with `REQ_DESC` are **deviation evidence**, NOT authoritative facts. Author spec body per `REQ_DESC` phrasing; record the conflicting string + `file:line` in trace's `Deviations`. Do NOT copy code strings verbatim into the spec.
|
|
320
|
+
|
|
321
|
+
After writing, proceed to the next REQ block.
|
|
322
|
+
|
|
323
|
+
### Step 4 — Summary report
|
|
324
|
+
|
|
325
|
+
Once all REQ blocks are processed (or skipped with warnings), produce a brief report following `references/step4-report-template.md`. The template defines the per-block table format, skipped-block list, and aggregates. Keep the in-session reply within ~40 lines; per-block detail belongs in spec / trace files.
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Forbidden
|
|
330
|
+
|
|
331
|
+
- **No nested LLM-agent skill calls** — no `gitnexus-exploring`, no `gitnexus-debugging`, no `gitnexus-refactoring`, no `gitnexus-impact-analysis`. They override this SKILL's instructions and cause role drift. **Exception**: `gitnexus-cli` is a CLI wrapper (not an LLM agent); using it for index management is allowed.
|
|
332
|
+
- **No modification of the Android project** — `.gradle`, `AndroidManifest.xml`, source files. This skill is read-only.
|