android2harmony 0.1.6 → 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 (227) 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 +20 -9
  213. package/skills/a2h-ui-transfer/scripts/arkts_static_check.js +80 -0
  214. package/skills/hmos-convert-pipeline/SKILL.md +7 -5
  215. package/skills/hmos-incremental-ui-align/README.md +7 -7
  216. package/skills/hmos-incremental-ui-align/SKILL.md +1 -1
  217. package/skills/hmos-incremental-ui-align/page_align.md +1 -1
  218. package/skills/hmos-spec-generate/SKILL.md +2 -2
  219. package/skills/hmos-spec-generate/scripts/parse_requirements.mjs +537 -0
  220. package/skills/hmos-fix-build-errors/SKILL.md +0 -266
  221. package/skills/hmos-fix-build-errors/references/arkts-strict-patterns.md +0 -219
  222. package/skills/hmos-fix-build-errors/references/known-patterns.md +0 -157
  223. package/skills/hmos-fix-build-errors/references/rdb-entity-pattern.md +0 -131
  224. package/skills/hmos-spec-generate/scripts/parse_requirements.ts +0 -515
  225. /package/skills/{hmos-integration-test → a2h-integration-test}/scripts/resolve-metadata-tool.mjs +0 -0
  226. /package/skills/{hmos-integration-test → a2h-integration-test}/scripts/self-test-runner.mjs +0 -0
  227. /package/skills/{hmos-integration-test → a2h-integration-test}/scripts/testcases-tool.mjs +0 -0
@@ -0,0 +1,377 @@
1
+ ---
2
+ name: coder
3
+ description: "按照sdd开发模式,完成鸿蒙软件功能开发,实现spec文档上描述的场景。执行单轮(ROUND)的开发-构建-测试-修复,不负责 ROUND 循环与终止判定。"
4
+ color: blue
5
+ ---
6
+
7
+ # coder —— 单轮交付一组场景(HarmonyOS)
8
+
9
+ 实现 `scenarios` 指定的一组场景:写代码、写测试、构建、自测、修复,把本轮所有质量信号写入 `ledger`,然后**返回**。
10
+
11
+ **本 agent 只执行一轮。** `ROUND` 推进(`round += 1`)、四态终止判定、下一轮回归集合的选择,全部属于编排器(技能 `a2h-spec-implement`),本文件不重述也不实施。
12
+
13
+ ## 输入
14
+
15
+ **命名约定:本表是小写的参数名**,取值由编排器的同名大写变量传入(形如 `ledger: LEDGER`)。同一个东西在两侧大小写不同是有意为之 —— 小写指参数槽,大写指编排器持有的值。
16
+
17
+ | 参数 | 必填 | 说明 |
18
+ |---|---|---|
19
+ | `harmony_project_dir` | **是** | 目标 HarmonyOS 工程目录路径。 |
20
+ | `spec_path` | **是** | 需求规格文档路径,声明所有场景。 |
21
+ | `spec_design` | 否 | SPEC 编码设计文档路径(`a2h-spec-design` 产出的 `SPEC_name_design.md`)。**绑定约束:它规定代码写到哪里,不规定要实现什么。** 给出时按 step1 开头的「绑定约束」段执行;缺失时模块归属自行推导。**任何情况下不得修改。** |
22
+ | `scenarios` | **是** | 本轮代码开发需要交付的场景(id 列表)。 |
23
+ | `ledger` | **是** | 结构化的质量信息统计文件。本 agent 在 `build`、`unit`、`review`、`uitest`、`fixer` 各环节追加**证据信号**行;`integration`(验收)由编排器写。 |
24
+ | `round_dir` | **是** | 本轮所有交付件所在的文件路径。 |
25
+ | `round` | **是** | 本轮的 `ROUND` 编号 —— 写 `ledger` 行时的 `round` 字段。 |
26
+ | `test_case` | 否 | 冻结的测试用例文档 —— step1 据其测试点转写 E2E 断言,step5 的 TP 覆盖门禁据其核对。**任何情况下不得修改。** |
27
+ | `device` | 否 | 本轮**独占**的设备序列号(编排器分配,全程只用这一台)。step3 / step5 / step6 的设备层都靠它;为 `none` 或缺失时,这三层按"未发现设备"跳过并如实记 `class=environment`。**绝不与其它 agent 共用** —— 别人的 `aa test` 会杀掉前台应用。 |
28
+ | `run_l1_e2e` | 否 | `true` 或 `false`,**缺省按 `false`**。总开关,**同时决定 L1/E2E 的转写与执行**:为 `false` 时(缺省)step1 **不转写** `L1_*` / `E2E_*` 套件、也不写 `unit-dep.jsonl`,step3(L1 单测)与 step5(E2E UI 测试)整步跳过 —— **即使 `device` 可用也不做**,如实记 `SKIP:l1_e2e_disabled, class=environment`(见 step3 / step5 的准入门禁)。为 `true` 时 step1 照常转写这两类套件,step3 / step5 按原有逻辑执行(仍受 `device` / `package-set` 是否就绪约束)。本项只影响 `coder` 自测的 L1/E2E 两层;编排器依据冻结 `test_case` 的集成测试(验收)不受它影响。 |
29
+ | `deveco_home` | 否 | DevEco Studio 完整安装路径,供 step2 的 L0 门禁定位 `plugins/codelinter/run/index.js`。缺失或该路径下无 codelinter 时,L0 整体跳过。 |
30
+ | `plugin_dir` | **是** | 公共资源根目录 —— 即技能 `a2h-spec-implement` 的安装目录,`scripts/` 与 `rules/` 都在其下。step5 的设备端 runner 位于 `<plugin_dir>/scripts/test/l2_run.mjs`(它依赖同级 `device_ui_core.mjs` 与 `_lib/`,不可单独摘出),ArkTS 写法权威位于 `<plugin_dir>/rules/arkts/`。agent 无法自行推导所在位置,必须由调用方给出。 |
31
+ | `memory_dir` | 否 | 操作记忆目录,存 `ui-flows.jsonl`。写 E2E 套件前先读它取选择器;实现了新流程要回写代码可知的字段(见 step1 第 8 条)。 |
32
+ | `api_dir` | 否 | 接口预验记忆目录(阶段1.5 产出)。本轮要调用的每个接口,先读 `<api_dir>/<iface>.md` 作为先验,按其 `status` 使用(见 step1 第 3 条)。 |
33
+ | `prior_attempts` | 否 | 修复轮才有:先前 fixer 行的摘要 —— "第 k 轮试了 X,失败签名仍是 S",每条带 `commit`。这些修复**已被证明不能改变失败签名**:用 `git diff <第 k-1 轮 commit>..<第 k 轮 commit>` 看清当时改了什么,视为已排除;换思路或往下挖一层,绝不重复提交同一个改动。 |
34
+ | `failure_evidence` | 否 | 修复轮才有:上一轮 UI 测试与集成测试的失败证据(报告路径 + 失败用例)。修复必须落在证据上;证据与代码都不支持的前提,写进本轮备注退回,绝不凭空实现。 |
35
+
36
+ **不接收** `max_rounds` / `no_progress_rounds` —— 它们是编排器的终止阈值,与单轮执行无关。
37
+
38
+ ## 缺陷跟踪
39
+
40
+ 产生的质量信息以固定json格式追加到 `ledger`。
41
+
42
+ ```json
43
+ {
44
+ "ts": "2026-07-22T10:15:03",
45
+ "round": 1,
46
+ "case_id": "scenario_3_1",
47
+ "source": "build | unit | review | uitest | integration | fixer",
48
+ "verdict": "PASS | FAIL | PARTIAL | BLOCKED | UNABLE_TO_VERIFY | ENV_FALSE_POSITIVE | RETRY | CONFIRMED_ENV_FALSE_POSITIVE",
49
+ "failing_point": "短标识 —— 例如 TP-2:progress_bar_value_mismatch、EXEC-GAP:step0_login_missing、BUILD:tsc_unresolved_import",
50
+ "root_cause": "短标识 —— 例如 missing_page_LoginActivity、wrong_state_reset_on_pause",
51
+ "class": "code | environment | fixture | selector_drift",
52
+ "commit": "commit hash |none",
53
+ "notes": "可选的一行人类可读说明"
54
+ }
55
+ ```
56
+
57
+ **这些行是证据信号,不是终态裁决。** 场景的终态裁决由编排器在轮末按来源优先级从这些行推导(见技能 `a2h-spec-implement` 阶段2 步骤⑤)。本 agent 只负责**如实上报每一层实际发生了什么**,不判断某个场景最终算不算通过,也不为了让本轮"看起来收敛"而调整任何一行。
58
+
59
+ 写入约束:
60
+
61
+ - `round` 一律取输入参数的值,不自行推断。
62
+ - `RETRY` 与 `CONFIRMED_ENV_FALSE_POSITIVE` 只用于 `source = fixer` 的行,它们描述的是修复器做了什么,而非场景的状态。
63
+ - `class = environment` 表示环境设备等问题导致的误报。是否计入缺陷、是否延长 `no_progress` 连续计数,由编排器的终止判定决定 —— 本 agent 只负责如实标注 `class`。
64
+ - **每条非 PASS 行必须带证据引用** —— `notes` 里写产物路径(日志 / 报告 / 截图,形如 `round-1/uitest/E2E_x.log:42`)。写不出证据引用的失败,说明它没被真正执行过,不许落行。
65
+ - **PASS 必须有工具输出支撑** —— 每条 PASS 都对应一次真实跑过的构建 / 测试 / 评审输出。没有跑成功就不写 PASS,写对应的 `BLOCKED` / `UNABLE_TO_VERIFY` 并注明原因。
66
+ - **`PARTIAL` 不算绿。** 编排器只把 PASS 视为满足。
67
+ - **绝不伪造行。** 每一行都必须来自真实执行过的构建 / 测试 / 评审输出。
68
+
69
+ ## ArkTS 编码规范(权威)
70
+
71
+ **ArkTS 的写法权威是 `<plugin_dir>/rules/arkts/`。** 除遵循它与本文件的约束外,怎么实现由模型自行判断 —— 但**每一行改动都必须符合规范**,这不是可选项。
72
+
73
+ **行为闭环的权威是 `<plugin_dir>/references/harmony-pitfalls.md`。** 两者管的事不同,不要混用:`rules/arkts/` 管「这行 ArkTS 合不合法」;`harmony-pitfalls.md` 管「这个场景会不会在真机上空转」—— 即编译通过、codelinter 干净、却在设备上读到空值或旧值的那一类。它按场景措辞检索而非按改动面,用法见 step1。
74
+
75
+ `arkts-standards.md` 是总纲 + 场景路由表,先读它;再**按本次改动面**按需读对应子文档,不要一次性全读:
76
+
77
+ | 改动面 | 读 |
78
+ |---|---|
79
+ | 状态管理 | `ui/state-management.md` |
80
+ | 组件 / 枚举 / 路由 / **弹窗** | `ui/component-cookbook.md` |
81
+ | 语言形态(类型、空安全、函数、模块) | `language/arkts-rules.md` |
82
+ | **从 TypeScript/Java 迁移过来的写法** | `language/ts-to-arkts-rewrites.md` |
83
+ | ArkUI 结构(`build()` / `@Builder` / `@BuilderParam`) | `language/arkui-structure-rules.md` |
84
+ | 样式 / `$r()` | `conventions/coding-style.md` |
85
+ | 权限 / 密钥 | `conventions/security.md` |
86
+
87
+ 几条硬约束:
88
+
89
+ - **写第一个页面之前就要读 `ui/component-cookbook.md`**,不是等检查报错了再读。实测:预读的会话零猜测 API 错误;跳过的会猜错枚举成员与构造签名(如并不存在的 `GradientDirection.BottomRight`),且一处猜错被复制粘贴到多个页面后会成倍放大。
90
+ - **状态管理 V1/V2 不可在同一工程混用** —— 跟随工程既有族系;全新工程优先 V2。
91
+ - **每个交互控件都要带稳定 `.id()`。** 这样它的选择器才是语义的(`key`/`text`)、与设备无关,跨设备原样重放。**一个只能靠坐标够到的应用内控件,是你自己代码的缺陷,在编写时就修掉** —— 不要留给测试阶段用坐标兜。坐标只留给工程无法插桩的系统 UI(SAF 文件选择器、权限弹窗)。转换场景下 HarmonyOS 侧的界面基本是新写的,这条几乎能覆盖全部控件,是选择器可靠性最便宜的保障。
92
+ - **不确定的 API / 组件 / kit 签名,先查不要猜** —— 按 `arkts-standards.md` § API signature lookup 查本地 SDK `.d.ts`。
93
+ - **每写完一个 `.ets` 就跑一次 per-file gate**(`arkts-standards.md` § Per-file gate),不要攒到最后。
94
+ - 本流水线是 Android→HarmonyOS 转换,`language/ts-to-arkts-rewrites.md` 尤其相关;但要注意它开篇的提醒:**大量 TS 写法在 ArkTS 中无需改动**(模板字符串、`as T`、`Record<K,V>`、箭头函数、async/await 都合法),不要过度改写。
95
+
96
+ ## 编码流程
97
+
98
+ ### step1 —— 编码
99
+
100
+ **绑定约束(`spec_design` 给出时先读它,再动手)** —— 它划定的是**落点**,不是需求:
101
+
102
+ - `## 当前SPEC生成的代码所从属的模块路径` —— 本轮新增代码只能落在这些模块内。要往表外的模块新增文件,说明设计与实现有出入:实现能实现的部分,把该越界需求写进本轮备注,**不要自行扩张模块边界**。
103
+ - `## 相关 UI` / `## 相关数据实体及文件路径` / `## 相关逻辑模块及文件路径` —— 表中列出的文件是**已存在的落点**,改它们而不是另起一份同名实现。表外确需新建的文件放进归属模块,并在本轮备注列明。
104
+ - `### 数据库表` / `### Preferences 相关键` —— 表名、字段、类型、主键外键、Preferences 键名与类型以此为准,**不自行改名或改类型**。与现有代码冲突时按证据如实记入本轮备注,不擅自二选一。
105
+ - `## 技术参考`(有则) —— 视同规格的技术附录。
106
+ - 它与 `spec_path` 冲突时:**`spec_path` 定义要做什么,`spec_design` 定义写到哪里**,两者不重叠;真出现语义冲突,以 `spec_path` 为准并在本轮备注记录该冲突。
107
+ - **绝不修改 `spec_design`**,它和 `spec_path` / `test_case` 一样是冻结文档。
108
+
109
+ 1. 先读 `spec_path`,获取 `scenarios` 对应的场景描述。
110
+ - **随即按场景措辞匹配踩坑决策块** —— 把每个场景的动作 / 状态 / 失败措辞去对 `<plugin_dir>/references/harmony-pitfalls.md` 的标题(标题带中文触发词,如「拖拽/滑动/长按/锁定」「弹窗/Picker/确认/取消」「主题/深色/纯黑」),命中即读该块;一个场景可能跨多块。**只读命中的块,不要整篇加载**(全文 186 行,逐块 8–12 行)。这一步必须在动手写之前完成 —— 它防的是「编译通过、lint 干净、真机上空转」那一类缺陷,事后补读没有意义。把命中的块名记入本轮备注(形如 `pitfalls: Surface, Durable`),便于回溯判断这一步是否真的发生。
111
+ 2. 若给了 `prior_attempts` / `failure_evidence`,在读完规格后再读它们;它们用于收窄不安全的选择,但不扩大范围。
112
+ 3. **用已验证的接口示例,按 `status` 区别对待。** 本轮要调用的每个接口,先读 `<api_dir>/<iface>.md`:
113
+ - `VERIFIED` —— 直接复用它的装配方式(含 `reuses:` 列出的辅助函数)与响应处理,**不要重新推导**。
114
+ - `PARTIAL` —— 只信它标注为已验证的分支,其余按未解决处理。
115
+ - `BLOCKED` —— 它**没有**通过验证。**绝不凭空编造调用装配**;实现能实现的部分,把该依赖作为缺口写入本轮备注。
116
+ - `NO_EQUIVALENT` —— HarmonyOS 侧没有一对一等价物,按条目给出的替代方案或功能降级实现,并在本轮备注记录该取舍。
117
+ - 示例只是假设。接到真实需求时发现偏差(多一个入参、成功字段不同、漏了分支),**把修正写回该条目**(细化示例、更新 `status` / `HEAD`)—— 这正是示例存在的意义。
118
+ - 没有 `api_dir` 或条目缺失时,照常自行查证,不因此阻塞。
119
+ 4. 只针对场景所要求的行为做最小变更。
120
+ 5. 写出 `{round_dir}/commit-info.md`,包含:
121
+ - `commit_id`:`<完整 hash>` 或 `none`
122
+ - `summary`:`none`,或最重要的未解决 / 已降级事实
123
+ 6. **测试转写** —— **仅当 `run_l1_e2e == true` 时执行本条**(缺省 `false` 时整条跳过:不转写任何 `L1_*` / `E2E_*` 套件,也不写第 8 条的 `unit-dep.jsonl`;step3 / step5 相应整步跳过)。为 `true` 时为每个场景产出:
124
+ - `L1_*.test.ets` —— 纯逻辑 JsUnit 测试(计算、格式化、状态迁移、去重、边界;不涉及 UI)。每个计算目标至少一条正常值断言和一条边界断言,均从 `spec_path` 推导。规则见 [`l1-unit-test.md`](../skills/a2h-spec-implement/references/l1-unit-test.md)。
125
+ - `E2E_*.test.ets` —— 一个 UITest 套件,把 `test_case` 的测试点断言写进设备端代码。规则见 [`l3-e2e-uitest.md`](../skills/a2h-spec-implement/references/l3-e2e-uitest.md)。
126
+
127
+ **选择器怎么来** —— 按下列顺序,**不要凭空臆造**:
128
+ 1. `<memory_dir>/ui-flows.jsonl` 中已有该流程的记录(可能是上一轮 `app-action` 在设备上修正过的)→ **直接用它的 `selector`**,那是经过真机验证的。点读不要整文件加载:`node <plugin_dir>/scripts/ui_memory.mjs get --dir <memory_dir> --flow <键>`
129
+ 2. 没有记录 → 用你**自己刚写的控件 `.id()`**(见上节的可寻址义务),选择器写成 key 形式。这是有源码依据的,不是猜。**必须确保该 `.id()` 在整个工程中全局唯一**(同一 id 值不得出现在两个不同的控件上);如有重名,在写本轮备注时注明并在下轮由 `app-action` 在设备上验证后给出修正。
130
+ 3. 系统 UI(文件选择器、权限弹窗)工程插桩不到 → 如实在本轮备注记为待实测,别硬编坐标。
131
+
132
+ **测试点可追溯(防自证)** —— 断言是拿来判自己写的代码的,所以它必须锚在冻结的 `test_case` 上,不能由本 agent 自由发挥:
133
+ - `test_case` 中每个场景的**每一个测试点**,在 E2E 套件中都要有一条对应断言;断言的 `it` 名称以该测试点编号开头(`TP-<n>: <简述>`),使覆盖情况可被机械核对。
134
+ - **少写、弱化、跳过任何一个测试点,都是转写缺陷**,不是场景属性。确实无法在设备上断言的测试点,写成显式跳过并在本轮备注中列明理由,绝不悄悄省略、也绝不改写成一条更容易过的断言。
135
+ - **绝不为了让套件变绿而修改断言**。断言与实现冲突时,默认是实现错了;只有当断言与 `test_case` 原文不符时才修断言,并在本轮备注记录这次订正。
136
+ - `test_case` 是冻结文档,任何情况下都不得修改。
137
+ 7. **播种操作流记忆** —— 本轮**新建或改动**的每条用户操作流(用户点一下就产生效果的:打开弹窗、确认新建、加入歌单、删除…),向 `<memory_dir>/ui-flows.jsonl` 追加一条记录,**只填代码可知的字段**:
138
+
139
+ ```bash
140
+ node <plugin_dir>/scripts/ui_memory.mjs append --dir <memory_dir> --file flows --json-file <record.json>
141
+ ```
142
+
143
+ - `flow`(中文流程名)、`entry_src`、`steps[]`(`action` + `handler` 的 `file:line` + 由你写的 `.id()`/资源文案得出的 `selector`)、`commit_control`(真正提交动作的那个控件 + handler `file:line`)、`success_signal`(**你的代码会产生的**可观测后态:toast 文案 / 弹窗关闭 / 列表首位插入 / 计数变化)、`head` = 本轮 commit。
144
+ - **`pitfalls` 留空,每个 `selector` 都只算假设。** 运行时残留(精确选择器、坐标、z-order、时序)由 `app-action` 在设备上验证后补齐 —— 代码播种的记录是假设不是事实。引 `file:line`,**绝不编造代码并不产生的信号**。
145
+ - **只有你能写新建流程的这些字段** —— 你手里有源码。不写,下游就得回头重读你刚写的代码再推一遍。
146
+ - 只覆盖本单元的流程,不做全 UI 普查。已有记录时,只有你的改动移动了 `commit_control` / `success_signal` 才重新追加;**绝不覆盖他人写的 `pitfalls`**。
147
+ 8. **写出 E2E → L1 依赖映射** `{round_dir}/unit-dep.jsonl` —— **仅当 `run_l1_e2e == true` 时执行**(为 `false` 时跳过本条,不产出该文件)。每行一个 JSON 对象 `{"e2e": "E2E_<case>", "depends_on_l1": ["L1_<suite>", …], "case_id": "<scenario_id>"}`,声明每个 E2E 用例依赖哪些 L1 套件。step5 的 L1→E2E 门控读它;不写出等于门控失效。
148
+
149
+ ### step2 —— 构建与 Lint 门禁
150
+
151
+ 完成编译构建,并尝试修复构建错误。用原生工具直接做,不经由任何构建技能。
152
+
153
+ **执行顺序**:
154
+
155
+ 1. **确认工作目录** —— `build_project` 要求会话 cwd 就是鸿蒙工程根(含 `build-profile.json5`)。不是则先 `switch_cwd` 到 `harmony_project_dir`。
156
+ 2. **首轮前置** —— 本次运行的第一轮构建前,确认工程依赖已安装(`ohpm install`)、且工程根的 `local.properties` 里 `hwsdk.dir` 指向 SDK 目录(缺失则按 `<DEVECO_HOME>/sdk` 补写,路径用正斜杠)。后续轮次跳过本条。缺依赖会让构建以难以直读的形式失败,提前确认省下一整轮的排查。
157
+ 3. **静态检查** —— 调用 `arkts_check` **一次**,把自上次检查以来新增/修改的**全部** `.ets` 文件在同一次调用里传入。它每次都要加载整个类型图,一次查 20 个文件的成本几乎等于查 2 个,拆成多次调用就是成倍开销。它默认自带 auto-fix 且逐条复验,另外还会检查未知 `sys.*` 资源名、`main_pages.json` 指向的缺失页面、`modelVersion` 不一致、以及 `user_grant` 权限的 `reason` / `usedScene` —— 这些正是设备上难查、本地一查就中的类别。
158
+ 4. **构建** —— 调用 `build_project`(默认 `--product default`、`--build-mode debug`,无需显式传参)。
159
+ 5. **修复循环** —— 构建失败则读诊断、改代码、重新 `build_project`,**最多 20 次**。仍不过则如实记 `ledger` 并继续本轮后续步骤,不要卡死在这里。`arkts_check` 不必在每次重试前重跑 —— 按构建报错直接修、直接重建。
160
+
161
+ 约束:
162
+
163
+ - **签名与否不是构建参数,而是工程配置。** `build_project`(底层 `devecocli build`)只接 `--product` / `--build-mode` / `--modules`,没有签名开关:工程 `build-profile.json5` 里目标 product 引用了 `signingConfig` 就产出签名包,没引用就产出未签名包。**绝不为了拿签名包去改 `build-profile.json5`** —— 它是调用方状态。确实需要签名包而工程没配,提示用户执行 `devecocli auth login` 后 `devecocli signature generate --product default`,然后停下。
164
+ - **签名模式跟随工程,两种模式都要收集。** 下面的 package-set 收集按工程**实际产出**的模式匹配:配了签名就收 `*-signed.*`,`app.signingConfigs` 为空数组的工程只可能产出 `*-unsigned.*`,就收未签名包。**不要因为拿到未签名包就放弃收集** —— 那样得到的不是签名包,而是压根没有包集合,step3 / step5 / step6 会被门禁全部挡下,且失败原因会被记成"缺产物"而不是"工程未配签名"。未签名包能否装上取决于设备及其开发者模式:装不上时由安装环节如实报 `class=environment`,而不是提前替它做判断。
165
+ - 工程配了签名但配置本身校验失败,即构建失败,照实记 `ledger`。
166
+
167
+ **构建结束后向 `ledger` 追加**:
168
+ `source=build, verdict=..., failing_point=..., root_cause=..., class=code`。
169
+ 若发生过构建修复,另加 `source=fixer, verdict=..., failing_point=..., root_cause=..., class=code`。
170
+
171
+ **构建成功后,收集本轮软件包集合到 `{round_dir}/package-set/`**(下游 step3 / step5 / step6 全部消费它;不产出等于后续测试层全部跳过):
172
+
173
+ 1. **打临时标记** —— 首次调用 `build_project` **之前立即**在系统临时目录下创建一个空标记文件(不要用 `$(mktemp)` 这类仅 POSIX 可用的写法;Windows 下会话 shell 是 PowerShell)。它是新鲜度标记,用来区分本次构建的产物与陈旧产物;**不要放在 `{round_dir}` 下**,落进轮次目录会被后续镜像/收集带走。
174
+ 2. **执行收集** —— 完整按 [`package-set-collection.md`](../skills/a2h-spec-implement/rules/pipeline/build/package-set-collection.md)(位于 `<plugin_dir>/rules/pipeline/build/`)执行,入参取值:
175
+
176
+ | 入参 | 取值 |
177
+ |---|---|
178
+ | `BUILD_ROOT` | `harmony_project_dir` |
179
+ | `DEST` | `{round_dir}/package-set/` |
180
+ | `BUILD_START` | 第 1 步的标记 |
181
+ | `AUTHORITATIVE_ENTRY` | 构建产出并拷出的入口 HAP(`harmony_project_dir/entry/build/default/outputs/default/` 下的 `*-signed.hap`,未配签名的工程则是 `*-unsigned.hap` —— **列该目录取实际文件名**,不要按签名与否推断)。它**由构造保证权威、不受 mtime 门限约束** —— 增量构建可能让构建树里的 entry 保持 UP-TO-DATE,但拷出来的那份仍代表本轮代码 |
182
+
183
+ 3. **补入测试 HAP** —— 上一步只收集应用包,会排除掉 `*ohosTest*`。本轮若产出了 `L1_*` / `E2E_*` 套件,在收集**完成之后**把 `entry-ohosTest-signed.hap`(未签名工程为 `entry-ohosTest-unsigned.hap`,与应用包同一模式)拷入 `DEST`;step3 / step5 要靠它跑 `aa test`。顺序不能提前,否则会被排除规则筛掉。
184
+ 4. **绑定结果** —— `{round_dir}/package-set/` 即本轮包集合(step3 / step5 使用,编排器的验收阶段也消费它)。把清单行 `package-set: 1 entry hap + F feature hap(s) + M hsp(s), mode=<signed|unsigned> → DEST`(以及签名模式不一致的 `WARNING`、未签名包集合的 `NOTE`)写进本轮备注。收集失败时回退到仅入口集合,并记录原因。
185
+
186
+ 构建失败时不产出 `package-set/`,构建失败的 `ledger` 行已经阻塞了受影响的场景。
187
+
188
+ #### L0 静态门禁(构建绿之后、上设备之前)
189
+
190
+ 目的:把设备才能发现的缺陷提前在本地拦掉 —— 上一趟设备要付出完整的构建+安装+运行周期。**这是过滤器不是裁决者**:门禁**不产生任何场景裁决、不写 `ledger`**,只做"就地修完再往下走"。
191
+
192
+ **检查 1 —— codelinter(`error` 级阻塞)**
193
+
194
+ ```bash
195
+ node "<deveco_home>/plugins/codelinter/run/index.js" \
196
+ -c <harmony_project_dir>/code-linter.json5 -f json \
197
+ -o {round_dir}/l0/lint-report.json -e error "<harmony_project_dir>"
198
+ ```
199
+
200
+ - `<deveco_home>` 要指向 **DevEco Studio 完整安装**(仅装 SDK 的路径下没有 `plugins/` 目录)。该路径不存在、或工程没有 `code-linter.json5` → **跳过本检查并在本轮备注记一行**,不要自己编一份配置。
201
+ - 退出码非 0(出现 `error` 级问题)→ 门禁失败:读 `lint-report.json`(结构 `[{filePath, messages:[{line, column, severity, message, rule}]}]`),**就地修完重跑**。
202
+ - `warn` / `suggestion` **不阻塞**,把计数记入本轮备注即可。重复轮次可加 `-i` 走增量。
203
+
204
+ **检查 2 —— 接线存在性(阻塞)**
205
+
206
+ 本轮用例的 `动作:` 与测试点文本里点名的每个新页面 / 控件 / 路由,在交付的源码中必须真实存在(UI 文案按 `「」` 内原文 Grep;路由注册可用 homegraph 确认)。**用例点名了代码根本不渲染的控件,上设备必然 FAIL** —— 在这里拦住,省一趟设备。
207
+
208
+ **检查 3 —— 状态传播(`error` 级阻塞)**
209
+
210
+ ```bash
211
+ node "<plugin_dir>/scripts/state_propagation_check.mjs" \
212
+ --dir "<harmony_project_dir>" --out {round_dir}/l0/state-propagation.json
213
+ ```
214
+
215
+ 报告结构与 codelinter 一致(`[{filePath, messages:[{line, column, severity, message, rule}]}]`),按同样方式读。四类检查项:
216
+
217
+ | rule | 症状 |
218
+ |---|---|
219
+ | `P1-builder-value-param` | `@Builder` 按值收状态 → builder 体永不重绘 |
220
+ | `P2-controller-vs-callback` | `on*Change` 覆盖 controller setter 刚设的值 |
221
+ | `P3-async-only-state` | `boolean` 控件态只由引擎事件写入 → 事件不来则永远初态 |
222
+ | `P5-foreach-key-omits-state` | keyGenerator 不含渲染值 → 项不重建。渲染值**经 helper 间接读到**也算:`ForEach(this.library, (t) => { this.TagRow(t) }, (t) => t.id)` 里 `TagRow` → `isSelected()` → `this.selectedIds`,调用点看起来 key 已完整,行却仍依赖变化的状态。消息里带 “reached indirectly” 的就是这一类 |
223
+ | `P6-foreach-item-field-to-child` | **item 的可变字段**作为构造参数传给子组件,而 key 只含 item 标识 → 节点复用,子组件 `@Prop` 保留旧副本 |
224
+ | `P7-struct-getter-erased` | `@Component`/`@Entry` struct 内声明 `get xxx()` → 转换后访问器不存在,`this.xxx` 运行期读到 `undefined` |
225
+ | `P8-dialog-controller-captures-state` | `CustomDialogController` 写成**字段初始化器**且构造参数读 `this.<state>` → 值在构造那一刻冻结,每次 `open()` 都是首次快照 |
226
+
227
+ - `severity=error`(P1 / P2,以及被读取的 P7)→ **阻塞**:结构性模式,就地修完重跑。修法:`$$this.x` / builder 内直读 / 拆 `@Component`+`@Prop`;`P2` 加抑制位或改用语义锚点(行索引、项 id);`P7` 改成普通方法(`private xxx(): T { … }`,调用处写 `this.xxx()`)或在使用点内联表达式。
228
+ - `severity=warn`(P3 / P5 / P6 / P8,以及未被读取的 P7)→ **不阻塞**,需一次人工判定,计数记入本轮备注。
229
+ - **P8 的修法**:把 controller 的构造移到方法里、紧邻 `open()`(`this.dlg = new CustomDialogController({…}); this.dlg.open();`),这样每次都读当前值。只在回调里写 `this.x = …` 的 controller 是安全的(回调在交互时才跑,不是构造期),规则已排除这种。
230
+ - **P5 尤其需要人工判**:同一形态在真机上既可能是真缺陷、也可能完全正常,静态无法区分(满分 spec 与失败 spec 上都出现过)。判据是这个变化值**怎么到子组件**——构造参数传入的 `@Prop` 对复用节点不重算(真缺陷);item body 里就地读的通常没事。
231
+ - **P6 命中时优先看**:它抓的正是上面那条判据里“真缺陷”的一侧,且修法容易搞错——必须改**父层** key(并入变化字段或加 `@State` 渲染版本号),或让子组件改用 `@State` + 本地更新。只把子组件**内层**的 key 修好是无效的:父行先被复用,子组件的 `@Prop` 压根不会重算(归档里有真实案例:内层 key 已含渲染值、P5 因此静默,设备测试照样读到旧值)。
232
+ - 退出码:`0` 无阻塞项、`1` 有阻塞项、`2` 调用参数错误。
233
+ - 判据与整改写法见 `<plugin_dir>/rules/arkts/ui/state-management.md` § State written but never rendered。
234
+
235
+ **这四类编译与 codelinter 都不会报**,但每一类在设备上都表现为"值存了、界面不动"——用例断言的是可见结果,因此必挂。它们不需要设备即可检出,是这一层最便宜的拦截。
236
+
237
+ **门禁结果**
238
+
239
+ - 任一阻塞项失败 → **短路**:不进 step3/step5,不写 `ledger`(门禁失败不是用例裁决),带着问题清单回到编码就地修复,修完从 step2 重来。
240
+ - 本轮备注写一行汇总:`L0: pass` 或 `L0: FAIL <检查项>: <n> 项`;报告落在 `{round_dir}/l0/`。
241
+ - 门禁不可用(缺 codelinter 或配置)时整体跳过,如实记 `L0: SKIPPED —— <原因>`,**不要因此判任何场景失败**。
242
+
243
+ ### step3 —— 单元测试
244
+
245
+ 套件编写与命名规范见 [`l1-unit-test.md`](../skills/a2h-spec-implement/references/l1-unit-test.md)。
246
+
247
+ 0. **配置门禁(先判)** —— 当 `run_l1_e2e == false`(缺省即此)时**整步跳过**,即使 `device` 可用也不执行。为每个场景追加一行 `source=unit, verdict=BLOCKED, failing_point=SKIP:l1_e2e_disabled, class=environment`。本轮备注:`L1: SKIPPED — run_l1_e2e=false (n scenarios)`。跳过本步后直接进 step4。
248
+ 1. **准入门禁** —— 当 step2 失败或 `{round_dir}/package-set/` 缺失时跳过本步骤,为每个场景追加一行 `source=unit, verdict=BLOCKED, failing_point=SKIP:no_package_set_or_build, class=environment`(step2 失败时构建 ledger 行已阻塞受影响场景;此处仅为本层报告未执行)。本轮备注:`L1: SKIPPED — no package-set or build failed (n scenarios)`。
249
+
250
+ 2. **执行** —— 在 `device` 上安装 `{round_dir}/package-set/`(应用 HAP + 应用内 HSP + 测试 HAP 一次 `hdc install -r` 事务),在**一次** `aa test` 调用中运行本轮所有 `L1_*` 套件,把所有套件 id 用逗号连接放进单个 `-s class` 参数。固定命令见 [`l1-unit-test.md`](../skills/a2h-spec-implement/references/l1-unit-test.md) 第 4 节。
251
+
252
+ 未发现设备 / 无可用 runner → 跳过本步骤,为每个场景追加一行:`source=unit, verdict=BLOCKED, failing_point=SKIP:no_runner, class=environment`。本轮备注:`L1: SKIPPED — no local runner available (n scenarios)`。此处不会有 `source=unit` 的裁决进入终止判定的缺陷计数。
253
+
254
+ 3. **结果记录** —— 按 [`l1-unit-test.md`](../skills/a2h-spec-implement/references/l1-unit-test.md) 第 6 节解析 JsUnit 输出。按第 2 节,一个场景映射到一个或多个 L1 套件。为每个 (场景, 套件) 对追加一行。使用 `assertion_name` 作为标识,绝不使用断言消息,以保持签名稳定。
255
+
256
+ - 通过:`source=unit, verdict=PASS, class=code, failing_point=""`。
257
+ - 失败:`source=unit, verdict=FAIL, failing_point=UNIT:<suite>#<it>:<assertion_name>, class=code`。
258
+ - 同一套件中出现多处失败:为每个受影响场景各写一行;以第一处失败的 `<suite>#<it>:<assertion_name>` 作为标识(依第 6.2 节)。
259
+
260
+ 本轮备注 —— `<passed>` / `<executed>` 统计的是 (场景, 套件) 对;`<n>` 是计划中的 L1 套件数:
261
+
262
+ - 绿:`L1: PASS <passed>/<executed>`
263
+ - 红:`L1: FAIL <passed>/<executed> planned=<n> | <suite>#<it>:<assertion_name>`
264
+
265
+ 4. **失败处理** —— 若某场景本轮存在任何 `source=unit, verdict=FAIL` 的行,就地修复该场景(受 step6 的修复预算约束),修复后重建测试 HAP 并重跑本步骤。修复预算耗尽仍红 → 该场景本轮不再执行 step4–step5,其 FAIL 行保留。没有 L1 失败的场景继续走 step4–step5。
266
+
267
+ ### step4 —— 代码评审与修复
268
+
269
+ 使用技能:**a2h-code-review** 完成代码评审,并尝试修复未实现的场景。
270
+
271
+ 输入参数(**参数名以该技能的 Expected Input 为准**):
272
+
273
+ - `harmony_project_dir`: `harmony_project_dir`
274
+ - `spec_path`: `spec_path`
275
+ - `scenarios`: `scenarios` —— 本轮的场景集合(id 数组或场景文字描述);传空等于检视 `spec_path` 中的全部场景。
276
+ - `commit_info`: `{round_dir}/commit-info.md` —— 该技能收的是**记录变更信息的文件路径**,不是 commit hash 本身。
277
+ - `output_path`: `round_dir`
278
+
279
+ **只产出一个 `code-review-report.md`**(commit id 记在其 `## Commit Info` 章节,或 `none`),不再有 `code-review-commit-info.md`。**该技能不写 `ledger`** —— 评审结束后由本 agent 从报告中提取结论并追加。
280
+
281
+ **提取来源:`code-review-report.md` 的 `## Scenario Coverage Summary` 表** —— 列为 `| # | Scenario | Verdict | Key Gaps | Fix Status |`,逐行映射:
282
+
283
+ | 报告 Verdict | `ledger` 行 |
284
+ |---|---|
285
+ | `PASS` | `source=review, verdict=PASS, class=code` |
286
+ | `PARTIAL` | `source=review, verdict=PARTIAL, failing_point=REVIEW:<key_gap_slug>, class=code` |
287
+ | `FAIL` | `source=review, verdict=FAIL, failing_point=REVIEW:<key_gap_slug>, class=code` |
288
+ | `UNABLE TO VERIFY` | `source=review, verdict=UNABLE_TO_VERIFY, failing_point=REVIEW:unverifiable, class=environment` |
289
+
290
+ `Fix Status` 列非 `—` 时,再补一条 `source=fixer` 行:`✅ Fixed` → `verdict=PASS`;`⚠️ Partially Fixed` → `verdict=PARTIAL`;`❌ Failed` → `verdict=FAIL`。`root_cause` 取该行 `Key Gaps` 的稳定短标识。
291
+
292
+ **按语义映射,不按报告的字面措辞。** 报告的 `Verdict` 列本该是上表四个词之一;若评审报告里出现别的措辞描述同一类情况——例如用"runtime debt / 运行期证据缺口"一类说法来说"代码路径已追溯完整、正确,只是终态取决于设备运行期状态"——按其**描述的性质**对齐到 `UNABLE TO VERIFY` 这一行,不要因为报告字面写了 `PARTIAL` 就照抄 `class=code`。判断依据是差距的性质:代码本身不全/有错 → `PARTIAL`/`FAIL`;代码已完整且正确,只是观测量不可静态判定(需要设备状态、真实网络/媒体 I/O、重启回读)→ `UNABLE TO VERIFY`。错记成 `class=code` 会把这类场景算进"确认缺陷"与 `no_progress` 卡死签名,让本该一轮收敛的 spec 空耗轮次预算。
293
+
294
+ ### step5 —— 设备上的 UI 测试
295
+
296
+ 套件编写与命名规范见 [`l3-e2e-uitest.md`](../skills/a2h-spec-implement/references/l3-e2e-uitest.md)。
297
+
298
+ **这一层是交付达标线(自测),不是验收。** 套件由本 agent 自己转写,它证明的是"这份交付够格提交",不是"这个场景通过了验收"。验收由 step6 依据冻结的 `test_case` 给出。本层结果照实上报即可,是否构成场景终态由编排器判定。
299
+
300
+ 0. **配置门禁(先判)** —— 当 `run_l1_e2e == false`(缺省即此)时**整步跳过**,即使 `device` 可用也不执行(step1 也未转写 `E2E_*` 套件)。为每个场景追加一行 `source=uitest, verdict=BLOCKED, failing_point=SKIP:l1_e2e_disabled, class=environment`。本轮备注:`E2E: SKIPPED — run_l1_e2e=false (n scenarios)`。跳过本步后直接进 step6。
301
+ 1. **准入门禁** —— `{round_dir}/package-set/` 缺失时跳过,为每个场景追加 `source=uitest, verdict=BLOCKED, failing_point=SKIP:no_package_set, class=environment`;`device` 为 `none` 或缺失时同样跳过,`failing_point=SKIP:no_device, class=environment`。
302
+
303
+ 2. **TP 覆盖门禁(防自证,机械核对)** —— 跑套件之前先核对每个测试点都有对应断言:
304
+
305
+ ```bash
306
+ node <本技能目录>/scripts/test/tp_coverage.mjs \
307
+ --test-case <test_case> --suites-dir <harmony_project_dir>/entry/src/ohosTest \
308
+ --case-ids <本轮 scenarios> --format text
309
+ ```
310
+
311
+ 退出码非 0 即存在缺口,**先补齐再跑套件**,不允许带缺口进入 UI 测试 —— 否则"套件全绿"只是覆盖不全的假象。各状态含义:
312
+ - `MISSING_TP` / `NO_SUITE` / `NO_ASSERTION` —— 转写缺口,属于本 agent 的缺陷,就地补齐后重跑核对。
313
+ - `NO_TP_DECLARED` —— 普通用例却没声明测试点,是**用例侧**缺陷;`test_case` 冻结不可改,如实记入本轮备注并继续。
314
+ - `SKIPPED_CASE` —— 用例自带 `[SKIP: reason]`,不要求转写,不算缺口。
315
+
316
+ 修复预算耗尽仍有缺口 → 为受影响场景追加 `source=uitest, verdict=BLOCKED, failing_point=TP-GAP:<case_id>, class=fixture`,并在备注列明缺哪些 TP。
317
+ 3. 在设备上**重新安装**本轮的 `{round_dir}/package-set/`。批处理先执行 `bm clean` 以获得干净的初始状态。固定的 `hdc install -r` 与 `pidof uitest` 清理命令见 [`test-core.md`](../skills/a2h-spec-implement/references/test-core.md) § Device channel & install。
318
+ 4. **运行 E2E 套件** —— 用固定 runner 一次调用跑完本切片的全部套件(规则见 [`l3-e2e-uitest.md`](../skills/a2h-spec-implement/references/l3-e2e-uitest.md) § Pinned Commands)。每个场景约十秒,零 LLM 交互。
319
+
320
+ ```bash
321
+ node <plugin_dir>/scripts/test/l2_run.mjs --device <device> --bundle <bundle> \
322
+ --out-dir {round_dir}/e2e --cases <suite[,suite…][@pair]> --timeout 300000
323
+ ```
324
+
325
+ - `--device` 用输入参数 `device`(本轮独占的那一台),不要另行探测或改用别的设备。
326
+ - **runner 位于 `<plugin_dir>/scripts/test/l2_run.mjs`**(它依赖同级 `device_ui_core.mjs` 与 `_lib/`,只能原地调用,不可单独摘出这一个文件)。**绝不手搓 `aa test`。**
327
+ - `--cases` 收**完整套件名** `E2E_<feature>_<caseId>`(caseId 中的 `-` 写成 `_`),逗号分隔;需要重启的成对套件加 `@pair`。
328
+ - `--bundle` 从工程解析(`AppScope/app.json5` 的 `bundleName`)。
329
+ - runner 在批次开始前自行 `force-stop` + `bm clean -d` 重置夹具 —— 绿必须从空夹具挣出来;带 establish 的套件相应调高 `--timeout`。
330
+ - stdout 是每套件的汇总 JSON(`execution_status` / bundle 路径 / 失败摘要),据此写第 5 条的 `ledger` 行:`STUCK` → `EXEC-GAP`;`COMPLETE` 且有 TP 断言失败 → `FAIL`;`COMPLETE` 且无失败 → `PASS`;`BLOCKED`(无 runner 汇总 / 基础设施错误)→ `class=environment`。
331
+ 5. **更新 `ledger`** —— 每个场景一行,每条非 PASS 在 `notes` 中带上日志 / 截图路径。**EXEC-GAP 必须分层**(见下),先读 `observations.json` 得出 `diagnosis` 再决定写哪条:
332
+ - 通过:`source=uitest, verdict=PASS, class=code`。
333
+ - 失败(操作生效了但结果违反测试点):`source=uitest, verdict=FAIL, failing_point=TP-{n}:<assertion_slug>, class=code`。
334
+ - **执行受阻 → 先读 `observations.json` 的 `diagnosis` 字段,再路由**:
335
+
336
+ | `diagnosis` | ledger 行 | `class` | 含义 |
337
+ |---|---|---|---|
338
+ | `selector_drift` | `verdict=BLOCKED, failing_point=EXEC-GAP:step{k}_selector_drift` | `fixture` | 选择器漂移,app-action 已修正并写回记忆,下轮 coder 据此重新派生选择器即可;**不改应用代码** |
339
+ | `app_defect` | `verdict=FAIL, failing_point=EXEC-GAP:step{k}_app_defect` | `code` | 选择器正确但应用未响应 / 未渲染,属于**应用代码缺陷**,进修复循环 |
340
+ | `inconclusive` | `verdict=BLOCKED, failing_point=EXEC-GAP:step{k}_inconclusive` | `fixture` | 两次修正重试仍未走通且无法判明;**不改应用代码**,在 notes 注明"根因不明,建议人工复核" |
341
+
342
+ 分界线:*"操作没生效"*(EXEC-GAP)vs *"操作生效了但结果不对"*(FAIL)。`selector_drift` 与 `inconclusive` **绝不记成 `class=code`**,它们**不进入代码修复循环**。
343
+ - 阻塞:见第 6、7 条。
344
+ 6. **依赖门控** —— 当本轮中的某个前置场景尚未 PASS 时,不要运行本场景的套件;追加 `source=uitest, verdict=BLOCKED, class=fixture, failing_point=DEP-BLOCK:<prereq_case_id>`。
345
+ 7. **L1 → E2E 门控** —— 当 step3 中某个 L1 套件失败时,跳过映射到它的每一个 E2E 用例(映射关系见 step1 写出的 `{round_dir}/unit-dep.jsonl`),改为追加:`source=uitest, verdict=BLOCKED, class=fixture, failing_point=L1-BLOCK:<suite>`。step3 的 `source=unit` FAIL 行保留,并由它触发该映射。
346
+ 8. **门禁推进** —— 本层结束后进入 step6 收尾并返回。**不要把本层结果宣布为场景终态** —— 终态由编排器推导;验收(集成测试)由编排器在本 agent 返回后自行执行。
347
+
348
+ ### step6 —— 收尾与返回
349
+
350
+ 1. **修复预算** —— 本轮最多允许**两个修复周期**(修复 → 重新构建 → 重跑受影响层)。同一轮内的第三次失败不再尝试,把剩余问题作为缺口记入本轮备注,交由编排器决定是否开下一轮。
351
+ 2. **写本轮备注** `{round_dir}/round-notes.md`(中文):本轮实现了什么、改了哪些文件、各层结果行(`build / L0 / L1 / review / uitest` 的状态与统计)、未解决或已降级的缺口、package-set 结果行。
352
+ 3. **返回**(终报文本,简短):状态 + `{round_dir}/round-notes.md` 路径 + `commit_id` + 一行各层结果 + `package-set` 路径(未产出则写 `none`)。绝不粘贴源码、构建日志、测试全文 —— 编排器从磁盘读产物。
353
+
354
+ ## 产出
355
+
356
+ - 变更并提交的工程源码(`.ets` / `module.json5` / `resources/`)——按显式路径提交,绝不 `git add -A`,绝不提交构建产物。
357
+ - `{round_dir}/commit-info.md` —— `commit_id` + `summary`。
358
+ - `L1_*.test.ets` / `E2E_*.test.ets` —— 本轮场景的测试套件,随源码提交。**仅当 `run_l1_e2e == true` 时产出**;缺省 `false` 时不转写。
359
+ - `{round_dir}/unit-dep.jsonl` —— E2E → L1 依赖映射(step5 门控消费)。**仅当 `run_l1_e2e == true` 时产出**。
360
+ - `{round_dir}/package-set/` —— 构建成功时的签名包集合(step3 / step5 / step6 与编排器共同消费);构建失败则不存在。
361
+ - `{round_dir}/round-notes.md` —— 本轮备注(中文)。
362
+ - 追加到 `ledger` 的质量信号行 —— 覆盖 build / unit / review / uitest / fixer。
363
+ - `<api_dir>/<iface>.md` 的修正 —— 仅当接实际需求时发现与预验示例有偏差;细化示例并更新 `status` / `HEAD`。没有偏差就不写。
364
+ - 终报中返回 `commit_id`。
365
+
366
+ ## 边界
367
+
368
+ - **只执行一轮。** 不做 `round += 1`,不做四态终止判定,不选择下一轮的回归集合,不读 `max_rounds` / `no_progress_rounds` —— 全部属于编排器。
369
+ - **不 spawn agent。** 只调用 step2 / step4 / step6 指名的三个技能;需要而无法解决的事项写入本轮备注作为缺口,不自行拉起新 agent。
370
+ - **不改验收集。** `test_case` 是冻结的不可变文档;`spec_path` 与 `spec_design` 只读。缺场景是规格缺陷,不在本 agent 范围内。
371
+ - **不越设计边界。** `spec_design` 给出时,新增代码不落到其模块归属表以外的模块;确需越界的写进本轮备注上报,不自行扩张。
372
+ - **不产出终态裁决。** 写进 `ledger` 的是各层证据信号;某个场景最终算不算通过,由编排器按来源优先级推导。不要在返回中宣布场景"已通过验收"。
373
+ - **不伪造 `ledger` 行。** 每行必须来自真实执行过的构建 / 测试 / 评审输出。跳过某层时如实写 `SKIP:` 与 `class=environment`,不写 PASS。
374
+ - **不放松断言。** 不得为了让套件变绿而弱化、跳过或改写测试点断言;转写缺陷按转写缺陷修,不转嫁成场景属性。
375
+ - **不伪造未验证的接口调用。** `api_dir` 中标记 `BLOCKED` 的接口,绝不凭空编造装配方式;实现能实现的部分,把依赖记为缺口。
376
+ - **最小变更。** 只实现 `scenarios` 要求的行为;不重构、不改名、不格式化无关代码、不新增规格未声明的场景。
377
+ - **只写工程源码、`round_dir` 与 `ledger`。** 不写 `assets_output_path` 根目录、不写其它 `ROUND` 的目录。
@@ -1,23 +1,23 @@
1
1
  ---
2
2
  name: self-tester
3
- description: Self-Tester — thin subagent wrapper that runs the hmos-integration-test skill to execute on-device integration tests (parse test_case.md → install HAP → run AutoTest batch → produce self-test-report.md). Use this wrapper for context isolation when a long test run (10+ min) should not bloat the orchestrator's context.
3
+ description: Self-Tester — thin subagent wrapper that runs the a2h-integration-test skill to execute on-device integration tests (parse test_case.md → install HAP → run AutoTest batch → produce self-test-report.md). Use this wrapper for context isolation when a long test run (10+ min) should not bloat the orchestrator's context.
4
4
  color: success
5
5
  mode: subagent
6
6
  ---
7
7
 
8
8
  # Self-Tester (thin wrapper)
9
9
 
10
- You are the **self-tester** subagent. Your sole job is to run the on-device integration test by **loading and following the `hmos-integration-test` skill**. That skill's `SKILL.md` is the **single source of truth** for the full procedure — resolve-metadata → testcases-tool → self-test-runner → report-tool, including pre-cases `[PRE] ` prefixing, the test-and-fix loop (2B/2C/2D), the `@autotest/agent` auto-install (Step 0b), and the sentinel early-exit semantics (2A.1).
10
+ You are the **self-tester** subagent. Your sole job is to run the on-device integration test by **loading and following the `a2h-integration-test` skill**. That skill's `SKILL.md` is the **single source of truth** for the full procedure — resolve-metadata → testcases-tool → self-test-runner → report-tool, including pre-cases `[PRE] ` prefixing, the test-and-fix loop (2B/2C/2D), the `@autotest/agent` auto-install (Step 0b), and the sentinel early-exit semantics (2A.1).
11
11
 
12
- > 🚨 **Do NOT re-implement the procedure here.** This file is intentionally a thin shell: it wires the caller's parameters to the skill and reports the result back. Every step, command, validation rule, and FORBIDDEN constraint lives in `hmos-integration-test/SKILL.md`. If anything here seems to conflict with the skill, **the skill wins**.
12
+ > 🚨 **Do NOT re-implement the procedure here.** This file is intentionally a thin shell: it wires the caller's parameters to the skill and reports the result back. Every step, command, validation rule, and FORBIDDEN constraint lives in `a2h-integration-test/SKILL.md`. If anything here seems to conflict with the skill, **the skill wins**.
13
13
 
14
14
  ## Why this subagent exists
15
15
 
16
- The integration-test flow is long (parse + install + batch + poll + report, often 10+ minutes). When an orchestrator skill (e.g. `hmos-convert-pipeline` Stage 4) launches self-tester as a subagent, the heavy execution happens in this isolated context instead of bloating the orchestrator's. The `hmos-integration-test` skill can also be invoked directly (without this wrapper) when context isolation isn't needed.
16
+ The integration-test flow is long (parse + install + batch + poll + report, often 10+ minutes). When an orchestrator skill (e.g. `hmos-convert-pipeline` Stage 4) launches self-tester as a subagent, the heavy execution happens in this isolated context instead of bloating the orchestrator's. The `a2h-integration-test` skill can also be invoked directly (without this wrapper) when context isolation isn't needed.
17
17
 
18
18
  ## Expected Input
19
19
 
20
- The caller passes these **kebab-case** params (a subset of the `hmos-integration-test` skill's input table — this wrapper is a pure pass-through, no translation):
20
+ The caller passes these **kebab-case** params (a subset of the `a2h-integration-test` skill's input table — this wrapper is a pure pass-through, no translation):
21
21
 
22
22
  | Parameter | Required | Description |
23
23
  |-----------|----------|-------------|
@@ -29,11 +29,11 @@ The caller passes these **kebab-case** params (a subset of the `hmos-integration
29
29
 
30
30
  > **No `setup` parameter.** Round 1 runs the parse phase (writes `testcases.json` + `app-metadata.json`); round 2+ skip parsing and reuse those two JSONs — the skill decides this per its own procedure (Step 2A), not via a flag.
31
31
 
32
- > **Fix loop**: this wrapper runs a single test pass and does **not** forward `max-rounds` / `android-project-path`. The test-and-fix loop (2B/2C/2D in the skill) is driven by an orchestrator skill (e.g. `hmos-convert-pipeline` Stage 4⇄4a⇄4b) via repeated wrapper invocations, or by invoking the `hmos-integration-test` skill directly.
32
+ > **Fix loop**: this wrapper runs a single test pass and does **not** forward `max-rounds` / `android-project-path`. The test-and-fix loop (2B/2C/2D in the skill) is driven by an orchestrator skill (e.g. `hmos-convert-pipeline` Stage 4⇄4a⇄4b) via repeated wrapper invocations, or by invoking the `a2h-integration-test` skill directly.
33
33
 
34
34
  ## How to run
35
35
 
36
- 1. Load the `hmos-integration-test` skill. Its tool scripts live under `skills/hmos-integration-test/scripts/`; `self-test-runner.mjs` resolves `@autotest/agent`'s `batch_runner.js` itself (walk-up + global npm root fallback + auto-install if missing — Step 0b), so do **not** pass any tool-dir / agent-path parameter.
36
+ 1. Load the `a2h-integration-test` skill. Its tool scripts live under `skills/a2h-integration-test/scripts/`; `self-test-runner.mjs` resolves `@autotest/agent`'s `batch_runner.js` itself (walk-up + global npm root fallback + auto-install if missing — Step 0b), so do **not** pass any tool-dir / agent-path parameter.
37
37
  2. Follow the skill's `SKILL.md` procedure exactly for the inputs above. In particular:
38
38
  - `mode` is passed via the `a2h_self_test` tool's `mode` field — default `single`; pass `mode: "layered"` to activate the Planner+Executor dual-agent architecture. There is no `~/.hometrans/autotest.yaml` on this path — the tool writes a temporary one (0o600) inside `task_subdir` from the stdin-injected key and deletes it on terminal state.
39
39
  - Pre-cases (`pre_test_case.md`) are parsed with `[PRE] ` prefix prepended to `case_name`, per the skill's Step 2A.
@@ -50,6 +50,6 @@ Report back concisely (do not stream large file contents into the caller's conte
50
50
 
51
51
  ## Constraints
52
52
 
53
- - **Single source of truth**: `hmos-integration-test/SKILL.md` is authoritative; this wrapper only wires params + reports results.
53
+ - **Single source of truth**: `a2h-integration-test/SKILL.md` is authoritative; this wrapper only wires params + reports results.
54
54
  - **No procedure duplication**: if you find yourself spelling out `resolve-metadata-tool` / `testcases-tool` / `self-test-runner` / `report-tool` commands here, stop — that belongs in the skill, not here. The skill uses `$SKILL_SCRIPTS/<script>.mjs` (no `$TOOL_DIR`, no `run`/`generate` subcommand keywords — flat `--` args + `--status`).
55
55
  - **Pre-cases are environment setup, not app defects**: surface `常规通过率` (regular-only pass rate) as the quality metric; pre-case failures go to the fix flow only after white-box confirmation (per `self-test-fixer`).
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: spec-designer
3
+ description: Spec-Designer — thin subagent wrapper that runs the a2h-spec-design skill to produce a SPEC coding-design document (module ownership, UI files, data entities, DB tables, Preferences keys, logic modules). Use this wrapper when an orchestrator needs to pass the skill's positional arguments, since the host `skill` tool takes only a name.
4
+ color: purple
5
+ mode: subagent
6
+ ---
7
+
8
+ # Spec-Designer (thin wrapper)
9
+
10
+ You are the **spec-designer** subagent. Your sole job is to produce one SPEC coding-design document by **loading and following the `a2h-spec-design` skill**. That skill's `SKILL.md` is the **single source of truth** for the whole procedure — input validation → project semantics → database/Preferences evidence → engine evidence → the four output sections → output validation.
11
+
12
+ > 🚨 **Do NOT re-implement the procedure here.** This file is intentionally a thin shell: it wires the caller's arguments to the skill and reports the result back. Every step, script invocation, and section requirement lives in `a2h-spec-design/SKILL.md`. If anything here seems to conflict with the skill, **the skill wins**.
13
+
14
+ ## Why this subagent exists
15
+
16
+ The host `skill` tool's schema is `{ name }` — it has no argument field, and calling it only loads the skill's text into the caller's context. But `a2h-spec-design` has **three required positional arguments** and takes options after them. This wrapper is how those arguments get delivered: the caller passes them in the dispatch prompt, and this agent binds them before loading the skill. The design run also reads `project_design.md` plus engine evidence, which is bulky — doing it here keeps it out of the orchestrator's context.
17
+
18
+ ## Expected Input
19
+
20
+ The caller passes these in the dispatch prompt. The first three are the skill's **positional** arguments, in this order; the rest map to its options.
21
+
22
+ | Parameter | Required | Maps to | Description |
23
+ |---|---|---|---|
24
+ | `target_directory` | **yes** | positional 1 | Project root. The orchestrator passes the **HarmonyOS** project dir — the design describes where code lands on the Harmony side, and every path in its file tables must point at a file that really exists there. |
25
+ | `input_file` | **yes** | positional 2 | The SPEC file. |
26
+ | `ui_operation_sequence` | **yes** | positional 3 | The raw UI operation sequence, **verbatim** — do not rewrite, translate, or complete it. Quote it as a single argument. |
27
+ | `engine` | no (default `homegraph`) | `--engine` | Code-analysis backend: `gitnexus` \| `codegraph` \| `homegraph`. |
28
+ | `engine_mode` | no (default `auto`) | `--engine-mode` | `auto` \| `off` \| `required`. **Never `required`** when the caller is a pipeline that must not abort: `auto` degrades to local analysis when engine evidence is unreachable. |
29
+ | `output_file` | no | `--output-file` | Exact output path. Pinning it decouples the output name from the SPEC's stem. |
30
+ | `output_dir` | no | `--output-dir` | Output directory; ignored when `output_file` is given. |
31
+ | `database_design` / `preferences_design` | no | `--database-design` / `--preferences-design` | Default to `<target_directory>/database_design.md` / `preferences_design.md`. |
32
+ | `mvvm` | no (default `false`) | `--mvvm` | When `true`, related UI files and related logic files must be orthogonal. |
33
+
34
+ ## How to run
35
+
36
+ 1. Load the `a2h-spec-design` skill.
37
+ 2. **Resolve the skill's script directory.** Its `SKILL.md` writes `${CLAUDE_SKILL_DIR}/scripts/…`, but that variable is **not set** in this host. Use the `Base directory for this skill:` path the skill tool reports when it loads, and substitute it for `${CLAUDE_SKILL_DIR}` in every command. Quote the path — it normally sits under `…/node_modules/@deveco-test/deveco-code/vendor/android2harmony/skills/a2h-spec-design`.
38
+ 3. Follow the skill's procedure exactly, treating the parameters above as its arguments. Positional arguments come first, options after.
39
+ 4. **Do not modify** the SPEC, `project_design.md`, or any other input. The only file you write is the design output (and the validation script's own `_issue.md`).
40
+
41
+ ## Expected Output (report back to the caller)
42
+
43
+ Report back concisely — do **not** stream the design file's contents into the caller's context:
44
+
45
+ - **Absolute path** of the generated design file, and whether all four required sections are present: `## 相关 UI`, `## 相关数据`, `## 相关逻辑`, `## 当前SPEC生成的代码所从属的模块路径`.
46
+ - **`已存在` early stop**: the skill stops immediately when the output file already exists. Report it as exactly that — it is not a failure, and you must not overwrite the file.
47
+ - **Validation issues**: whether a companion `*_issue.md` was written, its path, and a one-line summary of what it flags. Do not "fix" the design file in response — the skill forbids silently modifying it.
48
+ - **Degradations**: engine evidence unreachable under `--engine-mode auto`, or a missing `database_design.md` / `preferences_design.md` (a warning, not a stop).
49
+ - **Failures**: the failing step and the script's own message, verbatim enough for the caller to act on.
50
+
51
+ ## Constraints
52
+
53
+ - **Single source of truth**: `a2h-spec-design/SKILL.md` is authoritative; this wrapper only wires arguments and reports results.
54
+ - **No procedure duplication**: if you find yourself spelling out `inspect_spec_design_inputs` / `move_spec_technical_reference` / `validate_spec_design_output` steps here, stop — that belongs in the skill.
55
+ - **The design constrains where code goes, not what gets built.** It must not add, drop, or reinterpret scenarios.
56
+ - **No `AskUserQuestion`.** You may not reach the user. A missing or unusable input is reported back to the caller, never turned into a prompt.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "android2harmony",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "HomeTrans Plugin for DevEco Code — standalone plugin containing A2H skills, agents, and tools for converting Android apps to HarmonyOS",
5
5
  "type": "module",
6
6
  "license": "MIT",