@harmonyos-arkts/d2h 0.1.1 → 0.1.3

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/package.json CHANGED
@@ -1,45 +1,51 @@
1
- {
2
- "name": "@harmonyos-arkts/d2h",
3
- "version": "0.1.1",
4
- "description": "Install Android-to-HarmonyOS migration agents and skills into OpenCode or DevEco Code",
5
- "type": "module",
6
- "bin": {
7
- "d2h": "bin/install-opencode.mjs"
8
- },
9
- "files": [
10
- "bin/",
11
- "src/",
12
- "skills/",
13
- "agents/",
14
- "schemas/",
15
- "opencode/",
16
- ".claude-plugin/",
17
- "install-opencode.sh",
18
- "README.md",
19
- "LICENSE"
20
- ],
21
- "scripts": {
22
- "check": "node --check bin/install-opencode.mjs && node --check src/install-opencode.mjs && node scripts/check-skill-refs.mjs",
23
- "test": "node --test test/*.test.mjs",
24
- "prepublishOnly": "npm run check && npm test"
25
- },
26
- "engines": {
27
- "node": ">=20 <25"
28
- },
29
- "repository": {
30
- "type": "git",
31
- "url": "git+https://github.com/Harmony-Ai-Tool/android-to-hmos-migration.git"
32
- },
33
- "license": "MIT",
34
- "publishConfig": {
35
- "access": "public",
36
- "registry": "https://registry.npmjs.org/"
37
- },
38
- "keywords": [
39
- "android",
40
- "harmonyos",
41
- "arkts",
42
- "migration",
43
- "opencode"
44
- ]
45
- }
1
+ {
2
+ "name": "@harmonyos-arkts/d2h",
3
+ "version": "0.1.3",
4
+ "description": "Install Android-to-HarmonyOS migration agents and skills into OpenCode or DevEco Code",
5
+ "type": "module",
6
+ "bin": {
7
+ "d2h": "dist/bin/install-opencode.js"
8
+ },
9
+ "files": [
10
+ "dist/bin/",
11
+ "dist/src/",
12
+ "skills/",
13
+ "agents/",
14
+ "schemas/",
15
+ "opencode/",
16
+ ".claude-plugin/",
17
+ "install-opencode.sh",
18
+ "README.md",
19
+ "LICENSE"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsc -p tsconfig.json",
23
+ "check": "tsc --noEmit && npm run build && node dist/scripts/check-skill-refs.js",
24
+ "test": "npm run build && node --test dist/test/*.test.js",
25
+ "prepack": "npm run build",
26
+ "prepublishOnly": "npm run check && npm test"
27
+ },
28
+ "engines": {
29
+ "node": ">=20 <25"
30
+ },
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/Harmony-Ai-Tool/android-to-hmos-migration.git"
34
+ },
35
+ "license": "MIT",
36
+ "publishConfig": {
37
+ "access": "public",
38
+ "registry": "https://registry.npmjs.org/"
39
+ },
40
+ "keywords": [
41
+ "android",
42
+ "harmonyos",
43
+ "arkts",
44
+ "migration",
45
+ "opencode"
46
+ ],
47
+ "devDependencies": {
48
+ "@types/node": "^22.20.5",
49
+ "typescript": "^5.9.3"
50
+ }
51
+ }
@@ -27,17 +27,40 @@ values 资源(strings/colors/dimens 的迁移)、布局、Lottie、字体明
27
27
  | Android XML Drawable(vector/shape/layer-list/selector)转 SVG | `references/xml-drawable-to-svg-rules.md` |
28
28
  | 修复 SVG 显示问题(空白/不可见/尺寸错误/残留 Android 语法) | `references/svg-fix-patterns.md` |
29
29
 
30
- ## 输入
30
+ ## 输入与统一领域结果
31
31
 
32
32
  1. **Android 工程路径** — Android Gradle 工程根目录(含 `build.gradle` 或 `build.gradle.kts`)。
33
- 2. **HarmonyOS 工程路径** — 由 Preflight 创建或复用的工程(见 `preparing-migration-workspace`),通常是迁移工作区下的 `ohos/`,或 `.migration/config.json` 中 `--harmony-project` 配置的路径。图片写入 `<harmony>/entry/src/main/resources/`。本 skill 不创建工程壳;`ohos/` 尚不存在时先运行 Preflight。
33
+ 2. **HarmonyOS 工程路径** — 由 Preflight 创建或复用的工程(见 `preparing-migration-workspace`),通常是迁移工作区下的 `ohos/`,或 `.migration/config.json` 中 `--harmony-project` 配置的路径。图片写入 `<harmony>/entry/src/main/resources/`。本 skill 不创建工程壳;`ohos/` 尚不存在时由调用方先完成 Preflight。
34
+
35
+ 始终返回统一领域结果:
36
+
37
+ ```json
38
+ {
39
+ "status": "completed | partial | failed",
40
+ "changedFiles": [],
41
+ "sourceFiles": [],
42
+ "evidence": [],
43
+ "domainChecks": [],
44
+ "unresolved": [],
45
+ "verificationRequests": [],
46
+ "suggestedRemediation": [],
47
+ "details": {
48
+ "convertedResources": [],
49
+ "qualifierMappings": [],
50
+ "unmappedResources": [],
51
+ "unresolvedReferences": []
52
+ }
53
+ }
54
+ ```
55
+
56
+ `status` 只表示图片资源转换和静态完整性检查的领域状态,不代表工程已构建、设备显示已验证或迁移已完成。`changedFiles`、`sourceFiles`、`unmappedResources` 和 `unresolvedReferences` 必须列出真实路径或资源标识。构建、设备显示和交互影响核对写入 `verificationRequests`,由调用方选择执行方式。
34
57
 
35
58
  ## 工作流
36
59
 
37
60
  ### 第 1 步:校验输入
38
61
 
39
62
  1. 确认 Android 工程路径存在且含 `build.gradle` 或 `build.gradle.kts`。
40
- 2. 通过 `droid2hmos status <ANDROID_PROJECT>` 或 `.migration/config.json` 确认 HarmonyOS 工程位置,并确认 `entry/src/main/resources/` 存在;不存在时停止并先补 Preflight,不要猜测工程结构。
63
+ 2. 通过 `droid2hmos status <ANDROID_PROJECT>` 或 `.migration/config.json` 确认 HarmonyOS 工程位置,并确认 `entry/src/main/resources/` 存在;不存在时返回 `failed`,把缺少工程壳写入 `unresolved` 和 `suggestedRemediation`,不要猜测工程结构或自行调度 Preflight。
41
64
 
42
65
  ### 第 2 步:确定资源来源
43
66
 
@@ -47,7 +70,7 @@ values 资源(strings/colors/dimens 的迁移)、布局、Lottie、字体明
47
70
  - 多模块工程同时检查其它模块目录
48
71
  - 使用 flavor source set 时一并纳入(如 `app/src/debug/res/`、`app/src/flavor/res/`)
49
72
 
50
- 恒定从源码 `res/` 转换:仅由库依赖(AAR)提供的图片不在源码 `res/` 中,这类引用在报告中记为 unresolved,不尝试回收。
73
+ 恒定从源码 `res/` 转换:仅由库依赖(AAR)提供的图片不在源码 `res/` 中,这类引用在统一结果中记为 unresolved,不尝试回收。
51
74
 
52
75
  ### 第 3 步:清点与分类
53
76
 
@@ -60,7 +83,7 @@ values 资源(strings/colors/dimens 的迁移)、布局、Lottie、字体明
60
83
  | XML drawable:vector/shape/layer-list | `.xml`,根 `<vector>` / `<shape>` / `<layer-list>` | 转 SVG(第 4.2 步) |
61
84
  | XML drawable:selector | `.xml`,根 `<selector>` | 提取默认状态 → SVG(第 4.2 步) |
62
85
  | 自适应图标 | `.xml`,根 `<adaptive-icon>` | 转 layered-image JSON(第 4.3 步) |
63
- | ripple/animated-vector/animated-selector/transition/level-list 等 | `.xml`,对应根元素 | 不可映射 — 记入报告 |
86
+ | ripple/animated-vector/animated-selector/transition/level-list 等 | `.xml`,对应根元素 | 不可映射 — 记入统一结果 |
64
87
 
65
88
  忽略 `values*/`、`layout*/`、`menu/`、`raw/`、`font/`、`xml/`、`anim*/`、`color/` — 超出范围。只有 `values*/colors.xml` 和 `values*/dimens.xml` 被读取,用于解析 drawable 内的 `@color:`/`@dimen:` 引用(第 4.4 步)。
66
89
 
@@ -70,7 +93,7 @@ values 资源(strings/colors/dimens 的迁移)、布局、Lottie、字体明
70
93
 
71
94
  **4.1 位图与 nine-patch → `media/`**
72
95
  - 拷贝到限定符映射后的 `media/` 目录(完整限定符算法见 image-conversion-rules.md)
73
- - `.9.png` → 重命名为 `<name>_9.png`(HarmonyOS 禁止资源文件名中含 `.`,仅允许最后扩展名分隔符)。nine-patch 拉伸语义丢失 — 报告中记录
96
+ - `.9.png` → 重命名为 `<name>_9.png`(HarmonyOS 禁止资源文件名中含 `.`,仅允许最后扩展名分隔符)。nine-patch 拉伸语义丢失 — 在统一结果中记录
74
97
 
75
98
  **4.2 XML drawable → `media/` 中的 `.svg`**
76
99
  - 严格按 `references/xml-drawable-to-svg-rules.md` 执行 — 尤其是强制保留 `clip-path`、三分支 `fill` 规则和渐变处理
@@ -84,19 +107,19 @@ values 资源(strings/colors/dimens 的迁移)、布局、Lottie、字体明
84
107
  **4.4 解析 drawable 内引用**
85
108
  - SVG 填充/描边中的 `@color/name` → 从 `values*/colors.xml` 解析(沿引用链;兜底 `#000000` + 记录)
86
109
  - SVG 尺寸中的 `@dimen/name` → 从 `values*/dimens.xml` 解析(兜底:合理默认值 + 记录)
87
- - 未解析引用(库专属资源不在源码 `res/`)记入报告,绝不静默丢弃
110
+ - 未解析引用(库专属资源不在源码 `res/`)记入统一结果,绝不静默丢弃
88
111
 
89
112
  ### 第 5 步:完整性校验
90
113
 
91
- 1. 第 3 步发现的每个文件都有且只有一个结局:已转换,或在报告中列为 unmappable/unmapped
114
+ 1. 第 3 步发现的每个文件都有且只有一个结局:已转换,或在统一结果中列为 unmappable/unmapped
92
115
  2. 每个转换产物都实际存在于 HarmonyOS 工程
93
116
  3. 生成的 layered-image JSON 中每个 `$media:xxx` 引用都指向 `media/` 中存在的文件
94
117
  4. 每个转换后的 SVG 通过 `references/xml-drawable-to-svg-rules.md` 的自检
95
118
  5. HarmonyOS 工程已有 `.ets` 文件时,扫描 `$r('app.media.xxx')` 并核对每个引用的图片存在(已有 media 文件**不覆盖** — 合并,冲突记录)
96
119
 
97
- ### 第 6 步:生成报告
120
+ ### 第 6 步:组装领域结果
98
121
 
99
- 按 `maintaining-migration-report` 的轻量原则,把转换报告落盘到迁移工作区(如 `.migration/` 下)或直接向用户呈现,结构如下:
122
+ 把转换清单和静态校验结果写入统一领域结果;如需可读审计附件,可生成以下结构并把路径列入 `evidence`:
100
123
 
101
124
  ```
102
125
  # Android to HarmonyOS Image Conversion Report
@@ -134,15 +157,9 @@ values 资源(strings/colors/dimens 的迁移)、布局、Lottie、字体明
134
157
  - SVG self-checks passed: Yes/No
135
158
  ```
136
159
 
137
- 影响行为的结论(不可映射资源、丢失的 nine-patch 语义、未解析引用)必须回流到对应报告分片的说明,或按 orchestrator 约定写入 `discoveries.json`;不要只留在一次性报告里。
138
-
139
- ### 第 7 步:Git 检查点
160
+ 影响行为的结论(不可映射资源、丢失的 nine-patch 语义、未解析引用)必须进入 `unresolved`,并标明 `blocking`、来源、用户影响和建议补救。需要回流报告 ref 或 discoveries 的项通过结果交给调用方,本 skill 不直接更新迁移报告。
140
161
 
141
- 一个连贯、已校验的转换批次完成后,按仓库约定创建检查点(只纳入 HarmonyOS 工程内的资源文件):
142
-
143
- ```text
144
- droid2hmos checkpoint create <ANDROID_PROJECT> --message <MESSAGE> --include <harmony>/entry/src/main/resources
145
- ```
162
+ 转换完成后,将实际生成或修改的 HarmonyOS 资源写入 `changedFiles`,把对应 Android 源资源写入 `sourceFiles`;不要只返回计数。静态校验写入 `domainChecks`,待构建和设备核对写入 `verificationRequests`。
146
163
 
147
164
  ## 重要说明
148
165
 
@@ -152,6 +169,7 @@ droid2hmos checkpoint create <ANDROID_PROJECT> --message <MESSAGE> --include <ha
152
169
  - **转换恒定从源码 `res/` 出发**:仅库依赖(AAR)提供的图片不在其中;对它们的引用按 unresolved 报告,不做恢复。
153
170
  - 资源名保持 Android 原拼写 — 它们是标识符。
154
171
  - 解析 Android XML 时正确处理命名空间、注释和 CDATA;按 local name 匹配属性。
172
+ - 本 skill 不更新迁移报告、不暂存或提交文件、不创建 checkpoint、不调用 `complete`,也不选择仓库级构建、测试或设备命令。调用方消费统一领域结果并决定外层动作。
155
173
 
156
174
  ## 与其他 skill 的关系
157
175
 
@@ -159,4 +177,4 @@ droid2hmos checkpoint create <ANDROID_PROJECT> --message <MESSAGE> --include <ha
159
177
  - **arkts-app-identity**:它处理 App 级身份资源(app.json5 图标字段、版本号、包名);本 skill 负责 res/ 全量图片资产进 `media/`。启动器图标的位图/分层资产由本 skill 转换,app.json5 的接线归它。
160
178
  - **arkts-icon-sizing**:图片资产就位后,它修 `.ets` 消费侧丢失的 `.width()/.height()`;本 skill 只管资源侧。
161
179
  - **arkts-i18n**:values 资源(string.json 等)的迁移归它;本 skill 只把 colors.xml/dimens.xml 当查找源。
162
- - **maintaining-migration-report**:转换结论回流报告分片的轻量约定。
180
+ - **maintaining-migration-report**:调用方可把本 skill 返回的行为影响项、源码和证据映射到报告分片;本 skill 不直接写报告。
@@ -7,13 +7,13 @@ description: Review fresh AppGraph and SPEC results after Android analysis, iden
7
7
 
8
8
  Review the latest deterministic Android analysis and produce maintainable rule-improvement candidates. This is a read-only diagnostic step. Do not edit AppGraph, SPEC facts, Android source, rule packs, or analyzers.
9
9
 
10
- All `.migration/...` paths below live in the sibling migration workspace `<android-project>-migration/.migration/`. Fall back to the legacy `<android-project>/.migration/` only when the sibling workspace does not exist.
10
+ All `.migration/...` paths below live in the sibling migration workspace `<android-project>-migration/.migration/`. Never fall back to the legacy `<android-project>/.migration/`; if the sibling workspace or required artifacts are absent, return a structured unavailable/stale result.
11
11
 
12
12
  ## Preconditions
13
13
 
14
- 1. Run `droid2hmos analyze android <android-project>` successfully before this Skill.
14
+ 1. The caller must supply artifacts from a successful `droid2hmos analyze android <android-project>` run; this Skill does not run analysis itself.
15
15
  2. Locate `.migration/spec/index.json`, `.migration/spec/facts/`, and `.migration/appgraph/app-graph.json`.
16
- 3. Check that the SPEC `generation.sourceRevision`, when present, matches the Android Git HEAD. Treat a mismatch or missing required artifact as stale analysis: write no recommendations and ask for a new analysis run.
16
+ 3. Check that the SPEC `generation.sourceRevision`, when present, matches the Android Git HEAD. Treat a mismatch or missing required artifact as stale analysis: write no recommendations and return the structured result below. Do not run analysis or ask the user whether to run it.
17
17
  4. Keep all source and generated data local. Network access is unnecessary.
18
18
 
19
19
  ## Review workflow
@@ -34,7 +34,25 @@ All `.migration/...` paths below live in the sibling migration workspace `<andro
34
34
 
35
35
  ## Outputs
36
36
 
37
- Create or replace:
37
+ When analysis is missing or stale, return without creating or replacing opportunity reports:
38
+
39
+ ```json
40
+ {
41
+ "status": "stale",
42
+ "workspace": "<android-project>-migration/.migration/",
43
+ "staleReasons": [],
44
+ "requiredAction": "reanalyze-android",
45
+ "expectedArtifacts": [
46
+ ".migration/spec/index.json",
47
+ ".migration/spec/facts/",
48
+ ".migration/appgraph/app-graph.json"
49
+ ]
50
+ }
51
+ ```
52
+
53
+ The caller consumes `requiredAction` and decides the workflow transition. This Skill does not invoke `droid2hmos analyze android`, pause for a user choice, or continue against legacy/stale artifacts.
54
+
55
+ When inputs are fresh, create or replace:
38
56
 
39
57
  ```text
40
58
  .migration/rule-audit/rule-opportunities.json
@@ -55,4 +73,5 @@ When no evidence-backed rule improvement exists, write valid outputs with an emp
55
73
  - Do not turn host relationships into navigation edges.
56
74
  - Do not mark multiple targets as resolved.
57
75
  - Do not implement recommendations. A maintainer may later pass an accepted opportunity to the separate `appgraph-navigation-rules` Skill.
58
- - Audit failure is advisory and must not block HarmonyOS migration. Record the limitation and allow the orchestrator to continue to `report init`.
76
+ - With fresh inputs, an audit execution failure is advisory: record the limitation and return it to the caller. Missing or stale analysis is not an audit failure; return `requiredAction: reanalyze-android` as defined above.
77
+ - Do not advance an outer state, create a checkpoint, update the migration report, or invoke completion. Return findings or the stale result to the caller.
@@ -1,20 +1,46 @@
1
1
  ---
2
2
  name: harmonyos-migration-playbook
3
- description: Diagnose and reuse verified Android-to-HarmonyOS migration lessons for ArkTS compilation, HarmonyOS runtime, UI automation, protocol E2E, and Windows toolchains. Use during migration implementation, failure recovery, validation, or post-commit retrospectives; do not treat project-specific observations as universal platform rules.
3
+ description: Diagnose Android-to-HarmonyOS migration failures, check whether verified lessons apply, and return the smallest scoped fix or recommendation for ArkTS compilation, HarmonyOS runtime, UI automation, protocol E2E, and Windows toolchains. Use during implementation, failure recovery, validation, or retrospectives; do not control checkpoints or outer workflow state.
4
4
  ---
5
5
 
6
6
  # HarmonyOS migration playbook
7
7
 
8
8
  Use verified experience to shorten diagnosis without replacing current-project evidence.
9
9
 
10
+ ## Inputs and domain result
11
+
12
+ Accept the current symptom, in-scope files, SDK/tool versions, relevant logs or managed evidence, and any project lesson candidates. Do not infer success from an earlier project.
13
+
14
+ Return the same result shape whether called directly or from an orchestrator:
15
+
16
+ ```json
17
+ {
18
+ "status": "completed | partial | failed",
19
+ "changedFiles": [],
20
+ "sourceFiles": [],
21
+ "evidence": [],
22
+ "domainChecks": [],
23
+ "unresolved": [],
24
+ "verificationRequests": [],
25
+ "suggestedRemediation": [],
26
+ "details": {
27
+ "validatedRootCause": null,
28
+ "applicability": {},
29
+ "lessonCandidates": []
30
+ }
31
+ }
32
+ ```
33
+
34
+ `status` describes diagnosis and any in-scope fix only. `validatedRootCause` requires current-project evidence. Put repository-level build, test, device, or review needs in `verificationRequests`; do not choose the caller's checkpoint or workflow transition.
35
+
10
36
  ## Required operating loop
11
37
 
12
38
  1. Identify the current symptom and task boundary.
13
39
  2. Read only the relevant reference below.
14
40
  3. Check that the recorded applicability conditions match the current SDK, UI stack, runtime and code path.
15
41
  4. Reproduce or inspect evidence before applying a fix. Historical experience is a hypothesis until confirmed in the current project.
16
- 5. Apply the smallest in-scope fix and run the stated verification.
17
- 6. After validation, create an explicit Git checkpoint with `droid2hmos checkpoint create`; record a reusable lesson only when the root cause and fix are proven.
42
+ 5. If the request authorizes a change, apply the smallest in-scope fix; otherwise return the smallest concrete recommendation.
43
+ 6. Perform only domain-local checks available within scope. Return repository-level verification as `verificationRequests` and a reusable `lessonCandidates` entry only when the root cause and fix are supported by current-project evidence.
18
44
 
19
45
  ## Reference routing
20
46
 
@@ -42,6 +68,7 @@ Prefer narrower classifications. Public does not mean universal: a project-valid
42
68
  - Do not convert implementation defects into platform limitations or external blockers.
43
69
  - Do not claim a lesson is verified from a report, comment, code existence or compile success alone when runtime behavior is relevant.
44
70
  - Do not modify the public playbook from every task. First record the lesson in the current project; a reviewed, non-obvious and well-verified single-project lesson may be promoted as `project-validated` under `lesson-lifecycle.md` instead of waiting invisibly for another project.
71
+ - Do not stage or commit files, create a checkpoint, update the migration report, call `complete`, schedule full regression, or decide an outer workflow state. The caller owns those actions.
45
72
 
46
73
  ## Quick triage
47
74
 
@@ -6,7 +6,7 @@ Read `.migration/experience/lessons.md` when it exists. Select lessons by task t
6
6
 
7
7
  ## Record after validation and commit
8
8
 
9
- The orchestrator records a lesson only after the implementation is validated and committed through an explicit checkpoint. Before recording, confirm the repository state with `droid2hmos checkpoint status <android-project>`. Use this structure:
9
+ The playbook returns a lesson candidate only after the root cause and fix are supported by current-project evidence. The caller decides whether validation and checkpoint requirements are satisfied and whether to persist or promote the candidate. Use this structure:
10
10
 
11
11
  ```markdown
12
12
  ## <short title>
@@ -22,13 +22,13 @@ The orchestrator records a lesson only after the implementation is validated and
22
22
 
23
23
  Skip routine success, generic coding advice, speculative causes, duplicate lessons and details recoverable from the commit alone.
24
24
 
25
- If the project tracks `.migration/experience/lessons.md`, record the lesson there. The migration workspace `<android-project>-migration/` lives outside the Android Git repository, so `droid2hmos checkpoint create` (which commits inside the Android repo) can no longer include it; keep lessons as workspace-local run memory, or version the `<android-project>-migration/` directory independently if the project wants lesson history.
25
+ If the project tracks `.migration/experience/lessons.md`, the caller may persist an accepted candidate there. The migration workspace `<android-project>-migration/` lives outside the Android Git repository, so the lesson remains workspace-local run memory unless that workspace is versioned independently.
26
26
 
27
- In either case, use `droid2hmos checkpoint status <android-project>` to ensure the next migration unit does not inherit an unexplained dirty worktree. Do not use `--all` merely to capture the lesson.
27
+ This reference does not inspect, create, or time checkpoints and never recommends broad staging merely to capture a lesson.
28
28
 
29
29
  ## Promote to the public playbook
30
30
 
31
- `.migration/experience/lessons.md` is the source-project evidence log, not the cross-project knowledge base. Review a lesson after it is committed. If it is non-obvious, reproducible, useful beyond one task, bounded by explicit applicability conditions, and backed by real verification evidence, add its generalized form to the relevant public Playbook reference immediately as `project-validated`.
31
+ `.migration/experience/lessons.md` is the source-project evidence log, not the cross-project knowledge base. After the caller confirms acceptance, review whether a lesson is non-obvious, reproducible, useful beyond one task, bounded by explicit applicability conditions, and backed by real verification evidence. Only then may its generalized form enter the relevant public Playbook reference as `project-validated`.
32
32
 
33
33
  Public entries must contain:
34
34
 
@@ -24,7 +24,7 @@ droid2hmos service start mock-server <PROJECT> --health-url <URL> -- <command> [
24
24
 
25
25
  On Windows it asks `Win32_Process.Create` to create a short-lived host outside the command runner's process tree. The host starts the service with closed stdin and file-backed stdout/stderr, records the actual service PID, then exits. The outer launcher performs only a bounded health check and exits immediately after success.
26
26
 
27
- Do not substitute `Start-Process`, a foreground server command, or a project-local `spawn(..., { detached: true }).unref()` launcher. If the system-level creation mechanism is unavailable, stop and ask the user to start the service manually rather than risking a permanently blocked migration run.
27
+ Do not substitute `Start-Process`, a foreground server command, or a project-local `spawn(..., { detached: true }).unref()` launcher. If the system-level creation mechanism is unavailable, return a blocking external-service item in `unresolved`, put the manual start instruction in `suggestedRemediation`, and let the caller handle user coordination rather than risking an unbounded migration run.
28
28
 
29
29
  ## DevEco CLI login callback server lifecycle
30
30