android2harmony 0.1.5 → 0.1.6
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/agents/self-tester.md +33 -354
- package/dist/index.js +172 -76
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/skills/a2h-resource-convert/SKILL.md +36 -7
- package/skills/a2h-resource-convert/scripts/a2h_resource_convert.js +20 -0
- package/skills/a2h-resource-convert/scripts/app_identity.js +741 -0
- package/skills/a2h-ui-transfer/SKILL.md +14 -3
- package/skills/a2h-ui-transfer/references/conversion-procedure.md +5 -30
- package/skills/a2h-ui-transfer/scripts/android_parse_fast.js +137 -20
- package/skills/hmos-fix-build-errors/SKILL.md +1 -1
- package/skills/hmos-incremental-ui-align/README.md +251 -251
- package/skills/hmos-incremental-ui-align/SKILL.md +364 -364
- package/skills/hmos-integration-test/README.md +341 -0
- package/skills/hmos-integration-test/SKILL.md +446 -0
- package/skills/hmos-integration-test/scripts/report-tool.mjs +646 -0
- package/skills/hmos-integration-test/scripts/resolve-metadata-tool.mjs +147 -0
- package/skills/hmos-integration-test/scripts/self-test-runner.mjs +1006 -0
- package/skills/hmos-integration-test/scripts/testcases-tool.mjs +189 -0
- package/skills/hmos-spec-generate/SKILL.md +26 -24
- package/skills/hmos-spec-generate/scripts/parse_requirements.ts +515 -0
- package/skills/hmos-spec-generate/template/REQ.txt +22 -0
- package/skills/hmos-spec-generate/template/REQ.xlsx +0 -0
package/agents/self-tester.md
CHANGED
|
@@ -1,376 +1,55 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: self-tester
|
|
3
|
-
description: Self-Tester —
|
|
3
|
+
description: Self-Tester — thin subagent wrapper that runs the hmos-integration-test skill to execute on-device integration tests (parse test_case.md → install HAP → run AutoTest batch → produce self-test-report.md). Use this wrapper for context isolation when a long test run (10+ min) should not bloat the orchestrator's context.
|
|
4
4
|
color: success
|
|
5
5
|
mode: subagent
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# Self-Tester
|
|
8
|
+
# Self-Tester (thin wrapper)
|
|
9
9
|
|
|
10
|
-
You are
|
|
10
|
+
You are the **self-tester** subagent. Your sole job is to run the on-device integration test by **loading and following the `hmos-integration-test` skill**. That skill's `SKILL.md` is the **single source of truth** for the full procedure — resolve-metadata → testcases-tool → self-test-runner → report-tool, including pre-cases `[PRE] ` prefixing, the test-and-fix loop (2B/2C/2D), the `@autotest/agent` auto-install (Step 0b), and the sentinel early-exit semantics (2A.1).
|
|
11
11
|
|
|
12
|
-
> 🚨 **
|
|
12
|
+
> 🚨 **Do NOT re-implement the procedure here.** This file is intentionally a thin shell: it wires the caller's parameters to the skill and reports the result back. Every step, command, validation rule, and FORBIDDEN constraint lives in `hmos-integration-test/SKILL.md`. If anything here seems to conflict with the skill, **the skill wins**.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
## Expected Input
|
|
17
|
-
|
|
18
|
-
| Parameter | Required | Type | Description |
|
|
19
|
-
|-----------|----------|------|-------------|
|
|
20
|
-
| `hap_path` | always | path(s) | The package set: a single `.hap`/`.hsp` file, a directory, **or a comma-separated list** of files/dirs. The union across all entries must hold one entry HAP + any in-app HSPs / feature HAPs (which may live in different directories). The runner aggregates every listed package and installs them in one transaction. |
|
|
21
|
-
| `output_path` | always | path | Root output directory. All artifacts — `testcases.json`, `app-metadata.json`, `_extracted.json`, `self-test-report.md`, `task/` — are written here |
|
|
22
|
-
| `project_dir` | when `setup=true` | path | HarmonyOS 工程根目录(含 `AppScope/app.json5`),用于解析 `bundle_name` / `app_name` |
|
|
23
|
-
| `test_case_path` | when `setup=true` | path | Path to `test_case.md` |
|
|
24
|
-
| `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` |
|
|
25
|
-
| `setup` | optional (default `true`) | bool | `true` → run Phase S1-S4 (parse) then Phase T1-T8 (test). `false` → skip Phase S1-S4; expect `<output_path>/testcases.json` and `<output_path>/app-metadata.json` to already exist |
|
|
26
|
-
|
|
27
|
-
## Expected Output
|
|
28
|
-
|
|
29
|
-
| File | When written |
|
|
30
|
-
|------|--------------|
|
|
31
|
-
| `<output_path>/app-metadata.json` | S2 (when `setup=true`) |
|
|
32
|
-
| `<output_path>/_extracted.json` | S3.2 (when `setup=true`) — intermediate debug artifact |
|
|
33
|
-
| `<output_path>/testcases.json` | S4 (when `setup=true`) |
|
|
34
|
-
| `<output_path>/self-test-report.md` | T8 (always) |
|
|
35
|
-
| `<output_path>/task/task_<timestamp>/` | T6 (always) — per-case execution artifacts |
|
|
36
|
-
|
|
37
|
-
---
|
|
38
|
-
|
|
39
|
-
## Shared Utilities
|
|
40
|
-
|
|
41
|
-
### Resolving the AutoTest Tools Directory
|
|
42
|
-
|
|
43
|
-
All AutoTest tools are invoked directly via `node`. Resolve the tools directory once at the start (the global npm package always contains `tools/test-tools/autotest/` with `node_modules/`):
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
TOOL_DIR="$(npm root -g)/@buaa_smat/hometrans/tools/test-tools/autotest"
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
**Tool file mapping:**
|
|
50
|
-
|
|
51
|
-
| Tool | File | Example |
|
|
52
|
-
|---|---|---|
|
|
53
|
-
| selftest | `$TOOL_DIR/engine/self-test-runner.ts` | `node "$TOOL_DIR/engine/self-test-runner.ts" run --testcases ...` |
|
|
54
|
-
| testcases | `$TOOL_DIR/engine/testcases-tool.ts` | `node "$TOOL_DIR/engine/testcases-tool.ts" generate ...` |
|
|
55
|
-
| report | `$TOOL_DIR/engine/report-tool.ts` | `node "$TOOL_DIR/engine/report-tool.ts" generate ...` |
|
|
56
|
-
| resolve-metadata | `$TOOL_DIR/resolve-metadata-tool.ts` | `node "$TOOL_DIR/resolve-metadata-tool.ts" --project-dir ... --output ...` |
|
|
57
|
-
|
|
58
|
-
Each tool has its own commander CLI parsing, so sub-command names, flags, exit codes, and the strict stdout-JSON contract are exactly as documented in each phase below.
|
|
59
|
-
|
|
60
|
-
> **Dev-mode:** `dist/` only exists after `npm run build`; ensure `ht` on PATH points at the built package (e.g. via `npm link`). The agent never invokes `tsx` or the tools' `.js` directly.
|
|
61
|
-
|
|
62
|
-
> The `run` subcommand emits `{status:'RUNNING', pid, ...}` on success (no-`--timeout` backward-compat mode), or `{status:'FAILED', error}` if the batch process could not be spawned. With `--timeout` (the agent's normal mode — see T6), no `RUNNING` is emitted; the call blocks until terminal status and returns one final JSON line. On `FAILED`, no `batch.pid` is written; a subsequent `status` call returns `NOT_STARTED`.
|
|
63
|
-
|
|
64
|
-
### AutoTest Directory Locator
|
|
65
|
-
|
|
66
|
-
Used by T4 as an AutoTest-install precheck (S4 no longer needs it — the testcases tool is a pure JSON transform; and the selftest runner resolves this dir itself at run time). The AutoTest tools are installed by `ht init` under the HomeTrans tools dir, recorded in `HOMETRANS_TOOL_PATH` — the single tools-dir env var; there is no autotest-specific override.
|
|
67
|
-
|
|
68
|
-
A single command resolves the whole chain — **source-tree walk-up → env var `HOMETRANS_TOOL_PATH` → default `~/.hometrans/tools`** (there is no `config.json` layer), then falls back to walking up from `<output_path>` (for a sibling `test-tools/autotest`, or the legacy `agents/test-tools/autotest`) when `--from` is supplied. It prints the resolved dir on success and exits non-zero if nothing is found (**anchor the fallback at `<output_path>`, the sub-agent cwd is not guaranteed**):
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
node "$TOOL_DIR/engine/self-test-runner.ts" resolve-dir --from "<output_path>"
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
| Caller | Purpose | On failure |
|
|
75
|
-
|--------|---------|------------|
|
|
76
|
-
| 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 |
|
|
77
|
-
|
|
78
|
-
### Input Validation Template
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
mkdir -p "<output_path>" && test -f "<target-file>" && echo "OK"
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### app-metadata.json Contract
|
|
85
|
-
|
|
86
|
-
```json
|
|
87
|
-
{"bundle_name": "...", "app_name": "...", "project_root": "..."}
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
S2 writes the file to `<output_path>/app-metadata.json`. T2 reads from the same path. When `setup=false`, S2 is skipped and T2 reads the file that already exists at `<output_path>/app-metadata.json`.
|
|
91
|
-
|
|
92
|
-
### Path Quoting Rule
|
|
93
|
-
|
|
94
|
-
All filesystem paths in Bash commands MUST be double-quoted.
|
|
95
|
-
|
|
96
|
-
### Sentinel-FAIL Report Format
|
|
97
|
-
|
|
98
|
-
When T1, T3, T4, or T6 fails before the case table can be rendered, the agent writes a degraded `self-test-report.md` so callers can detect the early-exit without parsing a case table. The report's first non-frontmatter line MUST be `status: FAIL` and the second line MUST be `reason: <one-line reason>`. The rest of the report may be free-form context.
|
|
99
|
-
|
|
100
|
-
---
|
|
101
|
-
|
|
102
|
-
## Phase S1-S4 — Setup (when `setup=true`)
|
|
103
|
-
|
|
104
|
-
> 🚨 **Skip this entire phase when `setup=false`.** Go directly to Phase T1-T8.
|
|
105
|
-
|
|
106
|
-
---
|
|
107
|
-
|
|
108
|
-
### S1 — Validate Inputs
|
|
109
|
-
|
|
110
|
-
Run all validations in a single Bash command:
|
|
111
|
-
|
|
112
|
-
```bash
|
|
113
|
-
mkdir -p "<output_path>" && test -f "<test_case_path>" && echo "OK"
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
If the command fails, stop and report the error.
|
|
117
|
-
|
|
118
|
-
### S2 — Resolve App Metadata
|
|
119
|
-
|
|
120
|
-
Call `node "$TOOL_DIR/resolve-metadata-tool.ts"` to discover `bundle_name`/`app_name`
|
|
121
|
-
from the HarmonyOS project and write `app-metadata.json`:
|
|
122
|
-
|
|
123
|
-
```bash
|
|
124
|
-
node "$TOOL_DIR/resolve-metadata-tool.ts" --project-dir "<project_dir>" --output "<output_path>/app-metadata.json"
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Parse the JSON from stdout — `bundle_name` and `app_name` are needed in S3
|
|
128
|
-
for app-name → bundle-name replacement. The file at `--output` is also
|
|
129
|
-
written for downstream phases (T2 reads it when `setup=false`).
|
|
130
|
-
|
|
131
|
-
On non-zero exit, stop and report the stderr message as the failure reason.
|
|
132
|
-
|
|
133
|
-
### S3 — Parse test_case.md (LLM extraction)
|
|
134
|
-
|
|
135
|
-
> 🚨 **Two-phase architecture**: You (the LLM) extract into `_extracted.json`, then the testcases tool generates `testcases.json`. You do NOT write `testcases.json` directly.
|
|
136
|
-
|
|
137
|
-
**S3.1 — Read test_case.md**
|
|
138
|
-
|
|
139
|
-
Read the file at `test_case_path` in a single Read call.
|
|
140
|
-
|
|
141
|
-
Then resolve a pre-test-case source file:
|
|
142
|
-
1. If the caller provided `pre_test_case_path`, use that path directly.
|
|
143
|
-
2. Otherwise, check for `pre_test_case.md` in the same directory as `test_case.md`.
|
|
144
|
-
|
|
145
|
-
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.
|
|
146
|
-
|
|
147
|
-
**S3.2 — Extract into `_extracted.json`**
|
|
148
|
-
|
|
149
|
-
Write to `<output_path>/_extracted.json`:
|
|
14
|
+
## Why this subagent exists
|
|
150
15
|
|
|
151
|
-
|
|
152
|
-
{
|
|
153
|
-
"bundle_name": "<bundle_name from S2>",
|
|
154
|
-
"app_name": "<app_name from S2>",
|
|
155
|
-
"cases": [
|
|
156
|
-
{
|
|
157
|
-
"case_name": "<scenario title from ### Scenario: line>",
|
|
158
|
-
"actions": "<text from - 动作: line>",
|
|
159
|
-
"expected_results": "<text from - 预期结果: line>"
|
|
160
|
-
}
|
|
161
|
-
]
|
|
162
|
-
}
|
|
163
|
-
```
|
|
16
|
+
The integration-test flow is long (parse + install + batch + poll + report, often 10+ minutes). When an orchestrator skill (e.g. `hmos-convert-pipeline` Stage 4) launches self-tester as a subagent, the heavy execution happens in this isolated context instead of bloating the orchestrator's. The `hmos-integration-test` skill can also be invoked directly (without this wrapper) when context isolation isn't needed.
|
|
164
17
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
- **Pre-cases MUST be the first entries** of `cases`, in source order from `pre_test_case.md`. Each pre-case's `case_name` MUST be prefixed by `[PRE] ` (trailing space). Zero, one, or more `[PRE]` entries are all acceptable. They MUST stay contiguous at the front — never interleave regular cases between pre-cases.
|
|
168
|
-
- Each pre-case's title text comes from its own `### Scenario:` line.
|
|
169
|
-
- **Naming fallback** — if a pre-case has no `### Scenario:` line, use `[PRE] 前置设置`. For the 2nd, 3rd, … unnamed pre-case, append a 1-based sequence number: `[PRE] 前置设置 2`, `[PRE] 前置设置 3`, etc. Never produce two pre-cases with the same `case_name`.
|
|
170
|
-
- Example: if `pre_test_case.md` describes 授权流程 and 引导页跳过 (both with `### Scenario:` lines) → `cases[0].case_name = "[PRE] 授权弹窗一键允许"`, `cases[1].case_name = "[PRE] 跳过新手引导"`, then the regular cases follow.
|
|
171
|
-
- For each `### Scenario:` subsection under each `## Spec:` section in `test_case.md`:
|
|
172
|
-
- `case_name`: The scenario title text after `### Scenario:` (**no `[PRE]` prefix**).
|
|
173
|
-
- `actions`: The text after `- 动作:`. **Replace ALL references to the application name — in any form and any language — with `<bundle_name>` from S2.** This includes:
|
|
174
|
-
- the **literal placeholder `被测应用`** — TCG (the test-case generator) writes this exact token in every `打开 …` step when the app's real name was unknown at generation time. It is the app-under-test stand-in, so treat it as an app-name reference and replace **every** occurrence with `<bundle_name>` regardless of whether the real `app_name` string appears anywhere in the case;
|
|
175
|
-
- the English display name (e.g., "Simple Gallery"), Chinese name (e.g., "图库", "简单图库"), localized name (e.g., "Tuku"), and any variant with suffix (e.g., "图库应用", "Tuku应用", "Simple Gallery应用").
|
|
176
|
-
|
|
177
|
-
Do this for ALL occurrences, not just the first one.
|
|
178
|
-
- Example: if `bundle_name` is `com.example.tuku` and `app_name` is `Simple Gallery`:
|
|
179
|
-
- `打开 被测应用 -> 进入歌单页面` → `打开 com.example.tuku -> 进入歌单页面`
|
|
180
|
-
- `点击 Simple Gallery 图标启动应用` → `点击 com.example.tuku 图标启动应用`
|
|
181
|
-
- `打开图库应用` → `打开com.example.tuku`
|
|
182
|
-
- `从最近任务列表恢复图库应用` → `从最近任务列表恢复com.example.tuku`
|
|
183
|
-
- `expected_results`: The text after `- 预期结果:`. If multiple lines, join with `,`. Same app name → bundle_name replacement rule applies.
|
|
184
|
-
- The pre-case's `actions` / `expected_results` follow the **same app_name → bundle_name replacement rule**.
|
|
185
|
-
- **Lines to SKIP**: `- 前置条件:` and all its sub-items, `## 页面描述注解` section, `## 编号映射表` section.
|
|
186
|
-
- The `_extracted.json` has NO `preconditions` field.
|
|
187
|
-
|
|
188
|
-
### S4 — Generate testcases.json via `testcases-tool`
|
|
189
|
-
|
|
190
|
-
`testcases-tool` is a pure JSON transform (no device or AutoTest dir needed) — invoke it directly:
|
|
191
|
-
|
|
192
|
-
```bash
|
|
193
|
-
node "$TOOL_DIR/engine/testcases-tool.ts" generate "<output_path>/_extracted.json" "<output_path>/testcases.json" --validate
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
- `VALIDATION PASSED` → done.
|
|
197
|
-
- `VALIDATION FAILED` → check for unreplaced app names in `_extracted.json`, fix, re-run. Do NOT manually write `testcases.json`.
|
|
198
|
-
|
|
199
|
-
**Sanity-check `[PRE]` ordering** — run this command **if and only if** a `pre_test_case.md` was found and extracted in S3.1. If no pre-cases were extracted, skip this step (there is nothing to order):
|
|
200
|
-
|
|
201
|
-
```bash
|
|
202
|
-
node "$TOOL_DIR/engine/self-test-runner.ts" check-pre --testcases "<output_path>/testcases.json"
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
If assertion fails, edit `_extracted.json` to move all `[PRE]` entries contiguously to the front and re-run `node "$TOOL_DIR/engine/testcases-tool.ts" generate`.
|
|
206
|
-
|
|
207
|
-
---
|
|
208
|
-
|
|
209
|
-
## Phase T1-T8 — Test (always runs)
|
|
210
|
-
|
|
211
|
-
T1 expects `<output_path>/testcases.json` and `<output_path>/app-metadata.json` to exist. When `setup=true` they were just written by S4 and S2; when `setup=false` they were pre-existing (e.g., from a prior round's `setup=true` run).
|
|
212
|
-
|
|
213
|
-
---
|
|
214
|
-
|
|
215
|
-
### T1 — Validate Inputs
|
|
216
|
-
|
|
217
|
-
Validate `hap_path` (a comma-separated list of files/dirs — each entry a `.hap`/`.hsp` file or a directory; at least one `.hap` must exist across all entries):
|
|
218
|
-
|
|
219
|
-
```bash
|
|
220
|
-
node "$TOOL_DIR/engine/self-test-runner.ts" check-hap --hap "<hap_path>"
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
Then run the rest in a single Bash command:
|
|
224
|
-
|
|
225
|
-
```bash
|
|
226
|
-
mkdir -p "<output_path>" && test -f "<output_path>/testcases.json" && test -f "<output_path>/app-metadata.json" && echo "OK"
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
If `setup=false`, additionally verify each JSON parses and `testcases.json` is non-empty:
|
|
230
|
-
|
|
231
|
-
```bash
|
|
232
|
-
node "$TOOL_DIR/engine/self-test-runner.ts" check-inputs --testcases "<output_path>/testcases.json" --metadata "<output_path>/app-metadata.json"
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
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.:
|
|
236
|
-
|
|
237
|
-
- `reason: hap not found at <hap_path>`
|
|
238
|
-
- `reason: setup=false but testcases.json missing at <output_path>/testcases.json — re-run with setup=true`
|
|
239
|
-
- `reason: setup=false but testcases.json failed to parse — re-run with setup=true`
|
|
240
|
-
- `reason: setup=false but testcases.json is empty — re-run with setup=true`
|
|
241
|
-
- `reason: setup=false but app-metadata.json missing or malformed at <output_path>/app-metadata.json — re-run with setup=true`
|
|
242
|
-
|
|
243
|
-
Then stop.
|
|
244
|
-
|
|
245
|
-
### T2 — Read App Metadata
|
|
246
|
-
|
|
247
|
-
Read `<output_path>/app-metadata.json` and extract `<bundle_name>`, `<app_name>`, and `<project-root>`.
|
|
248
|
-
|
|
249
|
-
### T3 — Verify Device Connection
|
|
250
|
-
|
|
251
|
-
Run `npx --yes devecocli device list`:
|
|
252
|
-
- If at least one connected device or running emulator is returned → proceed.
|
|
253
|
-
- If no available devices are listed → write report with the sentinel format (`status: FAIL` / `reason: No HarmonyOS device connected`), then stop.
|
|
254
|
-
|
|
255
|
-
Record the device serial number.
|
|
256
|
-
|
|
257
|
-
### T4 — Locate AutoTest Directory & Verify autotest config
|
|
258
|
-
|
|
259
|
-
Find the `test-tools/autotest` directory using the **AutoTest Directory Locator** (Shared Utilities). 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.
|
|
260
|
-
|
|
261
|
-
The resolved path is used for this precheck only; do not pass it to any later phase — `node "$TOOL_DIR/engine/self-test-runner.ts" run` resolves the AutoTest directory itself at run time.
|
|
262
|
-
|
|
263
|
-
The model config is shared with UI alignment and resolved along the standard chain — **env var → `~/.hometrans/config.json` → ask**. The selftest runner reads it at run time (env `HOMETRANS_MODEL_API_KEY` overrides `autotest.unified_model.api_key`) and maps the api_key/model/device fields into `AUTOTEST_*` env vars for the batch launcher — you do **not** create or edit any YAML. Just verify the api_key is usable: the `HOMETRANS_MODEL_API_KEY` OS environment variable is set, **or** every model endpoint defined in the `autotest` block of `~/.hometrans/config.json` has a real (non-placeholder) `api_key`.
|
|
264
|
-
|
|
265
|
-
```bash
|
|
266
|
-
node "$TOOL_DIR/engine/self-test-runner.ts" check-config
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
If this does not print `OK` (exit non-zero — failure modes: config file missing / unparseable, no `autotest` block in it, no model endpoint (`unified_model` / `execute_model` / `decision_model`) defined, or an endpoint `api_key` empty / still the placeholder with no `HOMETRANS_MODEL_API_KEY` env var override), write `self-test-report.md` with the sentinel format (`status: FAIL` / `reason: model api_key not configured — set HOMETRANS_MODEL_API_KEY env var or run ht init`; copy the command's printed error message into `reason:` for specifics), then stop.
|
|
270
|
-
|
|
271
|
-
### T5 — Clean Task Directory
|
|
272
|
-
|
|
273
|
-
| Shell | Example |
|
|
274
|
-
|-------|---------|
|
|
275
|
-
| bash / sh | `rm -rf "<output_path>/task" && echo "Task directory cleaned" \|\| echo "Task directory does not exist, skipping cleanup"` |
|
|
276
|
-
| PowerShell | `Remove-Item -LiteralPath "<output_path>/task" -Recurse -Force -ErrorAction SilentlyContinue; Write-Output "Task directory cleaned"` |
|
|
277
|
-
|
|
278
|
-
### T6 — Run `node "$TOOL_DIR/engine/self-test-runner.ts" run --timeout`
|
|
279
|
-
|
|
280
|
-
> 🚨 **MANDATORY**: Environment setup, HAP installation, test execution, polling, and timeout auto-kill are all handled by a **single invocation** of `node "$TOOL_DIR/engine/self-test-runner.ts" run --timeout`. The script synchronously executes:
|
|
281
|
-
> 1. Read & validate the `autotest` config from `~/.hometrans/config.json` (env `HOMETRANS_MODEL_API_KEY` overrides the api_key) and map its api_key/model/device fields into `AUTOTEST_*` env vars for the batch launcher
|
|
282
|
-
> 2. Kill any stale previous batch recorded in `batch.pid` (via `killProcessTree`)
|
|
283
|
-
> 3. `hdc uninstall` + `hdc install -r`
|
|
284
|
-
> 4. Normalize testcases JSON into JSONL (filling missing `uuid`/`spec`)
|
|
285
|
-
> 5. Launch `node batch-launcher.ts` (the `@autotest/agent` engine, constructing `new AutoTestAgent({...})` from the `AUTOTEST_*` env) as a **detached background process** and write `batch.pid`
|
|
286
|
-
> 6. **Polling loop**: sleep 60s, probe status, until terminal status or `--timeout` elapsed. On timeout, auto-kill the batch tree and return `TIMEOUT`.
|
|
287
|
-
>
|
|
288
|
-
> Without `--timeout` the script returns `RUNNING` JSON immediately after spawn (backward-compat; not used by this agent). With `--timeout`, **no `RUNNING` JSON is emitted** — only one final terminal JSON line on stdout when the loop exits.
|
|
289
|
-
|
|
290
|
-
> **FORBIDDEN actions** (violating any of these invalidates the entire test run):
|
|
291
|
-
> - ❌ Calling `node batch-launcher.ts` directly — always go through `node "$TOOL_DIR/engine/self-test-runner.ts" run`
|
|
292
|
-
> - ❌ Reading source code of the `self-test-runner` tool or any `AutoTest` module
|
|
293
|
-
> - ❌ Running `hdc install -r` separately
|
|
294
|
-
> - ❌ Writing a shell loop or Python loop to iterate over cases yourself
|
|
295
|
-
|
|
296
|
-
Run as a **background task** (`run_in_background: true`) — the call may block for up to caseCount × 12min (720s/case = batch-launcher `CASE_TIMEOUT_MS=10min` + 20% margin). One call, one final JSON on stdout. Pass `--timeout auto`: the CLI reads `--testcases` and derives the budget itself — no shell-side case counting or arithmetic, and the command is identical on bash and PowerShell:
|
|
297
|
-
|
|
298
|
-
```
|
|
299
|
-
node "$TOOL_DIR/engine/self-test-runner.ts" 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>" --timeout auto
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
> The TIMEOUT JSON does not carry the budget. When the sentinel `reason:` needs the concrete value (`timed out after <timeout>s`), read it from the runner's log line `--timeout auto: <N> 条用例 × 720s = <total>s` in the background task output — do not recompute.
|
|
303
|
-
|
|
304
|
-
When the background task returns, parse the **last line of stdout** as the terminal status JSON. Branch on `status`:
|
|
305
|
-
|
|
306
|
-
| `status` | Exit code | Meaning | Action |
|
|
307
|
-
|-----------|----------|---------|--------|
|
|
308
|
-
| `COMPLETED` | 0 | All cases finished, `summary.json` written | Record `pass_count`/`fail_count`/`unknown_count`/`pass_rate`/`task_subdir` for T7/T8; proceed to T7 |
|
|
309
|
-
| `CRASHED` | 3 | Batch died without producing `summary.json` | Write CRASHED report with sentinel (`status: FAIL` / `reason: AutoTest batch crashed`), include `log_tail` from JSON; stop |
|
|
310
|
-
| `TIMEOUT` | 5 | `--timeout` elapsed, batch auto-killed | Write TIMEOUT report with sentinel (`status: FAIL` / `reason: AutoTest batch timed out after <timeout>s`), include `cases_done`/`last_case`/`log_tail` from the JSON for partial-result context; stop |
|
|
311
|
-
| `NOT_STARTED` | 4 | Race: `batch.pid` vanished between spawn and first poll | Write FAIL report with sentinel `reason: launch failed (no batch.pid)`; stop |
|
|
312
|
-
| `FAILED` | 1 | Spawn-time failure (config error, install failed, etc.) | Write FAIL report with sentinel `reason: <error field from JSON>`; stop |
|
|
313
|
-
|
|
314
|
-
> 🚨 **CRITICAL**: While `run --timeout` is in the background, do NOT read `task_results.jsonl`, HTML reports, MD reports, `agent.log`, or any other output file. These files are being actively written and contain incomplete data. Only proceed to T7 after the background call returns a terminal JSON.
|
|
315
|
-
|
|
316
|
-
**User-initiated abort (rare)**: if the user cancels mid-run, the agent's background Bash task is killed by the harness but the detached batch keeps running. To release the device immediately, call `node "$TOOL_DIR/engine/self-test-runner.ts" kill --task-dir "<output_path>/task"`. The next `run` invocation also auto-cleans a stale `batch.pid` on startup.
|
|
317
|
-
|
|
318
|
-
### T7 — Read results after completion
|
|
319
|
-
|
|
320
|
-
After `COMPLETED`:
|
|
321
|
-
1. Read stdout log from `<output_path>/self_test_*.log` (full runner log).
|
|
322
|
-
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.
|
|
323
|
-
- `report_dir` is the absolute path to that case's execution directory. You MUST include this as `**AutoTest 任务路径**` in the report for EVERY case.
|
|
324
|
-
- **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.
|
|
325
|
-
3. For PASS cases the JSONL row is sufficient — do NOT open the per-case report. For FAIL / UNKNOWN cases with empty `reason`, you may peek at the runner log of last resort:
|
|
326
|
-
|
|
327
|
-
| Shell | Example |
|
|
328
|
-
|-------|---------|
|
|
329
|
-
| bash / sh | `tail -40 "<report_dir>/agent.log"` |
|
|
330
|
-
| PowerShell | `Get-Content -LiteralPath "<report_dir>/agent.log" -Tail 40` |
|
|
331
|
-
|
|
332
|
-
This caps token usage. **Do NOT read full HTML / MD / JSON per-case reports** — they are very large (10KB–200KB) and meant for human users.
|
|
18
|
+
## Expected Input
|
|
333
19
|
|
|
334
|
-
|
|
20
|
+
The caller passes these **kebab-case** params (a subset of the `hmos-integration-test` skill's input table — this wrapper is a pure pass-through, no translation):
|
|
335
21
|
|
|
336
|
-
|
|
22
|
+
| Parameter | Required | Description |
|
|
23
|
+
|-----------|----------|-------------|
|
|
24
|
+
| `hap-path` | yes | Package set (entry HAP + any in-app HSPs / feature HAPs); file / dir / comma-list. Always installed via `hdc uninstall` + `hdc install -r`. |
|
|
25
|
+
| `output-path` | yes | Root output dir for all artifacts (`testcases.json`, `app-metadata.json`, `_extracted.json`, `self-test-report.md`, `task/`) |
|
|
26
|
+
| `project-dir` | round 1 | HarmonyOS project root (含 `AppScope/app.json5`) for resolve-metadata; auto-derived from `hap-path`/`test-case-path` when omitted |
|
|
27
|
+
| `test-case-path` | round 1 | Path to `test_case.md` |
|
|
28
|
+
| `pre-test-case-path` | optional | Path to `pre_test_case.md`; auto-discovered in `test-case-path`'s dir when omitted |
|
|
337
29
|
|
|
338
|
-
>
|
|
30
|
+
> **No `setup` parameter.** Round 1 runs the parse phase (writes `testcases.json` + `app-metadata.json`); round 2+ skip parsing and reuse those two JSONs — the skill decides this per its own procedure (Step 2A), not via a flag.
|
|
339
31
|
|
|
340
|
-
**
|
|
341
|
-
- `<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 `bundle_name` as the suite name.
|
|
342
|
-
- `<device_serial>` — from T3.
|
|
343
|
-
- `<entry_hap>` — the **entry HAP** for display (never the raw comma string). If `hap_path` is a single `.hap` file, use it. If it is a directory or comma-separated list, pick a `.hap` named `entry-*` if present, otherwise the first `.hap` found across the entries.
|
|
344
|
-
- `<task_subdir>` — from T6 final JSON.
|
|
32
|
+
> **Fix loop**: this wrapper runs a single test pass and does **not** forward `max-rounds` / `android-project-path`. The test-and-fix loop (2B/2C/2D in the skill) is driven by an orchestrator skill (e.g. `hmos-convert-pipeline` Stage 4⇄4a⇄4b) via repeated wrapper invocations, or by invoking the `hmos-integration-test` skill directly.
|
|
345
33
|
|
|
346
|
-
|
|
34
|
+
## How to run
|
|
347
35
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
--device "<device_serial>" \
|
|
354
|
-
--suite "<suite_name>" \
|
|
355
|
-
--out "<output_path>/self-test-report.md" \
|
|
356
|
-
--validate
|
|
357
|
-
```
|
|
36
|
+
1. Load the `hmos-integration-test` skill. Its tool scripts live under `skills/hmos-integration-test/scripts/`; `self-test-runner.mjs` resolves `@autotest/agent`'s `batch_runner.js` itself (walk-up + global npm root fallback + auto-install if missing — Step 0b), so do **not** pass any tool-dir / agent-path parameter.
|
|
37
|
+
2. Follow the skill's `SKILL.md` procedure exactly for the inputs above. In particular:
|
|
38
|
+
- `mode` is passed via the `a2h_self_test` tool's `mode` field — default `single`; pass `mode: "layered"` to activate the Planner+Executor dual-agent architecture. There is no `~/.hometrans/autotest.yaml` on this path — the tool writes a temporary one (0o600) inside `task_subdir` from the stdin-injected key and deletes it on terminal state.
|
|
39
|
+
- Pre-cases (`pre_test_case.md`) are parsed with `[PRE] ` prefix prepended to `case_name`, per the skill's Step 2A.
|
|
40
|
+
3. The skill writes: `<output-path>/self-test-report.md`, `<output-path>/task/task_<ts>/`, and (round 1 only) `<output-path>/testcases.json` + `<output-path>/app-metadata.json` + `<output-path>/_extracted.json`.
|
|
358
41
|
|
|
359
|
-
|
|
360
|
-
- `VALIDATION FAILED` → fix upstream data and re-run; do NOT hand-write the report.
|
|
42
|
+
## Expected Output (report back to the caller)
|
|
361
43
|
|
|
362
|
-
|
|
44
|
+
Report back concisely (do not stream large file contents into the caller's context):
|
|
363
45
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
46
|
+
- **Terminal status** from `a2h_self_test_status`: `COMPLETED` (with `pass_count` / `fail_count` / `unknown_count` / `pass_rate` / `task_subdir`) | `CRASHED` | `NOT_STARTED` | `TIMEOUT` (the skill killed `pid` after exceeding `max_elapsed`).
|
|
47
|
+
- **Path** to `<output-path>/self-test-report.md`.
|
|
48
|
+
- **Early-exit (environmental) failures**: the sentinel `reason:` line (config / device / `@autotest/agent` missing + auto-install failed / batch crash / precondition failure). These are **NOT application defects** — do NOT enter the fix flow; surface the reason so the user can fix the environment. (The skill, not this agent, decides `stop_reason = agent_early_exit` from the sentinel `reason:`.)
|
|
49
|
+
- Do **not** read full per-case HTML/MD/JSON reports back into the caller — they are large (10KB–200KB); point the caller to the files / `task_subdir`.
|
|
367
50
|
|
|
368
|
-
|
|
51
|
+
## Constraints
|
|
369
52
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
> - keeps `含前置通过率` only as a secondary reference with an explicit disclaimer;
|
|
374
|
-
> - tells the 建议 reader that pre-failures should be treated as environment problems first, and only enter the fix flow if a white-box review confirms a real code bug.
|
|
375
|
-
>
|
|
376
|
-
> Downstream agents — especially `self-test-fixer` — must respect this framing: **do not modify application code based on a pre-case failure unless white-box review concludes the failure surfaces a genuine app defect**. This rationale is intentional and load-bearing; do not collapse it into a one-liner.
|
|
53
|
+
- **Single source of truth**: `hmos-integration-test/SKILL.md` is authoritative; this wrapper only wires params + reports results.
|
|
54
|
+
- **No procedure duplication**: if you find yourself spelling out `resolve-metadata-tool` / `testcases-tool` / `self-test-runner` / `report-tool` commands here, stop — that belongs in the skill, not here. The skill uses `$SKILL_SCRIPTS/<script>.mjs` (no `$TOOL_DIR`, no `run`/`generate` subcommand keywords — flat `--` args + `--status`).
|
|
55
|
+
- **Pre-cases are environment setup, not app defects**: surface `常规通过率` (regular-only pass rate) as the quality metric; pre-case failures go to the fix flow only after white-box confirmation (per `self-test-fixer`).
|