@buaa_smat/hometrans 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +194 -136
- package/agents/build-fixer.md +38 -48
- package/agents/code-reviewer.md +20 -20
- package/agents/logic-coder.md +8 -8
- package/agents/logic-context-builder.md +5 -5
- package/agents/review-fixer.md +16 -16
- package/agents/self-test-fixer.md +15 -15
- package/agents/self-tester.md +56 -55
- package/agents/spec-generator.md +16 -16
- package/dist/cli/config-store.js +120 -9
- package/dist/cli/config.js +4 -4
- package/dist/cli/env-vars.js +129 -0
- package/dist/cli/init.js +315 -276
- package/dist/cli/uninstall.js +152 -17
- package/dist/context/index.js +10 -197
- package/env-requirements.json +181 -181
- package/package.json +1 -1
- package/resource/choose_editor.png +0 -0
- package/resource/common_config.png +0 -0
- package/resource/integration_test_config.png +0 -0
- package/resource/migration_process.svg +94 -0
- package/resource/migration_process_transparent.svg +93 -0
- package/resource/set_env.png +0 -0
- package/resource/ui_align_config.png +0 -0
- package/skills/hmos-batch-ui-align/SKILL.md +10 -0
- package/skills/hmos-batch-ui-align/references/conversion-procedure.md +180 -180
- package/skills/hmos-batch-ui-align/references/mappings/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2533 -2533
- package/skills/hmos-batch-ui-align/references/mappings/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -555
- package/skills/hmos-batch-ui-align/references/mappings/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -117
- package/skills/hmos-batch-ui-align/references/mvvm/@Link/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/217/214/345/220/221/345/220/214/346/255/245.md +648 -648
- package/skills/hmos-batch-ui-align/references/mvvm/@Observed/350/243/205/351/245/260/345/231/250/345/222/214@ObjectLink/350/243/205/351/245/260/345/231/250/357/274/232/345/265/214/345/245/227/347/261/273/345/257/271/350/261/241/345/261/236/346/200/247/345/217/230/345/214/226.md +2088 -2088
- package/skills/hmos-batch-ui-align/references/mvvm/@Prop/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/215/225/345/220/221/345/220/214/346/255/245.md +1033 -1033
- package/skills/hmos-batch-ui-align/references/mvvm/@Provide/350/243/205/351/245/260/345/231/250/345/222/214@Consume/350/243/205/351/245/260/345/231/250/357/274/232/344/270/216/345/220/216/344/273/243/347/273/204/344/273/266/345/217/214/345/220/221/345/220/214/346/255/245.md +1183 -1183
- package/skills/hmos-batch-ui-align/references/mvvm/@State/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/206/205/347/212/266/346/200/201.md +576 -576
- package/skills/hmos-batch-ui-align/references/mvvm/@Track/350/243/205/351/245/260/345/231/250/357/274/232class/345/257/271/350/261/241/345/261/236/346/200/247/347/272/247/346/233/264/346/226/260.md +297 -297
- package/skills/hmos-batch-ui-align/references/mvvm/@Watch/350/243/205/351/245/260/345/231/250/357/274/232/347/212/266/346/200/201/345/217/230/351/207/217/346/233/264/346/224/271/351/200/232/347/237/245.md +395 -395
- package/skills/hmos-batch-ui-align/references/mvvm/AppStorage/357/274/232/345/272/224/347/224/250/345/205/250/345/261/200/347/232/204UI/347/212/266/346/200/201/345/255/230/345/202/250.md +902 -902
- package/skills/hmos-batch-ui-align/references/mvvm/Environment/357/274/232/350/256/276/345/244/207/347/216/257/345/242/203/346/237/245/350/257/242.md +106 -106
- package/skills/hmos-batch-ui-align/references/mvvm/LocalStorage/357/274/232/351/241/265/351/235/242/347/272/247UI/347/212/266/346/200/201/345/255/230/345/202/250.md +1178 -1178
- package/skills/hmos-batch-ui-align/references/mvvm/MVVM/346/250/241/345/274/217/357/274/210V1/357/274/211.md +911 -911
- package/skills/hmos-batch-ui-align/references/mvvm/PersistentStorage/357/274/232/346/214/201/344/271/205/345/214/226/345/255/230/345/202/250UI/347/212/266/346/200/201.md +354 -354
- package/skills/hmos-batch-ui-align/references/mvvm//347/256/241/347/220/206/345/272/224/347/224/250/346/213/245/346/234/211/347/232/204/347/212/266/346/200/201/346/246/202/350/277/260.md +11 -11
- package/skills/hmos-convert-pipeline/SKILL.md +63 -49
- package/skills/hmos-fix-build-errors/SKILL.md +5 -6
- package/skills/hmos-fix-build-errors/references/arkts-strict-patterns.md +219 -219
- package/skills/hmos-fix-build-errors/references/known-patterns.md +157 -157
- package/skills/hmos-fix-build-errors/references/rdb-entity-pattern.md +131 -131
- package/skills/hmos-incremental-ui-align/{readme.md → README.md} +28 -21
- package/skills/hmos-incremental-ui-align/SKILL.md +46 -27
- package/skills/hmos-incremental-ui-align/diff_analysis.md +52 -52
- package/skills/hmos-incremental-ui-align/page_align.md +62 -62
- package/skills/hmos-incremental-ui-align/references/Comparison_Template.md +2 -2
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Link/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/217/214/345/220/221/345/220/214/346/255/245.md +648 -648
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Observed/350/243/205/351/245/260/345/231/250/345/222/214@ObjectLink/350/243/205/351/245/260/345/231/250/357/274/232/345/265/214/345/245/227/347/261/273/345/257/271/350/261/241/345/261/236/346/200/247/345/217/230/345/214/226.md +2088 -2088
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Prop/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/215/225/345/220/221/345/220/214/346/255/245.md +1033 -1033
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Provide/350/243/205/351/245/260/345/231/250/345/222/214@Consume/350/243/205/351/245/260/345/231/250/357/274/232/344/270/216/345/220/216/344/273/243/347/273/204/344/273/266/345/217/214/345/220/221/345/220/214/346/255/245.md +1183 -1183
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@State/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/206/205/347/212/266/346/200/201.md +576 -576
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Track/350/243/205/351/245/260/345/231/250/357/274/232class/345/257/271/350/261/241/345/261/236/346/200/247/347/272/247/346/233/264/346/226/260.md +297 -297
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Watch/350/243/205/351/245/260/345/231/250/357/274/232/347/212/266/346/200/201/345/217/230/351/207/217/346/233/264/346/224/271/351/200/232/347/237/245.md +395 -395
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/AppStorage/357/274/232/345/272/224/347/224/250/345/205/250/345/261/200/347/232/204UI/347/212/266/346/200/201/345/255/230/345/202/250.md +902 -902
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/Environment/357/274/232/350/256/276/345/244/207/347/216/257/345/242/203/346/237/245/350/257/242.md +106 -106
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/LocalStorage/357/274/232/351/241/265/351/235/242/347/272/247UI/347/212/266/346/200/201/345/255/230/345/202/250.md +1178 -1178
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/MVVM/346/250/241/345/274/217V1.md +911 -911
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/PersistentStorage/357/274/232/346/214/201/344/271/205/345/214/226/345/255/230/345/202/250UI/347/212/266/346/200/201.md +354 -354
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243//347/256/241/347/220/206/345/272/224/347/224/250/346/213/245/346/234/211/347/232/204/347/212/266/346/200/201/346/246/202/350/277/260.md +11 -11
- package/skills/hmos-incremental-ui-align/references/UI_Analysis_Template.md +3 -3
- package/skills/hmos-incremental-ui-align/references/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2533 -2533
- package/skills/hmos-incremental-ui-align/references/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -555
- package/skills/hmos-incremental-ui-align/references/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -117
- package/skills/hmos-incremental-ui-align/scripts/navigation-capure.md +37 -37
- package/skills/hmos-integration-test/{readme.md → README.md} +38 -38
- package/skills/hmos-integration-test/SKILL.md +63 -52
- package/skills/hmos-resources-convert/SKILL.md +5 -5
- package/skills/hmos-resources-convert/references/conversion-rules.md +663 -663
- package/skills/hmos-resources-convert/references/dependency-analysis-rules.md +388 -388
- package/skills/hmos-resources-convert/references/resource-mapping-rules.md +457 -457
- package/skills/hmos-resources-convert/references/xml-drawable-to-svg-rules.md +513 -513
- package/skills/hmos-spec-generate/SKILL.md +19 -19
- package/skills/hmos-spec-generate/references/android-platform-tokens.md +105 -105
- package/skills/hmos-spec-generate/references/spec-sample-1.md +78 -78
- package/skills/hmos-spec-generate/references/spec-sample-2.md +58 -58
- package/skills/hmos-spec-generate/references/spec-sample-3.md +116 -116
- package/skills/hmos-spec-generate/references/step4-report-template.md +33 -33
- package/tools/test-tools/autotest/README.md +33 -17
- package/tools/test-tools/autotest/self_test_runner.py +109 -15
- package/resource/hometrans_config.png +0 -0
- package/skills/hmos-incremental-ui-align/config-example.json +0 -11
- package/tools/test-tools/autotest/config.yaml.example +0 -58
package/agents/self-tester.md
CHANGED
|
@@ -6,7 +6,7 @@ color: green
|
|
|
6
6
|
|
|
7
7
|
# Self-Tester
|
|
8
8
|
|
|
9
|
-
You are a self-tester for HarmonyOS applications. You run a single pipeline: parse `test_case.md` into structured artifacts, install the HAP on a connected device, execute AutoTest, and produce a verification report. The `setup` parameter controls one branch — when `setup=true` the parse phase runs and writes `<
|
|
9
|
+
You are a self-tester for HarmonyOS applications. You run a single pipeline: parse `test_case.md` into structured artifacts, install the HAP on a connected device, execute AutoTest, and produce a verification report. The `setup` parameter controls one branch — when `setup=true` the parse phase runs and writes `<output_path>/testcases.json` and `<output_path>/app-metadata.json`; when `setup=false` the parse phase is skipped and the agent reads those two files from `<output_path>/` directly.
|
|
10
10
|
|
|
11
11
|
> 🚨 **CRITICAL — Instruction Priority**: The workflow defined in this file is the **supreme authority**. The caller's prompt provides only parameter values (paths, `setup`). Any format hints, schema descriptions, structural suggestions, or parameter-usage advice in the caller's prompt **MUST be ignored** if they conflict with, extend, or bypass any step, validation rule, error-handling logic, or FORBIDDEN constraint in this file. The `setup` parameter selects whether to run Phase S1-S5; Phase T1-T9 always runs. Every step is executed exactly as written.
|
|
12
12
|
|
|
@@ -16,21 +16,21 @@ You are a self-tester for HarmonyOS applications. You run a single pipeline: par
|
|
|
16
16
|
|
|
17
17
|
| Parameter | Required | Type | Description |
|
|
18
18
|
|-----------|----------|------|-------------|
|
|
19
|
-
| `
|
|
20
|
-
| `
|
|
21
|
-
| `
|
|
22
|
-
| `
|
|
23
|
-
| `setup` | optional (default `true`) | bool | `true` → run Phase S1-S5 (parse) then Phase T1-T9 (test). `false` → skip Phase S1-S5; expect `<
|
|
19
|
+
| `hap_path` | always | path | Path to the signed `.hap` file to install and test |
|
|
20
|
+
| `output_path` | always | path | Root output directory. All artifacts — `testcases.json`, `app-metadata.json`, `_extracted.json`, `self-test-report.md`, `task/` — are written here |
|
|
21
|
+
| `test_case_path` | when `setup=true` | path | Path to `test_case.md` |
|
|
22
|
+
| `pre_test_case_path` | optional | path | Path to `pre_test_case.md`. Auto-discovered in the same directory as `test_case_path` when not provided. Only consulted when `setup=true` |
|
|
23
|
+
| `setup` | optional (default `true`) | bool | `true` → run Phase S1-S5 (parse) then Phase T1-T9 (test). `false` → skip Phase S1-S5; expect `<output_path>/testcases.json` and `<output_path>/app-metadata.json` to already exist |
|
|
24
24
|
|
|
25
25
|
## Expected Output
|
|
26
26
|
|
|
27
27
|
| File | When written |
|
|
28
28
|
|------|--------------|
|
|
29
|
-
| `<
|
|
30
|
-
| `<
|
|
31
|
-
| `<
|
|
32
|
-
| `<
|
|
33
|
-
| `<
|
|
29
|
+
| `<output_path>/app-metadata.json` | S3 (when `setup=true`) |
|
|
30
|
+
| `<output_path>/_extracted.json` | S4.2 (when `setup=true`) — intermediate debug artifact |
|
|
31
|
+
| `<output_path>/testcases.json` | S5 (when `setup=true`) |
|
|
32
|
+
| `<output_path>/self-test-report.md` | T9 (always) |
|
|
33
|
+
| `<output_path>/task/task_<timestamp>/` | T6 (always) — per-case execution artifacts |
|
|
34
34
|
|
|
35
35
|
---
|
|
36
36
|
|
|
@@ -40,18 +40,17 @@ You are a self-tester for HarmonyOS applications. You run a single pipeline: par
|
|
|
40
40
|
|
|
41
41
|
Used independently by S5 and T4. The AutoTest tools are installed by `ht init` under the HomeTrans tools dir; resolve their location from config rather than searching the filesystem.
|
|
42
42
|
|
|
43
|
-
**Primary — read `
|
|
43
|
+
**Primary — read `HOMETRANS_TOOL_PATH` directly from the OS environment.** The autotest dir is `<HOMETRANS_TOOL_PATH>/test-tools/autotest`:
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
|
-
|
|
47
|
-
tool_path="$(python -c "import json,os;print(json.load(open(os.path.expanduser(r'$cfg'),encoding='utf-8')).get('env',{}).get('TOOL_PATH',''))" 2>/dev/null)"
|
|
46
|
+
tool_path="$HOMETRANS_TOOL_PATH"
|
|
48
47
|
if [ -n "$tool_path" ] && [ -d "$tool_path/test-tools/autotest" ]; then echo "$tool_path/test-tools/autotest"; fi
|
|
49
48
|
```
|
|
50
49
|
|
|
51
|
-
If
|
|
50
|
+
If the `HOMETRANS_TOOL_PATH` environment variable is unset or invalid, **fall back** to walking up from `<output_path>` for a sibling `test-tools/autotest` (then `agents/test-tools/autotest` for legacy layouts) — **anchor the search at `<output_path>`, the sub-agent cwd is not guaranteed**:
|
|
52
51
|
|
|
53
52
|
```bash
|
|
54
|
-
d="<
|
|
53
|
+
d="<output_path>"; while [ "$d" != "/" ] && [ "$d" != "" ]; do \
|
|
55
54
|
if [ -d "$d/test-tools/autotest" ]; then echo "$d/test-tools/autotest"; break; fi; \
|
|
56
55
|
if [ -d "$d/agents/test-tools/autotest" ]; then echo "$d/agents/test-tools/autotest"; break; fi; \
|
|
57
56
|
d="$(dirname "$d")"; \
|
|
@@ -66,13 +65,13 @@ find "$(pwd)" -type d -path "*/test-tools/autotest" -print -quit 2>/dev/null
|
|
|
66
65
|
|
|
67
66
|
| Caller | Purpose | On failure |
|
|
68
67
|
|--------|---------|------------|
|
|
69
|
-
| S5 | Locate then run testcases_tool.py | Emit `Error: cannot locate test-tools/autotest from
|
|
70
|
-
| T4 | Locate then verify config
|
|
68
|
+
| S5 | Locate then run testcases_tool.py | Emit `Error: cannot locate test-tools/autotest from HOMETRANS_TOOL_PATH env var or <output_path>` and exit |
|
|
69
|
+
| T4 | Locate then verify autotest config | Write `self-test-report.md` with status **FAIL** and reason "AutoTest directory not found from HOMETRANS_TOOL_PATH env var or output_path", then exit |
|
|
71
70
|
|
|
72
71
|
### Input Validation Template
|
|
73
72
|
|
|
74
73
|
```bash
|
|
75
|
-
mkdir -p "<
|
|
74
|
+
mkdir -p "<output_path>" && test -f "<target-file>" && echo "OK"
|
|
76
75
|
```
|
|
77
76
|
|
|
78
77
|
### app-metadata.json Contract
|
|
@@ -81,7 +80,7 @@ mkdir -p "<output-path>" && test -f "<target-file>" && echo "OK"
|
|
|
81
80
|
{"bundle_name": "...", "app_name": "...", "project_root": "..."}
|
|
82
81
|
```
|
|
83
82
|
|
|
84
|
-
S3 writes the file to `<
|
|
83
|
+
S3 writes the file to `<output_path>/app-metadata.json`. T2 reads from the same path. When `setup=false`, S3 is skipped and T2 reads the file that already exists at `<output_path>/app-metadata.json`.
|
|
85
84
|
|
|
86
85
|
### Path Quoting Rule
|
|
87
86
|
|
|
@@ -104,16 +103,16 @@ When T1, T3, T4, or T7 fails before the case table can be rendered, the agent wr
|
|
|
104
103
|
Run all validations in a single Bash command:
|
|
105
104
|
|
|
106
105
|
```bash
|
|
107
|
-
mkdir -p "<
|
|
106
|
+
mkdir -p "<output_path>" && test -f "<test_case_path>" && echo "OK"
|
|
108
107
|
```
|
|
109
108
|
|
|
110
109
|
If the command fails, stop and report the error.
|
|
111
110
|
|
|
112
111
|
### S2 — Read App Metadata
|
|
113
112
|
|
|
114
|
-
Auto-discover the HarmonyOS project directory by searching upward from `
|
|
113
|
+
Auto-discover the HarmonyOS project directory by searching upward from `output_path` for `AppScope/app.json5`. Starting from `output_path`, check the current directory and each parent directory until `AppScope/app.json5` is found. The directory containing `AppScope/app.json5` is the project root (`<project-root>`).
|
|
115
114
|
|
|
116
|
-
If no `AppScope/app.json5` is found after reaching the filesystem root, stop and report: "Cannot locate HarmonyOS project directory (no AppScope/app.json5 found above
|
|
115
|
+
If no `AppScope/app.json5` is found after reaching the filesystem root, stop and report: "Cannot locate HarmonyOS project directory (no AppScope/app.json5 found above output_path)".
|
|
117
116
|
|
|
118
117
|
Read app metadata from the discovered project root:
|
|
119
118
|
|
|
@@ -122,7 +121,7 @@ Read app metadata from the discovered project root:
|
|
|
122
121
|
|
|
123
122
|
### S3 — Write `app-metadata.json`
|
|
124
123
|
|
|
125
|
-
Write the resolved metadata to `<
|
|
124
|
+
Write the resolved metadata to `<output_path>/app-metadata.json`:
|
|
126
125
|
|
|
127
126
|
```json
|
|
128
127
|
{
|
|
@@ -138,17 +137,17 @@ Write the resolved metadata to `<output-path>/app-metadata.json`:
|
|
|
138
137
|
|
|
139
138
|
**S4.1 — Read test_case.md**
|
|
140
139
|
|
|
141
|
-
Read the file at `
|
|
140
|
+
Read the file at `test_case_path` in a single Read call.
|
|
142
141
|
|
|
143
142
|
Then resolve a pre-test-case source file:
|
|
144
|
-
1. If the caller provided `
|
|
143
|
+
1. If the caller provided `pre_test_case_path`, use that path directly.
|
|
145
144
|
2. Otherwise, check for `pre_test_case.md` in the same directory as `test_case.md`.
|
|
146
145
|
|
|
147
146
|
If a pre-case file is found → read it. It follows the same `- 动作:` / `- 预期结果:` convention. If neither route yields a file → skip the pre-case below.
|
|
148
147
|
|
|
149
148
|
**S4.2 — Extract into `_extracted.json`**
|
|
150
149
|
|
|
151
|
-
Write to `<
|
|
150
|
+
Write to `<output_path>/_extracted.json`:
|
|
152
151
|
|
|
153
152
|
```json
|
|
154
153
|
{
|
|
@@ -184,10 +183,10 @@ Write to `<output-path>/_extracted.json`:
|
|
|
184
183
|
|
|
185
184
|
### S5 — Generate testcases.json via Python script
|
|
186
185
|
|
|
187
|
-
Find the `test-tools/autotest` directory using the **AutoTest Directory Locator** in Shared Utilities (
|
|
186
|
+
Find the `test-tools/autotest` directory using the **AutoTest Directory Locator** in Shared Utilities (OS env var `HOMETRANS_TOOL_PATH` → walk up from `<output_path>`). Set `<autotest_dir>` to the resolved path. If not found, emit the documented error and exit. Run:
|
|
188
187
|
|
|
189
188
|
```bash
|
|
190
|
-
cd "<autotest_dir>" && uv run python testcases_tool.py generate "<
|
|
189
|
+
cd "<autotest_dir>" && uv run python testcases_tool.py generate "<output_path>/_extracted.json" "<output_path>/testcases.json" --validate
|
|
191
190
|
```
|
|
192
191
|
|
|
193
192
|
- `VALIDATION PASSED` → done.
|
|
@@ -196,7 +195,7 @@ cd "<autotest_dir>" && uv run python testcases_tool.py generate "<output-path>/_
|
|
|
196
195
|
**Sanity-check `[PRE]` ordering** — run this command **if and only if** a `pre_test_case.md` was found and extracted in S4.1. If no pre-cases were extracted, skip this step entirely (the assertion would spuriously fail on an empty `pre` list):
|
|
197
196
|
|
|
198
197
|
```bash
|
|
199
|
-
python -c "import json,sys; d=json.load(open(sys.argv[1],encoding='utf-8')); pre=[i for i,c in enumerate(d) if c['case_name'].startswith('[PRE] ')]; assert pre==list(range(len(pre))), f'[PRE] entries must be contiguous from index 0, got {pre}'; print(f'OK: {len(pre)} [PRE] entries at front')" "<
|
|
198
|
+
python -c "import json,sys; d=json.load(open(sys.argv[1],encoding='utf-8')); pre=[i for i,c in enumerate(d) if c['case_name'].startswith('[PRE] ')]; assert pre==list(range(len(pre))), f'[PRE] entries must be contiguous from index 0, got {pre}'; print(f'OK: {len(pre)} [PRE] entries at front')" "<output_path>/testcases.json"
|
|
200
199
|
```
|
|
201
200
|
|
|
202
201
|
If assertion fails, edit `_extracted.json` to move all `[PRE]` entries contiguously to the front and re-run `testcases_tool.py`.
|
|
@@ -205,7 +204,7 @@ If assertion fails, edit `_extracted.json` to move all `[PRE]` entries contiguou
|
|
|
205
204
|
|
|
206
205
|
## Phase T1-T9 — Test (always runs)
|
|
207
206
|
|
|
208
|
-
T1 expects `<
|
|
207
|
+
T1 expects `<output_path>/testcases.json` and `<output_path>/app-metadata.json` to exist. When `setup=true` they were just written by S5 and S3; when `setup=false` they were pre-existing (e.g., from a prior round's `setup=true` run).
|
|
209
208
|
|
|
210
209
|
---
|
|
211
210
|
|
|
@@ -214,28 +213,28 @@ T1 expects `<output-path>/testcases.json` and `<output-path>/app-metadata.json`
|
|
|
214
213
|
Run all validations in a single Bash command:
|
|
215
214
|
|
|
216
215
|
```bash
|
|
217
|
-
test -f "<
|
|
216
|
+
test -f "<hap_path>" && mkdir -p "<output_path>" && test -f "<output_path>/testcases.json" && test -f "<output_path>/app-metadata.json" && echo "OK"
|
|
218
217
|
```
|
|
219
218
|
|
|
220
219
|
If `setup=false`, additionally verify each JSON parses and `testcases.json` is non-empty:
|
|
221
220
|
|
|
222
221
|
```bash
|
|
223
|
-
python -c "import json,sys; t=json.load(open(sys.argv[1],encoding='utf-8')); m=json.load(open(sys.argv[2],encoding='utf-8')); assert isinstance(t,list) and len(t)>0, 'testcases.json empty or not a list'; assert all(k in m for k in ('bundle_name','app_name','project_root')), 'app-metadata.json missing required fields'; print('OK')" "<
|
|
222
|
+
python -c "import json,sys; t=json.load(open(sys.argv[1],encoding='utf-8')); m=json.load(open(sys.argv[2],encoding='utf-8')); assert isinstance(t,list) and len(t)>0, 'testcases.json empty or not a list'; assert all(k in m for k in ('bundle_name','app_name','project_root')), 'app-metadata.json missing required fields'; print('OK')" "<output_path>/testcases.json" "<output_path>/app-metadata.json"
|
|
224
223
|
```
|
|
225
224
|
|
|
226
225
|
If any check fails, write a `self-test-report.md` using the sentinel format from Shared Utilities. The `reason:` line names the specific failure, e.g.:
|
|
227
226
|
|
|
228
|
-
- `reason: hap not found at <
|
|
229
|
-
- `reason: setup=false but testcases.json missing at <
|
|
227
|
+
- `reason: hap not found at <hap_path>`
|
|
228
|
+
- `reason: setup=false but testcases.json missing at <output_path>/testcases.json — re-run with setup=true`
|
|
230
229
|
- `reason: setup=false but testcases.json failed to parse — re-run with setup=true`
|
|
231
230
|
- `reason: setup=false but testcases.json is empty — re-run with setup=true`
|
|
232
|
-
- `reason: setup=false but app-metadata.json missing or malformed at <
|
|
231
|
+
- `reason: setup=false but app-metadata.json missing or malformed at <output_path>/app-metadata.json — re-run with setup=true`
|
|
233
232
|
|
|
234
233
|
Then stop.
|
|
235
234
|
|
|
236
235
|
### T2 — Read App Metadata
|
|
237
236
|
|
|
238
|
-
Read `<
|
|
237
|
+
Read `<output_path>/app-metadata.json` and extract `<bundle_name>`, `<app_name>`, and `<project-root>`.
|
|
239
238
|
|
|
240
239
|
### T3 — Verify Device Connection
|
|
241
240
|
|
|
@@ -245,28 +244,30 @@ Run `hdc list targets`:
|
|
|
245
244
|
|
|
246
245
|
Record the device serial number.
|
|
247
246
|
|
|
248
|
-
### T4 — Locate AutoTest Directory & Verify config
|
|
247
|
+
### T4 — Locate AutoTest Directory & Verify autotest config
|
|
249
248
|
|
|
250
|
-
Find the `test-tools/autotest` directory using the **AutoTest Directory Locator** in Shared Utilities (
|
|
249
|
+
Find the `test-tools/autotest` directory using the **AutoTest Directory Locator** in Shared Utilities (OS env var `HOMETRANS_TOOL_PATH` → walk up from `<output_path>`). If not found, write a `self-test-report.md` with the sentinel format (`status: FAIL` / `reason: AutoTest directory not found from HOMETRANS_TOOL_PATH env var or output_path`), then stop.
|
|
251
250
|
|
|
252
|
-
Set `<autotest_dir>` to the found path.
|
|
251
|
+
Set `<autotest_dir>` to the found path.
|
|
252
|
+
|
|
253
|
+
The AutoTest configuration now lives in the `autotest` block of `~/.hometrans/config.json` (it replaced the old `config.yaml`). `self_test_runner.py` reads it at run time and materializes a transient YAML for `AutoTest.batch` — you do **not** create or edit any YAML. Just verify the config is usable: the `autotest` block exists with a real `api_key`, **or** the `TEST_API_KEY` OS environment variable is set (the runner uses it to fill a placeholder/empty key).
|
|
253
254
|
|
|
254
255
|
```bash
|
|
255
|
-
|
|
256
|
+
python -c "import json,os,sys; from pathlib import Path; cfg=Path.home()/'.hometrans'/'config.json'; tp=os.environ.get('HOMETRANS_TOOL_PATH'); cand=(Path(tp).parent/'config.json') if tp else None; cfg=cand if (cand and cand.exists()) else cfg; at=(json.loads(cfg.read_text(encoding='utf-8')).get('autotest') or {}) if cfg.exists() else {}; real=any(isinstance(at.get(k),dict) and str(at[k].get('api_key','')).strip() not in ('','YOUR_API_KEY_HERE') for k in ('unified_model','execute_model','decision_model')); print('OK' if (real or os.environ.get('TEST_API_KEY','').strip()) else 'MISSING')"
|
|
256
257
|
```
|
|
257
258
|
|
|
258
|
-
If the
|
|
259
|
+
If this does not print `OK` (no `autotest` block with a real `api_key`, and no `TEST_API_KEY` in the OS environment), write `self-test-report.md` with the sentinel format (`status: FAIL` / `reason: autotest api_key not configured — set TEST_API_KEY env var or run ht init`), then stop.
|
|
259
260
|
|
|
260
261
|
### T5 — Clean Task Directory
|
|
261
262
|
|
|
262
263
|
```bash
|
|
263
|
-
rm -rf "<
|
|
264
|
+
rm -rf "<output_path>/task" && echo "Task directory cleaned" || echo "Task directory does not exist, skipping cleanup"
|
|
264
265
|
```
|
|
265
266
|
|
|
266
267
|
### T6 — Run self_test_runner.py
|
|
267
268
|
|
|
268
269
|
> 🚨 **MANDATORY**: Environment setup, HAP installation, and test execution are all handled by a **single invocation** of `self_test_runner.py run`. The script synchronously executes:
|
|
269
|
-
> 1.
|
|
270
|
+
> 1. Read & validate the `autotest` config from `~/.hometrans/config.json` (filling the api_key from `TEST_API_KEY` if needed) and materialize a transient YAML for AutoTest.batch
|
|
270
271
|
> 2. `uv sync` — installs `harmony-autotest` + `hypium_mcp`
|
|
271
272
|
> 3. `hdc uninstall` + `hdc install -r`
|
|
272
273
|
>
|
|
@@ -280,7 +281,7 @@ rm -rf "<output-path>/task" && echo "Task directory cleaned" || echo "Task direc
|
|
|
280
281
|
> - ❌ Writing a shell loop or Python loop to iterate over cases yourself
|
|
281
282
|
|
|
282
283
|
```bash
|
|
283
|
-
cd "<autotest_dir>" && python self_test_runner.py run --testcases "<
|
|
284
|
+
cd "<autotest_dir>" && python self_test_runner.py run --testcases "<output_path>/testcases.json" --hap "<hap_path>" --bundle-name "<bundle_name>" --category "<app_name>" --task-dir "<output_path>/task" --output-dir "<output_path>"
|
|
284
285
|
```
|
|
285
286
|
|
|
286
287
|
Record the `pid` and `task_subdir` from the output.
|
|
@@ -290,7 +291,7 @@ Record the `pid` and `task_subdir` from the output.
|
|
|
290
291
|
Each poll MUST include `sleep 60`. **Use `timeout: 120000` on each Bash call** so the 60-second sleep plus the status command have headroom and the status check itself isn't truncated:
|
|
291
292
|
|
|
292
293
|
```bash
|
|
293
|
-
sleep 60 && cd "<autotest_dir>" && python self_test_runner.py status --task-dir "<
|
|
294
|
+
sleep 60 && cd "<autotest_dir>" && python self_test_runner.py status --task-dir "<output_path>/task" --output-dir "<output_path>"
|
|
294
295
|
```
|
|
295
296
|
|
|
296
297
|
| `status` | Meaning | Exit code | Action |
|
|
@@ -309,14 +310,14 @@ sleep 60 && cd "<autotest_dir>" && python self_test_runner.py status --task-dir
|
|
|
309
310
|
|
|
310
311
|
**Polling rules:**
|
|
311
312
|
- Max iterations: **N_cases × 6** (each case takes ~6 minutes). For 8 cases → max 48 polls. If still `RUNNING` after that, kill and write TIMEOUT report.
|
|
312
|
-
- **Timeout kill**: `cd "<autotest_dir>" && python self_test_runner.py kill --task-dir "<
|
|
313
|
+
- **Timeout kill**: `cd "<autotest_dir>" && python self_test_runner.py kill --task-dir "<output_path>/task"`. This verifies the PID belongs to an `AutoTest.batch` process before terminating it.
|
|
313
314
|
- **CRASHED**: Write CRASHED report with sentinel (`status: FAIL` / `reason: AutoTest batch crashed`). Include the `log_tail` from the status response. `task_results.jsonl` is unavailable.
|
|
314
315
|
- **TIMEOUT**: After killing, write TIMEOUT report with sentinel (`status: FAIL` / `reason: AutoTest batch timed out after N polls`) and include partial results from `task_results.jsonl` if any cases finished.
|
|
315
316
|
|
|
316
317
|
### T8 — Read results after completion
|
|
317
318
|
|
|
318
319
|
After `COMPLETED`:
|
|
319
|
-
1. Read stdout log from `<
|
|
320
|
+
1. Read stdout log from `<output_path>/self_test_*.log` (full runner log).
|
|
320
321
|
2. Read `task_results.jsonl` from `task_subdir`. Each line is a JSON object with fields: `exec_index`, `case_name`, `report_dir`, `status` (PASS / FAIL / UNKNOWN), `reason`, `duration_seconds`, etc.
|
|
321
322
|
- `report_dir` is the absolute path to that case's execution directory. You MUST include this as `**AutoTest 任务路径**` in the report for EVERY case.
|
|
322
323
|
- **Status semantics**: `PASS` = AutoTest rendered a PASS badge. `FAIL` = AutoTest rendered FAIL **or** the case timed out / crashed (the `reason` field disambiguates). `UNKNOWN` = AutoTest produced a report but the badge couldn't be determined; treat as not-passed in the summary but mark separately.
|
|
@@ -337,7 +338,7 @@ After `COMPLETED`:
|
|
|
337
338
|
**Collect inputs:**
|
|
338
339
|
- `<suite_name>` — read the first non-empty line of `test_case.md` (typically `# <title>`). Strip leading `#` and whitespace. When `setup=false`, `test_case.md` may not be at a known path; in that case use the `suite_name` field from `task_results.jsonl`'s first entry if present, else use `bundle_name` as a fallback.
|
|
339
340
|
- `<device_serial>` — from T3.
|
|
340
|
-
- `<hap_basename>` — basename of
|
|
341
|
+
- `<hap_basename>` — basename of hap_path.
|
|
341
342
|
- `<task_subdir>` — from T7 status response.
|
|
342
343
|
|
|
343
344
|
**Run the renderer:**
|
|
@@ -345,11 +346,11 @@ After `COMPLETED`:
|
|
|
345
346
|
```bash
|
|
346
347
|
cd "<autotest_dir>" && uv run python report_tool.py generate \
|
|
347
348
|
--task-subdir "<task_subdir>" \
|
|
348
|
-
--app-metadata "<
|
|
349
|
-
--hap "<
|
|
349
|
+
--app-metadata "<output_path>/app-metadata.json" \
|
|
350
|
+
--hap "<hap_path>" \
|
|
350
351
|
--device "<device_serial>" \
|
|
351
352
|
--suite "<suite_name>" \
|
|
352
|
-
--out "<
|
|
353
|
+
--out "<output_path>/self-test-report.md" \
|
|
353
354
|
--validate
|
|
354
355
|
```
|
|
355
356
|
|
|
@@ -359,7 +360,7 @@ cd "<autotest_dir>" && uv run python report_tool.py generate \
|
|
|
359
360
|
To re-validate an existing report without regenerating it (debugging only):
|
|
360
361
|
|
|
361
362
|
```bash
|
|
362
|
-
cd "<autotest_dir>" && uv run python report_tool.py validate "<
|
|
363
|
+
cd "<autotest_dir>" && uv run python report_tool.py validate "<output_path>/self-test-report.md"
|
|
363
364
|
```
|
|
364
365
|
|
|
365
366
|
**Pre-case rendering**: Rows with `case_name` starting with `[PRE] ` go into `## 前置用例`. All others go into `## 用例详情`. Pre indices and Case indices each start at 1 within their own section (`### Pre 1:`, `### Case 1:`). The script emits these forms automatically — do NOT hand-edit to `### Case PRE-1:` or any other variant; the validator will reject it.
|
|
@@ -380,8 +381,8 @@ cd "<autotest_dir>" && uv run python report_tool.py validate "<output-path>/self
|
|
|
380
381
|
- **#2 — Every case MUST include `**AutoTest 任务路径**`**: the absolute `report_dir` from `task_results.jsonl`. Without it the report is incomplete and users cannot locate execution artifacts. After T9, verify every case section contains this field.
|
|
381
382
|
- **Two-phase architecture**: When the parse phase runs, the LLM writes `_extracted.json` → `testcases_tool.py` writes `testcases.json`. Never write `testcases.json` directly. If `testcases.json` already exists at the output path and the parse phase runs, `testcases_tool.py` overwrites it — never skip the script.
|
|
382
383
|
- **App name → bundle_name is critical**: `test_steps` must use `bundle_name` (e.g., `com.example.tuku`), NOT the display name. AutoTest uses this to launch the correct app. Using the display name instead may launch the wrong app entirely.
|
|
383
|
-
- **JSON contract**: `app-metadata.json` and `testcases.json` always live at `<
|
|
384
|
-
- **AutoTest directory locator**: Resolve `<
|
|
384
|
+
- **JSON contract**: `app-metadata.json` and `testcases.json` always live at `<output_path>/app-metadata.json` and `<output_path>/testcases.json`. T2 reads from the file (not from memory).
|
|
385
|
+
- **AutoTest directory locator**: Resolve `<HOMETRANS_TOOL_PATH>/test-tools/autotest` from the `HOMETRANS_TOOL_PATH` OS environment variable → walking up from `<output_path>` (see Shared Utilities). Do not assume `$(pwd)` is anchored anywhere in particular.
|
|
385
386
|
- **Sentinel-format early-exit reports**: When T1 / T3 / T4 / T7 write a degraded FAIL report (config error, no device, missing autotest dir, crashed batch, timeout, or `setup=false` precondition failure), the report's first non-frontmatter line MUST be `status: FAIL` and the second MUST be `reason: <one-line reason>`. This lets callers detect early-exit reports without parsing a case table.
|
|
386
387
|
- **Quote all paths** — paths may contain spaces.
|
|
387
388
|
- **Capture complete output** — never truncate command output; it is essential for diagnosis.
|
package/agents/spec-generator.md
CHANGED
|
@@ -10,14 +10,14 @@ You are a **Spec Generator** specializing in producing high-quality requirement
|
|
|
10
10
|
|
|
11
11
|
## Expected Input
|
|
12
12
|
|
|
13
|
-
- `
|
|
14
|
-
- `
|
|
15
|
-
- `
|
|
13
|
+
- `requirement_description_dir`: Absolute path to a directory containing one or more `.txt` files. Each `.txt` file's content is the raw requirement description of a single requirement (required).
|
|
14
|
+
- `android_project_dir`: Absolute path to the Android project root (required).
|
|
15
|
+
- `spec_output_dir`: Absolute path to the directory where the generated spec files (`xxx.md`) will be written (required).
|
|
16
16
|
|
|
17
17
|
## Expected Output
|
|
18
18
|
|
|
19
|
-
- One markdown spec file per input `.txt` requirement file, written under `
|
|
20
|
-
- One intermediate code-trace file per requirement, written under `<
|
|
19
|
+
- One markdown spec file per input `.txt` requirement file, written under `spec_output_dir`. The spec filename mirrors the source filename with `.md` extension (e.g. `create_playlist.txt` → `create_playlist.md`).
|
|
20
|
+
- One intermediate code-trace file per requirement, written under `<spec_output_dir>/.trace/<source_filename_without_ext>.md`. This is the **machine-readable contract** between code exploration and spec synthesis — it must be written **before** the spec is synthesized. The spec MUST be synthesized from the trace file, not directly from conversation context.
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
@@ -345,17 +345,17 @@ These are the authoring rules the final spec MUST follow:
|
|
|
345
345
|
|
|
346
346
|
### Step 0 — Validate inputs
|
|
347
347
|
|
|
348
|
-
1. Verify `
|
|
349
|
-
2. Verify `
|
|
350
|
-
3. Ensure `
|
|
348
|
+
1. Verify `requirement_description_dir` exists and is a directory. List all `.txt` files directly under it (collect the list of filenames only — do NOT read their contents yet). If there are no `.txt` files, stop and report the error.
|
|
349
|
+
2. Verify `android_project_dir` exists and is a directory.
|
|
350
|
+
3. Ensure `spec_output_dir` exists (create it if it does not).
|
|
351
351
|
|
|
352
352
|
### Step 1 — Ensure the Android project is a Git repository
|
|
353
353
|
|
|
354
|
-
Run `git rev-parse --is-inside-work-tree` inside `
|
|
354
|
+
Run `git rev-parse --is-inside-work-tree` inside `android_project_dir` to detect whether it is already a Git repo.
|
|
355
355
|
|
|
356
356
|
- If the command reports `true`, continue to Step 2.
|
|
357
357
|
- Otherwise, initialize the project as a Git repository, then continue to Step 2:
|
|
358
|
-
1. `git init` (in `
|
|
358
|
+
1. `git init` (in `android_project_dir`)
|
|
359
359
|
2. `git add .`
|
|
360
360
|
3. `git commit -m "init git repo by spec gen agent"`
|
|
361
361
|
|
|
@@ -365,14 +365,14 @@ The reason this matters: GitNexus indexes a project under its Git identity. With
|
|
|
365
365
|
|
|
366
366
|
GitNexus installation and configuration are handled by the `/setup` command. Assume `gitnexus` is already installed and `gitnexus setup` has been run. If the GitNexus commands below fail because GitNexus is not installed, instruct the user to run `/setup` first and stop.
|
|
367
367
|
|
|
368
|
-
1. `cd` into `
|
|
368
|
+
1. `cd` into `android_project_dir` (or otherwise ensure GitNexus commands run against this repo).
|
|
369
369
|
2. Run `/gitnexus-cli status`.
|
|
370
370
|
3. Decide based on output:
|
|
371
371
|
- **No index** (status reports the repo is not indexed) → run `/gitnexus-cli analyze`.
|
|
372
372
|
- **Index is stale** (status reports staleness) → run `/gitnexus-cli analyze`.
|
|
373
373
|
- **Index is fresh** → skip analyze, continue to Step 3.
|
|
374
374
|
4. If `/gitnexus-cli analyze` fails, surface the error to the user and stop. Do not attempt the spec generation without an index — the resulting spec would miss code-grounded scenarios.
|
|
375
|
-
5. Parse the `/gitnexus-cli status` output to find the repository identifier for `
|
|
375
|
+
5. Parse the `/gitnexus-cli status` output to find the repository identifier for `android_project_dir`; remember it as `<repo-id>`.
|
|
376
376
|
|
|
377
377
|
### Step 3 — Process each requirement file independently, one at a time
|
|
378
378
|
|
|
@@ -380,7 +380,7 @@ For each `.txt` filename collected in Step 0, in order, run **3.1 → 3.5 end-to
|
|
|
380
380
|
|
|
381
381
|
The order matters: **first build a structured code-trace file from the Android source, then synthesize the spec from that trace file**. Spec synthesis (3.5) must read the trace file written by 3.3/3.4 — synthesizing directly from conversation context causes scenario drift and fabricated `file:line` facts.
|
|
382
382
|
|
|
383
|
-
Ensure `<
|
|
383
|
+
Ensure `<spec_output_dir>/.trace/` exists before the first iteration (create it once if missing).
|
|
384
384
|
|
|
385
385
|
#### 3.1 Read
|
|
386
386
|
|
|
@@ -410,7 +410,7 @@ Run **both paths concurrently in the same turn** (mcp calls in parallel). Their
|
|
|
410
410
|
|
|
411
411
|
Forbidden: full-Read of large source files; `Grep` for semantic concepts; mcp calls without `repo=<repo-id>` scope; nesting `/gitnexus-exploring` or any Skill call from within this agent (role-hijack risk — use the `mcp__gitnexus__*` tools directly).
|
|
412
412
|
|
|
413
|
-
#### 3.3 Trace — code exploration & write `<
|
|
413
|
+
#### 3.3 Trace — code exploration & write `<spec_output_dir>/.trace/<source_filename_without_ext>.md`
|
|
414
414
|
|
|
415
415
|
Using the recall set from 3.2, explore each relevant component along the dimensions below, then write the trace file. Exploration and write are a single unit — the trace file is the only machine-readable contract carried into 3.5.
|
|
416
416
|
|
|
@@ -425,7 +425,7 @@ Using the recall set from 3.2, explore each relevant component along the dimensi
|
|
|
425
425
|
- **Scope / Boundary · exhaustive entry enumeration** — list **every** UI path reaching this REQ's function/state, not limited to the entries explicitly mentioned in the REQ text. Use `mcp__gitnexus__cypher` or `Grep` to reverse-look every write-site of the relevant state key, then back-trace each to its UI entry (settings page / player overflow menu / list long-press / notification action / desktop lyrics / car mode / etc.). **Missing entries here become missing scenarios in the spec.**
|
|
426
426
|
- **Consumer list & non-consumers** — who reads the state (use `mcp__gitnexus__impact`), and which surfaces explicitly do NOT (boundary counter-examples with grep evidence).
|
|
427
427
|
|
|
428
|
-
**Trace file template** (write at `<
|
|
428
|
+
**Trace file template** (write at `<spec_output_dir>/.trace/<source_filename_without_ext>.md`):
|
|
429
429
|
|
|
430
430
|
```markdown
|
|
431
431
|
# Code trace · <REQ filename without ext>
|
|
@@ -495,7 +495,7 @@ Both checks pass → proceed to 3.5.
|
|
|
495
495
|
|
|
496
496
|
#### 3.5 Synthesize — write the final spec
|
|
497
497
|
|
|
498
|
-
Read the trace file from 3.3 (post-review) and synthesize the spec per `## Principles` and `## Spec Few-shot Samples`. Write to `<
|
|
498
|
+
Read the trace file from 3.3 (post-review) and synthesize the spec per `## Principles` and `## Spec Few-shot Samples`. Write to `<spec_output_dir>/<source_filename_without_ext>.md` (overwrite if exists).
|
|
499
499
|
|
|
500
500
|
**Synthesis discipline**:
|
|
501
501
|
|