deveco_hmigbot 0.21.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/LICENSE +26 -0
  2. package/README.md +50 -0
  3. package/agents/hmigbot-worker.md +61 -0
  4. package/agents/hmigbot.md +22 -0
  5. package/agents/workflow-subagent.md +55 -0
  6. package/commands/hmigbot.md +17 -0
  7. package/dist/index.js +1 -0
  8. package/manifest.json +19 -0
  9. package/package.json +29 -0
  10. package/skills/migrate-core/FILES.md +26 -0
  11. package/skills/migrate-core/SKILL.md +484 -0
  12. package/skills/migrate-core/references/README.md +64 -0
  13. package/skills/migrate-core/references/flow/arkts-vector-gate.md +55 -0
  14. package/skills/migrate-core/references/flow/build-error-patterns.md +52 -0
  15. package/skills/migrate-core/references/flow/conventions-template.md +244 -0
  16. package/skills/migrate-core/references/flow/navigation-migration.md +42 -0
  17. package/skills/migrate-core/references/flow/platform-api-guards.md +59 -0
  18. package/skills/migrate-core/references/flow/platform-model-gaps.md +43 -0
  19. package/skills/migrate-core/references/flow/resource-conversion.md +46 -0
  20. package/skills/migrate-core/references/flow/ui-layout-semantics.md +124 -0
  21. package/skills/migrate-core/references/flow/unit-breakdown.md +42 -0
  22. package/skills/migrate-core/references/host-capabilities.md +24 -0
  23. package/skills/migrate-core/references/topics/app-identity.md +214 -0
  24. package/skills/migrate-core/references/topics/env-doctor.md +245 -0
  25. package/skills/migrate-core/references/topics/i18n/README.md +458 -0
  26. package/skills/migrate-core/references/topics/i18n/references/code-examples.md +304 -0
  27. package/skills/migrate-core/references/topics/i18n/references/common-pitfalls.md +354 -0
  28. package/skills/migrate-core/references/topics/i18n/references/dynamic-language-switch.md +464 -0
  29. package/skills/migrate-core/references/topics/i18n/references/language-codes.md +104 -0
  30. package/skills/migrate-core/references/topics/icon-sizing.md +98 -0
  31. package/skills/migrate-core/references/topics/library-migration/README.md +234 -0
  32. package/skills/migrate-core/references/topics/library-migration/closed-source-sdk.md +128 -0
  33. package/skills/migrate-core/references/topics/library-migration/download-api-decision.md +84 -0
  34. package/skills/migrate-core/references/topics/library-migration/library-mapping-table.md +100 -0
  35. package/skills/migrate-core/references/topics/library-migration/napi-compile-guide.md +84 -0
  36. package/skills/migrate-core/references/topics/library-migration/ohpm-search-guide.md +73 -0
  37. package/skills/migrate-core/references/topics/library-migration/stdlib-mapping-table.md +34 -0
  38. package/skills/migrate-core/references/topics/resources/aar-decompile.md +25 -0
  39. package/skills/migrate-core/references/topics/resources/conversion-rules.md +625 -0
  40. package/skills/migrate-core/references/topics/resources/dependency-analysis-rules.md +328 -0
  41. package/skills/migrate-core/references/topics/resources/material-design-icons.md +173 -0
  42. package/skills/migrate-core/references/topics/resources/svg-fix-patterns.md +175 -0
  43. package/skills/migrate-core/references/topics/resources/xml-drawable-to-svg-rules.md +513 -0
  44. package/skills/migrate-core/references/topics/system-capabilities/README.md +331 -0
  45. package/skills/migrate-core/references/topics/system-capabilities/avplayer-guide.md +161 -0
  46. package/skills/migrate-core/references/topics/system-capabilities/background-tasks.md +403 -0
  47. package/skills/migrate-core/references/topics/system-capabilities/browser-intent.md +121 -0
  48. package/skills/migrate-core/references/topics/system-capabilities/camera-picker.md +118 -0
  49. package/skills/migrate-core/references/topics/system-capabilities/document-picker.md +246 -0
  50. package/skills/migrate-core/references/topics/system-capabilities/file-utils.md +131 -0
  51. package/skills/migrate-core/references/topics/system-capabilities/permission-helper.md +112 -0
  52. package/skills/migrate-core/references/topics/system-capabilities/photo-access-helper.md +208 -0
  53. package/skills/migrate-core/references/topics/system-capabilities/print-management.md +213 -0
  54. package/skills/migrate-core/references/topics/system-capabilities/share-panel.md +177 -0
  55. package/skills/migrate-core/references/topics/system-capabilities/system-settings.md +322 -0
  56. package/skills/migrate-core/references/topics/system-capabilities/telephony-dial.md +49 -0
  57. package/skills/migrate-core/references/topics/system-capabilities/video-playback.md +42 -0
  58. package/skills/migrate-core/references/topics/system-capabilities/webview-patterns.md +38 -0
  59. package/skills/migrate-core/references/topics/ui-alignment/README.md +344 -0
  60. package/skills/migrate-core/references/topics/ui-alignment/references/dark-mode.md +47 -0
  61. package/skills/migrate-core/references/topics/ui-alignment/references/layout-mapping.md +301 -0
  62. package/skills/migrate-core/references/topics/ui-alignment/references/visual-patterns.md +411 -0
  63. package/skills/migrate-core/scripts/closure/check-anchors.mjs +186 -0
  64. package/skills/migrate-core/scripts/closure/check-api-guards.mjs +175 -0
  65. package/skills/migrate-core/scripts/closure/check-consumers.mjs +301 -0
  66. package/skills/migrate-core/scripts/closure/check-permissions.mjs +165 -0
  67. package/skills/migrate-core/scripts/closure/check-resources.mjs +130 -0
  68. package/skills/migrate-core/scripts/closure/check-routes.mjs +527 -0
  69. package/skills/migrate-core/scripts/closure/check-safearea.mjs +122 -0
  70. package/skills/migrate-core/scripts/closure/check-stubs.mjs +69 -0
  71. package/skills/migrate-core/scripts/closure/closure-suite.mjs +256 -0
  72. package/skills/migrate-core/scripts/closure/idioms.json +105 -0
  73. package/skills/migrate-core/scripts/convert/convert-resources.mjs +437 -0
  74. package/skills/migrate-core/scripts/feasibility/feasibility.mjs +235 -0
  75. package/skills/migrate-core/scripts/feasibility/tables/cross-platform.json +11 -0
  76. package/skills/migrate-core/scripts/feasibility/tables/deprecated-api.json +10 -0
  77. package/skills/migrate-core/scripts/feasibility/tables/imported-arkts-core.json +425 -0
  78. package/skills/migrate-core/scripts/feasibility/tables/lib-equivalence.json +206 -0
  79. package/skills/migrate-core/scripts/feasibility/tables/system-capabilities.json +22 -0
  80. package/skills/migrate-core/scripts/front.mjs +107 -0
  81. package/skills/migrate-core/scripts/interface/ark-extract.mjs +172 -0
  82. package/skills/migrate-core/scripts/interface/interface.mjs +152 -0
  83. package/skills/migrate-core/scripts/ledger/ledger.mjs +383 -0
  84. package/skills/migrate-core/scripts/ledger/parse-cards.mjs +98 -0
  85. package/skills/migrate-core/scripts/lib/literals.mjs +37 -0
  86. package/skills/migrate-core/scripts/lib/scan.mjs +315 -0
  87. package/skills/migrate-core/scripts/smoke/align-sdk.mjs +118 -0
  88. package/skills/migrate-core/scripts/smoke/ensure-sign.mjs +53 -0
  89. package/skills/migrate-core/scripts/smoke/smoke.mjs +238 -0
  90. package/skills/migrate-core/scripts/smoke/verdict.mjs +31 -0
  91. package/skills/migrate-core/scripts/smoke/walk.mjs +480 -0
  92. package/skills/migrate-core/scripts/transpile/mapping.json +76 -0
  93. package/skills/migrate-core/scripts/transpile/transpile-layout.mjs +404 -0
  94. package/skills/migrate-core/scripts/vectors/run-arkts-vectors.mjs +107 -0
  95. package/skills/migrate-core/scripts/vectors/setup-arkts-test.mjs +90 -0
  96. package/skills/migrate-core/scripts/wire/extractors.mjs +258 -0
  97. package/skills/migrate-core/scripts/wire/wire-routes.mjs +507 -0
  98. package/skills/migrate-core/templates/acceptance.js +365 -0
  99. package/skills/migrate-core/templates/explore.js +86 -0
  100. package/skills/migrate-core/templates/implement.js +211 -0
  101. package/skills/migrate-core/templates/mig_slices.js +491 -0
@@ -0,0 +1,46 @@
1
+ # 资源确定性转换(S2 用)
2
+
3
+ 资源转换不要交给子代理手写——用脚本一次转完,结果可复查、可重跑。脚本在本技能 `scripts/convert/convert-resources.mjs`(在真实迁移项目中验证过,已通用化)。
4
+
5
+ ## 用法
6
+
7
+ ```bash
8
+ node <本技能目录>/scripts/convert/convert-resources.mjs \
9
+ --src <Android 源码根> --dst <HarmonyOS 工程根> --out <$SPEC/front> [--app-name <应用名>] [--module <模块名>=entry]
10
+ ```
11
+
12
+ 跑完看输出统计 + `$SPEC/front/resource-manifest.json`,把统计写进 plan.md;`conflicts/skipped/warnings` 逐条过一眼,需要人工处理的(见下)记进 instructions 对应单元。
13
+
14
+ ## 映射规则(脚本实现的)
15
+
16
+ | Android | HarmonyOS | 说明 |
17
+ |---|---|---|
18
+ | values*/strings.xml | `resources/<locale>/element/string.json` | name 逐字保留;`values-zh-rCN`→`zh_CN` 等 locale 映射;CDATA/xliff/转义清洗 |
19
+ | plurals | `element/plural.json` | quantity 结构保留 |
20
+ | values/colors.xml | `base/element/color.json` | 引用型(`@color/x`)告警、人工解析 |
21
+ | values-night/colors.xml | `dark/element/color.json` | 同名颜色深浅色自动切换 |
22
+ | vector drawable XML | `base/media/<name>.svg` | path/group/gradient 支持;clip-path 丢弃并告警 |
23
+ | mipmap ic_launcher* | `base/media` + `AppScope` | 取最高密度可用的 |
24
+ | integers/dimens | 只进 manifest | 实现单元写成常量类,不落资源 |
25
+ | 多模块同名资源 | 先到先得(app 模块优先),冲突记 manifest.conflicts | 冲突多时人工裁决 |
26
+
27
+ ## 脚本不做的(写进对应单元的 SECTION)
28
+
29
+ - shape/selector/layer-list 等非 vector drawable → 实现单元用组件属性自绘(圆角/边框/按压态)。
30
+ - 9-patch、位图资源 → 需要的由单元按密度挑一份拷贝。
31
+ - 主题 token 设计(亮/暗语义色)→ S2 设计时从源主题提炼,写进 conventions 的主题节;不要硬编码在脚本里。
32
+ - 带格式化参数的字符串(%1$s 等)→ 资源原样保留,运行时格式化工具由基础设施单元提供。
33
+
34
+ ## 使用纪律
35
+
36
+ - 资源转换在**任何实现单元开工前**完成,单元直接引用 `$r('app.string.x')` / `$r('app.media.ic_x')`,禁止各自造资源名。
37
+ - 单元遇到缺失图标:记录到 `$SPEC/front/missing-icons.txt` 并用相近图标替代,不许编造资源名(构建会挂)。
38
+
39
+ ## 两条路径的选择(默认脚本;库资源缺口时升级)
40
+
41
+ | 路径 | 什么时候用 | 局限 |
42
+ |---|---|---|
43
+ | **默认:本脚本** | 资源基本都在源码树 res/ 里(多数开源应用、自研应用) | 只扫源码树,拿不到 AAR/三方库自带的资源 |
44
+ | **备选:宿主的资源反编/转换类技能**(先核对 `<available_skills>` 实名,装了才用;本包不随附) | 出现库资源缺口信号时加载:转换报告/构建报错里有解析不出的引用(`@color/material_*`、`@style/Widget.*` 等);build.gradle 依赖里有带资源的库(Material Components 等);XML drawable 复杂(大量 selector/shape/layer-list);SVG 显示异常要修 | 此类技能通常需要 Android 工程能构建出 APK(反编拿合并资源集)+ 本机有 Java;图标下载需联网——**离线环境用相近已有图标替代并记录**。宿主没有此类技能时:缺口逐条记入 `$SPEC/front/missing-icons.txt`,以相近资源替代,汇报里全量列出 |
45
+
46
+ 两条路径落点一致(`<module>/src/main/resources`),先跑脚本、发现缺口再用备选补,不冲突。已有工程时只用备选技能的转换/依赖解析部分,跳过它的"新建工程"步骤。
@@ -0,0 +1,124 @@
1
+ # UI 布局语义差异(仅 UI 单元必读;2b 拷入 spec/ 并写进各 UI 单元 SECTION 首行)
2
+
3
+ 这里列的缺陷共同特征:**语法合法、编译通过、构建绿灯,逐属性对照还会被确认成"翻译正确"**——
4
+ 因为它们源于两个平台对同一概念的**默认值/定义不同**,而不是译者把值写错了。
5
+ 实测(一次全量迁移的产出统计):Column 110 处只有 37 处显式写了对齐、Row 119 处只有 45 处,
6
+ 其余全部落在"两端默认值相反"的射程内,对错取决于运气而非翻译。
7
+
8
+ ## 1. 对齐默认值两端相反(最高频)
9
+
10
+ | 容器 | ArkUI 默认 | Android 对应容器默认 | 迁移结论 |
11
+ |---|---|---|---|
12
+ | `Column`(水平=交叉轴) | `.alignItems(HorizontalAlign.Center)` **居中** | LinearLayout(vertical) 未写 gravity = **start(左)** | 源没写 gravity → 必须显式 `.alignItems(HorizontalAlign.Start)` |
13
+ | `Row`(垂直=交叉轴) | `.alignItems(VerticalAlign.Center)` **居中** | LinearLayout(horizontal) 未写 gravity = **top(顶)** | 源没写 gravity → 必须显式 `.alignItems(VerticalAlign.Top)`(源是 center_vertical 时 Center 才对) |
14
+ | `Column`/`Row` 主轴 | `.justifyContent(FlexAlign.Start)` 起始 | 同为 start/top | 主轴默认恰好一致;但 **Row 的水平位置由主轴决定**,见硬规则② |
15
+ | `Stack` | `alignContent: Alignment.Center` **正中** | FrameLayout 未写 layout_gravity = **top\|start(左上)** | 必须显式 `Stack({ alignContent: Alignment.TopStart })`(子级差异用 `.align()`/`alignRules`) |
16
+ | `Image` | `.objectFit(ImageFit.Cover)` **居中裁剪** | ImageView 未写 scaleType = **fitCenter(完整等比显示)** | 必须显式 `.objectFit(ImageFit.Contain)`(或按源 scaleType 译,见 §3) |
17
+
18
+ 出处(devecocli docs read 可复核):Column/Row/Stack 默认值见官方 API 参考
19
+ `ts-container-column` / `ts-container-row` / `ts-container-stack`;Image 默认居中裁剪见官方 FAQ `faqs-arkui-1386`。
20
+
21
+ **八条硬规则:**
22
+
23
+ 1. **Android 侧"没写 gravity"是有语义的(= start/top),不等于 ArkUI 侧可以"没写 alignItems"。**
24
+ 每个 Column/Row/Stack/Image 都显式写上表五类属性;值从源 XML 译出,源没写就写 Start/Top/TopStart/Contain。
25
+ 居中确为本意时(空态插图、按钮内图标)写 Center 并在该行注明依据即可。
26
+ 2. **决定水平位置的属性在两种容器上不同名,禁止混淆**:`Column` 的水平方向是交叉轴 →
27
+ `.alignItems(HorizontalAlign.*)`;`Row` 的水平方向是**主轴** → `.justifyContent(FlexAlign.*)`。
28
+ 一个 Row 写了完全正确的 `.alignItems(VerticalAlign.Center)`(对应源的 `center_vertical`),
29
+ 对"内容靠左还是居中"仍然什么都没说——正确的纵轴设置最容易被当成"对齐已处理"而放过。
30
+ 判据:宽度撑满的 Row 里有收缩宽度的 Text 时,必须能指出是哪个属性把它定在了左边。
31
+ 3. **修存量代码禁止盲改**(如把所有没写 alignItems 的 Column 批量补 Start):源 XML 写了
32
+ `gravity="center"` 的容器,ArkUI 的居中默认值恰好"碰对",批量补 Start 反而把对的改错。
33
+ 逐容器以**源 XML 为地面真值**核对(流程见 §4)。
34
+ 4. **底/右锚定禁放普通流**:源为 `layout_constraint(Bottom|End|Right)_to*`、`alignParent(Bottom|End)`、
35
+ `layout_gravity` 含 bottom/end 的元素,必须用 `Stack({ alignContent })`/`alignRules()`/
36
+ 主轴 `FlexAlign.End`(或前置 `layoutWeight(1)` 占位)表达锚定——放进普通 Column/Row 流里
37
+ 内容一变长就被挤出屏(短内容时看不出错)。内容高度可变的页面外层套 `Scroll`。
38
+ **子元素自己的 `.align(Alignment.BottomEnd)` 不是定位**(官方通用属性文档:`align` "设置当前组件绘制区域内的
39
+ 子组件的对齐方式",适用 Stack/Button/Text/Scroll 等,不含 Row/Column)——它不改变该组件在父 `Stack` 里的位置
40
+ (Stack 的 `alignContent` 对全部子元素生效;绝对定位用 `position`,`alignRules` 只在 RelativeContainer 内)。右下 FAB 之类的角锚定
41
+ 用独立的 `Stack({ alignContent: Alignment.BottomEnd })` 覆盖层、`RelativeContainer + alignRules`
42
+ 或 `.position()`;真机核对:`walk.mjs dump` 的 `geometry` 行给出每个节点中心的归一化坐标(0=左/上,1=右/下),右下角锚定应接近 (1,1)。
43
+ 5. **NavDestination 必须显式声明标题栏**:ArkUI 默认带系统标题栏+左上返回键,Android NoActionBar
44
+ 页面默认没有——源无标题栏 → `.hideTitleBar(true)`;源有 → `.title()` 照源。
45
+ 设置位置在**壳层路由的 `NavDestination()`**(如统一的 PageMap builder),不在各页面内。
46
+ 6. **封装视觉的自定义组件,内部根必须撑满组件框**:调用侧加在组件上的 `.width/.height/.padding`
47
+ 只作用于**外框**,不进内部视觉根——背景/渐变/圆角画在内部容器上时,内部必须
48
+ `.width('100%').height('100%')`(或把尺寸/内边距作为参数在内部应用),否则视觉只有内容大小、
49
+ 浮在正确尺寸的空槽里(Android 的 padding+background 在 view 边界内,语义相反)。
50
+ 7. **Scroll 内容短于视口时默认居中排布**(官方 FAQ faqs-arkui-725):源为 ScrollView/NestedScrollView
51
+ (顶对齐)必须显式 `.align(Alignment.TopStart)`;受 `layoutWeight`/固定高约束的 Scroll 尤其如此。
52
+ 8. **层叠中撑满的子组件吞点击**:`Stack` 里排位靠后(更上层)的 `width/height('100%')` 容器会拦截
53
+ 其下全部点击且无任何报错。纯装饰/锚定载体层必须 `.hitTestBehavior(HitTestMode.None)`;
54
+ 每个可点元素确认其上无未设透传的撑满兄弟。
55
+
56
+ ## 2. 间距与尺寸语义
57
+
58
+ | 误译 | 为什么会发生 | 后果 | 怎么写对 |
59
+ |---|---|---|---|
60
+ | 容器 `space` 与子组件同轴 `margin` 叠加 | space 译自源的固定间距,margin 又逐子照搬 | 间隙加倍("空隙过大"的主因之一) | **二选一**:等距用 `space`,不等距全用 margin;同轴不并存 |
61
+ | `.width('100%')` + 左右 `margin` | 直觉认为 100% 会自动扣掉 margin | 实际宽度 = 父宽 + 左右 margin,**右侧溢出**、圆角被裁 | 父容器 `.padding({left,right})` + 子 `.width('100%')`,或子 `.layoutWeight(1)` |
62
+ | "N dp 图标 + P dp padding" 直译成 `.width(N).padding(P)` | Android `wrap_content` 视图最终尺寸 = 内容 + padding;ArkUI `.width(N)` 是外框,padding 从 N 里**扣** | 内容区压成 N−2P(P≥N/2 时为 0:**照常占位、完全不可见**) | 源为 wrap_content 时 ArkUI 声明尺寸 = 内容 + 2×padding(`.width(N+2P).padding(P)`);源显式 `layout_width="48dp"` 时按 48 直译即可 |
63
+ | 负 margin 被当笔误丢弃 | 负值看起来像错误 | 内容整体下移(常见于贴合状态栏的头图) | 在源里 grep `margin.*="-` 逐个确认已译出 |
64
+ | 右/下锚定写成常量 `.position()` 坐标 | 参考 view tree 只给出**参考设备上的绝对解** | 更窄屏幕上元素移出可视区被裁 | 源是 `gravity="end"`/`constraintEnd_toEndOf`/`alignParentBottom` 的,用对齐属性/`alignRules()`/父尺寸表达式,不写死坐标 |
65
+ | `.margin(N)` Length 简写 | 以为只是"间距" | 四向全含左右——与 `width('100%')` 并存同样右溢 | 全宽子组件的水平间距一律沉到父 `.padding`,简写只用于四向确实相等且非全宽的场合 |
66
+ | `calc()` 写法 | `calc(100%-32vp)` 无空格 | 运行期解析失败(API10+ 才支持 calc) | 运算符两侧必须空格:`calc(100% - 32vp)` |
67
+
68
+ ## 3. 其他高频属性差异(速查)
69
+
70
+ | Android | ArkUI | 注意 |
71
+ |---|---|---|
72
+ | `View.GONE` / `View.INVISIBLE` | `.visibility(Visibility.None)` / `.visibility(Visibility.Hidden)` | None 不占位(GONE)、Hidden 占位不显示(INVISIBLE),别混 |
73
+ | `scaleType`:fitCenter / centerCrop / fitXY / center | `ImageFit`:Contain / Cover / Fill / None | 逐值对译,**别落到两端默认值上**(见 §1 表) |
74
+ | `ellipsize="end"` + `maxLines` | `.textOverflow({ overflow: TextOverflow.Ellipsis })` **必须配** `.maxLines(n)` | 只写 textOverflow 不写 maxLines 不生效 |
75
+ | `layout_weight` | `.layoutWeight(n)` | 参与分配的**所有兄弟**都要设;设了 layoutWeight 的方向不再写固定尺寸 |
76
+ | `lineSpacingExtra` N + textSize S | `.lineHeight(S+N)`(近似) | ArkUI 无"行间距"概念只有行高;Android TextView 默认还含字体内边距(includeFontPadding),文本块高度略高于 ArkUI,对不上时以此解释,不要用 margin 硬凑 |
77
+ | 背景 `<shape>` 圆角 | `.borderRadius(r)` | 子内容(图片等)要跟着圆角裁剪需加 `.clip(true)` |
78
+ | `elevation` | `.shadow({ radius, color, offsetX, offsetY })` | 无一比一换算,按视觉近似 |
79
+ | `dp` / `sp` | `vp` / `fp` | 数值 1:1;view tree bounds 是 px,只用于算比例不直接当 vp |
80
+ | Compose `alignByBaseline` / XML `layout_alignBaseline` | `Flex({...}).alignItems(ItemAlign.Baseline)`(Row 的 `VerticalAlign` 只有 Top/Center/Bottom) | 金额"¥ 99.00"这类混字号基线对齐用 Flex 或单 Text 多 Span;别写成"ArkUI 无基线对齐"登降级 |
81
+ | `FlowRow(horizontalArrangement/verticalArrangement = spacedBy)` | `Flex({ wrap: FlexWrap.Wrap, space: { main: LengthMetrics.vp(8), cross: LengthMetrics.vp(4) } })`(API 12) | 有 space 参数,不用逐子项 margin 近似 |
82
+ | `LazyVerticalStaggeredGrid` + `span = FullLine` 整行头/混排 | `WaterFlow({ sections })` 分段:整行头一段 `crossCount:1`,商品一段 `crossCount:2`(API 12 `WaterFlowSections`) | 不要退化成 List 两两成行;FlowItem 本身不跨列但分段可以 |
83
+ | `ScrollState.value` / `NestedScrollConnection` 读滚动量 | `List/WaterFlow/Grid.onDidScroll((offset, state) => …)`(API 12,`ScrollableCommonMethod`);`Scroll.onDidScroll((xOffset, yOffset, state) => …)` 签名不同 | 要"先吃掉位移再滚"用 `onScrollFrameBegin`;别写"Scroll 不支持 onDidScroll" |
84
+
85
+ ## 4. 写 UI 单元前的轻量 XML 对照(三步,每单元约两分钟)
86
+
87
+ 开写一个页面/组件前,对它的源 layout XML 跑一遍:
88
+
89
+ ```bash
90
+ grep -nE 'gravity|orientation|layout_weight|scaleType|visibility|margin|padding|ellipsize|maxLines|constraint(Bottom|End|Right|Baseline)_to|alignParent(Bottom|End|Right)' <源 layout 及其 include>.xml
91
+ ```
92
+
93
+ 1. **提取**:整理成"容器 → 对齐/间距声明"清单;**没写 gravity 的容器也要列**,标注"未写 = start/top"。
94
+ 2. **翻译**:写 ArkTS 时逐容器对照清单,显式写出 §1 的五类属性;间距按 §2 第一行决定 space 还是 margin。
95
+ 3. **自查**:写完跑 §5 机械门,数量对不上就回头补。
96
+
97
+ ## 5. 机械自查门(单元自查与 verify 抽查通用)
98
+
99
+ ```bash
100
+ E=<单元产出目录>
101
+ # ① 裸容器差值:声明数 − 显式对齐数 = 待核对数(不是缺陷数,逐个回源 XML 核对)
102
+ grep -rno "Column(" $E --include='*.ets' | wc -l ; grep -rno "alignItems(HorizontalAlign\." $E --include='*.ets' | wc -l
103
+ grep -rno "Row(" $E --include='*.ets' | wc -l ; grep -rnoE "alignItems\(VerticalAlign\.|justifyContent\(FlexAlign\." $E --include='*.ets' | wc -l
104
+ # ② Stack 未显式 alignContent
105
+ grep -rn "Stack(" $E --include='*.ets' | grep -v alignContent
106
+ # ③ Image 未显式 objectFit(Image( 与 .objectFit 通常不同行,按文件数差值核对)
107
+ grep -rln "Image(" $E --include='*.ets' | xargs grep -Ln "objectFit" 2>/dev/null
108
+ # ④ 同元素 width('100%') + 左右 margin(溢出)
109
+ grep -rn -A4 "width('100%')" $E --include='*.ets' | grep -E "margin.*(left|right)"
110
+ # ⑤ 带 space 的容器:其直接子组件是否又写了同轴 margin(双计,人工抽查命中处)
111
+ grep -rn "space:" $E --include='*.ets'
112
+ # ⑥ 锚定对账:源底/右锚数 vs 产物锚定表达数,差值大 = 锚定被摊进了普通流(硬规则④)
113
+ grep -rEc 'constraint(Bottom|End|Right)_to|alignParent(Bottom|End|Right)' <源 layout 目录>
114
+ grep -rEo 'alignRules|Alignment\.(Bottom|BottomStart|BottomEnd|End)|FlexAlign\.End' $E --include='*.ets' | wc -l
115
+ # ⑧ 误把 .align 当定位(硬规则④):Stack 子元素上出现 .align(Alignment.Bottom*/End*) 逐个核对——要的是父 Stack alignContent / alignRules / position
116
+ grep -rnE "\.align\(Alignment\.(Bottom|BottomEnd|BottomStart|End|TopEnd)\)" $E --include='*.ets'
117
+ # ⑦ 撑满层叠子组件候选(硬规则⑧):含 Stack 且有 100% 尺寸的文件,逐个确认可交互或已设 HitTestMode.None
118
+ grep -rlnE "\.(width|height)\('100%'\)" $E --include='*.ets' | xargs grep -ln 'Stack(' 2>/dev/null
119
+ ```
120
+
121
+ ①③⑤输出的是**待核对清单**而非缺陷清单——回源 XML 确认;居中/裁剪确为源本意的,注明依据即通过。
122
+
123
+ ---
124
+ 出处:默认值均引官方文档(§1 表下方 doc id 可用 devecocli docs read 复核)。
@@ -0,0 +1,42 @@
1
+ # 拆单元、分波与 SECTION 写法(2b/3 用)
2
+
3
+ ## 拆单元规则
4
+
5
+ - **一个单元 = 一个子代理一轮能稳定做完的子系统片**。标尺不是定数而是可靠性:产出个位数文件、一轮内能收尾是经验安全区;预估要长跑的必拆(例:数据库层拆成 建库/读/写 三个单元)。**过大的单元是超时和整波失败的主因**(实测教训:一个装下整个大页面族的单元跑了数小时直到超时)。
6
+ - 每个单元有稳定 id(`u-<名>`)、明确 targetPath、明确完成标准。
7
+ - **波内互不依赖**。典型分波(示例,按项目的依赖图调整,不是规定):wave 0 不依赖任何单元(基础设施/模型/事件/配置),wave 1 只依赖 wave 0(存储/网络/解析),wave 2 依赖前两波(服务/核心逻辑/公共 UI 组件),wave 3 页面(依赖公共组件),最后一个集成单元(wave 尾)独占壳文件做收口。
8
+ - 同波单元要用同一个符号时:该符号所在单元放进更早的波,或把接口约定写死在 conventions(如事件 API 形状),实现方照约定实现。
9
+ - **共享文件**两种处理:能预建的(路由表壳、资源清单)S2 就建好;不能预建的(module.json5、main_pages.json、壳页面)列入 implement 的 `sharedFiles`,单元只提交"需要的修改"由集成代理统一应用,或划给独占单元。
10
+ - **反向依赖用注入回调**:底层模块需要触发上层逻辑(删文件、触发下载)时,底层暴露 `setXxxHook(cb)`(未注册即 no-op),由上层单元/集成单元注册。禁止底层 import 上层。
11
+
12
+ ## instructions.md 的 SECTION 写法
13
+
14
+ 每单元一节,子代理只读自己的 SECTION + 文件头部公共说明。文件头写:工单卡片自足(conventions+SECTION 已内嵌);需要背景再读 explore 产物与源码、目标工程路径、资源已就绪说明。**UI 单元(页面/组件/弹窗)的 SECTION 首行额外点名 `$SPEC(=$DST/spec)/ui-layout-semantics.md` 的 §5 自查门**;非 UI 单元不加。
15
+
16
+ 单节模板:
17
+
18
+ ```markdown
19
+ ## SECTION: u-<名>
20
+ **目标**:<一句话>。产出 `<targetPath>`:
21
+ - `<文件>.ets`:<该文件做什么。关键 API 形状直接写出来(方法签名/字段),实现语义指向
22
+ explore 文档具体小节 + 源码具体路径。已知的坑当场写(如"X 与 Y 的依赖方向:不得反向 import,用注入回调")>
23
+ - …每个产出文件一条
24
+ **规格来源**:explore/<区>.md §<节> + 源码 `<$SRC>/<路径>`
25
+ **注意**:<容易做错的点、与源的刻意差异、哨兵值语义>
26
+ **完成标准**:<可检查的清单:导出哪些符号、覆盖哪些枚举/分支(全量点名)、无外部依赖等;
27
+ ```
28
+
29
+ 好坏对比:
30
+ - ❌ "实现事件总线"——没有 API 形状,两个单元会写出不兼容的总线。
31
+ - ✅ "EventBus.ets:`on(type, cb)/off/post/postSticky/getSticky`,type 用事件类构造函数标识,post 前拷贝回调列表,回调必须主线程;sticky 语义见 explore/events.md(新订阅者立即收到最近值)"。
32
+ - ❌ 完成标准:"功能正常"。
33
+ - ✅ 完成标准:"26 个模型类全部导出;SortOrder 全部 17 个成员 code 照源;无 UI 依赖;summary 列出每文件导出符号"。
34
+
35
+ ## implement 调用与单元表的对应(workflow 工具形态)
36
+
37
+ - `units[i].section` = SECTION id;`wave` = 波次号;单元特有技能放 `units[i].skills`。
38
+ - **检查集中**:检查只配置在 gate(`$ <命令>` 形式,退出码即裁决),不进单元。
39
+ 单元自身只做廉价自查:重读自己的编辑、最多跑一次仅覆盖本单元文件的秒级静态检查
40
+ (不循环修复、不跑全工程构建——并行兄弟会抢构建守护进程与输出目录)。
41
+ - 一波一次 implement 调用、`runName: 'implement_run<N>'`;单元表和状态同步维护在 plan.md。
42
+ - 波间衔接:上一波的 debt/envNotes 先固化进 conventions §J,再发下一波。
@@ -0,0 +1,24 @@
1
+ # DevEco Code 宿主能力盘点表(宿主优先原则的执行依据)
2
+
3
+ 原则:**宿主有的不自建**——宿主工具有平台维护、结构化输出、IDE 集成三重优势;
4
+ 本套件脚本是兜底。此表在首次宿主会话(试点)实测填写,此后随宿主版本更新。
5
+
6
+ 盘点程序(migrate-core 阶段一第 2 步执行):
7
+ 1. 列出会话可用工具全集(工具面板/工具列表)与已装技能清单;
8
+ 2. 对下表逐行核对:存在→记工具名与输入输出形态;不存在→该行走"兜底"列;
9
+ 3. 新发现的宿主件(表外的)追加行,并检查套件里是否有可退役的自建件。
10
+
11
+ | 能力 | 期望的宿主件 | 实测(名称/形态/限制) | 兜底 |
12
+ |---|---|---|---|
13
+ | 工程创建 | `devecocli create --project-path <dir> --app-name <X> --bundle-name <Y>` | **实测无头可跑**(自动探测本机 SDK API 级别,产出含 IDE 默认图标的标准工程);deveco-create-project 技能是它的会话式封装,加载器不继承 bash 环境时直接跑命令即可 | 手工 scaffold(不再随包带模板工程) |
14
+ | 构建 | build_project(结构化错误,IDE 可跳转) | **实测可用**;依赖 ohpm registry,网络断时 install 步失败→回退 hvigorw(两单实测) | `$ hvigorw` 退出码 |
15
+ | 静态检查 | arkts_check / codelinter | 待实测(历史证据:存在;@kit 声明有已知误报,以 hvigor 为准) | codelinter CLI |
16
+ | **界面核验** | verify_ui | **不在默认阶梯**:VL 模型驱动,单次 12 分钟量级;报"应用未安装"是其内部 startApp 解析 `bm dump` 失败即判未装(无重试,本机 64 次启动 11 次中招,与签名无关,`bm dump` 手工 16 次零失败);判定文本亦有"点击未生效"类误判。只作补充证据,报未安装先 `walk.mjs alive` 核实再重试一次 | `$HMIG/scripts/smoke/walk.mjs`(确定性控件树断言+截图+崩溃,单飞) |
17
+ | 设备控制 | start_app + devecocli device/run | **实测可用**(装启/设备列表/跳过构建重装);uitest 长按时长不足是已知限制 | hdc + uitest uiInput |
18
+ | 模拟器 | 模拟器 | **实测在位**(Pura 90 2,全链路走查可用;无触觉/部分 picker 形态不可达) | 手动起模拟器 |
19
+ | 崩溃日志 | faultlogger 读取 | 待实测 | hdc shell + hmos-jscrash-analysis 技能 |
20
+ | 官方文档检索 | retriever 技能(已随包) | 已知:hmos-arkui/arkts-knowledge-retriever | references/ 语料 |
21
+ | 权限预放行 | headless 运行的权限策略 | 待实测(引擎有自动应答,策略随宿主) | 安装期预授权清单 |
22
+
23
+ 填表完成后:把"实测"列同步进 migrate-core 阶段一的盘点说明,退役重复自建件,
24
+ 表交 git 版本化——这张表就是"亲和性适配"的账本。
@@ -0,0 +1,214 @@
1
+ <!-- 原技能 arkts-app-identity,已吸收为 migrate-core 语料专题,不再单独注册 -->
2
+ > Android App 身份信息迁移到 HarmonyOS:App 名称(label)、图标(含 layered_image.json 分层自适应图标)、版本号(versionName/versionCode)、包名/厂商(app.json5 的 bundleName/vendor)。当用户需要迁移这些身份字段、或发现 app.json5 中 bundleName/vendor/versionName 仍是模板默认值时触发,从 AndroidManifest.xml / build.gradle 提取原值。即使只说"app 名字不对""图标没迁移""包名还是默认的"也应触发。不处理全量资源迁移(用 android2hmos_resources_convert)、运行时权限或深度链接。
3
+
4
+ # ArkTS App Identity — 应用身份迁移
5
+
6
+ ## 定位
7
+
8
+ 从 Android 项目提取 App 身份信息(名称、图标、版本号、包名),生成 HarmonyOS 对应配置文件。
9
+
10
+ 本 skill 在迁移流程中的位置:阶段二·静态前场建工程时执行,先于一切页面实现。
11
+
12
+ ```
13
+ Android 项目 → [本 skill] → app.json5 + string.json + 图标资源
14
+ ```
15
+
16
+ ---
17
+
18
+ ## 输入
19
+
20
+ | 项 | 内容 |
21
+ |----|------|
22
+ | **必须** | Android 项目根路径 |
23
+ | **可选** | `spec/baseline/feature-base.md` App 身份段(如果 spec 阶段已提取) |
24
+ | **可选** | `scope`:`full`(默认,写全部身份字段)/ `dev-identity`(仅 dev 安全字段 app_name / versionName / versionCode / 图标,**跳过 bundleName / vendor**——见 Step 3 说明) |
25
+
26
+ 自动定位以下文件:
27
+ - `app/src/main/AndroidManifest.xml`(或扫描 `**/AndroidManifest.xml`)
28
+ - `app/build.gradle` 或 `app/build.gradle.kts`
29
+ - `**/res/values/strings.xml`(或 `common.gradle` 中的 `resValue`)
30
+ - `**/res/mipmap-xxxhdpi/ic_launcher*.png`
31
+ - `**/res/mipmap-anydpi-v26/ic_launcher.xml`(自适应图标定义)
32
+
33
+ ---
34
+
35
+ ## 输出
36
+
37
+ | 文件 | 内容 | 说明 |
38
+ |------|------|------|
39
+ | `AppScope/app.json5` | bundleName, vendor, versionCode, versionName, icon, label | 更新已有文件,不覆盖无关字段 |
40
+ | `AppScope/resources/base/element/string.json` | app_name 字段 | 更新 app_name 值 |
41
+ | `AppScope/resources/base/media/foreground.png` | 前景图标 | 从 Android xxxhdpi 提取 |
42
+ | `AppScope/resources/base/media/background.png` | 背景图标 | 从 Android xxxhdpi 提取 |
43
+ | `AppScope/resources/base/media/layered_image.json` | 自适应图标配置 | 生成或验证 |
44
+ | `entry/src/main/resources/base/media/startIcon.png` | 启动图标 | 复制 foreground 或 ic_launcher |
45
+ | `entry/src/main/resources/base/element/string.json` | EntryAbility_label | 更新为 app_name |
46
+ | 映射报告(输出到控制台) | Android 原值 → HarmonyOS 填充值 | 供用户确认 |
47
+
48
+ ---
49
+
50
+ ## 核心映射规则
51
+
52
+ ```
53
+ Android → HarmonyOS
54
+ ──────────────────────────────────────────────────────
55
+ applicationId → bundleName
56
+ 规则: 保持原值,或用户自定义
57
+ 示例: de.example.app → com.example.app
58
+
59
+ android:label / app_name (string) → app.json5 label ($string:app_name)
60
+ 规则: 从 strings.xml 或 build.gradle resValue 解析真实值
61
+
62
+ versionName → versionName
63
+ 规则: 保持一致
64
+
65
+ versionCode → versionCode
66
+ 规则: 保持一致
67
+
68
+ namespace / applicationId 的组织名 → vendor
69
+ 规则: 提取第二段 (com.example.app → example)
70
+
71
+ mipmap-xxxhdpi/ic_launcher.png → foreground.png
72
+ 规则: 优先 xxxhdpi,降级到 xxhdpi/xhdpi
73
+
74
+ ic_launcher_background.png → background.png
75
+ 规则: 优先 xxxhdpi,如不存在生成纯色 PNG
76
+
77
+ adaptive-icon XML (ic_launcher.xml) → layered_image.json
78
+ 格式: { "layered-image": { "background": "$media:background", "foreground": "$media:foreground" } }
79
+ ```
80
+
81
+ ---
82
+
83
+ ## 工作流程
84
+
85
+ ### Step 1: 提取 Android 身份信息
86
+
87
+ ```
88
+ 1. Read AndroidManifest.xml
89
+ → 提取 android:label (通常是 @string/app_name)
90
+ → 提取 android:icon (通常是 @mipmap/ic_launcher)
91
+
92
+ 2. Read build.gradle / build.gradle.kts
93
+ → 提取 applicationId / namespace
94
+ → 提取 versionName, versionCode
95
+ → 检查 buildTypes 中的 resValue (动态 app_name)
96
+
97
+ 3. Read strings.xml (如果 label 是 @string 引用)
98
+ → 解析 app_name 的实际文本值
99
+ → 如果 build.gradle 有 resValue 覆盖,使用 release buildType 的值
100
+ ```
101
+
102
+ ### Step 2: 提取图标资源
103
+
104
+ ```
105
+ 4. 定位图标文件
106
+ 优先级: mipmap-xxxhdpi > mipmap-xxhdpi > mipmap-xhdpi > mipmap-hdpi
107
+ 文件: ic_launcher.png, ic_launcher_foreground.png, ic_launcher_background.png
108
+
109
+ 5. 检查自适应图标
110
+ 文件: mipmap-anydpi-v26/ic_launcher.xml
111
+ 如果存在:
112
+ → 解析 <foreground android:drawable="@xxx"/>
113
+ → 解析 <background android:drawable="@xxx"/>
114
+ → 定位对应的 PNG 文件
115
+ ```
116
+
117
+ ### Step 3: 生成 HarmonyOS 配置
118
+
119
+ ```
120
+ 6. 更新 AppScope/app.json5
121
+ 仅更新以下字段(保留其他字段不变):
122
+ - versionCode: 保持
123
+ - versionName: 保持
124
+ - icon: "$media:layered_image" (不变)
125
+ - label: "$string:app_name" (不变)
126
+ - bundleName: 从 applicationId 映射 ⚠️ 仅 scope=full
127
+ - vendor: 从 namespace 提取组织名 ⚠️ 仅 scope=full
128
+
129
+ > **scope=dev-identity(静态前场建工程时用)**:**跳过 bundleName / vendor**——
130
+ > 二者与签名证书 / AGC 应用上架强绑定,属部署期决策(迁移 ledger C-类目,对应 D-009)。
131
+ > dev 阶段写入真实 bundleName 会与脚手架签名配置 / 后续 AGC 注册不一致,反致装机失败;
132
+ > 保留脚手架占位值,待部署期由 `scope=full`(或人工)统一落地。dev 阶段只消除
133
+ > app_name / versionName 的脚手架默认值(这些无签名影响、却卡真机识别与验收)。
134
+
135
+ 7. 更新 AppScope/resources/base/element/string.json
136
+ 更新 app_name 的 value 字段
137
+
138
+ 8. 复制图标文件
139
+ - foreground.png → AppScope/resources/base/media/foreground.png
140
+ - background.png → AppScope/resources/base/media/background.png
141
+ - ic_launcher.png → entry/src/main/resources/base/media/startIcon.png
142
+ - ic_launcher.png → entry/src/main/resources/base/media/ic_launcher.png (如存在)
143
+
144
+ 9. 生成/验证 layered_image.json
145
+ 确保内容为:
146
+ {
147
+ "layered-image": {
148
+ "background": "$media:background",
149
+ "foreground": "$media:foreground"
150
+ }
151
+ }
152
+
153
+ 10. 更新 entry/src/main/resources/base/element/string.json
154
+ 更新 EntryAbility_label 的 value 与 app_name 一致
155
+ ```
156
+
157
+ ### Step 4: 输出映射报告
158
+
159
+ ```
160
+ 11. 输出对照表:
161
+ | 字段 | Android 原值 | HarmonyOS 填充值 |
162
+ |------|-------------|-----------------|
163
+ | 应用名称 | 示例应用 | 示例应用 |
164
+ | 包名 | de.example.app | com.example.app |
165
+ | 版本号 | 3.11.0 | 3.11.0 |
166
+ | 版本码 | 3110095 | 3110095 |
167
+ | 厂商 | danoeh | danoeh |
168
+ | 图标 | mipmap-xxxhdpi/ic_launcher.png | foreground.png (XXkb) |
169
+
170
+ 提示用户确认 bundleName 映射(可能需要调整前缀)。
171
+ ```
172
+
173
+ ---
174
+
175
+ ## 边界情况处理
176
+
177
+ | 场景 | 处理方式 |
178
+ |------|---------|
179
+ | 多模块项目,icon 在子模块 | 从 AndroidManifest.xml 追踪 icon 引用,跨模块定位 |
180
+ | build.gradle.kts (Kotlin DSL) | 同时支持 Groovy 和 KTS 语法解析 |
181
+ | 无 adaptive-icon (API < 26) | 只有单个 ic_launcher.png → 复制为 foreground.png,生成纯白 background.png |
182
+ | app_name 在 build.gradle resValue 中动态定义 | 优先使用 release buildType 的 resValue |
183
+ | 多 flavor 的 applicationId | 使用默认 applicationId(无 flavor 后缀) |
184
+ | feature-base.md App 身份段已存在 | 直接从 feature-base.md 读取映射值,跳过 Android 项目扫描 |
185
+
186
+ ---
187
+
188
+ ## 跨 Skill 协作
189
+
190
+ | 协作对象 | 关系 |
191
+ |---------|------|
192
+ | `android2hmos_resources_convert` | 它处理全量资源,本 skill 只处理 app 级身份资源 |
193
+ | 工程脚手架 | scaffold 模板生成后,本 skill 填充真实值 |
194
+ | 末端验收 | App 身份校验项验证本 skill 的产出 |
195
+
196
+ ---
197
+
198
+ ## 触发 Prompt 示例
199
+
200
+ ```
201
+ 迁移 app 图标
202
+ ```
203
+
204
+ ```
205
+ app 名字不对
206
+ ```
207
+
208
+ ```
209
+ 配置应用信息
210
+ ```
211
+
212
+ ```
213
+ bundleName 还是默认的
214
+ ```