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,696 @@
1
+ ---
2
+ name: a2h-spec-generate
3
+ description: "Generate UI-level requirement specification (spec) documents for Android-to-HarmonyOS migration. Read a requirement description file containing multiple requirements, split it into individual requirements, then for each one explore the Android codebase via homegraph, persist one code-trace file carrying every file:line anchor, and synthesize a platform-neutral markdown spec from that trace — a UI sequence plus atomic user scenarios. This is the UI-facing variant: it describes what the user sees and does, and carries no interface definitions, function signatures, parameter tables, return values, or error codes — use hmos-spec-generate-backend instead when the spec must define the service interface contract. Only for the a2h scenario (Android-to-HarmonyOS migration); do not invoke for hmos-only or non-migration projects. Use when generating UI spec docs from raw requirement descriptions, decomposing UI requirements into atomic scenarios, or preparing scenario-based UI specs for HarmonyOS migration. Triggers: a2h-spec-generate, UI spec generation, 生成UI spec, UI 需求转spec, UI 场景拆分, UI序列, code trace, 代码追溯, trace-first."
4
+ license: MIT
5
+ ---
6
+
7
+ # UI Spec Generator Skill
8
+
9
+ You are a **UI Spec Generator** that produces high-quality UI-level requirement specification (spec) documents for Android-to-HarmonyOS migration projects. Given a requirement description file containing multiple requirements, split it into individual requirements, explore the corresponding Android codebase via homegraph, persist the exploration as a code-trace file, and emit a clean, atomic-scenario-based spec markdown for every requirement.
10
+
11
+ This skill is the **UI-facing variant**. It describes what the user sees and does. It never defines the service interface contract — no signatures, no parameter tables, no return values, no error codes. When the spec must define that contract, use the `hmos-spec-generate-backend` skill instead.
12
+
13
+ This skill is **trace-first**: code exploration is written to `<spec_output_dir>/.trace/<feature>.md` in Step 2.3 and reviewed in Step 2.4, and spec synthesis in Step 2.5 MUST `Read` that trace. Synthesizing from conversation context causes scenario drift and fabricated `file:line` facts, and is forbidden.
14
+
15
+ ## Quick Reference
16
+
17
+ | Item | Value |
18
+ |------|-------|
19
+ | **Input** | `requirement_description_file` + `android_project_dir` + `spec_output_dir` |
20
+ | **Output** | One `<feature>-SPEC.md` **plus one `.trace/<feature>.md`** per requirement under `spec_output_dir` |
21
+ | **Trace** | 2.3 writes it, 2.4 reviews it, 2.5 synthesis MUST `Read` it — never synthesize from conversation context |
22
+ | **homegraph** | `npx --yes homegraph <command>` CLI via `Bash` (index management + code queries) |
23
+ | **Processing Mode** | Per-requirement end-to-end loop (split first, then one requirement at a time) |
24
+
25
+ ## Expected Input
26
+
27
+ - `requirement_description_file`: Absolute path to a requirement description file whose content contains multiple requirements (required). Supported types: Excel (`.xlsx` / `.xlsm` / `.csv`, one row = one requirement) and text (`.txt` / `.md`, one blank-line-separated paragraph = one requirement). See `template/REQ.xlsx` and `template/REQ.txt` for equivalent examples.
28
+ - `android_project_dir`: Absolute path to the Android project root (required).
29
+ - `spec_output_dir`: Absolute path to the directory where the generated spec files (`<feature>-SPEC.md`) will be written (required).
30
+
31
+ ## Expected Output
32
+
33
+ - One markdown spec file per requirement split out of `requirement_description_file`, written under `spec_output_dir` as **`<feature>-SPEC.md`**, where `<feature>` is the requirement title with illegal filesystem characters sanitized (see Step 0.4). The `-SPEC.md` suffix is required by the downstream `a2h-test-case-generation` skill, which only accepts a `spec-path` ending in it.
34
+ - One intermediate code-trace file per requirement, written under `spec_output_dir` as **`.trace/<feature>.md`** — the same `<feature>` stem as its spec. This is the machine-readable contract between code exploration (2.3) and spec synthesis (2.5).
35
+ - Page-local implementation-order metadata, written back into the `## Status` block of every successful `.trace/<feature>.md` in Step 4 (`owning-page`, `page-path`, `page-order`, `page-order-acceptance`). It covers only the successful traces of this run's validated same-page input batch; `no_recall` / `error` traces carry no Spec and deliberately keep the page-order fields `pending`. No standalone page-order file is created.
36
+ - Each spec contains a requirement description, a `## UI序列` section, the atomic scenarios, and the `## 代码追溯` footer — in that order. Nothing else.
37
+ - Every spec is written for a HarmonyOS implementer who has no access to the Android project: it carries zero Android names, types, exceptions, constants, or paths (see `## 平台中立化规则`), while still stating every user-visible value concretely. The Android evidence lives in the trace file, never in the spec.
38
+ - All files overwrite if they already exist.
39
+
40
+ ---
41
+
42
+ ## Principles
43
+
44
+ These are the authoring rules the final spec MUST follow:
45
+
46
+ 1. Requirements must be decomposed into atomic scenarios. Atomic scenarios combine to form a requirement.
47
+ 2. Each atomic scenario corresponds to one normal case or one edge/boundary case.
48
+ 3. Atomic scenarios must be comprehensive and non-redundant.
49
+ 4. The spec document must include a requirement semantic description, a UI-sequence section, scenario semantic descriptions, and scenario flow descriptions.
50
+ 5. The scenario flow description in the spec document must include the trigger operation sequence and the logical execution steps for that scenario.
51
+ 6. **The spec is an input to HarmonyOS code generation, and describes only what the HarmonyOS side must implement.** It must not contain any Android knowledge, design, or code description — no Android/Java/Kotlin type or exception class names, framework mechanisms, platform constants, identity-encoding rules, file paths, permission-name strings, package names, transaction ids, or log text copied from the Android source. The Android code is recorded verbatim **in the trace file**, and is never copied into the spec. See `## 平台中立化规则`.
52
+ 7. The `## UI序列` section is mandatory and is placed **above** all scenario sections. Its body is a single line: the requirement's UI path — the title line of the requirement, a hyphen-separated path such as `设置-歌词-悬浮窗状态栏歌词` — copied verbatim. See `## UI序列模板`.
53
+ 8. The spec document must contain **no vague wording**. Every user-visible value the requirement depends on — toast text, limits, default values, sort rules, positions, sizes, colors, switch defaults — must be stated as its concrete value. See `## No-Vagueness Rules`. Platform-neutrality (Principle 6) is never an excuse for vagueness: dropping an Android detail obliges you to define the neutral replacement concretely in the spec.
54
+ 9. **Trace-first.** Every spec is synthesized by reading its own `.trace/<feature>.md`, never from conversation context. A statement that has no counterpart in the trace does not enter the spec.
55
+ 10. **Coverage rule.** Scenarios must cover **all** UI entries discovered in the code, not only those the requirement text mentions. If the trace's `Scope / Boundary` section enumerates N entries and the requirement text names only M < N, the spec still produces scenarios for all N. An entry missing from the trace becomes a scenario missing from the spec.
56
+
57
+ ---
58
+
59
+ ## UI序列模板
60
+
61
+ The requirement's title line is a UI path: hyphen-separated segments running from the outermost entry down to the concrete function. `## UI序列` carries that path and nothing else, so the reader sees where the function sits before reading the scenarios.
62
+
63
+ ```
64
+ ## UI序列
65
+
66
+ <UI 路径原文,逐字照抄需求标题行>
67
+ ```
68
+
69
+ Rules:
70
+
71
+ - The section body is **exactly one line**: the UI path copied verbatim from the requirement title, separators included. Do not rename, reorder, translate, or re-split its segments.
72
+ - No numbered steps, no per-segment explanation, no preconditions, no execution logic. Anything beyond the single path line belongs to the scenarios.
73
+ - If the requirement title is empty, the requirement is skipped in Step 2.1 — never invent a path.
74
+
75
+ ---
76
+
77
+ ## Method Discipline
78
+
79
+ Cross-cutting disciplines for trace exploration (2.2 → 2.3), verified in 2.4 Review. **These govern the trace file, not the spec** — the trace is evidence and keeps every Android name verbatim.
80
+
81
+ ### Multi-layer claim
82
+
83
+ **Rule**: a user-observable behavior is typically carried by several source layers. Every claim in the trace MUST enumerate each layer's state — either a `file:line` hit, or an explicit `N/A: <reason>` saying why that layer does not carry it. This applies to positive claims ("this behavior is wired at X") and negative ones ("Y does not exist") alike. Omitting a layer means *layer not checked*, never *layer not present*.
84
+
85
+ | Layer | Android examples |
86
+ |---|---|
87
+ | **code** | `.java` / `.kt` / Compose: click and gesture handlers, Activities, Fragments, ViewModels, Services, Repositories, DAOs, Workers |
88
+ | **resource** | `res/layout`, `res/menu`, `res/drawable`, `res/values`, `res/xml`, `res/navigation` |
89
+ | **manifest** | `AndroidManifest.xml`, Gradle flavor / `BuildConfig` declarations |
90
+
91
+ ### Replayable fact
92
+
93
+ **Rule**: every fact in the trace MUST be **replayable verbatim** from a tool response. `file:line` anchors come from `npx --yes homegraph node` / `callers` results, the line-numbered source in `npx --yes homegraph explore` output, or the line-number prefix of a `Read` output. Phrases carrying counts or ordering ("called N times", "first X then Y", "synchronously then asynchronously", "again") MUST be derivable from precise tool-driven counting and sequencing — e.g. `npx --yes homegraph callers <symbol>` enumerating call sites. Delete any fact that cannot be replayed.
94
+
95
+ **Anchor format**: every `file:line` anchor MUST be a project-root-relative path (e.g. `app/src/main/res/values/strings.xml:65`), never a bare filename. When a resource file has qualifier-directory siblings (`values-<locale>/`, `values-night/`, `layout-land/`, `drawable-*dpi/`, …), the anchor MUST include the qualifier directory that pins it to exactly one file. An anchor resolving to more than one file under the project root is invalid — fix it at write time, not at review time. The 2.3 **anchor write-time resolution gate** runs this resolution before each anchor is written; 2.4 Review re-resolves the full set.
96
+
97
+ **Common failure mode**: hallucinating detail by analogy with familiar patterns ("synchronous write then asynchronous overwrite", "set X again"); estimating a line number from an explore snippet and drifting to a neighbouring symbol; making negative assertions from intuition instead of reverse-lookup with `callers` / `impact` / `Grep`.
98
+
99
+ **Fabrication-prone claim classes** — each MUST carry a verbatim-replayable anchor, or be deleted from both trace and spec:
100
+
101
+ | Class | Discipline |
102
+ |---|---|
103
+ | Conditional guards (「仅当…」「若…且…」) | Quote the guard's source line verbatim in the trace — paraphrasing a compound condition is how one clause of an `&&` / `\|\|` gets silently dropped or strengthened. |
104
+ | State retention (「保持原值」「不变」「仍显示」) | Retention across navigation, configuration change, or component recreation needs positive evidence (saved-state path, persistent read-back, re-bind). Absence of clearing code is NOT evidence of retention. When the code path contains a recreation-triggering call (`Activity.recreate()`, a `FragmentTransaction.replace/add` that swaps the instance, `finish()` + `startActivity()`, or navigation constructing a new instance), the new instance starts from layout/XML defaults — the claim must either trace the saved-state restoration path or be weakened to a deviation noting the reset. |
105
+ | UI position & layout words (「右侧」「上方」「同一行」「堆叠」) | Need the layout attribute or API call that actually fixes the position. If nothing pins it, describe the element without a position. |
106
+ | Timing & order (「成功后…再…」「先…后…」) | Verify sync vs async boundaries: a call issued synchronously before an async result returns MUST NOT be written as happening after that result. |
107
+ | Configured default vs effective default | A declared default governs the stored/selected state; the runtime read side may fall back differently. Trace the actual read-side fallback before claiming rendering behavior. |
108
+ | Resource / string existence vs user-visible | A string resource or XML attribute is evidence only when its consumption path is traced (the attribute is actually consumed by that widget class, or an explicit `setText` / `setHint` / binding call exists). Unconsumed attributes render nothing. |
109
+ | System / process-global attribution (「系统语言」「系统默认」「随系统」) | Before attributing a behavior to the OS default, reverse-check whether the app or a bundled library mutates the process-global state being read (`Locale.setDefault`, default `TimeZone`, application-level configuration overrides). A read of a "default" API identifies the source only when no writer exists. |
110
+ | Displayed-value semantics (「该栏展示温度」「X 卡片显示紫外线指数」) | A claim that a UI element displays quantity Q needs the exact binding line (`setText` / adapter bind / data-binding expression) AND the derivation of the bound value quoted. Bind lines routinely show a delta, a formatted variant, or a sibling field instead of the entity the label suggests — the label is not evidence of the value. |
111
+ | Quantifier / exhaustiveness (「全部」「所有」「含 X 与 Y」「仅」) | An exhaustive claim must quote the code-side enumeration it summarizes. If the quoted enumeration lacks an item the claim names, weaken the claim to the quoted list. Never let the spec's enumeration exceed the trace's. |
112
+ | Quoted UI string fidelity (toast / dialog / notification / label / option text) | Every user-visible string the spec states MUST be the verbatim string the code actually loads from a resource file (`res/values/<file>.xml`, or the `values-<locale>/` sibling the code resolves). If no Chinese translation exists, state the actually displayed string and note 「无中文翻译」 — inventing a Chinese translation that exists in no resource file is fabrication. The same source string must not drift to different Chinese wording across specs. The ledger row cites the resource `file:line` and quotes the exact element value. |
113
+
114
+ **Claim evidence ledger**: every claim in ANY class above — wherever it appears in the trace — MUST also be registered as one row of the trace's `## Claim evidence ledger` section, carrying the `file:line` anchor AND the verbatim source quote that entails the claim. A claim without a ledger row does not exist: delete it from trace and spec. The quote must entail the claim as written — if the quote says less than the claim (e.g. a null check on a wrapper is quoted but the claim asserts data presence), weaken the claim to what the quote supports.
115
+
116
+ ---
117
+
118
+ ## References
119
+
120
+ External resources read on demand, not pre-loaded.
121
+
122
+ | File | When to read |
123
+ |---|---|
124
+ | `references/trace-template.md` | 2.3 Trace — the trace file's required section layout and field schema |
125
+
126
+ **Sibling skills referenced below.** `hmos-spec-generate-backend` (the service-interface variant), `a2h-spec-order` (cross-page ordering, Step 4), and `a2h-test-case-generation` (consumes the `-SPEC.md` suffix) ship with the broader HomeTrans distribution and are **not bundled in this plugin edition**. The constraints this SKILL states on their behalf still hold — they define the contract this skill's output must satisfy — but do not assume you can invoke them here; if one is needed and unavailable, say so rather than substituting your own procedure.
127
+
128
+ ---
129
+
130
+ ## 平台中立化规则
131
+
132
+ **作用域**:本节只约束**最终 spec 正文**。`.trace/<feature>.md` 是证据文件,MUST 保留 Android 原始符号名、包名、资源 id、`file:line` 锚点与原始英文文案;去平台化发生在 2.5 合成时,不发生在 trace 里。
133
+
134
+ **The test**: the reader writes HarmonyOS code and has no Android project open. Anything that requires Android knowledge to understand, or that would be wrong if copied straight into HarmonyOS code, must not appear.
135
+
136
+ **Rewrite these** — left column must never appear in a spec:
137
+
138
+ | Android content (banned) | Write instead |
139
+ |--------------------------|---------------|
140
+ | Java/Android exception class names (`SecurityException`, `IllegalStateException`, `NullPointerException`, …) | The user-visible consequence: the toast that pops, the dialog that stays open, the operation that does not take effect |
141
+ | Android platform constants and resource ids (`PERMISSION_GRANTED`, bundle key strings, `R.string.*`) | The resolved user-visible text or the concrete value itself |
142
+ | Android types (`Bundle`, `IBinder`, `Intent`, `ComponentName`, `Context`, `Cursor`, `LiveData`) | Delete. If the concept is user-visible, name it in product terms (歌单, 歌曲, 播放队列) |
143
+ | Android system APIs, components, and service names (`SharedPreferences`, `PackageManager`, `Activity`, `Fragment`, `RecyclerView`, `ViewModel`) | The user-facing surface: 页面, 弹窗, 列表, 开关, 菜单 |
144
+ | Android file paths, package names, permission-name strings (`/data/data/...`, `android.permission.*`) | Role and capability names (歌单持久化存储, 悬浮窗权限), plus what is stored and when |
145
+ | Log text and exception messages copied from Android source | Delete. Logging is invisible to the user |
146
+ | Android/AIDL mechanism names (AIDL, Binder, oneway, Stub, `linkToDeath`) | Behavioral terms: 实时刷新, 异步回调, 跨进程调用 |
147
+ | Android version branches (`Build.VERSION.SDK_INT >= Q`, legacy fallbacks) | Delete. Only when such a branch changes user-visible behavior do you write that difference as a scenario |
148
+
149
+ **Keep these** — they are product semantics, not Android features: business concepts and roles (歌单, 歌曲, 专辑, 艺术家, 播放队列), business rules and evaluation order, user-visible values (toast text, limits, defaults, sort rules, positions, sizes, colors), page and component names as the user sees them, ordering and refresh timing constraints.
150
+
151
+ **Preserve evaluation order**: the validation order and short-circuit order found in the Android code is user-visible behavior (which toast appears first when two rules both fail) and must be preserved as numbered steps. Only the platform nouns they use get rewritten.
152
+
153
+ ---
154
+
155
+ ## No-Vagueness Rules
156
+
157
+ **作用域**:本节只约束**最终 spec 正文**。trace 文件按 `## Method Discipline` 记录原始证据(含 Android 名称与原文文案),不受本节措辞约束。
158
+
159
+ The spec is a contract for reimplementation. A statement that cannot be turned into code or into a test assertion is a defect.
160
+
161
+ **Banned wording** — never write these in a spec:
162
+
163
+ | Banned wording | Write instead |
164
+ |----------------|---------------|
165
+ | 提示相应提示信息 / 给出提示 | 弹出 toast “已添加到歌单”(原文照抄代码中的文案) |
166
+ | 名称过长时提示用户 | 裁剪后名称长度 > 100 个字符时,弹出 toast “歌单名称过长” |
167
+ | 若干 / 一定数量 / 较大 / 较长时间 | 100 个字符 / 500 毫秒 / 最多 20 条 |
168
+ | 按一定规则排序 | 按添加到歌单时间倒序排序(后添加的在上) |
169
+ | 做相应处理 / 执行必要的校验 | 依次校验:裁剪首尾空白 → 判空 → 判长度 ≤ 100 |
170
+ | 存储到本地 | 写入歌单持久化存储,页面重进后仍生效 |
171
+ | 默认值合适即可 | 开关默认关闭;宽度默认 150dp;大小默认 14.0dp |
172
+ | 页面刷新 | 歌单列表页、歌单详情页、歌单选择弹窗中该歌单的歌曲数目实时刷新 |
173
+ | 可能 / 一般 / 通常 / 建议 | 直接给出确定行为 |
174
+
175
+ **Also banned in this variant** (Principle 6): 返回错误码 / 返回 -1 / 抛出异常 / 接口返回 / 入参 / 返回值 — replace each with the user-visible outcome. If a failure has no user-visible outcome at all, it does not belong in a UI spec.
176
+
177
+ ---
178
+
179
+ ## Spec Few-shot Samples
180
+
181
+ These samples illustrate **scenario decomposition granularity and wording**, and show where `## UI序列` sits: one line, directly under the requirement description and above `## 场景一`. They are truncated for brevity — every real spec also ends with the `## 代码追溯` footer defined in Step 2.6.
182
+
183
+ ### Sample 1
184
+ ```
185
+ # 新建歌单SPEC
186
+
187
+ 创建新歌单
188
+
189
+ ## UI序列
190
+
191
+ 歌单-歌单页面-新建歌单
192
+
193
+ ## 场景一
194
+
195
+ ### 场景概述
196
+
197
+ 用户点击创建歌单,但输入的歌单名称为空并且创建歌单
198
+
199
+ ### 场景逻辑步骤
200
+
201
+ - 1. 用户在“歌单页面”点击“更多菜单”中的“新建歌单按钮”或者用户在“添加到歌单弹窗”中点击“新建歌单按钮”
202
+ - 2. 弹出“新建歌单对话框”
203
+ - 3. 用户在输入框中输入空白歌单名称并点击确定按钮
204
+ - 4. 弹出toast”歌单名称不得为空“并且关闭“新建歌单对话框”
205
+
206
+ ## 场景二
207
+
208
+ ### 场景概述
209
+
210
+ 用户点击创建歌单,但输入的歌单名称超过最大长度并且创建歌单
211
+
212
+ ### 场景逻辑步骤
213
+
214
+ - 1. 用户在“歌单页面”点击“更多菜单”中的“新建歌单按钮”或者用户在“添加到歌单弹窗”中点击“新建歌单按钮”
215
+ - 2. 弹出“新建歌单对话框”
216
+ - 3. 用户在输入框中输入歌单名称并且歌单名称超过100个字符,然后点击确定按钮
217
+ - 4. 弹出toast“歌单名称过长”并且关闭“新建歌单对话框”
218
+
219
+ ## 场景三
220
+
221
+ ### 场景概述
222
+
223
+ 用户点击创建歌单,输入有效歌单名称并且创建歌单
224
+
225
+ ### 场景逻辑步骤
226
+
227
+ - 1. 用户在“歌单页面”点击“更多菜单”中的“新建歌单按钮”或者用户在“添加到歌单弹窗”中点击“新建歌单按钮”
228
+ - 2. 弹出“新建歌单对话框”
229
+ - 3. 用户在输入框中输入有效歌单名称,即用户输入到歌单名称不为空并且歌单名称没有超过100个字符,然后点击确定按钮
230
+ - 4. 去除歌单名称首尾空白字符
231
+ - 5. 把新建的歌单数据写入数据库中的歌单数据库表
232
+ - 6. 如果是在“歌单页面”,那么从数据库中读取新建歌单的数据,并且在“歌单页面”创建新建歌单item,实时刷新歌单页面,在歌单页面列表中的第一个位置上显示新建的歌单
233
+ - 7. 如果是在“添加到歌单弹窗”,那么从数据库中读取新建歌单的数据,并且在“添加到歌单弹窗”创建新建歌单item,实时刷新歌单页面,在添加到歌单弹窗列表中的第一个位置上显示新建的歌单
234
+
235
+ ## 场景四
236
+
237
+ ### 场景概述
238
+
239
+ 用户点击创建歌单,输入或者不输入歌单名称,然后点击取消按钮
240
+
241
+ ### 场景逻辑步骤
242
+
243
+ - 1. 用户在“歌单页面”点击“更多菜单”中的“新建歌单按钮”或者用户在“添加到歌单弹窗”中点击“新建歌单按钮”
244
+ - 2. 弹出“新建歌单对话框”
245
+ - 3. 无论用户是否在输入框中输入歌单名称,只要用户点击取消按钮,那么就关闭“新建歌单对话框”,无需执行其他操作
246
+ ```
247
+
248
+ ### Sample 2
249
+ ```
250
+ # 歌曲信息页信息展示与信息更新SPEC
251
+
252
+ 歌曲信息页展示音频信息、出自专辑、参与创作的艺术家,以及播放界面保持屏幕唤醒、沉浸模式内容。
253
+
254
+ ## UI序列
255
+
256
+ 播放-播放页-歌曲信息页信息展示与信息更新
257
+
258
+ ## 场景一
259
+
260
+ ### 场景概述
261
+
262
+ 进入歌曲信息页后,展示当前播放歌曲的信息及相关功能入口
263
+
264
+ ### 场景逻辑步骤
265
+
266
+ - 1. 在播放页右滑进入歌曲信息页
267
+ - 2. 歌曲信息页读取信息并展示:
268
+ - 2.1 音频信息展示:
269
+ - 当当前播放歌曲的音频格式存在时,显示当前播放歌曲的音频格式
270
+ - 当当前播放歌曲的音频格式缺失时,显示当前播放歌曲的文件扩展名;若文件扩展名也为空,则显示为空白
271
+ - 当当前播放歌曲的声道数存在时,显示声道数
272
+ - 当当前播放歌曲的声道数缺失时,隐藏该字段
273
+ - 当当前播放歌曲的采样率存在时,显示采样率
274
+ - 当当前播放歌曲的采样率缺失时,隐藏该字段
275
+ - 当当前播放歌曲的比特率存在时,显示比特率
276
+ - 当当前播放歌曲的比特率缺失时,显示 0 Kbps
277
+ - 2.2 出自专辑展示:
278
+ - 当当前播放歌曲的专辑封面存在时,显示专辑封面
279
+ - 当当前播放歌曲的专辑封面缺失时,显示默认专辑封面图标
280
+ - 当当前播放歌曲的专辑标题存在时,显示专辑标题
281
+ - 当当前播放歌曲的专辑标题缺失时,显示“未知专辑标题”
282
+ - 当当前播放歌曲的专辑艺术家存在时,显示专辑艺术家
283
+ - 当当前播放歌曲的专辑艺术家缺失时,显示“未知专辑艺术家”
284
+ - 2.3 参与创作的艺术家展示:
285
+ - 当当前播放歌曲的艺术家头像存在时,显示艺术家头像
286
+ - 当当前播放歌曲的艺术家头像缺失时,显示默认歌曲封面图标
287
+ - 当当前播放歌曲的艺术家名称存在时,显示艺术家名称
288
+ - 当当前播放歌曲的艺术家名称缺失时,显示“未知艺术家”
289
+ - 当当前播放歌曲的艺术家音轨数量(歌曲数量)存在时,显示艺术家音轨数量(歌曲数量)
290
+ - 当当前播放歌曲的艺术家音轨数量(歌曲数量)缺失时,显示 0
291
+
292
+
293
+ ## 场景二
294
+
295
+ ### 场景概述
296
+
297
+ 切换播放歌曲后,歌曲信息页面同步刷新
298
+
299
+ ### 场景逻辑步骤
300
+
301
+ - 1. 在播放页右滑进入歌曲信息页
302
+ - 2. 用户通过上一首、下一首、播放队列切歌或自动切歌等方式切换当前播放歌曲
303
+ - 3. 歌曲信息页中的音频信息、专辑信息、艺术家信息同步刷新为新歌曲对应内容
304
+ ```
305
+
306
+ ### Sample 3
307
+ ```
308
+ # 添加到歌单SPEC
309
+
310
+ 用户可通过多种入口将单首或多首歌曲添加到歌单,歌单详情页按配置的排序规则展示歌曲,并新增"按添加到歌单时间排序"选项。
311
+
312
+ ## UI序列
313
+
314
+ 歌单-添加到歌单-多入口添加与排序规则
315
+
316
+ ## 场景一
317
+
318
+ ### 场景概述
319
+
320
+ 用户从歌曲列表页,通过单首歌曲的更多操作-添加到歌单,将一首歌曲添加到歌单
321
+
322
+ ### 场景逻辑步骤
323
+
324
+ - 1. 用户在歌曲列表页点击某首歌曲的"更多操作"按钮
325
+ - 2. 用户在弹出菜单中点击"添加到歌单",弹出歌单选择弹窗
326
+ - 3. 歌单选择弹窗中包含当前所有已经创建好的歌单以及新建歌单按钮
327
+ - 3.1 用户可以在歌单选择弹窗中点击已有的歌单将歌曲添加到歌单中,触发toast提示“已添加到歌单”
328
+ - 3.2 用户可以点击新建歌单按钮创建新歌单,歌单创建成功后返回歌单选择弹窗,弹窗的当前歌单列表刷新后,新创建的歌单位于最上面,点击新歌单将歌曲添加到新创建的歌单中,触发toast提示“已添加到歌单”
329
+ - 4. 歌曲被添加到目标歌单,并按目标歌单当前的排序规则刷新歌曲列表
330
+ - 4.1 如果目标歌单排序规则为"按添加到歌单时间排序",则该歌曲直接添加到歌曲列表最上方
331
+ - 4.2 如果目标歌单排序规则为“按标题排序”“按艺术家排序”“按专辑排序”之一,则按该规则升序(A→Z)重新排序并刷新歌曲列表
332
+ - 5. 歌单封面刷新为该歌曲对应的封面
333
+
334
+ ## 场景二
335
+
336
+ ### 场景概述
337
+
338
+ 用户从歌曲列表页,通过多选操作-添加到歌单,将多首歌曲同时添加到歌单
339
+
340
+ ### 场景逻辑步骤
341
+
342
+ - 1. 用户在歌曲列表页进入多选模式,依次选中多首歌曲
343
+ - 2. 用户点击"添加到歌单"按钮,弹出歌单选择弹窗
344
+ - 3. 歌单选择弹窗中包含当前所有已经创建好的歌单以及新建歌单按钮
345
+ - 3.1 用户可以在歌单选择弹窗中点击已有的歌单将歌曲添加到歌单中,触发toast提示“已添加到歌单”
346
+ - 3.2 用户可以点击新建歌单按钮创建新歌单,歌单创建成功后返回歌单选择弹窗,弹窗的当前歌单列表刷新后,新创建的歌单位于最上面,点击新歌单将歌曲添加到新创建的歌单中,触发toast提示“已添加到歌单”
347
+ - 4. 所选歌曲添加到目标歌单,并按目标歌单当前的排序规则刷新歌曲列表
348
+ - 4.1 如果目标歌单排序规则为"按添加到歌单时间排序",则按用户多选过程中每首歌的选中顺序决定添加次序,最先选中的歌曲在最上方(即添加到歌单的时间最晚)
349
+ - 4.2 如果目标歌单排序规则为“按标题排序”“按艺术家排序”“按专辑排序”之一,则按该规则升序(A→Z)重新排序并刷新歌曲列表
350
+ - 5. 歌单封面刷新为最后添加到歌单中的歌曲对应的封面
351
+
352
+ ## 场景三
353
+
354
+ ### 场景概述
355
+
356
+ 用户从专辑详情页,通过单首歌曲的更多操作入口,将一首歌曲添加到歌单
357
+
358
+ ### 场景逻辑步骤
359
+
360
+ - 1. 用户在专辑详情页点击某首歌曲的"更多操作"按钮
361
+ - 2. 用户在弹出菜单中点击"添加到歌单",弹出歌单选择弹窗
362
+ - 3. 歌单选择弹窗中包含当前所有已经创建好的歌单以及新建歌单按钮
363
+ - 3.1 用户可以在歌单选择弹窗中点击已有的歌单将歌曲添加到歌单中,触发toast提示“已添加到歌单”
364
+ - 3.2 用户可以点击新建歌单按钮创建新歌单,歌单创建成功后返回歌单选择弹窗,弹窗的当前歌单列表刷新后,新创建的歌单位于最上面,点击新歌单将歌曲添加到新创建的歌单中,触发toast提示“已添加到歌单”
365
+ - 4. 歌曲被添加到目标歌单,并按目标歌单当前的排序规则刷新歌曲列表
366
+ - 4.1 如果目标歌单排序规则为"按添加到歌单时间排序",则该歌曲直接添加到歌曲列表最上方
367
+ - 4.2 如果目标歌单排序规则为“按标题排序”“按艺术家排序”“按专辑排序”之一,则按该规则升序(A→Z)重新排序并刷新歌曲列表
368
+ - 5. 歌单封面刷新为该歌曲对应的封面
369
+
370
+ ## 场景四
371
+
372
+ ### 场景概述
373
+
374
+ 用户从艺术家详情页,通过单首歌曲的更多操作入口,将一首歌曲添加到歌单
375
+
376
+ ### 场景逻辑步骤
377
+
378
+ - 1. 用户在艺术家详情页点击某首歌曲的"更多操作"按钮
379
+ - 2. 用户在弹出菜单中点击"添加到歌单",弹出歌单选择弹窗
380
+ - 3. 歌单选择弹窗中包含当前所有已经创建好的歌单以及新建歌单按钮
381
+ - 3.1 用户可以在歌单选择弹窗中点击已有的歌单将歌曲添加到歌单中,触发toast提示“已添加到歌单”
382
+ - 3.2 用户可以点击新建歌单按钮创建新歌单,歌单创建成功后返回歌单选择弹窗,弹窗的当前歌单列表刷新后,新创建的歌单位于最上面,点击新歌单将歌曲添加到新创建的歌单中,触发toast提示“已添加到歌单”
383
+ - 4. 歌曲被添加到目标歌单,并按目标歌单当前的排序规则刷新歌曲列表
384
+ - 4.1 如果目标歌单排序规则为"按添加到歌单时间排序",则该歌曲直接添加到歌曲列表最上方
385
+ - 4.2 如果目标歌单排序规则为“按标题排序”“按艺术家排序”“按专辑排序”之一,则按该规则升序(A→Z)重新排序并刷新歌曲列表
386
+ - 5. 歌单封面刷新为该歌曲对应的封面
387
+
388
+ ## 场景五
389
+
390
+ ### 场景概述
391
+
392
+ 用户从文件夹详情页,通过单首歌曲的更多操作入口,将一首歌曲添加到歌单
393
+
394
+ ### 场景逻辑步骤
395
+
396
+ - 1. 用户在文件夹详情页点击某首歌曲的"更多操作"按钮
397
+ - 2. 用户在弹出菜单中点击"添加到歌单",弹出歌单选择弹窗
398
+ - 3. 歌单选择弹窗中包含当前所有已经创建好的歌单以及新建歌单按钮
399
+ - 3.1 用户可以在歌单选择弹窗中点击已有的歌单将歌曲添加到歌单中,触发toast提示“已添加到歌单”
400
+ - 3.2 用户可以点击新建歌单按钮创建新歌单,歌单创建成功后返回歌单选择弹窗,弹窗的当前歌单列表刷新后,新创建的歌单位于最上面,点击新歌单将歌曲添加到新创建的歌单中,触发toast提示“已添加到歌单”
401
+ - 4. 歌曲添加到目标歌单,并按目标歌单当前的排序规则刷新歌曲列表
402
+ - 4.1 如果目标歌单排序规则为"按添加到歌单时间排序",则该歌曲直接添加到歌曲列表最上方
403
+ - 4.2 如果目标歌单排序规则为“按标题排序”“按艺术家排序”“按专辑排序”之一,则按该规则升序(A→Z)重新排序并刷新歌曲列表
404
+ - 5. 歌单封面刷新为该歌曲对应的封面
405
+
406
+ ## 场景六
407
+
408
+ ### 场景概述
409
+
410
+ 用户从文件夹详情页,通过多选操作,将多首歌曲同时添加到歌单
411
+
412
+ ### 场景逻辑步骤
413
+
414
+ - 1. 用户在文件夹详情页进入多选模式,依次选中多首歌曲
415
+ - 2. 用户点击"添加到歌单"按钮,弹出歌单选择弹窗
416
+ - 3. 歌单选择弹窗中包含当前所有已经创建好的歌单以及新建歌单按钮
417
+ - 3.1 用户可以在歌单选择弹窗中点击已有的歌单将歌曲添加到歌单中,触发toast提示“已添加到歌单”
418
+ - 3.2 用户可以点击新建歌单按钮创建新歌单,歌单创建成功后返回歌单选择弹窗,弹窗的当前歌单列表刷新后,新创建的歌单位于最上面,点击新歌单将歌曲添加到新创建的歌单中,触发toast提示“已添加到歌单”
419
+ - 4. 所选歌曲添加到目标歌单,并按目标歌单当前的排序规则刷新歌曲列表
420
+ - 4.1 如果目标歌单排序规则为"按添加到歌单时间排序",则按用户多选过程中每首歌的选中顺序决定添加次序,最先选中的歌曲在最上方(即添加到歌单的时间最晚)
421
+ - 4.2 如果目标歌单排序规则为“按标题排序”“按艺术家排序”“按专辑排序”之一,则按该规则升序(A→Z)重新排序并刷新歌曲列表
422
+ - 5. 歌单封面刷新为最后添加到歌单中的歌曲对应的封面
423
+
424
+ ## 场景七
425
+
426
+ ### 场景概述
427
+
428
+ 用户进入歌单详情页,查看歌单名称及歌曲列表
429
+
430
+ ### 场景逻辑步骤
431
+
432
+ - 1. 用户点击某个歌单进入歌单详情页
433
+ - 2. 页面顶部展示歌单名字
434
+ - 3. 页面下方展示歌单包含的歌曲列表,歌曲按照当前歌单配置的排序规则进行展示
435
+ - 4. 新建歌单的默认排序规则为"按添加到歌单时间排序"(后添加到歌单的歌曲排在上面)
436
+
437
+ ## 场景八
438
+
439
+ ### 场景概述
440
+
441
+ 用户在歌单详情页切换排序规则为"按添加到歌单时间排序"以外的其他规则
442
+
443
+ ### 场景逻辑步骤
444
+
445
+ - 1. 用户在歌单详情页点击排序选项入口
446
+ - 2. 用户选择“按添加到歌单时间排序”以外的排序规则,可选项为“按标题排序”“按艺术家排序”“按专辑排序”
447
+ - 3. 歌曲列表按所选规则重新排序并刷新展示
448
+ - 4. 该排序规则在用户再次切换前保持生效,后续新添加的歌曲按该规则插入对应位置
449
+
450
+ ## 场景九
451
+
452
+ ### 场景概述
453
+
454
+ 当用户尝试将已存在于目标歌单中的歌曲再次添加到该歌单时,不会重复添加
455
+
456
+ ### 场景逻辑步骤
457
+
458
+ - 1. 用户通过任意入口(单首或多选)选择歌曲并添加到目标歌单,触发toast提示“已添加到歌单”
459
+ - 2. 如果所选歌曲中存在已在目标歌单中的歌曲,该歌曲不会被重复添加,其原有的添加时间保持不变
460
+ - 3. 对于本次操作中尚未在目标歌单中的歌曲,按对应排序规则正常添加
461
+
462
+ ## 场景十
463
+
464
+ ### 场景概述
465
+
466
+ 用户在歌单选择弹窗中取消添加到歌单操作
467
+
468
+ ### 场景逻辑步骤
469
+
470
+ - 1. 用户通过任意入口触发"添加到歌单",弹出歌单选择弹窗
471
+ - 2. 用户通过点击弹窗外部区域关闭弹窗
472
+ - 3. 歌单内容不发生任何变化,用户返回操作前的页面状态
473
+
474
+
475
+ ## 场景十一
476
+
477
+ ### 场景概述
478
+
479
+ 歌单选择弹窗需要包含当前所有已创建的歌单及歌曲信息
480
+
481
+ ### 场景逻辑步骤
482
+
483
+ - 1. 用户通过添加到歌单操作触发歌单选择弹窗
484
+ - 2. 歌单选择弹窗通过列表形式展示当前所有已经创建好的歌单,每个歌单对应的歌曲数目是准确的
485
+
486
+ ## 场景十二
487
+
488
+ ### 场景概述
489
+
490
+ 添加歌曲到歌单后,歌单的歌曲数量需要实时刷新
491
+
492
+ ### 场景逻辑步骤
493
+
494
+ - 1. 用户将歌曲添加到歌单
495
+ - 2. 歌单列表页,歌单详情页,歌单选择弹窗中该歌单对应的歌曲数目需要实时刷新
496
+ ```
497
+
498
+ ---
499
+
500
+ ## Workflow
501
+
502
+ ### Step 0 — Validate inputs, split requirements, and derive the page batch
503
+
504
+ 1. Verify `requirement_description_file` exists and is a readable file, then split its content into individual requirements by input type. Keep each requirement's text verbatim and record them in order; do NOT analyze them yet. If no requirement can be extracted, stop and report the error.
505
+ - **Excel type (`.xlsx` / `.xlsm` / `.csv`)**: run `node <skill-dir>/scripts/parse_requirements.mjs --input <requirement_description_file> --json` via `Bash` to read the file content. Each item of the returned JSON array is one raw requirement: `uiPath` is the title, `description` is the requirement body. If the script errors, surface it verbatim and stop.
506
+ - **Text type (`.txt` / `.md`)**: read the content directly and split it into individual requirements (each requirement starts with a title line followed by its description; requirements are separated by blank lines).
507
+ 2. Verify `android_project_dir` exists and is a directory.
508
+ 3. Ensure `spec_output_dir` exists (create it if it does not), then ensure `<spec_output_dir>/.trace/` exists (create it once, before the first requirement is processed).
509
+ 4. **Derive the `<feature>` stem** for each requirement — the requirement **title line in full**, with only illegal filesystem characters sanitized:
510
+ - Replace each of `< > : " / \ | ? *` and every ASCII control character with `-`. Do not shorten, translate, re-split, or summarize the title; the stem keeps the whole UI path (e.g. `设置-歌词-悬浮窗状态栏歌词`).
511
+ - Collapse a run of consecutive `-` produced by sanitization into one, and trim leading/trailing `-` and whitespace.
512
+ - The same `<feature>` is the filename stem of **both** outputs: `<feature>-SPEC.md` and `.trace/<feature>.md`. They must never diverge — the spec's `## 代码追溯` footer points at the trace by this stem.
513
+ - If two requirements sanitize to the same stem, append `-2`, `-3`, … in source order and note the collision in the Step 3 report.
514
+ 5. **Derive page ownership** for each requirement from its `title` and `body`:
515
+ - `owning-page`: the user-visible page, dialog, sheet, or other UI surface that owns the requested interactions. Normalize requirements describing the same surface to the same value even when their final title segments describe different controls or behaviors.
516
+ - `page-path`: the ordered user navigation path from the normal app entry to `owning-page`, preserving page boundaries. Do not treat a control/action name as another page. Join segments with ` → ` and keep the same canonical spelling for every trace of the same `owning-page`.
517
+ - A genuinely page-less shared capability uses `owning-page: __shared_capability__` and `page-path: []` — the literal bracket form is the canonical empty spelling; do not force it onto an arbitrary caller page. The trace's `## UI序列` still mirrors the requirement title line verbatim (see `## UI序列模板`); page ownership is separate from that route display.
518
+ 6. **Enforce the page-batch boundary before any code exploration**:
519
+ - Exclude requirements with an empty `title` from this boundary determination (they are skipped and carry no `owning-page`). If no requirement remains to be processed, stop and report the skip list; there is no page batch to generate or order.
520
+ - All remaining requirements in this input MUST normalize to exactly one `owning-page`. A batch for `__shared_capability__` is allowed only when every such requirement has that same virtual owner.
521
+ - If two or more owners remain, stop before Step 1. Report each owner with its REQ titles and ask the caller to split the source file into one file per page. Do not generate a partial set or silently choose a page.
522
+ - Preserve the ordered successful candidates as this run's **page batch**. This page batch — not unrelated `*-SPEC.md` files that happen to share `spec_output_dir` — is the only scope of Step 4.
523
+
524
+ Step 0 output: an ordered list of `(title, description, feature, owning-page, page-path)` tuples plus a skip list and one validated page-batch owner. Keep this mapping available to Steps 2, 3, and 4.
525
+
526
+ ### Step 1 — Ensure homegraph has a fresh index for the project
527
+
528
+ homegraph is invoked exclusively through its CLI via `Bash`. Always prefix commands with `npx` (e.g. `npx --yes homegraph status <android_project_dir>`); `npx` resolves the binary without requiring a global install. All index management and code query commands share the same CLI — there is no MCP surface in this skill.
529
+
530
+ homegraph indexes per-project into a local `.homegraph/` directory; there is no central repo registry. Always pass the Android project path as the positional `[path]` argument to scope the command to the Android project (this skill's working directory is the spec project, NOT the Android project, so omitting the path queries the wrong project).
531
+
532
+ Procedure:
533
+
534
+ 1. Run `npx --yes homegraph status <android_project_dir>` to inspect the index state.
535
+ 2. Decide based on the output:
536
+ - **Not indexed** (no `.homegraph/`) → run `npx --yes homegraph init -i <android_project_dir>`, wait for completion.
537
+ - **Stale** (`npx --yes homegraph status` output does NOT contain `[OK] Index is up to date`) → run `npx --yes homegraph sync <android_project_dir>` (incremental; use `npx --yes homegraph index <android_project_dir> --force` for a full rebuild), wait for completion.
538
+ - **Fresh** → proceed to Step 2.
539
+
540
+ **Hard fail policy** — any of the following stops the skill and surfaces the error to the user; do NOT degrade to `Read` + `Grep`:
541
+
542
+ - `homegraph` CLI is not reachable via `npx` → ask the user to install it (`npm install -g homegraph` or `npx --yes homegraph install`).
543
+ - `npx --yes homegraph status`, `init`, `sync`, or `index` returns an error → surface the error verbatim and stop. Do not attempt spec generation without an index — the resulting spec would miss code-grounded scenarios.
544
+ - Any `npx --yes homegraph` query reports the project is not indexed → verify `init -i` ran against `android_project_dir`.
545
+
546
+ ### Step 2 — Process each requirement independently, one at a time
547
+
548
+ For each `(title, description, feature, owning-page, page-path)` tuple from Step 0, in order, run 2.1 → 2.6 end-to-end before moving to the next requirement. Do NOT batch code exploration across requirements.
549
+
550
+ Order matters: **build the trace from the Android project first, then synthesize the spec from the trace.** 2.5 MUST `Read` the trace file written in 2.3 / 2.4. Recalling from conversation context causes scenario drift and fabricated `file:line` facts (Principle 9).
551
+
552
+ All `npx --yes homegraph` query commands (`query` / `explore` / `node` / `callers` / `callees` / `impact` / `files`) resolve their target project from the current working directory's nearest `.homegraph/` index, so run every one of them from inside the Android project root using a subshell — e.g. `cd <android_project_dir> && npx --yes homegraph explore "<query>"`. The index commands (`status` / `init` / `sync` / `index`) take an explicit path argument instead, see Step 1. This skill's working directory is the spec project, NOT the Android project, so a query run from elsewhere silently queries the wrong project or none. Use the CLI directly — do NOT invoke any MCP tool or nested exploration skill. If any `npx --yes homegraph` call fails unexpectedly, surface the error and stop.
553
+
554
+ #### 2.1 Scope
555
+
556
+ Take this requirement's title + description verbatim as the raw requirement under analysis. If it is empty, warn and skip to the next requirement. Extract from the description: the UI path / page anchors, the primary user intent, the key entities (data models, persistence key names, setting names), and every explicit boundary condition it already states (default values, toggle states, message text, length limits).
557
+
558
+ #### 2.2 Recall — locate entry points (dual-path union)
559
+
560
+ Run both paths in the **same turn** (emit the lookups together); the deduplicated union is the recall result.
561
+
562
+ | Path | Approach | What it catches |
563
+ |---|---|---|
564
+ | **Path 1 · By-concept** | For each entity / UI anchor / intent verb from 2.1, run `npx --yes homegraph explore "<concept>"`; use `query "<concept>"` and `node "<symbol\|file>"` to pin location, signature, and source. Candidates: Activities, Fragments, Composables, ViewModels, Services, Repositories, DAOs. Cross-validate symbol name, file path, and source against the requirement text. | Direct hits: the page obviously implementing the requirement; data models named after its entities |
565
+ | **Path 2 · Reverse-by-usage** | Take the most discriminative keyword (settings/persistence key, unique business term, visible label). `query` → candidate symbol → `callers <symbol>`; repeat upward, or use `impact <symbol>`. Stop at an Activity / Fragment / Composable host. Record intermediate dialogs, menus, and nested components that reference the target state as separate entries. | Deeply nested consumers, pass-through navigation pages, manifest declarations, dynamic dispatch |
566
+
567
+ **Behavioral requirements with no literal keyword** (e.g. 「切歌后 X 同步刷新」): extract anchors as `(动作动词, 受影响实体)` tuples and feed both into Path 1's `query` and Path 2's seed symbol search.
568
+
569
+ **Terse requirements** — body under ~20 substantive characters, or only topical keywords with no concrete verb / entity: run two mandatory broad enumeration passes before concluding. Pass A enumerates `AndroidManifest.xml` and `res/` plus the relevant Activity/Fragment/Composable hosts; Pass B runs `query` / `explore` + `Grep` for EACH distinct keyword to enumerate ALL settings or configuration screens referencing it or a related term. Terse requirements routinely span several unrelated settings pages — anchoring on the single most obvious page is the primary failure mode here. Mark `terse-req: true` in the trace `## Status`; when ≥3 plausible hosts survive, list them as `candidate-hosts`; when fewer than 3 survive, ask via `AskUserQuestion` rather than guessing silently.
570
+
571
+ **Both paths return zero** → ask via `AskUserQuestion` whether the user will name an entry point. If declined, write a trace with `status: no_recall`, skip 2.3's remaining sections and 2.4 / 2.5 / 2.6, and flag the requirement in the Step 3 report. Do NOT fabricate entry points.
572
+
573
+ **Also interrupt with `AskUserQuestion`** when the requirement contains ambiguous scope phrases (「任意入口」「相关页面」「所有相关位置」) that the trace cannot map to a unique component set, or when deviations from the requirement text exceed five and touch core behavior (the requirement may be stale).
574
+
575
+ #### 2.3 Trace — explore and write `<spec_output_dir>/.trace/<feature>.md`
576
+
577
+ `Read` `references/trace-template.md` for the required sections and field schema. Exploration and writing are a single unit: the trace is the only machine-readable contract carried into 2.5. Write the `## Status` block with this requirement's `owning-page` and `page-path` from Step 0; leave `page-order: pending` and `page-order-acceptance: pending` — Step 4 replaces them after intra-page ordering.
578
+
579
+ **Exploration order** (every CLI call runs from inside `<android_project_dir>`):
580
+
581
+ | # | Action | Tool |
582
+ |---|---|---|
583
+ | 1 | Survey candidate symbols for each anchor from 2.1 / 2.2 | `explore` / `query` / `node` |
584
+ | 2 | Full call chain, up and down | `callers` / `callees` / `impact` |
585
+ | 3 | Reverse-lookup state writers, call-site counting, aggregation | repeated `callers` per symbol + `Grep` (count hits verbatim) |
586
+ | 4 | Exact literal positioning — preference keys, DAO columns, `android:key`, deep-link actions, `strings.xml` resource ids | `Grep` |
587
+ | 5 | Final `file:line` verification and zero-hit counter-evidence | `Read` (small window) / `Grep` |
588
+
589
+ **Information coverage** — apply each dimension to every recalled entry: trigger code (control + event callback, filling `code` and `resource`); end-to-end call chain (filling `data_flow`, each hop anchored); state writes and persistence (keys recorded verbatim, trace only); side effects and cross-boundary work (system events, notifications, background work, widgets, deep links); manifest / Gradle declarations (filling `manifest`, or `N/A: <reason>`); deviations from the requirement text; **exhaustive entry enumeration** (all UI paths touching this feature or state, beyond the requirement text — omitted here means omitted from the spec, Principle 10); and the consumer / non-consumer boundary.
590
+
591
+ **Anchor write-time resolution gate** — before writing ANY `file:line` into the trace, resolve it to exactly one file under the project root: run `Glob` or `Grep --include` on the bare filename and confirm a single match. Two recurring collisions: a layout `res/layout/<x>.xml` that also exists as a preference `res/xml/<x>.xml`, and a `res/values/<x>.xml` with `values-<locale>/` or `values-night/` siblings. When the filename is not unique, the anchor MUST carry the qualifier subdirectory that pins it (`app/src/main/res/values/strings.xml`, never bare `strings.xml`). An anchor that cannot be resolved to exactly one file MUST NOT be written — record `N/A: ambiguous, N candidates at <list>` and re-evidence the claim from a unique path.
592
+
593
+ **Literal collection is mandatory, not opportunistic.** The trace's `## User-visible literals` table is where 2.5 gets every value `## No-Vagueness Rules` demands: exact toast / dialog text (resolve `strings.xml` resource ids to their actual string with `Grep`, and check for a `values-zh/` sibling), length / count / duration limits, default values, sort keys and directions, positions, sizes, colors, switch defaults. If a literal is not found on the first pass, run a second targeted query (`query` on the constant name, `Grep` on the resource id) before recording it as not found.
594
+
595
+ Signatures, parameter types, return values, and error codes encountered along the way belong in the trace as evidence when they anchor a user-visible behavior, but are deliberately discarded at 2.5 — they have no place in a UI spec (Principle 6).
596
+
597
+ #### 2.4 Review — no fabrication, no omission, method-discipline compliant
598
+
599
+ Run every check below against the trace from 2.3. Any failure returns to 2.3 (rewrite / supplement / fix); judge convergence yourself, there is no external iteration cap. All checks pass → proceed to 2.5.
600
+
601
+ 1. **No fabrication** — every declared `file:line` exists (sample-verify via `node` or `Read`); every behavioral claim is source-supported; every boundary claim carries tool evidence.
602
+ 2. **No omission** — every detail in the requirement text has a counterpart in the trace (entry, behavior, or deviation). A feature the requirement names but the code does not implement is recorded as a **deviation**, not dropped as an omission.
603
+ 3. **Anchor resolvability** — re-resolve **every** `file:line` in the trace (the full set, not a sample) to exactly one file under the project root. A bare filename, or a resource path that also matches a qualifier-directory sibling, fails. A failure here means the 2.3 write-time gate was skipped: return to 2.3 and add the qualifier subdirectory.
604
+ 4. **Multi-layer completeness** — every Entry and Touched-entry has all three layer fields filled, each a hit or an explicit `N/A: <reason>`. Every Non-consumer claim has all four structured fields (`claim` / `closure_layers` / `tools` / `zero_hits`).
605
+ 5. **Trigger wiring anchored** — each entry's `code` layer points at the listener / callback registration line, not only the handler body.
606
+ 6. **Replayability** — sample-verify random anchors via `node` / `Read` (≥1 line of drift fails); sample-verify every count or ordering phrase against the source (unreplayable fails).
607
+ 7. **Fabrication-prone claims audit** — every claim falling in a class listed under `## Method Discipline` carries a verbatim-replayable anchor of the required kind. Any without → delete or re-evidence it.
608
+ 8. **String verifiability audit** — for every user-visible string quoted in the trace, `Grep` the exact string against `res/values/*.xml` and the `values-<locale>/` sibling the code resolves. A quoted string found verbatim in no resource file is invented → fail. When no `values-zh/` translation exists, the trace records the actual displayed string plus 「无中文翻译」. This audit is mechanical: enumerate, `Grep` each, fail on any miss.
609
+ 9. **Ledger entailment audit** — for every ledger row, re-`Read` the anchored lines and confirm the quote is exact **and** entails the claim as phrased. A quote saying less than the claim → weaken the claim; a quote absent or paraphrased → fail. Then sweep the whole trace for fabrication-prone-class claims missing from the ledger; finding one fails the review.
610
+ 10. **Section presence audit** — the trace contains every H2 section from `references/trace-template.md`, with an explicit `None` where truly empty. A missing section fails.
611
+ 11. **Terse-requirement coverage** — when `terse-req: true`, every settings screen discovered in 2.2's Pass B has at least one Entry or Touched-entry. A discovered-but-untraced screen fails.
612
+
613
+ #### 2.5 Synthesize — draft the spec from the trace, then self-check
614
+
615
+ **`Read` the trace file first.** Then generate the spec from it per `## Principles`, `## UI序列模板`, `## 平台中立化规则`, `## No-Vagueness Rules`, and `## Spec Few-shot Samples`: the requirement description, `## UI序列` (the requirement title copied verbatim), the atomic scenarios, and the `## 代码追溯` footer.
616
+
617
+ Synthesis discipline:
618
+
619
+ - **Coverage** — the trace's `Scope / Boundary` section lists N entries; the spec produces scenarios for all N even when the requirement text named only M < N (Principle 10).
620
+ - **Implicit-trigger coverage** — every entry in the trace's `Implicit triggers` section appears in the spec either as its own scenario or as a main step of an existing one. Listed in the trace but absent from the spec is a scenario omission.
621
+ - **Ledger gate** — a spec statement in any fabrication-prone class (guard / retention / position / order / default / string-visibility / global-attribution / displayed-value / quantifier) may enter the spec ONLY if the trace's ledger carries a row whose quoted code entails it. No row → drop the qualifier and describe the element without the unproven part. This applies to **every sentence, scenario titles included** — a title saying 「保持原值」 is a claim exactly like a step saying it, and a title must never contradict the weakened phrasing of its own steps.
622
+ - **Literal transfer** — every concrete value the spec states comes from the trace's `## User-visible literals` table. A value that is in the spec but not in the trace is fabricated.
623
+ - **Deviation summary** — when the trace's `Deviations from REQ_DESC` section is non-empty, append a short section at the end of the spec naming each inconsistency in user-facing language. When a claim was downgraded for lack of evidence, state both possible user-visible outcomes (「若 A 则用户看到…;若 B 则用户看到…」) — 「证据不足」 alone is not actionable.
624
+
625
+ **Self-check before writing** — re-read the drafted spec and verify each item; fix the draft, or return to 2.3 for another query, until all pass:
626
+
627
+ 1. `## UI序列` exists, sits above `## 场景一`, and its body is exactly one line quoting the requirement title verbatim — no numbered steps, no explanation. It matches the trace's `ui-sequence` field exactly.
628
+ 2. Every scenario's steps are expressed as what the user does and what the user then sees.
629
+ 3. No banned wording from `## No-Vagueness Rules` remains — scan for 提示 / 若干 / 一定 / 相应 / 刷新 / 默认 / 可能 / 通常 / 等 and replace each with its concrete value from the trace.
630
+ 4. Every toast string, limit, default, sort rule, and position in the spec appears in the trace's `## User-visible literals` table with its anchor.
631
+ 5. **Platform-neutrality scan** — search the whole document for these and rewrite every hit per `## 平台中立化规则`: `Android`, `android.`, `Java`, `Kotlin`, `Exception`, `Binder`, `AIDL`, `Bundle`, `Intent`, `Context`, `Cursor`, `Activity`, `Fragment`, `ViewModel`, `RecyclerView`, `SharedPreferences`, `R.string`, `permission.`, `/data/`, `.apk`, plus any dotted package-style identifier, any verbatim English exception message, and any `file:line` anchor that leaked out of the trace. The `## 代码追溯` footer's relative path to `.trace/<feature>.md` is the single permitted exception.
632
+ 6. **Marker-word second pass** — scan every sentence (scenario titles, steps, and deviation notes alike) for 右侧 / 左侧 / 上方 / 下方 / 同一行 / 保持 / 不变 / 仍显示 / 全部 / 所有 / 含 / 仅 / 仅当 / 之后 / 先…后 / 立即 / 默认 / 文案为 / 系统 / 随系统 and equivalents. Every sentence containing one must map to a trace ledger row; no row → rewrite the sentence without the unproven part. This pass is mechanical — check sentences one by one, do not skim.
633
+ 7. Scenario steps read as behavior a HarmonyOS developer can implement without ever opening the Android project.
634
+
635
+ #### 2.6 Write
636
+
637
+ Write the spec to `<spec_output_dir>/<feature>-SPEC.md` (overwrite if exists), ending with this fixed footer:
638
+
639
+ ```markdown
640
+ ## 代码追溯
641
+
642
+ - 本 SPEC 相关源码对应信息(源码锚点 file:line、入口枚举、数据流、证据台账)见 `.trace/<feature>.md`(相对本文件目录)。
643
+ ```
644
+
645
+ The footer is a top-level (`##`) section of the spec, sibling to the scenarios rather than nested inside the last one, and `<feature>` is this spec's own filename stem — the relative path must actually resolve to the trace written in 2.3.
646
+
647
+ Rationale: the trace exists for spec synthesis, but readers of the spec — the HarmonyOS implementer, a later reviewer, downstream conversion work — need a way back to the source evidence. The spec body stays platform-neutral prose; the footer is the single pointer telling them where the anchors, entry enumeration, data flow, and evidence ledger live.
648
+
649
+ Then move on to the next requirement.
650
+
651
+ ### Step 3 — Report
652
+
653
+ After all requirements have been processed (or skipped with a warning), report a brief per-requirement generation summary. The page-local ordering is derived afterwards in Step 4; until Step 4 runs, every successful trace's page-order fields still read `pending`.
654
+
655
+ **Per requirement**: requirement title, spec path, trace path, recall status (`ok` / `no_recall` / `error`), scenario count in the spec, deviation count in the trace, and `terse-req` when true.
656
+
657
+ **Aggregates**: requirements processed, traces written, scenarios produced, deviations recorded across all traces, and the count of `no_recall` / skipped requirements with their reasons (including any `<feature>` stem collisions resolved by suffixing).
658
+
659
+ Keep the reply under ~40 lines — per-requirement detail belongs in the spec and trace files, not the reply.
660
+
661
+ ### Step 4 — Page-order metadata in the per-SPEC traces
662
+
663
+ Once every requirement is processed (or skipped with a warning) and reported, derive the implementation order **inside the one validated page batch** and write the result back into the `## Status` block of every successful trace, `<spec_output_dir>/.trace/<feature>.md`. This skill creates **no** `page-order.md` or other standalone order document; it owns this page-local order only. **Do not** compare, score, or interleave other pages, and **do not** write `conversion-order.md` — cross-page ordering belongs to `a2h-spec-order`.
664
+
665
+ **Scope**: include exactly the successful traces (and their Specs) whose requirements occur in this invocation's validated same-page input. `no_recall` / `error` traces are excluded — they carry no Spec and keep `page-order: pending` / `page-order-acceptance: pending` by design; `a2h-spec-order` ignores them. Do not sweep unrelated `*-SPEC.md` files from `spec_output_dir`; separate page batches may use sibling output directories under one future campaign root.
666
+
667
+ **Incremental re-runs**: when re-running this page's input (e.g. after `a2h-spec-order` directs a re-generation), re-derive the order over the union of this invocation's successful traces and any retained same-`owning-page` traces already in `<spec_output_dir>/.trace/`, then renumber every allowed trace contiguously from 1. Do not keep stale numbers; the resulting sequence must be a unique contiguous `page-order` per `owning-page`.
668
+
669
+ 1. **Sort REQs inside the page**:
670
+ - Put a correctness-prerequisite REQ before the REQs it enables. A prerequisite is valid only when its trace proves that implementing the later REQ first would make persistence, read-back, state updates, or a minimal verifiable loop incorrect. Mere code reuse is not a prerequisite. If the proved prerequisites form a cycle, stop and report the cycle with its evidence rather than breaking it arbitrarily (the same rule `a2h-spec-order` applies at cross-page scope).
671
+ - Sort the remaining REQs by a 0–5 **enablement** rating, descending. `5`: difficult to mock or bound, ambiguous in data ownership, and correctness-relevant across several features. `3`: reused across several features but cleanly isolatable. `1`: control-local. Repeated persistence keys, storage operations, data-flow hops, and consumers are evidence. Do not promote by feature name alone.
672
+ - When enablement ratings differ by at most one level, preserve proven control/action click order, then keep functionally similar REQs adjacent.
673
+ - Break complete ties by spec filename.
674
+ - Record the ratings, prerequisite reasoning, and supporting REQ/spec/trace anchors while deciding; do not emit them in the spec. The page's trace files are the evidence source; do not invent dependencies from familiar UI patterns.
675
+ 2. **UI-visible acceptance constraint**: every row carries a one-line acceptance action describing which stub data/behavior is replaced and exactly how to observe it. Prefer a normal click path from the app entry. If a fixture, permission, reset, app-data clear, first-launch condition, or other state preparation is unavoidable, name it explicitly rather than hiding the trigger in passive voice.
676
+ 3. For the trace of each ordered feature, replace its pending fields with exactly:
677
+
678
+ ```markdown
679
+ page-order: <unique positive integer, contiguous from 1 inside this owning-page>
680
+ page-order-acceptance: <one non-empty UI-visible acceptance action>
681
+ ```
682
+
683
+ 4. **Mechanical self-check before writing**: every successful page-batch spec has exactly one matching trace with the same `owning-page`; the trace's `page-order` values form a unique contiguous sequence starting at `1`; every `page-order-acceptance` is non-empty and names required state preparation; and the order obeys all proved intra-page prerequisites and the ordering above. Re-read every changed trace after writing — a stale `pending` value, a duplicated number, or a missing acceptance action fails the run.
684
+
685
+ ---
686
+
687
+ ## Forbidden
688
+
689
+ - **No spec synthesis without a trace** — 2.5 may only synthesize from the file written in 2.3 and reviewed in 2.4. Synthesizing from conversation context is the failure mode this whole workflow exists to prevent.
690
+ - **No trace content in the spec body** — `file:line` anchors, Android symbol names, package names, resource ids, and raw evidence stay in the trace. The `## 代码追溯` footer's relative path is the only pointer the spec carries.
691
+ - **No interface contract in the spec** — no signatures, parameter tables, return values, or error codes. That is `hmos-spec-generate-backend`'s job (Principle 6).
692
+ - **No standalone page-order document** — page-order metadata lives only inside each `.trace/<feature>.md` `## Status` block; do not create `page-order.md` or any other standalone order file.
693
+ - **No cross-page artifacts** — do not compare or score other pages, and do not write `conversion-order.md`; cross-page ordering belongs to `a2h-spec-order` after every page batch is ready.
694
+ - **No fabricated entry points** — when both recall paths return zero and the user declines to name one, write `status: no_recall` and move on.
695
+ - **No MCP graph tools and no nested exploration skills** — use the `npx --yes homegraph` CLI only. Skills or agent instructions an indexer may have written into the target project (e.g. a `.claude/skills/` directory) override this SKILL's instructions and cause role drift.
696
+ - **No modification of the Android project** — manifests, build files, resources, and sources are read-only.