android2harmony 0.1.7 → 0.1.8

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 (226) hide show
  1. package/agents/api-analyzer.md +113 -0
  2. package/agents/app-action.md +122 -0
  3. package/agents/code-reviewer.md +191 -295
  4. package/agents/coder.md +377 -0
  5. package/agents/self-tester.md +8 -8
  6. package/agents/spec-designer.md +56 -0
  7. package/package.json +1 -1
  8. package/skills/a2h-app-req-gen/SKILL.md +174 -0
  9. package/skills/a2h-app-req-gen/references/spec-handoff.md +99 -0
  10. package/skills/a2h-app-req-gen/references/subagent-render.md +115 -0
  11. package/skills/a2h-app-req-gen/scripts/reqgen/analyzer-jvm/build.gradle.kts +41 -0
  12. package/skills/a2h-app-req-gen/scripts/reqgen/analyzer-jvm/gradle/wrapper/gradle-wrapper.jar +0 -0
  13. package/skills/a2h-app-req-gen/scripts/reqgen/analyzer-jvm/gradle/wrapper/gradle-wrapper.properties +8 -0
  14. package/skills/a2h-app-req-gen/scripts/reqgen/analyzer-jvm/gradle.properties +3 -0
  15. package/skills/a2h-app-req-gen/scripts/reqgen/analyzer-jvm/gradlew +251 -0
  16. package/skills/a2h-app-req-gen/scripts/reqgen/analyzer-jvm/gradlew.bat +94 -0
  17. package/skills/a2h-app-req-gen/scripts/reqgen/analyzer-jvm/settings.gradle.kts +17 -0
  18. package/skills/a2h-app-req-gen/scripts/reqgen/analyzer-jvm/src/main/java/dev/reqgen/analyzer/jvm/RawAnalysisDetector.java +1911 -0
  19. package/skills/a2h-app-req-gen/scripts/reqgen/analyzer-jvm/src/main/java/dev/reqgen/analyzer/jvm/RawIssueRegistry.java +37 -0
  20. package/skills/a2h-app-req-gen/scripts/reqgen/analyzer-jvm/src/main/java/dev/reqgen/analyzer/jvm/RawJson.java +146 -0
  21. package/skills/a2h-app-req-gen/scripts/reqgen/analyzer-jvm/src/main/java/dev/reqgen/analyzer/jvm/RawLocation.java +96 -0
  22. package/skills/a2h-app-req-gen/scripts/reqgen/analyzer-jvm/src/main/java/dev/reqgen/analyzer/jvm/RawRecordWriter.java +227 -0
  23. package/skills/a2h-app-req-gen/scripts/reqgen/analyzer-jvm/src/main/resources/META-INF/services/com.android.tools.lint.client.api.IssueRegistry +1 -0
  24. package/skills/a2h-app-req-gen/scripts/reqgen/analyzer-jvm/src/main/resources/dev/reqgen/analyzer/jvm/raw-record-v1.schema.json +93 -0
  25. package/skills/a2h-app-req-gen/scripts/reqgen/assets/dashboard.html +151 -0
  26. package/skills/a2h-app-req-gen/scripts/reqgen/gradle/reqgen-lint.init.gradle +60 -0
  27. package/skills/a2h-app-req-gen/scripts/reqgen/gradle/reqgen-model.init.gradle +204 -0
  28. package/skills/a2h-app-req-gen/scripts/reqgen/package.json +14 -0
  29. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/backend.js +323 -0
  30. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/cli.js +811 -0
  31. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/gap-audit-link.js +62 -0
  32. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/index.js +66 -0
  33. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/merge.js +605 -0
  34. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/name-trace.js +153 -0
  35. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/orchestrate.js +1324 -0
  36. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/output-parse.js +50 -0
  37. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/overview.js +10 -0
  38. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/pool.js +23 -0
  39. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/post-merge-fix.js +146 -0
  40. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/prompt-loader.js +51 -0
  41. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/prompt.js +967 -0
  42. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/prompts.md +301 -0
  43. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/serve.js +78 -0
  44. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/short-id.js +46 -0
  45. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/snapshot.js +267 -0
  46. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/types.js +1 -0
  47. package/skills/a2h-app-req-gen/scripts/reqgen/src/agent-render/validate.js +122 -0
  48. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/callback-call-sites.js +62 -0
  49. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/gap-audit/build.js +1291 -0
  50. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/gap-audit/index.js +1 -0
  51. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/graph/area-ownership.js +392 -0
  52. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/graph/build.js +1995 -0
  53. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/graph/callback-flow.js +277 -0
  54. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/graph/component-variants.js +725 -0
  55. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/graph/index.js +15 -0
  56. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/names/index.js +12 -0
  57. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/names/policy.js +469 -0
  58. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/names/traceability.js +468 -0
  59. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/req-model/build.js +1066 -0
  60. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/req-model/index.js +1 -0
  61. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/source-facts/android-interaction-registry.js +174 -0
  62. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/source-facts/android.js +1062 -0
  63. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/source-facts/area-titles.js +678 -0
  64. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/source-facts/builder.js +350 -0
  65. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/source-facts/compose-api-registry.js +395 -0
  66. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/source-facts/compose-call-sites.js +2008 -0
  67. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/source-facts/compose.js +9059 -0
  68. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/source-facts/dynamic-repeated-call-sites.js +529 -0
  69. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/source-facts/index.js +1 -0
  70. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/source-facts/interaction-effects.js +1149 -0
  71. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/source-facts/jvm.js +6272 -0
  72. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/source-facts/normalize.js +33 -0
  73. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/source-facts/pending-intents.js +565 -0
  74. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/source-facts/resource-id.js +42 -0
  75. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/source-facts/route-state-variants.js +781 -0
  76. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/source-facts/state.js +234 -0
  77. package/skills/a2h-app-req-gen/scripts/reqgen/src/analysis/source-facts/types.js +1 -0
  78. package/skills/a2h-app-req-gen/scripts/reqgen/src/android/extract.js +40 -0
  79. package/skills/a2h-app-req-gen/scripts/reqgen/src/android/index.js +6 -0
  80. package/skills/a2h-app-req-gen/scripts/reqgen/src/android/manifest.js +513 -0
  81. package/skills/a2h-app-req-gen/scripts/reqgen/src/android/resources.js +398 -0
  82. package/skills/a2h-app-req-gen/scripts/reqgen/src/android/types.js +1 -0
  83. package/skills/a2h-app-req-gen/scripts/reqgen/src/android/views.js +447 -0
  84. package/skills/a2h-app-req-gen/scripts/reqgen/src/android/xml-parser.js +175 -0
  85. package/skills/a2h-app-req-gen/scripts/reqgen/src/cli.js +398 -0
  86. package/skills/a2h-app-req-gen/scripts/reqgen/src/contracts/area-graph.js +1 -0
  87. package/skills/a2h-app-req-gen/scripts/reqgen/src/contracts/artifact.js +1 -0
  88. package/skills/a2h-app-req-gen/scripts/reqgen/src/contracts/common.js +16 -0
  89. package/skills/a2h-app-req-gen/scripts/reqgen/src/contracts/diagnostic.js +10 -0
  90. package/skills/a2h-app-req-gen/scripts/reqgen/src/contracts/gap-audit.js +14 -0
  91. package/skills/a2h-app-req-gen/scripts/reqgen/src/contracts/index.js +11 -0
  92. package/skills/a2h-app-req-gen/scripts/reqgen/src/contracts/name-traceability.js +26 -0
  93. package/skills/a2h-app-req-gen/scripts/reqgen/src/contracts/raw-fact.js +40 -0
  94. package/skills/a2h-app-req-gen/scripts/reqgen/src/contracts/req-model.js +1 -0
  95. package/skills/a2h-app-req-gen/scripts/reqgen/src/contracts/run.js +19 -0
  96. package/skills/a2h-app-req-gen/scripts/reqgen/src/contracts/semantic-completeness.js +11 -0
  97. package/skills/a2h-app-req-gen/scripts/reqgen/src/contracts/source-facts.js +1 -0
  98. package/skills/a2h-app-req-gen/scripts/reqgen/src/core/output-guard.js +41 -0
  99. package/skills/a2h-app-req-gen/scripts/reqgen/src/core/stable-id.js +92 -0
  100. package/skills/a2h-app-req-gen/scripts/reqgen/src/dashboard-cli.js +169 -0
  101. package/skills/a2h-app-req-gen/scripts/reqgen/src/diagnostics.js +104 -0
  102. package/skills/a2h-app-req-gen/scripts/reqgen/src/dump/dump.js +1028 -0
  103. package/skills/a2h-app-req-gen/scripts/reqgen/src/dump/index.js +1 -0
  104. package/skills/a2h-app-req-gen/scripts/reqgen/src/dump-cli.js +251 -0
  105. package/skills/a2h-app-req-gen/scripts/reqgen/src/generation/artifacts.js +49 -0
  106. package/skills/a2h-app-req-gen/scripts/reqgen/src/generation/index.js +18 -0
  107. package/skills/a2h-app-req-gen/scripts/reqgen/src/generation/quality-report.js +125 -0
  108. package/skills/a2h-app-req-gen/scripts/reqgen/src/generation/render.js +353 -0
  109. package/skills/a2h-app-req-gen/scripts/reqgen/src/generation/types.js +2 -0
  110. package/skills/a2h-app-req-gen/scripts/reqgen/src/graph/paths.js +474 -0
  111. package/skills/a2h-app-req-gen/scripts/reqgen/src/jvm/index.js +15 -0
  112. package/skills/a2h-app-req-gen/scripts/reqgen/src/jvm/protocol.js +408 -0
  113. package/skills/a2h-app-req-gen/scripts/reqgen/src/jvm/runner.js +452 -0
  114. package/skills/a2h-app-req-gen/scripts/reqgen/src/pipeline/index.js +8 -0
  115. package/skills/a2h-app-req-gen/scripts/reqgen/src/pipeline/output.js +165 -0
  116. package/skills/a2h-app-req-gen/scripts/reqgen/src/pipeline/run-stage1.js +891 -0
  117. package/skills/a2h-app-req-gen/scripts/reqgen/src/project/discovery.js +299 -0
  118. package/skills/a2h-app-req-gen/scripts/reqgen/src/project/gradle-model.js +358 -0
  119. package/skills/a2h-app-req-gen/scripts/reqgen/src/project/gradle-runner.js +165 -0
  120. package/skills/a2h-app-req-gen/scripts/reqgen/src/project/resource-profile.js +60 -0
  121. package/skills/a2h-app-req-gen/scripts/reqgen/src/project/types.js +1 -0
  122. package/skills/a2h-app-req-gen/scripts/reqgen/src/spec-handoff-cli.js +151 -0
  123. package/skills/a2h-app-req-gen/scripts/reqgen/src/spec-handoff.js +1004 -0
  124. package/skills/a2h-app-req-gen/scripts/reqgen/src/stage2-cli.js +109 -0
  125. package/skills/a2h-app-req-gen/scripts/reqgen/src/stage2-input.js +419 -0
  126. package/skills/a2h-app-req-gen/scripts/reqgen/src/stage2-name-trace-input.js +95 -0
  127. package/skills/a2h-app-req-gen/scripts/reqgen/src/validation/area-graph.js +444 -0
  128. package/skills/a2h-app-req-gen/scripts/reqgen/src/validation/index.js +7 -0
  129. package/skills/a2h-app-req-gen/scripts/reqgen/src/validation/req-model.js +580 -0
  130. package/skills/a2h-app-req-gen/scripts/reqgen/src/validation/req-text.js +195 -0
  131. package/skills/a2h-app-req-gen/scripts/reqgen/src/validation/semantic-area-graph.js +1431 -0
  132. package/skills/a2h-app-req-gen/scripts/reqgen/src/validation/types.js +1 -0
  133. package/skills/a2h-app-req-gen/scripts/reqgen-audit.mjs +298 -0
  134. package/skills/a2h-app-req-gen/scripts/reqgen-selfcheck.mjs +555 -0
  135. package/skills/a2h-code-review/SKILL.md +379 -0
  136. package/skills/{hmos-integration-test → a2h-integration-test}/README.md +6 -6
  137. package/skills/{hmos-integration-test → a2h-integration-test}/SKILL.md +6 -6
  138. package/skills/{hmos-integration-test → a2h-integration-test}/scripts/report-tool.mjs +1 -1
  139. package/skills/a2h-spec-design/SKILL.md +330 -0
  140. package/skills/a2h-spec-design/scripts/inspect_spec_design_inputs.mjs +207 -0
  141. package/skills/a2h-spec-design/scripts/move_spec_technical_reference.mjs +198 -0
  142. package/skills/a2h-spec-design/scripts/validate_spec_design_output.mjs +256 -0
  143. package/skills/a2h-spec-generate/SKILL.md +696 -0
  144. package/skills/a2h-spec-generate/references/trace-template.md +115 -0
  145. package/skills/a2h-spec-generate/scripts/parse_requirements.mjs +537 -0
  146. package/skills/a2h-spec-generate/template/REQ.txt +22 -0
  147. package/skills/a2h-spec-generate/template/REQ.xlsx +0 -0
  148. package/skills/a2h-spec-implement/SKILL.md +548 -0
  149. package/skills/a2h-spec-implement/references/harmony-pitfalls.md +186 -0
  150. package/skills/a2h-spec-implement/references/l1-unit-test.md +185 -0
  151. package/skills/a2h-spec-implement/references/l3-e2e-uitest.md +167 -0
  152. package/skills/a2h-spec-implement/references/test-core.md +132 -0
  153. package/skills/a2h-spec-implement/rules/arkts/arkts-standards.md +184 -0
  154. package/skills/a2h-spec-implement/rules/arkts/conventions/coding-style.md +96 -0
  155. package/skills/a2h-spec-implement/rules/arkts/conventions/security.md +126 -0
  156. package/skills/a2h-spec-implement/rules/arkts/language/arkts-rules.md +650 -0
  157. package/skills/a2h-spec-implement/rules/arkts/language/arkui-structure-rules.md +173 -0
  158. package/skills/a2h-spec-implement/rules/arkts/language/ts-to-arkts-rewrites.md +58 -0
  159. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v1/@Link/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/217/214/345/220/221/345/220/214/346/255/245.md +648 -0
  160. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v1/@Observed/350/243/205/351/245/260/345/231/250/345/222/214@ObjectLink/350/243/205/351/245/260/345/231/250/357/274/232/345/265/214/345/245/227/347/261/273/345/257/271/350/261/241/345/261/236/346/200/247/345/217/230/345/214/226.md +2089 -0
  161. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v1/@Prop/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/215/225/345/220/221/345/220/214/346/255/245.md +1033 -0
  162. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v1/@Provide/350/243/205/351/245/260/345/231/250/345/222/214@Consume/350/243/205/351/245/260/345/231/250/357/274/232/344/270/216/345/220/216/344/273/243/347/273/204/344/273/266/345/217/214/345/220/221/345/220/214/346/255/245.md +1183 -0
  163. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v1/@State/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/206/205/347/212/266/346/200/201.md +576 -0
  164. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v1/@Track/350/243/205/351/245/260/345/231/250/357/274/232class/345/257/271/350/261/241/345/261/236/346/200/247/347/272/247/346/233/264/346/226/260.md +297 -0
  165. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v1/@Watch/350/243/205/351/245/260/345/231/250/357/274/232/347/212/266/346/200/201/345/217/230/351/207/217/346/233/264/346/224/271/351/200/232/347/237/245.md +395 -0
  166. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v1/AppStorage/357/274/232/345/272/224/347/224/250/345/205/250/345/261/200/347/232/204UI/347/212/266/346/200/201/345/255/230/345/202/250.md +903 -0
  167. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v1/Environment/357/274/232/350/256/276/345/244/207/347/216/257/345/242/203/346/237/245/350/257/242.md +106 -0
  168. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v1/LocalStorage/357/274/232/351/241/265/351/235/242/347/272/247UI/347/212/266/346/200/201/345/255/230/345/202/250.md +1178 -0
  169. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v1/MVVM/346/250/241/345/274/217/357/274/210V1/357/274/211.md +911 -0
  170. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v1/PersistentStorage/357/274/232/346/214/201/344/271/205/345/214/226/345/255/230/345/202/250UI/347/212/266/346/200/201.md +355 -0
  171. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v1//347/256/241/347/220/206/345/272/224/347/224/250/346/213/245/346/234/211/347/232/204/347/212/266/346/200/201/346/246/202/350/277/260.md +11 -0
  172. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v2/!!/350/257/255/346/263/225/357/274/232/345/217/214/345/220/221/347/273/221/345/256/232.md +216 -0
  173. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v2/@Computed/350/243/205/351/245/260/345/231/250/357/274/232/350/256/241/347/256/227/345/261/236/346/200/247.md +442 -0
  174. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v2/@Event/350/243/205/351/245/260/345/231/250/357/274/232/350/247/204/350/214/203/347/273/204/344/273/266/350/276/223/345/207/272.md +169 -0
  175. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v2/@Local/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/206/205/351/203/250/347/212/266/346/200/201.md +763 -0
  176. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v2/@Monitor/350/243/205/351/245/260/345/231/250/357/274/232/347/212/266/346/200/201/345/217/230/351/207/217/344/277/256/346/224/271/345/274/202/346/255/245/347/233/221/345/220/254.md +2088 -0
  177. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v2/@ObservedV2/350/243/205/351/245/260/345/231/250/345/222/214@Trace/350/243/205/351/245/260/345/231/250/357/274/232/347/261/273/345/261/236/346/200/247/345/217/230/345/214/226/350/247/202/346/265/213.md +1258 -0
  178. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v2/@Once/357/274/232/345/210/235/345/247/213/345/214/226/345/220/214/346/255/245/344/270/200/346/254/241.md +175 -0
  179. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v2/@Param/357/274/232/347/273/204/344/273/266/345/244/226/351/203/250/350/276/223/345/205/245.md +850 -0
  180. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v2/@Provider/350/243/205/351/245/260/345/231/250/345/222/214@Consumer/350/243/205/351/245/260/345/231/250/357/274/232/350/267/250/347/273/204/344/273/266/345/261/202/347/272/247/345/217/214/345/220/221/345/220/214/346/255/245.md +862 -0
  181. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v2/@Type/350/243/205/351/245/260/345/231/250/357/274/232/346/240/207/350/256/260/347/261/273/345/261/236/346/200/247/347/232/204/347/261/273/345/236/213.md +110 -0
  182. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v2/AppStorageV2/357/274/232/345/272/224/347/224/250/345/205/250/345/261/200UI/347/212/266/346/200/201/345/255/230/345/202/250.md +301 -0
  183. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v2/MVVM/346/250/241/345/274/217/357/274/210V2/357/274/211.md +1411 -0
  184. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v2/PersistenceV2/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 +1392 -0
  185. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v2/getTarget/346/216/245/345/217/243/357/274/232/350/216/267/345/217/226/347/212/266/346/200/201/347/256/241/347/220/206/346/241/206/346/236/266/344/273/243/347/220/206/345/211/215/347/232/204/345/216/237/345/247/213/345/257/271/350/261/241.md +288 -0
  186. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v2/makeObserved/346/216/245/345/217/243/357/274/232/345/260/206/351/235/236/350/247/202/345/257/237/346/225/260/346/215/256/345/217/230/344/270/272/345/217/257/350/247/202/345/257/237/346/225/260/346/215/256.md +768 -0
  187. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v2//347/212/266/346/200/201/347/256/241/347/220/206V1/345/222/214V2/346/267/267/347/224/250/346/214/207/345/257/274/357/274/210API version 19/345/217/212/344/271/213/345/220/216/357/274/211.md" +829 -0
  188. package/skills/a2h-spec-implement/rules/arkts/official/mvvm-v2//347/212/266/346/200/201/347/256/241/347/220/206/346/246/202/350/277/260.md +184 -0
  189. package/skills/a2h-spec-implement/rules/arkts/ui/component-cookbook.md +431 -0
  190. package/skills/a2h-spec-implement/rules/arkts/ui/state-management.md +152 -0
  191. package/skills/a2h-spec-implement/rules/arkts/ui/ui-quality.md +67 -0
  192. package/skills/a2h-spec-implement/rules/arkts/ui/ui-runtime-diagnosis.md +32 -0
  193. package/skills/a2h-spec-implement/rules/pipeline/build/package-set-collection.md +43 -0
  194. package/skills/a2h-spec-implement/scripts/_lib/common.mjs +97 -0
  195. package/skills/a2h-spec-implement/scripts/_lib/config.mjs +70 -0
  196. package/skills/a2h-spec-implement/scripts/_lib/lessons_cli.mjs +48 -0
  197. package/skills/a2h-spec-implement/scripts/build_lessons.mjs +24 -0
  198. package/skills/a2h-spec-implement/scripts/code_pattern_lessons.mjs +26 -0
  199. package/skills/a2h-spec-implement/scripts/device_ui.mjs +433 -0
  200. package/skills/a2h-spec-implement/scripts/device_ui_core.mjs +895 -0
  201. package/skills/a2h-spec-implement/scripts/ledger/aggregate_run.mjs +207 -0
  202. package/skills/a2h-spec-implement/scripts/manifest/emit_summary_line.mjs +37 -0
  203. package/skills/a2h-spec-implement/scripts/manifest/finalize_run.mjs +115 -0
  204. package/skills/a2h-spec-implement/scripts/manifest/render_final_summary.mjs +78 -0
  205. package/skills/a2h-spec-implement/scripts/manifest/root_mirror.mjs +137 -0
  206. package/skills/a2h-spec-implement/scripts/package.json +12 -0
  207. package/skills/a2h-spec-implement/scripts/state_propagation_check.mjs +676 -0
  208. package/skills/a2h-spec-implement/scripts/test/l2_run.mjs +244 -0
  209. package/skills/a2h-spec-implement/scripts/test/tp_coverage.mjs +231 -0
  210. package/skills/a2h-spec-implement/scripts/ui_memory.mjs +161 -0
  211. package/skills/a2h-spec-implement/scripts/utils/ensure_app.mjs +134 -0
  212. package/skills/a2h-ui-transfer/SKILL.md +2 -2
  213. package/skills/hmos-convert-pipeline/SKILL.md +7 -5
  214. package/skills/hmos-incremental-ui-align/README.md +7 -7
  215. package/skills/hmos-incremental-ui-align/SKILL.md +1 -1
  216. package/skills/hmos-incremental-ui-align/page_align.md +1 -1
  217. package/skills/hmos-spec-generate/SKILL.md +2 -2
  218. package/skills/hmos-spec-generate/scripts/parse_requirements.mjs +537 -0
  219. package/skills/hmos-fix-build-errors/SKILL.md +0 -266
  220. package/skills/hmos-fix-build-errors/references/arkts-strict-patterns.md +0 -219
  221. package/skills/hmos-fix-build-errors/references/known-patterns.md +0 -157
  222. package/skills/hmos-fix-build-errors/references/rdb-entity-pattern.md +0 -131
  223. package/skills/hmos-spec-generate/scripts/parse_requirements.ts +0 -515
  224. /package/skills/{hmos-integration-test → a2h-integration-test}/scripts/resolve-metadata-tool.mjs +0 -0
  225. /package/skills/{hmos-integration-test → a2h-integration-test}/scripts/self-test-runner.mjs +0 -0
  226. /package/skills/{hmos-integration-test → a2h-integration-test}/scripts/testcases-tool.mjs +0 -0
@@ -0,0 +1,548 @@
1
+ ---
2
+ name: a2h-spec-implement
3
+ description: "迭代式迁移 Android项目代码 到 鸿蒙的转换流水线。触发词:'Android-to-HarmonyOS conversion'、'安卓功能迁移至鸿蒙',或任何将 Android 工程转换为 HarmonyOS 的请求。只允许在安卓迁移鸿蒙场景下调用,不适用于general场景的sdd开发。"
4
+ ---
5
+
6
+ # 技能信息
7
+
8
+ 从一个 Android 工程和一份需求规格出发,通过运行一个完整的流水线来交付 HarmonyOS 功能。先梳理出`SPEC`的交付场景清单;随后按实际开发验证结果进行多ROUND的开发验证迭代,直到实现清单中的功能场景。编码前的一次性接口预验(不确定的接口与 Android→HarmonyOS 能力映射)由 `skip_api_preverify` 控制,**默认跳过**。
9
+
10
+ ## 技能参数解析
11
+
12
+ - `android_project_dir`:Android 源工程路径(必填)。
13
+ - `harmony_project_dir`:目标 HarmonyOS 工程目录路径(必填)。
14
+ - `spec_file_path`:需求规格文档路径(必填)。
15
+ - `spec_design_file_path`:SPEC 编码设计文档路径(可选)。即 `a2h-spec-design` 技能产出的 `SPEC_name_design.md`,把本次实现钉在既定的模块归属、UI 文件、数据实体、数据库表、Preferences 键与逻辑模块上。传入时它是**绑定约束**,参与阶段1的场景梳理并透传给每一轮 `coder`;不传时各阶段按无约束运行(此时模块归属由 `coder` 自行推导)。
16
+ - `assets_output_path`:存放所有输出与报告文件的目录(可选)。默认为 `<harmony_project_dir>/.hometrans`;若不存在则创建。
17
+ - `test_case_path`:驱动轮内集成测试的自测用例文件路径(可选)。
18
+ - `pre_test_case_path`:前置测试用例文件(可选)。
19
+ - `max_rounds`:ROUND的最大上限(可选,默认 `10`)。
20
+ - `no_progress_rounds`:主要的卡死探测器 —— 连续 N 轮失败签名不变即判定 `no_progress` 并结束`ROUND`循环(可选,默认 `3`)。
21
+ - `skip_test`:`true` 或 `false`(可选,默认 `true`)。
22
+ - `run_l1_e2e`:`true` 或 `false`(可选,**默认 `false`**)。总开关,**同时决定 `coder` 的 L1/E2E 是否转写与执行**:默认 `false` 时 `coder` 既**不转写** `L1_*` / `E2E_*` 套件、也不执行 L1 单元测试(step3)与 E2E UI 测试(step5)—— 每轮只跑构建 / L0 / 评审。它与 `skip_test` 正交:`skip_test` 管的是编排器依据冻结 `TEST_CASE` 的集成测试(验收,步骤④.7),本项管的是 `coder` 的自测两层。为 `false` 时即使分配了设备也不跑 L1/E2E;为 `true` 时按原有逻辑转写并执行(仍受设备是否可用约束)。
23
+ - `skip_api_preverify`:`true` 或 `false`(可选,**默认 `true`**)。控制阶段 1.5 接口预验是否执行。默认 `true` 时整阶段跳过:不派发 `api-analyzer`,不产出 `API_DIR` / `API_INDEX`,`coder` 派发时省略 `api_dir` 行 —— 每一轮的接口查证由 `coder` 自行完成(`coder` 的 `api_dir` 是选填,缺失时照常自行查证,不阻塞)。为 `false` 时按阶段 1.5 的原有逻辑执行一次预验。**取舍**:跳过省下一次性的预验开销,代价是「猜 API」的成本从一次性付清变成每轮重付,`NO_EQUIVALENT`(HarmonyOS 侧无一对一等价物)这类会改变实现方式的结论要到 ROUND 深处才暴露。转换任务里 Android→HarmonyOS 能力映射不确定较多时,建议显式传 `false`。
24
+ - `run_spec_design`:`true` 或 `false`(可选,**默认 `false`**)。控制阶段 0.5 是否自动调用 `a2h-spec-design` 技能生成 `SPEC_DESIGN`。仅在**未显式传入 `spec_design_file_path`** 时生效 —— 显式传入者优先级最高,此时整个阶段 0.5 跳过。为 `true` 时编排器在场景梳理之前生成一次编码设计,把模块归属、UI 文件、数据实体、数据库表与 Preferences 键钉死;生成失败或前置文档缺失一律降级为 `SPEC_DESIGN = none` 并继续,**绝不中止流水线**(设计是约束不是输入源)。默认 `false` 是因为该技能硬依赖 `project_design.md`,而该文档由工程侧自行维护、并非本流水线的产物。
25
+
26
+ 如果用户没有显示传递某个参数,请理解用户的输入,并且提取对应参数的值
27
+
28
+ ## 技能中变量定义
29
+
30
+ | 变量 | 对应 |
31
+ | ----------------------- |----------------------------------------------------------------------------------------------------------------------|
32
+ | `ANDROID` | `android_project_dir` |
33
+ | `HMOS` | `harmony_project_dir` |
34
+ | `SPEC` | `spec_file_path` |
35
+ | `SPEC_DESIGN` | `spec_design_file_path` —— 为空时视为 `none`,所有引用它的地方整行省略,不传空值 |
36
+ | `RUN_SPEC_DESIGN` | `run_spec_design` —— 为空时按 `false` 处理(默认不自动生成 SPEC 编码设计) |
37
+ | `PROJECT_DESIGN` | 阶段 0.5 探测到的工程语义文档:`HMOS/.hometrans/project_design.md`,回退 `HMOS/project_design.md`;两处皆无时为 `none`,阶段 0.5 整体跳过。 |
38
+ | `OUTPUT` | `assets_output_path` |
39
+ | `TEST_CASE` | `test_case_path` |
40
+ | `PRE_TEST_CASE` | `pre_test_case_path` |
41
+ | `MAX_ROUNDS` | `max_rounds` |
42
+ | `NO_PROGRESS_ROUNDS` | `no_progress_rounds` |
43
+ | `SKIP_TEST` | `skip_test` |
44
+ | `RUN_L1_E2E` | `run_l1_e2e` —— 为空时按 `false` 处理(默认不执行 L1/E2E) |
45
+ | `SKIP_API_PREVERIFY` | `skip_api_preverify` —— 为空时按 `true` 处理(默认跳过阶段 1.5 接口预验) |
46
+ | `ROUND` | 包含代码开发,代码检视,测试,修复的一轮完整流程;一次运行会执行多个`ROUND`直到收敛或判定卡死 |
47
+ | `LEDGER` | `OUTPUT/convergence.jsonl` —— 结构化的质量信息统计。`build`、`unit`、`review`、`uitest`、`integration` 与 `fixer` 各环节都会向该文件追加行,作为终止判定的唯一依据。 |
48
+ | `SCENARIO_LIST` | `OUTPUT/logic/scenarios.json` —— 阶段1产出的交付场景清单(含被排除的 `[SKIP:]` 场景)。通过率分母以它为准。 |
49
+ | `MANIFEST` | `OUTPUT/pipeline-manifest.md` —— 进度跟踪、缺陷汇总与最终汇总统一落盘于此。 |
50
+ | `SKILL_DIR` | 本技能自身的目录(含 `scripts/`、`references/` 与 `rules/`)—— 本技能自有脚本一律以它为前缀。 |
51
+ | `DEVICE_POOL` | 环境检查探测到的可用设备序列号列表(已剔除 `Unauthorized`/`Offline`)。 |
52
+ | `DEVICE` | 本次运行独占的设备序列号,取自 `DEVICE_POOL`;无可用设备时为 `none`。 |
53
+ | `PLUGIN_DIR` | **等于 `SKILL_DIR`** —— 公共 `scripts/` 与 `rules/` 都随本技能目录发布。设备端 runner `scripts/test/l2_run.mjs` 依赖同级 `device_ui_core.mjs` 与 `_lib/`,`scripts/` 整棵树必须**整体移动、保持相对布局**,绝不单独摘出某个文件放到别处。派发 agent 时把本技能目录的绝对路径作为 `plugin_dir` 传下去 —— agent 无法自行推导它的位置。 |
54
+ | `MEMORY_DIR` | `OUTPUT/memory/` —— 操作记忆目录,存 `ui-flows.jsonl`(选择器与操作流记录),跨ROUND复用。 |
55
+ | `API_DIR` | `OUTPUT/memory/api/` —— 按接口存放实测用法示例,跨ROUND复用。**仅当 `SKIP_API_PREVERIFY == false` 时产出**。 |
56
+ | `API_INDEX` | `OUTPUT/api.md` —— 接口预验总表与阻塞门。**仅当 `SKIP_API_PREVERIFY == false` 时产出**。 |
57
+ | `DEVECO_HOME` | DevEco Studio本地安装路径 |
58
+ | `DEVECO_SDK_HOME` | 鸿蒙SDK路径,通常位于 <DEVECO_HOME>/sdk |
59
+ | `IS_GIT_REPO` | `HMOS` 是否为 git 工作树(预检探测,见「版本控制检测」)。为 `false` 时步骤③的 HEAD 校验、`BASELINE_COMMIT` 与步骤⑥的 diff 一并降级。 |
60
+
61
+ ---
62
+
63
+ # 技能执行流程
64
+
65
+ ## 环境检查
66
+
67
+ ### 参数获取
68
+
69
+ 只需获取两个 DevEco 路径变量。宿主(DevEco Code)已把它们注入每个 shell 会话,故先读环境变量(Windows PowerShell 用 `$env:VAR`,macOS 与 Linux 用 `echo "$VAR"`);读不到再查 `~/.hometrans/config.json`(monorepo 的 `ht init` 产物,纯插件安装下可能不存在);两处皆无或值无效则询问用户。
70
+
71
+ | 变量 | 对应config.json文件中配置参数 | 有效条件 |
72
+ | ------------------------- | ----------------------------------------- | -------------------------- |
73
+ | `DEVECO_HOME` | `env.DEVECO_HOME` / `env.DEVECO_SDK_HOME` | 该路径下存在 DevEco Studio安装后的文件 |
74
+ | `DEVECO_SDK_HOME` | `env.DEVECO_SDK_HOME` | 该路径下存在 鸿蒙SDK文件 |
75
+
76
+
77
+ ### 工具检查
78
+
79
+ **devecocli**:鸿蒙工程的构建 CLI。`coder` 每轮构建用的原生 `build_project` 工具底层就是它 —— 它不可用意味着**每一轮的构建都会失败**。
80
+
81
+ ```bash
82
+ devecocli --version
83
+ ```
84
+
85
+ 不可用 → **中止流水线**(不派发任何 agent),并提示:`npm i -g @deveco/deveco-cli`(需 DevEco Studio ≥ 6.1.0)。这是少数几个值得 fail-fast 的前置条件之一:让它在预检暴露,好过拖到第一轮构建时才炸、且此前已白跑掉场景梳理(以及接口预验,若其未被跳过)。
86
+
87
+ **codelinter** :用于对代码进行静态检查,检测语法,性能等缺陷。
88
+
89
+ - **codelinter 执行文件**
90
+
91
+ 检查文件`<DEVECO_HOME>/plugins/codelinter/run/index.js`存在,如果不存在则该工具不可用,后续跳过使用该工具的验证流程
92
+
93
+ - **codelinter 检查配置文件**
94
+
95
+ 检查文件 **`HMOS`/code-linter.json5** 存在,如果不存在则该工具不可用,后续跳过使用该工具的验证流程
96
+
97
+ 两者齐备时,`L0` 静态门禁可用(`coder` step2 执行);缺任一则该门禁整体跳过,并在 `MANIFEST` 记一条降级。
98
+
99
+ ### 设备检测
100
+
101
+ **唯一检测形式** —— 绝不手搓 `hdc` 解析:
102
+
103
+ ```bash
104
+ node PLUGIN_DIR/scripts/device_ui.mjs devices
105
+ ```
106
+
107
+ 输出形如 `{"ok":true,"devices":["<serial>\t<status>","..."],"count":N}`。
108
+
109
+ - 每项以 `\t` 分隔序列号与状态,**只接纳状态正常的设备**;`Unauthorized` / `Offline` 等一律剔除(它们连不上,会让整轮设备层白跑)。
110
+ - 把可用序列号列表记为 `DEVICE_POOL`。
111
+ - `DEVICE_POOL` 为空 —— **不中止流水线**:置 `SKIP_TEST=true` 继续(仅构建与评审层可跑),在 `MANIFEST` 记一条 `设备缺失: 全流程降级为跳过设备测试 —— 需人工复核`,并按阶段2 步骤⑤的规则把这些场景标注为自测收敛。
112
+ - 用户显式传了设备时,与本次探测结果取交集;交集为空按上一条处理。
113
+
114
+ **独占分配** —— 一台设备同一时刻只能归一个使用者(`coder` 的 step3/step5、编排器的集成测试、`app-action` 的诊断、`api-analyzer` 的实测——仅当阶段 1.5 执行时)。本次运行从 `DEVICE_POOL` 取一台记为 `DEVICE` 并全程独占;共享设备会让彼此的 `aa test` 互相杀掉前台应用,产生无法复现的假失败。
115
+
116
+ ### 版本控制检测
117
+
118
+ **鸿蒙工程不保证是 git 仓库** —— DevEco Code 新建的工程、以及用户直接打开的既有目录,都可能没有 `.git`。本流水线有三处依赖 git(步骤③的 HEAD 前进校验、`BASELINE_COMMIT`、步骤⑥的 diff),必须先探测,不能想当然:
119
+
120
+ ```bash
121
+ git -C HMOS rev-parse --is-inside-work-tree
122
+ ```
123
+
124
+ 输出 `true` → `IS_GIT_REPO = true`,三处按原有逻辑执行。命令报错或输出非 `true` → `IS_GIT_REPO = false`,向 `MANIFEST` 记一条 `版本控制缺失: HMOS 非 git 工作树 —— HEAD 校验与影响面 diff 降级,需人工复核` 并记入自主决策,随后:
125
+
126
+ - **步骤③** 去掉 HEAD 前进那一条,只核对 `round-notes.md` / `LEDGER` 新行 / `package-set/` 三项磁盘事实。
127
+ - **`BASELINE_COMMIT = none`**,`coder` 报的 `commit_id` 一律按 `none` 处理,`LEDGER` 的 `commit` 字段填 `none`。
128
+ - **步骤⑥** 直接走它自己的回退路径(所有此前通过的场景),不尝试 diff。
129
+
130
+ **不要为此 `git init`。** 工程是调用方的状态,替用户建仓库会把构建产物、`.hometrans/` 与 SDK 缓存一并纳入版本控制,且用户此后每次操作都要面对一个不是自己建的仓库。缺 git 只是失去「HEAD 动过」这一条证据,其余三项磁盘事实足以判定本轮是否落地 —— 这也正是完成度校验一开始就列了四项而非一项的原因。
131
+
132
+ **这一条不中止流水线。** 它与 `devecocli` 不同:`devecocli` 不可用意味着每轮构建必败,而缺 git 只是少一条校验与一次影响面收窄。
133
+
134
+ ---
135
+
136
+ ## 进度跟踪
137
+
138
+ 使用 `MANIFEST` 记录任务执行进度
139
+
140
+ 每个阶段开始前标记为 `in_progress`,结束后标记为 `completed`并记录该阶段执行的时间信息,使用`Round {r}` 的形式标记具体Round, 格式如下:
141
+
142
+ ```markdown
143
+ ## Duration Summary
144
+
145
+ | Phase / Round | Status | Start | End | Duration (H:MM:SS) |
146
+ |--------------|-------|-------|-----|--------------------|
147
+ | Phase 0 — Preflight | completed | 2026-07-22T10:00:00 | 2026-07-22T10:00:12 | 0:00:12 |
148
+ | Phase 0.5 — Spec Design | skipped | — | — | — |
149
+ | Phase 1 — Scenario Roster | in_progress | 2026-07-22T10:00:13 | ... | ... |
150
+ | Phase 1.5 — API Pre-verification | skipped | — | — | — |
151
+ | Round 1 | pending | ... | ... | ... |
152
+ | Round 2 | pending | ... | ... | ... |
153
+ | Phase 3 — Finalization | pending | ... | ... | ... |
154
+ | **TOTAL** | — | first start | last end | **H:MM:SS** |
155
+ ```
156
+
157
+ `Phase 0.5` 与 `Phase 1.5` 行按实际情况记录:命中各自的跳过条件时记 `skipped` 且三个时间列留 `—`(两者均默认跳过);执行时按普通阶段记 `in_progress` / `completed` 与时间。
158
+
159
+ ---
160
+
161
+ ## 缺陷跟踪
162
+
163
+ 产生的质量信息以固定json格式追加到 `LEDGER`。
164
+
165
+ ```json
166
+ {
167
+ "ts": "2026-07-22T10:15:03",
168
+ "round": 1,
169
+ "case_id": "scenario_3_1",
170
+ "source": "build | unit | review | uitest | integration | fixer",
171
+ "verdict": "PASS | FAIL | PARTIAL | BLOCKED | UNABLE_TO_VERIFY | ENV_FALSE_POSITIVE | RETRY | CONFIRMED_ENV_FALSE_POSITIVE",
172
+ "failing_point": "短标识 —— 例如 TP-2:progress_bar_value_mismatch、EXEC-GAP:step0_login_missing、BUILD:tsc_unresolved_import",
173
+ "root_cause": "短标识 —— 例如 missing_page_LoginActivity、wrong_state_reset_on_pause",
174
+ "class": "code | environment | fixture | selector_drift",
175
+ "commit": "commit hash |none",
176
+ "notes": "可选的一行人类可读说明"
177
+ }
178
+ ```
179
+ `ROUND`循环结束后,调用 `aggregate_run.mjs` 从`LEDGER`完成缺陷统计(缺陷数量、通过率等),输出缺陷汇总行(追加到 `MANIFEST`):
180
+ ```bash
181
+ node SKILL_DIR/scripts/ledger/aggregate_run.mjs --ledger LEDGER --scenarios SCENARIO_LIST --rounds {rounds_executed} --stop-reason {stop_reason}
182
+ ```
183
+ ### `MANIFEST` 中的缺陷汇总格式
184
+ ```markdown
185
+ Defect Summary
186
+
187
+ | Rounds | Terminal Passed | Defects Found | Defects Fixed | Remaining | Pass Rate (Q/O) | Stop Reason |
188
+ |--------|-----------------|---------------|---------------|-----------|-----------------|-------------|
189
+ | 3 | 4/6 | 3 | 2 | 1 | 80% / 67% | no_progress |
190
+ ```
191
+ 根据终止判断的逻辑,Stop Reason包含`all_passed`、`no_progress`、`no_confirmed_defects` 或 `max_rounds_reached` 4种
192
+
193
+ ---
194
+
195
+ ## 流水线执行
196
+
197
+ ### 阶段 0.5 —— SPEC 编码设计
198
+
199
+ 在梳理场景之前,先把「代码往哪里写」钉死:调用 `a2h-spec-design` 技能,从 `SPEC` 与工程语义文档产出 `SPEC_DESIGN`。它约束落地位置(模块归属、UI 文件、数据实体、数据库表、Preferences 键、逻辑模块),**不约束场景集合**。
200
+
201
+ **跳过条件(任一命中即整阶段跳过)** —— 命中时 `MANIFEST` 的 `Phase 0.5` 行记 `skipped` 并注明原因:
202
+
203
+ 1. `spec_design_file_path` 已显式传入 —— 用户给定的设计优先,不覆盖、不重算。此时 `SPEC_DESIGN` 保持传入值,无需记降级。
204
+ 2. `RUN_SPEC_DESIGN == false`(默认)—— `SPEC_DESIGN = none`,不记降级(这是显式选择,不是失败)。
205
+ 3. `PROJECT_DESIGN == none` —— `SPEC_DESIGN = none`,向 `MANIFEST` 记一条 `设计前置缺失: 未找到 project_design.md —— 模块归属由 coder 自行推导,需人工复核` 并记入自主决策。`a2h-spec-design` 缺该文档会 fail-fast,本流水线不允许因此中止,故在此提前判掉。
206
+
207
+ **① 幂等探测** —— 若 `OUTPUT/SPEC_DESIGN.md` 已存在,直接置 `SPEC_DESIGN = OUTPUT/SPEC_DESIGN.md` 并跳过后续步骤。该技能遇到同名输出会**立即停止并报已存在**,重跑流水线时不先探测就会白撞一次。
208
+
209
+ **② 探测 `PROJECT_DESIGN`** —— 按 `HMOS/.hometrans/project_design.md` → `HMOS/project_design.md` 的顺序取第一个存在的文件;两处皆无则按跳过条件 3 处理。
210
+
211
+ **③ 抽取 UI 操作序列** —— `ui_operation_sequence` 是该技能的必填位置参数。从 `SPEC` 的 `## UI序列` 章节取其正文单行,**原样传递,不改写、不翻译、不补全**(`a2h-spec-generate` 产出的 SPEC 必带该节)。`SPEC` 没有该节时,取 SPEC 标题行的 UI 路径;两者都取不到则按跳过条件 3 的方式降级跳过,不向用户弹窗阻塞。
212
+
213
+ **④ 派发 `spec-designer`** —— 经该包装器调用 `a2h-spec-design`,**不要直接调 `Skill`**:宿主的 `skill` 工具只收一个 `name`,没有参数字段,而该技能有三个必填位置参数。参数走派发 prompt,包装器在其隔离上下文里载入技能并绑定它们:
214
+
215
+ ```
216
+ Agent(
217
+ subagent_type="spec-designer",
218
+ prompt="target_directory: HMOS
219
+ input_file: SPEC
220
+ ui_operation_sequence: \"<ui_operation_sequence>\"
221
+ engine: homegraph
222
+ engine_mode: auto
223
+ output_file: OUTPUT/SPEC_DESIGN.md"
224
+ )
225
+ ```
226
+
227
+ 四处参数选择的理由:
228
+
229
+ - `target_directory` 传 `HMOS` 而非 `ANDROID`:该技能要求文件路径表的每一行都指向**真实存在**的文件,且模块粒度取自 `project_design.md` —— 它描述的是鸿蒙侧的落地位置。
230
+ - `output_file` 钉成 `OUTPUT/SPEC_DESIGN.md`:默认输出名是 `<SPEC 文件名>_design.md` 且落在 SPEC 所在目录,随 SPEC 命名漂移。钉死文件名后,阶段 0.5 的幂等探测与阶段 1/各轮 `coder` 的引用都有唯一路径。
231
+ - `engine_mode: auto`:引擎证据取不到时降级为本地分析而非报错,与本流水线「失败即降级」的取向一致。绝不传 `required`。
232
+ - `engine: homegraph` 是技能默认值,写出来是为了显式:`a2h-spec-design` 在 Step 6 取引擎证据用的是 `mcp__homegraph__*` **MCP 工具**,而本插件不注册任何 MCP server,**这些工具在 DevEco Code 里不存在**,所以这一路实际总是靠 `auto` 降级为本地分析。它不构成失败,也无需为此单独记降级 —— 但别把它误读为「引擎证据已生效」。(本流水线步骤⑥用的是 homegraph 的 **CLI** 形式,那一路可用;两者同名不同接口,别混。)
233
+
234
+ **⑤ 完成度校验** —— `OUTPUT/SPEC_DESIGN.md` 存在,且含 `## 相关 UI` / `## 相关数据` / `## 相关逻辑` / `## 当前SPEC生成的代码所从属的模块路径` 四节。满足则 `SPEC_DESIGN = OUTPUT/SPEC_DESIGN.md`。
235
+
236
+ 若同时存在伴生的 `OUTPUT/SPEC_DESIGN_issue.md`(该技能的输出校验产物),把它的问题原样摘入 `MANIFEST` 并记入自主决策,**不阻塞、不改写设计文件** —— 校验问题意味着这份约束可能不准,需人工复核,但不构成中止理由。
237
+
238
+ **⑥ 失败降级** —— `spec-designer` 报错或未返回、输出缺失、或四节校验不通过:置 `SPEC_DESIGN = none`,向 `MANIFEST` 记一条 `设计生成失败: <原因> —— 模块归属由 coder 自行推导,需人工复核` 并记入自主决策,继续进入阶段 1。**本阶段的任何失败都不中止流水线**,理由同 `## 错误处理` 中 `spec_design_file_path` 不可读的那一条:设计是约束不是输入源,缺了只是失去约束。
239
+
240
+ 包装器返回「已存在」时按步骤①处理(幂等命中,不是失败):置 `SPEC_DESIGN = OUTPUT/SPEC_DESIGN.md`,不重算、不覆盖。
241
+
242
+ **本阶段不写 `LEDGER`** —— 它不产出任何场景裁决。
243
+
244
+ ---
245
+
246
+ ### 阶段 1 —— 场景梳理
247
+
248
+ 从`SPEC`梳理出本次要交付的场景清单,并把不可验证的场景显式排除。**不拆分交付批次** —— `ROUND`循环一次交付清单里的全部场景。
249
+
250
+ #### 规则
251
+
252
+ - **`[SKIP: reason]` 场景排除出交付集** —— 它们在真机上不可观测验证(白盒 / 跨应用 / 前置不可达 / 工具不可驱动等)。不要漏记:为每个这类场景向 `LEDGER` 追加一行 `verdict=BLOCKED, class=environment, failing_point=SKIP:<reason>`,升级给人工。它们也不计入通过率的任何分母
253
+ - **建议交付顺序**:`[P0]` 主路径先于 `[P1]`/`[P2]`,优先级取自 `TEST_CASE` 中每个场景必带的 `[PX]` 标签;场景引用了其他场景产物的排在后面,基础层(数据模型与持久化)先于其消费方。全部场景同轮交付,故该顺序不改变执行,只写入 `notes` 供人工阅读与 `coder` 参考
254
+ - **`SPEC_DESIGN != none` 时,先读它**:它的 `## 相关 UI` / `## 相关数据` / `## 相关逻辑` 三张文件路径表给出了本 SPEC 会落地的文件集合,`## 当前SPEC生成的代码所从属的模块路径` 给出模块归属。它约束的是**去哪里写**,不是场景集合 —— 不得据它增删任何场景
255
+ - 只阅读`SPEC`(以及 `SPEC_DESIGN`)与确认场景清单所必需的代码;不决定任何场景如何实现
256
+ - 绝不漏掉场景:每个场景要么进入 `scenarios`,要么进入 `skipped` 且有对应的 `LEDGER` 行,二者合计覆盖 `SPEC` 全集
257
+
258
+ #### 输出
259
+
260
+ 将场景清单输出到 `SCENARIO_LIST`(单个 JSON 对象):
261
+ ```json
262
+ {
263
+ "scenarios": ["scenario_1_1", "scenario_1_2"],
264
+ "skipped": [{ "case_id": "scenario_2_3", "reason": "cross_app" }],
265
+ "notes": "建议顺序:P0 主路径 scenario_1_1 先于边缘变体 scenario_1_2"
266
+ }
267
+ ```
268
+
269
+ 字段说明:
270
+ - `scenarios` —— 本次交付的场景id,即首轮的 `ROUND_SCENARIOS`
271
+ - `skipped` —— 被 `[SKIP:]` 排除的场景及其原因;每一项都必须有对应的 `LEDGER` 行
272
+ - `notes` —— 建议交付顺序与分组依据(共享页面 / 模块),供人工阅读
273
+
274
+ ---
275
+
276
+ ### 阶段 1.5 —— 接口预验
277
+
278
+ **跳过条件** —— `SKIP_API_PREVERIFY == true`(默认)时整阶段跳过:不派发 `api-analyzer`,不创建 `API_DIR` / `API_INDEX`,`MANIFEST` 的 `Phase 1.5` 行记 `skipped`,并向自主决策记一条 `接口预验已跳过: 接口查证下沉到每轮 coder —— 需人工复核`。直接进入阶段 2;`coder` 派发块按下述规则省略 `api_dir` 行。本阶段的其余内容仅在 `SKIP_API_PREVERIFY == false` 时适用。
279
+
280
+ 在任何编码开始之前,把「猜 API」的成本一次性付清。**整条流水线只执行一次**,产出被后续所有ROUND的 `coder` 复用 —— 放进 `coder` 里就变成每轮重付,失去意义。
281
+
282
+ Android→HarmonyOS 转换的主要返工来源是**能力映射猜错**:Android 侧的某个能力在 HarmonyOS 侧对应哪个 API 不确定,甚至没有一对一等价物。这类错误只会在设备测试阶段、用例深处才暴露。
283
+
284
+ ```
285
+ Agent(
286
+ subagent_type="api-analyzer",
287
+ prompt="android_project_dir: ANDROID
288
+ harmony_project_dir: HMOS
289
+ spec_path: SPEC
290
+ test_case_path: TEST_CASE
291
+ api_dir: API_DIR
292
+ api_index: API_INDEX
293
+ backend: {人工给定的可达后端,缺失则留空}
294
+ device: DEVICE"
295
+ )
296
+ ```
297
+
298
+ **完成度校验** —— `API_INDEX` 存在;每个入选接口在 `API_DIR` 下有对应条目。不满足则记录并继续(本阶段失败不中止流水线)。
299
+
300
+ **阻塞门** —— 读取 `API_INDEX` 的 `## 阻塞门` 章节:
301
+
302
+ - 有场景依赖了 `status=BLOCKED` 的接口 → 流水线照常启动,但把该阻塞写入首轮的 `prior_attempts`,让 `coder` 知道这里不能凭空装配(`api-analyzer` 已明令:调不通的接口不许伪造调用)。若这些场景最终因此失败,其停止原因如实记为依赖阻塞,不算代码缺陷。
303
+ - 某接口 `status=NO_EQUIVALENT` → 这会改变场景的实现方式。把该结论写入首轮 `prior_attempts`,并记入自主决策供人工复核。
304
+ - **阻塞门不中止流水线**,只改变输入与记录。
305
+
306
+ 若待验列表为空(`API_INDEX` 只有一行「无需提前验证的接口」),本阶段零成本通过。
307
+
308
+ ---
309
+
310
+ ### 阶段 2 —— ROUND执行
311
+
312
+ 对 `SCENARIO_LIST` 的全部交付场景运行 `ROUND` 循环,直到四态终止判定给出 `stop_reason`。
313
+
314
+ **`ROUND` 循环归编排器所有。** `coder` 只执行一轮;`ROUND` 推进、终止判定、下一轮回归集合的选择,全部在本阶段完成,`coder` 不参与。
315
+
316
+ #### 运行初始化
317
+
318
+ - 读 `SCENARIO_LIST`:`{scenarios}` 是其 `scenarios` 字段。
319
+ - 重置:`round = 1`、`rounds_executed = 0`、`stop_reason = none`。
320
+ - 重置签名连续计数:`last_signature = none`、`signature_repeat_count = 0`。
321
+ - 设置 `LAST_GOOD_PACKAGE_SET = none` —— 最近一次成功构建产出的 `package-set/`。
322
+ - 从 `DEVICE_POOL` 取一台设备记为 `DEVICE`,本次运行全程独占,收尾时归还;池空则 `DEVICE = none`(设备层按 `SKIP_TEST=true` 处理)。
323
+ - 设置 `BASELINE_COMMIT` —— 回归集合选择用它做 diff 起点。`IS_GIT_REPO == true` 时取 `git -C HMOS rev-parse --short HEAD`;否则为 `none`。
324
+ - 设置 `ROUND_SCENARIOS = {scenarios}` —— 第 1 轮交付全部场景。
325
+ - 将该任务标记为 `in_progress`。
326
+
327
+ #### ROUND 循环
328
+
329
+ 每一轮按下列顺序执行。每条质量信号由 `coder` 在产生时即写入 `LEDGER`。
330
+
331
+ **① 建 `ROUND` 目录** —— `ROUND_DIR = OUTPUT/round-{round}/`,递增 `rounds_executed`。`IS_GIT_REPO == true` 时记录 `PRE_SPAWN_HEAD = git -C HMOS rev-parse --short HEAD`;否则 `PRE_SPAWN_HEAD = none`(步骤③相应少一条校验)。
332
+
333
+ **② 调用 `coder`** —— 参数逐项对齐 `agents/coder.md` 的输入表;`prior_attempts` 与 `failure_evidence` 仅在 `rounds_executed > 1` 时传入;`spec_design` 仅在 `SPEC_DESIGN != none` 时给出该行,为空时整行省略(不传空值)。`api_dir` 同理 —— 仅在阶段 1.5 实际执行(`SKIP_API_PREVERIFY == false`)时给出该行;跳过预验时整行省略,不传空值(`coder` 的 `api_dir` 是选填,缺失时它照常自行查证接口,不因此阻塞)。
334
+
335
+ ```
336
+ Agent(
337
+ subagent_type="coder",
338
+ prompt="harmony_project_dir: HMOS
339
+ spec_path: SPEC
340
+ spec_design: SPEC_DESIGN
341
+ scenarios: ROUND_SCENARIOS
342
+ ledger: LEDGER
343
+ round_dir: ROUND_DIR
344
+ round: {round}
345
+ api_dir: API_DIR
346
+ memory_dir: MEMORY_DIR
347
+ plugin_dir: PLUGIN_DIR
348
+ device: DEVICE
349
+ deveco_home: DEVECO_HOME
350
+ test_case: TEST_CASE
351
+ run_l1_e2e: RUN_L1_E2E
352
+ prior_attempts: {LEDGER 中先前 fixer 行的摘要,每条带 commit}
353
+ failure_evidence: {上一轮的UI测试与集成测试失败,附报告路径}"
354
+ )
355
+ ```
356
+
357
+ **③ 完成度客观校验** —— 绝不轻信 agent 口头返回的「已完成」。一次中途断连会让 agent 返回却没有落地任何工作。`coder` 返回后,在推进本轮之前逐项核对磁盘事实:
358
+
359
+ - **(仅 `IS_GIT_REPO == true`)**`git -C HMOS rev-parse --short HEAD` 相对 `PRE_SPAWN_HEAD` 已前进 —— 若 `coder` 报了 `commit_id` 而 HEAD 未动,是幽灵提交,按剩余工作重新派发(带上 `prior_attempts`),绝不在其上继续推进。`IS_GIT_REPO == false` 时**跳过本条**:非 git 工作树里 `git rev-parse` 必然报错,把它当作「HEAD 未前进」会让每一轮都被误判为未完成、无休止重新派发同一份已经落地的工作,一路空烧到 `max_rounds_reached`。
360
+ - `ROUND_DIR/round-notes.md` 已写出。
361
+ - `LEDGER` 中出现了本轮(`round={round}`)的新行。
362
+ - 构建成功时 `ROUND_DIR/package-set/` 存在且非空。
363
+ - 任一项不满足 —— 把缺失事实记入 `ROUND_DIR/verify-failure.md`,本轮按未完成处理。
364
+
365
+ **④ 更新最近成功包集合** —— 若 `ROUND_DIR/package-set/` 存在且非空,则 `LAST_GOOD_PACKAGE_SET = ROUND_DIR/package-set/`;否则保持原值。
366
+
367
+ **④.5 执行缺口修复路由** —— 扫本轮 `LEDGER` 中 `failing_point` 以 `EXEC-GAP:` 开头的行(操作没生效,而非结果不符)。这类失败**不能靠再开一轮解决** —— `coder` 手里的信息和上一轮完全相同,只会再猜一次选择器。必须先到设备上取得新信息。
368
+
369
+ 对每条这样的场景(`DEVICE != none` 时):
370
+
371
+ ```
372
+ Agent(
373
+ subagent_type="app-action",
374
+ prompt="task: {该场景在 TEST_CASE 中的 ### Scenario 块}
375
+ capture_list: {按该用例的判定锚点逐行给出,一趟抓齐}
376
+ harmony_project_dir: HMOS
377
+ output_dir: ROUND_DIR/gap/{case_id}
378
+ memory_dir: MEMORY_DIR
379
+ device: DEVICE
380
+ plugin_dir: PLUGIN_DIR
381
+ hap_path: ROUND_DIR/package-set/"
382
+ )
383
+ ```
384
+
385
+ **完成度校验** —— `ROUND_DIR/gap/{case_id}/observations.json` 存在且带 `execution-status`;否则记录并按未诊断处理。
386
+
387
+ 按其 `diagnosis` 分流:
388
+
389
+ - `selector_drift` —— 修正已由 `app-action` 写回 `MEMORY_DIR/ui-flows.jsonl`。**不需要改应用代码**:下一轮把该场景放进 `ROUND_SCENARIOS`,`coder` 会从修正后的记录重新派生套件(step1 选择器来源第 1 条)。
390
+ - `app_defect` —— 选择器没问题,是应用真的没渲染 / 没响应。把 `observations.json` 路径并入下一轮的 `failure_evidence`,走正常的代码修复。
391
+ - `inconclusive` —— 两次修正重试仍未判明。记入自主决策供人工复核;该场景本次运行不再重复派发诊断,避免空转。
392
+
393
+ `DEVICE = none` 时跳过本步,`EXEC-GAP` 场景保持原样。**本步不写 `LEDGER`** —— 诊断不是场景裁决。
394
+
395
+ **④.7 集成测试(验收)** —— 由**编排器自己执行**,不交给 `coder`。这是全流水线唯一依据冻结 `TEST_CASE` 的验收:写代码的 agent 不能自己发起、自己读报告、自己写结论,否则前面建立的写/判分离在这一层失效。
396
+
397
+ **跳过条件** —— `SKIP_TEST=true`、`TEST_CASE` 缺失、`DEVICE = none`、或 `ROUND_DIR/package-set/` 不存在。跳过时为本轮每个场景追加一行:
398
+ `source=integration, verdict=UNABLE_TO_VERIFY, failing_point=SKIP:<no_device|no_test_case|no_package_set>, class=environment`。
399
+
400
+ 否则派发 `self-tester`(**它用 kebab-case 参数**),由它在隔离上下文里载入并执行 `a2h-integration-test`:
401
+
402
+ ```
403
+ Agent(
404
+ subagent_type="self-tester",
405
+ prompt="test-case-path: TEST_CASE
406
+ hap-path: ROUND_DIR/package-set/
407
+ output-path: ROUND_DIR
408
+ project-dir: HMOS
409
+ pre-test-case-path: PRE_TEST_CASE"
410
+ )
411
+ ```
412
+
413
+ 三条硬约束:
414
+
415
+ - **必须经 `self-tester` 包装器,不要直接调 `Skill`。** 宿主的 `skill` 工具只收一个 `name`,没有参数字段 —— 直接调等于一个参数都传不进去,该技能会退回它自己的默认值。这里最致命的是 `max-rounds`:它自带 test-and-fix 循环,默认 `3`,于是在 `ROUND` 之内再套一层循环,`ROUND` 归属失控、`LEDGER` 的 `round` 对不上。包装器**本身就是单趟**(它不转发 `max-rounds`,也不驱动修复循环),所以无需再传 `max-rounds: 1` —— 单趟这件事由包装器的契约保证,不靠传参。
416
+ - **不传 `android-project-path`。** 它只服务于该技能的修复循环,而这一路根本不跑修复循环(见下段「验收 FAIL 不在本轮修」)。包装器也不转发它。
417
+ - **必填参数一个都不能少。** `test-case-path` / `hap-path` / `output-path` 缺一不可。包装器跑在子代理里,**够不到用户**,缺参既问不出来也弹不了窗:要么被它按自身规则从 `hap-path` 反推(`project-dir` 可以,其余不行),要么直接失败。宁可按跳过条件判定为跳过,也不要用不完整参数派发。`project-dir` 显式传 `HMOS` 而不依赖反推 —— 反推是从 `hap-path` 往上找含 `AppScope/app.json5` 的目录,多模块工程里可能找歪。
418
+
419
+ **包装器与技能都不写 `LEDGER`**,只产出 `ROUND_DIR/self-test-report.md`。由编排器读该报告写 `LEDGER` 行 —— **以报告文件为准,不以包装器的返回文本为准**(它返回的是终态摘要与路径,不是裁决)。**必须先判 sentinel,再解析用例表**:
420
+
421
+ 1. **sentinel 检查(先做)** —— 用 `Read` 读 `ROUND_DIR/self-test-report.md` 的开头(`limit: 10` 足够,哨兵报告的 `status:` / `reason:` 就在最前几行),从中取这两行。**不要用 `grep -m1 -E`**:Windows 上会话 shell 是 PowerShell,POSIX `grep` 那套写法不通,而这一步判的是「环境早退还是应用缺陷」,判不出就会把早退误算成场景 FAIL。确实要走 shell 时按平台分写 —— PowerShell 用 `Select-String -Pattern '^status:' -Path ... | Select-Object -First 1`,POSIX 用 `grep -m1 -E`。
422
+
423
+ 首行为 `status: FAIL` —— 这是**降级哨兵报告**,表示测试在渲染用例表之前就早退了(环境 / 连通性 / API 版本不匹配等),**没有用例表可解析**。为每个场景追加:
424
+ `source=integration, verdict=UNABLE_TO_VERIFY, failing_point=EARLY-EXIT:<reason 短标识>, class=environment`。
425
+ **绝不因此判任何场景 FAIL** —— 早退不是应用缺陷。
426
+
427
+ 2. **正常用例表** —— `## 用例详情` 下的 `### Case N:` 逐条映射;`## 前置用例` 下的 `### Pre N:`(`case_name` 以 `[PRE] ` 开头)是**前置夹具不是场景**,不为它们写场景行:
428
+
429
+ | 报告状态 | `LEDGER` 行 |
430
+ |---|---|
431
+ | `PASS` | `source=integration, verdict=PASS, class=code` |
432
+ | `FAIL` | `source=integration, verdict=FAIL, failing_point=<用例失败点短标识>, class=code`(`reason` 指明是超时/崩溃则据实填) |
433
+ | `UNKNOWN` | `source=integration, verdict=UNABLE_TO_VERIFY, failing_point=BADGE-UNKNOWN, class=environment` —— 徽标判不出属于**证据缺口**,不是已确认缺陷,绝不当 FAIL 计入 |
434
+
435
+ 某条**前置用例**失败 → 依赖它的场景记 `verdict=BLOCKED, class=fixture, failing_point=PRE-BLOCK:<pre_case_name>`,而不是 FAIL。
436
+
437
+ **验收 FAIL 不在本轮修。** `coder` 的轮内修复预算只覆盖它自己那几层(构建 / L0 / L1 / 评审 / UI测试)。集成测试跑在交付之后,真 FAIL 直接结束本轮,由下一轮的 `coder` 带着 `failure_evidence` 修 —— 这里**不要**再开第二个修复循环。
438
+
439
+ **⑤ 四态终止判定** —— 只读取本轮的 `LEDGER` 行。
440
+
441
+ **写与判分离:** `coder` 写入的是各层**证据信号**,不是终态裁决;场景的终态裁决在这里推导,推导规则固定,不因 `coder` 的措辞或返回文本而改变。当 `coder` 的返回与 `LEDGER` 行冲突时,以 `LEDGER` 为准。
442
+
443
+ - 每个场景取**时间最新**的那条非 fixer 行作为终态裁决;同一时刻并列时,按来源优先级 `integration(3) > uitest(2) > unit(1) > review(0)` 取高者(`build` 与未知来源按 0 处理)。此规则与 `aggregate_run.mjs` 的实现严格一致 —— 两边分歧会导致轮内判定与最终统计对不上。
444
+ - **忽略所有 `source=fixer` 的行** —— 它们描述修复器做了什么,不是场景状态。
445
+ - **跳过 `class=environment` 的行** —— 环境误报不计入缺陷总数,不延长 `no_progress` 连续计数,也不阻塞终止判定。
446
+ - **`PARTIAL` 不算绿** —— 只有 PASS 视为满足。
447
+
448
+ **验收载体的强弱要分清。** `integration`(步骤④.7,编排器执行)依据冻结的 `TEST_CASE` 判定,是**验收**;`uitest`(`coder` step5,当 `run_l1_e2e=true` 时)的套件由 `coder` 自己转写,是**交付达标线**。判据是机械的:`aggregate_run.mjs` 输出的 `per_case[].last_source` 即该场景的胜出来源。当某场景 `terminal_verdict=PASS` 而 `last_source != integration`(典型情况:`SKIP_TEST=true`,或 `run_l1_e2e=false` 导致无 `uitest` 层,或未发现设备导致步骤④.7 跳过),该场景的"通过"仅由自测证明或无自测证明:
449
+
450
+ - 照常参与四态判定,不阻塞收敛。
451
+ - 但必须在 `MANIFEST` 的自主决策章节记录一条:`自测收敛: 场景 {case_ids} 仅通过自转写套件验证,未经 TEST_CASE 验收 —— 需人工复核`。
452
+ - 阶段3 的最终汇总中,这些场景在通过率旁标注 `(self-test only)`,不与经验收的通过混计。
453
+
454
+ 按顺序评估这四种状态:
455
+
456
+ 1. **`all_passed`** —— 每个场景都是 PASS。设 `stop_reason = all_passed`,退出循环。
457
+ 2. **`no_confirmed_defects`** —— 没有任何场景是 `class=code` 的 FAIL / PARTIAL / BLOCKED;所有非 PASS 项要么是 `ENV_FALSE_POSITIVE`,要么是纯环境性的 `UNABLE_TO_VERIFY`。设 `stop_reason = no_confirmed_defects` 并退出 —— 既然没有代码缺陷,再来一轮只会重复同样的结果。
458
+ 3. **`no_progress`** —— 构造本轮签名:对每个非 PASS 且 **`class != environment`** 的场景(即 `code` / `fixture` / `selector_drift` 都计入),取 `failing_point|root_cause` 组成排序后的元组。`environment` 是唯一不计入的类别 —— 与缺陷统计口径一致。把 `fixture` 计入是必要的:经步骤④.5 诊断仍为 `inconclusive` 的执行缺口,症状会轮轮不变,只有计入签名才能被识别为卡死并及时退出,否则它既不算缺陷、又拿不到 PASS,会把轮次预算空烧到 `max_rounds_reached`。若它等于 `last_signature`,则递增 `signature_repeat_count`;否则置为 1 并更新 `last_signature`。任一属性发生变化,连续计数即停止。当 `signature_repeat_count >= NO_PROGRESS_ROUNDS` 时,设 `stop_reason = no_progress` 并退出。
459
+ 4. **`max_rounds_reached`** —— 若 `round == MAX_ROUNDS`,设 `stop_reason = max_rounds_reached` 并退出。
460
+ 5. **否则** —— 进入步骤 ⑥,`round += 1`,回到步骤 ①。
461
+
462
+ **⑥ 选择下一轮的回归集合** —— 将本轮 HEAD 与 `BASELINE_COMMIT` 做 diff(`git -C HMOS diff BASELINE_COMMIT..HEAD --name-only`)。对变更的符号用 **homegraph CLI** 查影响面,与 `a2h-code-review` 的调用形式一致:
463
+
464
+ ```bash
465
+ npx -y homegraph impact <symbol> -p HMOS -j
466
+ npx -y homegraph callers <symbol> -p HMOS -j
467
+ ```
468
+
469
+ 工程路径是 `-p` / `--path`(**不是** `--project`),`-j` 让输出为 JSON 便于解析;两条命令的 `<symbol>` 都是位置参数。不确定时先 `npx -y homegraph <cmd> --help` 查一次,别猜 —— 猜错的选项在这套 CLI 里是直接报错,不是静默回退。
470
+
471
+ `ROUND_SCENARIOS` = 本轮未 PASS 的场景 ∪ 受影响且此前已通过的场景。
472
+
473
+ **用 CLI,不要用 `mcp__homegraph__*` 工具。** 本插件不注册任何 MCP server(`src/index.ts` 的 `tool` hook 只暴露 `a2h_app_feature_verify` / `a2h_self_test` / `a2h_self_test_status`),那些 `mcp__homegraph__*` 名字在 DevEco Code 里根本不存在,调用即失败并白走一次回退。CLI 这一路则由 `npx -y` 保证可用:本地没有就现拉最新版。首次查询前需确保索引存在 —— 按 `a2h-code-review` Step 2 的规则先 `npx -y homegraph status HMOS`,未索引则 `npx -y homegraph init -i HMOS`,索引过期则 `npx -y homegraph sync HMOS`;`init` / `sync` / `index` 一律显式传 `timeout: 600000`(10 分钟),别依赖 Bash 工具的隐式默认值。
474
+
475
+ **回退** —— `IS_GIT_REPO == false`(拿不到 diff 起点)、`npx` 不可用或离线拉包失败、索引超时、或查询无有效输出:退化为所有此前通过的场景,并把该降级记入自主决策。回退只是让回归集合变大(多跑几个已通过场景),不影响正确性。
476
+
477
+ #### ROUND循环收尾
478
+
479
+ `ROUND` 循环退出后,运行 `finalize_run.mjs` 聚合缺陷统计并写出汇总行。
480
+
481
+ ```bash
482
+ node SKILL_DIR/scripts/manifest/finalize_run.mjs --output OUTPUT --ledger LEDGER --scenarios SCENARIO_LIST --rounds {rounds_executed} --stop-reason {stop_reason} --max-rounds {MAX_ROUNDS}
483
+ ```
484
+
485
+ 当 `stdout.ok=true`:把 `stdout.defect_row` 追加到 `MANIFEST` 的 Defect Summary,用 `stdout.summary_line` 更新任务描述,并通过 `TodoWrite` 标记为 `completed`。当 `stdout.ok=false`(缺陷统计不变式被破坏):脚本已写出 `OUTPUT/finalize-failure.md`,记录该失败并仍然标记为完成。`no_progress` 与 `max_rounds_reached` 是终止状态,不是错误。
486
+
487
+ 产物镜像(最后一轮的报告、最近一次成功的 HAP 集合)统一由阶段3 的 `root_mirror.mjs` 完成 —— 它直接从 `OUTPUT/round-*/` 取数,本步不再重复搬一次。
488
+
489
+ ---
490
+
491
+ ### 阶段 3 —— 收尾
492
+
493
+ 在 `ROUND` 循环收尾之后:
494
+
495
+ 1. 缺陷与通过率总计已由 `ROUND` 循环收尾的 `finalize_run.mjs` 写入 `OUTPUT/aggregates/run-total.json`;本步直接读取它,把缺陷汇总行写入 `MANIFEST`,不重复聚合。
496
+
497
+ 2. **根目录镜像** —— 调用 `root_mirror.mjs`,把规范产物拷到 `OUTPUT/` 根目录以保持向后兼容。该脚本镜像:
498
+ - `OUTPUT/code-review-report.md` ← 含该文件的最后一轮的 `code-review-report.md`。
499
+ - `OUTPUT/self-test-report.md` + `OUTPUT/self-test-fix-report.md` ← 对应的最后一轮文件(若存在)。
500
+ - `OUTPUT/package-set/` ← `package-set/` 非空的最后一轮(先清空再拷贝)。若源与目标相同则跳过。若从未构建成功,则保持 `OUTPUT/package-set/` 原样不动。
501
+ - `OUTPUT/entry-default-signed.hap`(未签名工程为 `OUTPUT/entry-default-unsigned.hap`)← 尽力拷贝 `OUTPUT/package-set/` 中那个唯一的 `entry-*.hap`,供旧有消费方使用。镜像名如实反映产物的签名状态:未签名产物**不会**被拷成 `-signed` 名,否则消费方拿到的是名字承诺可安装、内容却装不上的文件。
502
+
503
+ ```bash
504
+ node SKILL_DIR/scripts/manifest/root_mirror.mjs --output OUTPUT
505
+ ```
506
+
507
+ 3. **自主决策摘要** —— 依据所有记录在案的自主决策(预检降级、**SPEC 编码设计的跳过或降级**、**`HMOS` 非 git 工作树导致的 HEAD 校验与 diff 降级**、场景梳理回退、homegraph 回退式回归选择、环境误报判定、**自测收敛的场景**、**转写缺陷订正**、**接口预验的跳过、或其后端假设与 `NO_EQUIVALENT` 取舍**)撰写 `## 自主决策记录(待人工复核纠正)` 章节。其中"仅经自测通过、未经 `TEST_CASE` 验收"的场景必须逐条列出 —— 这是本流水线最需要人工复核的一类结论。
508
+ 4. **最终汇总** —— 调用 `render_final_summary.mjs`,向用户打印最终流水线汇总并写入 `MANIFEST`。
509
+
510
+ ```bash
511
+ node SKILL_DIR/scripts/manifest/render_final_summary.mjs \
512
+ --stop-reason {stop_reason} \
513
+ --rounds {rounds_executed} \
514
+ --max-rounds {MAX_ROUNDS} \
515
+ --skip-test-auto {true|false}
516
+ ```
517
+
518
+ 将 `stdout.summary_text` 打印给用户,并把 `stdout.summary_markdown` 追加到 `MANIFEST`。
519
+
520
+ ---
521
+
522
+ ## 错误处理
523
+
524
+ - **只有四种情况会中止流水线。** 其中三种在阶段 1 之前检查:必填参数缺失或格式错误、`DEVECO_HOME` 无法解析、`devecocli` 不可用。第四种是阶段 1 之后 `SCENARIO_LIST` 缺失。
525
+ - **模型 apiKey 不再是中止条件。** 它由宿主解析并经 stdin 注入,编排器在预检期无从判断其有效性(见「参数获取」)。缺失时步骤④.7 的 `a2h_self_test` 会明确报错,按 `a2h-integration-test` 的 Step 0 提示用户配置即可 —— 那属于该场景的 `UNABLE_TO_VERIFY`,不是流水线中止理由。
526
+ - **`HMOS` 非 git 工作树不中止流水线。** 按「版本控制检测」置 `IS_GIT_REPO = false` 并降级三处 git 用法。
527
+ - **其余所有失败都转化为一条 `LEDGER` 记录和一个停止原因。** 签名重建失败、UI 测试场景持续 `BLOCKED`、设备不可达、homegraph 不可用、场景梳理失败、**接口预验失败或接口 `BLOCKED`**(预验被跳过时本项不适用) —— 这些都不会中止流水线。每一项都降级到其既定回退方案并继续执行。
528
+ - **`spec_design_file_path` 传了但不可读,不中止流水线。** 置 `SPEC_DESIGN = none`,在 `MANIFEST` 记一条 `设计约束缺失: <路径> 不可读 —— 模块归属由 coder 自行推导,需人工复核`,并记入自主决策。它是约束不是输入源,缺了只是失去约束,不影响流水线跑通。
529
+ - **阶段 0.5 的一切失败都不中止流水线。** `project_design.md` 缺失、`## UI序列` 抽不到、`spec-designer` 报错或未返回、输出缺失或四节校验不通过 —— 一律置 `SPEC_DESIGN = none`、记 `MANIFEST` 降级与自主决策后继续。理由同上条。特别地,`a2h-spec-design` 自身对缺失 `project_design.md` 是 fail-fast 的,本流水线**不继承**该行为:阶段 0.5 在派发前先探测,探测不到就不派发。
530
+ - **`LEDGER` 是终止判定与缺陷计数的权威来源。** 当 Markdown 报告与 `LEDGER` 行冲突时,以 `LEDGER` 为准。要修的是写出错误行的那个 agent。绝不能通过重新解析散文报告来「订正」`LEDGER`。
531
+ - **绝不伪造 `LEDGER` 行。** 编排器只为自己直接掌握的信号写 `LEDGER` 行:阶段1 排除的 `[SKIP:]` 场景,以及步骤④.7 集成测试(验收)的裁决。凡是源自构建输出、评审、单元测试或 UI 测试的场景裁决,都只能由 `coder` 在对应步骤中产出。
532
+
533
+ ---
534
+
535
+ ## 职责边界
536
+
537
+ - **编排器(本技能)拥有:** 环境检查、**SPEC 编码设计的派发与降级(阶段 0.5)**、场景梳理、接口预验的派发与阻塞门(当 `SKIP_API_PREVERIFY == false`)、`ROUND`循环推进、**集成测试(验收)及其 `LEDGER` 行**、执行缺口修复路由、四态终止判定、回归集合选择、agent 完成度校验、`ROUND`循环收尾与流水线收尾、`[SKIP:]` 场景的 `LEDGER` 行。
538
+ - **`app-action` 拥有:** 交互式设备操作与 `ui-flows.jsonl` 记忆;被派发去诊断 `EXEC-GAP`,判明选择器漂移还是应用缺陷并修正记录。**只抓取不判定**,不写 `LEDGER`。
539
+ - **`api-analyzer` 拥有:** 全流水线**一次**的接口分流与实测验证,产出 `API_DIR` 条目与 `API_INDEX`。不写业务代码,不参与 `ROUND`。**仅在 `SKIP_API_PREVERIFY == false` 时被派发**;默认跳过时接口查证归各轮 `coder`。
540
+ - **`coder` 拥有:** 单轮内的编码、测试转写(当 `run_l1_e2e=true` 时)、TP 覆盖门禁(`scripts/test/tp_coverage.mjs`,当 `run_l1_e2e=true` 时)、构建、L0 门禁、`package-set`收集、单元测试(当 `run_l1_e2e=true` 时)、代码评审、UI 测试(当 `run_l1_e2e=true` 时),以及**这些层**的轮内修复与**证据信号** `LEDGER` 行。**不含集成测试**。
541
+ - **`spec-designer`(薄包装器)拥有:** 全流水线**一次**的 SPEC 编码设计产出(`SPEC_DESIGN`),实际procedure在它载入的 `a2h-spec-design` 技能里。它不写业务代码、不参与 `ROUND`、不写 `LEDGER`、不增删场景。**仅在阶段 0.5 未被跳过时派发**。
542
+ - **`self-tester`(薄包装器)拥有:** 单趟的设备集成测试执行,实际procedure在它载入的 `a2h-integration-test` 技能里。它产出 `self-test-report.md`,**不写 `LEDGER`**,也不驱动修复循环。
543
+ - **`a2h-spec-design` 与 `a2h-integration-test` 经包装器 agent 调用,不由编排器直接 `Skill`。** 宿主的 `skill` 工具只收一个 `name`(无参数字段)且只把技能正文载入当前上下文 —— 需要传参的技能只能靠 agent 的 prompt 送参数。`a2h-code-review` 不需要包装器:它由 `coder` 在自己的上下文里调用,参数同样经 prompt 传递。
544
+ - **三个下游技能都不写 `LEDGER`**,只产出报告;`LEDGER` 行由调用方从报告中提取后写入 —— `a2h-code-review` 由 `coder` 写(它调用它),`a2h-integration-test` 由**编排器**写(步骤④.7 经 `self-tester` 派发)。它们各自的参数名与调用形式以其自身契约为准。构建不经技能:`coder` 用原生 `arkts_check` / `build_project` 完成构建与编译修复,`source=build`(及修复时的 `source=fixer`)行由 `coder` 直接写入。
545
+ - **写与判分离:** `coder` 上报各层实际发生了什么;**场景终态由编排器推导**。`coder` 不宣布场景通过验收,编排器不改写 `coder` 的证据行 —— 要修的是写出错误行的那一环,绝不通过重新解析散文报告来「订正」`LEDGER`。
546
+ - **验收 ≠ 自测:** 依据冻结 `TEST_CASE` 的 `integration` 是验收;`coder` 自转写套件的 `uitest`(当 `run_l1_e2e=true` 时)是交付达标线。仅由后者证明通过的场景要标注并记入自主决策。当 `run_l1_e2e=false`(默认)时,`coder` 不转写也不执行 L1/E2E 层,每轮只经过构建 / L0 / 评审,所有场景的通过必须依赖验收(`integration`)或标注为自主决策。
547
+ - **所有 agent 都不做的事:** 修改 `SPEC`、`SPEC_DESIGN`、`TEST_CASE`、`PRE_TEST_CASE`(冻结文档);伪造任何 `LEDGER` 行;为了收敛而放松断言。
548
+ - `MAX_ROUNDS` / `NO_PROGRESS_ROUNDS` 只属于编排器,不传给 `coder`。