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,184 @@
1
+ # 状态管理概述
2
+ <!--Kit: ArkUI-->
3
+ <!--Subsystem: ArkUI-->
4
+ <!--Owner: @jiyujia926-->
5
+ <!--Designer: @zhangboren-->
6
+ <!--Tester: @TerryTsao-->
7
+ <!--Adviser: @zhang_yixin13-->
8
+
9
+ 在前文的描述中,构建的页面主要为静态界面。如果要构建一个动态的、有交互的界面,就需要引入“状态”的概念。
10
+
11
+ **图1** 效果图  
12
+
13
+ ![Video_2023-03-06_152548](figures/Video_2023-03-06_152548.gif)
14
+
15
+ 上面的示例中,用户与应用程序的交互触发了文本状态变更,状态变更引起了UI渲染,UI从“Hello World”变更为“Hello ArkUI”。
16
+
17
+ 在声明式UI编程框架中,UI是程序状态的运行结果,用户构建了一个UI模型,其中应用的运行时状态作为参数。当参数改变时,UI作为返回结果,也将进行对应的改变。这些运行时的状态变化导致的UI重新渲染,在ArkUI中统称为状态管理机制。
18
+
19
+ 自定义组件中的变量,必须使用装饰器装饰,才能成为状态变量,状态变量的改变会引起UI的渲染刷新。如果不使用状态变量,UI只能在初始化时渲染,后续将不会再刷新。下图展示了State和View(UI)之间的关系。
20
+
21
+ ![zh-cn_image_0000001562352677](figures/zh-cn_image_0000001562352677.png)
22
+
23
+ - View(UI):UI渲染,指将build方法内的UI描述和\@Builder装饰的方法内的UI描述映射到界面。
24
+
25
+ - State:状态,指驱动UI更新的数据。通过触发组件的事件方法,改变状态数据。状态数据的改变,引起UI的重新渲染。
26
+
27
+ 在阅读状态管理文档前,开发者需要了解UI范式基本语法。建议提前阅读[基本语法概述](./arkts-basic-syntax-overview.md)、[声明式UI描述](./arkts-declarative-ui-description.md)、[状态管理术语](./arkts-state-management-glossary.md)和[自定义组件-创建自定义组件](./arkts-create-custom-components.md)。
28
+
29
+ >**说明:**
30
+ >
31
+ >当前状态管理的功能仅支持在UI主线程使用,不能在子线程、Worker、TaskPool中使用。
32
+
33
+ ## 状态管理版本介绍
34
+
35
+ 当前状态管理分为V1、V2两个版本。
36
+ 1. V2是V1的增强版本,正在持续迭代优化来为开发者提供更多功能和灵活性。
37
+ 2. 对于新开发的应用,建议直接使用V2版本范式来进行开发。
38
+ 3. 对于已经使用V1的应用,如果V1的功能和性能已能满足需求,则不必立即切换到V2。
39
+
40
+ ## 状态管理(V1)
41
+
42
+ 开发者可以选择使用状态管理V1版本进行应用开发。
43
+
44
+ ### 装饰器总览
45
+
46
+ ArkUI状态管理V1提供了多种装饰器,通过使用这些装饰器,状态变量不仅可以观察组件内的改变,还可以在不同组件层级间传递,比如父子组件、跨组件层级,也可以观察全局范围内的变化。根据状态变量的影响范围,将所有的装饰器可以大致分为:
47
+
48
+ - 管理组件内状态的装饰器:组件级别的状态管理,可以观察同一个组件树上(即同一个页面内)组件内或不同组件层级的变量变化。
49
+
50
+ - 管理应用级状态的装饰器:应用级别的状态管理,可以观察不同页面,甚至不同UIAbility的状态变化,是应用内全局的状态管理。
51
+
52
+ 装饰器可按数据传递形式和同步类型分为:只读的单向传递和可变更的双向传递。
53
+
54
+ 图示如下,具体装饰器的介绍,可详见<!--RP1-->[管理组件拥有的状态](arkts-state.md)<!--RP1End-->和<!--RP2-->[管理应用拥有的状态](arkts-application-state-management-overview.md)<!--RP2End-->。开发者可以利用这些能力来实现数据和UI的联动。
55
+
56
+ ![zh-cn_image_0000001502704640](figures/zh-cn_image_0000001502704640.png)
57
+
58
+ 上图中,Components部分的装饰器为组件级别的状态管理,Application部分为应用的状态管理。开发者可以通过[@StorageLink](arkts-appstorage.md#storagelink)/[@LocalStorageLink](arkts-localstorage.md#localstoragelink)实现应用和组件状态的双向同步,通过[@StorageProp](arkts-appstorage.md#storageprop)/[@LocalStorageProp](arkts-localstorage.md#localstorageprop)实现应用和组件状态的单向同步。
59
+
60
+ <!--RP1-->[管理组件拥有的状态](arkts-state.md)<!--RP1End-->,即图中Components级别的状态管理:
61
+
62
+ - [\@State](arkts-state.md):\@State装饰的变量拥有其所属组件的状态,可以作为其子组件单向和双向同步的数据源。当其数值改变时,会引起相关组件的渲染刷新。
63
+
64
+ - [\@Prop](arkts-prop.md):\@Prop装饰的变量可以和父组件建立单向同步关系,\@Prop装饰的变量是可变的,但修改不会同步回父组件。
65
+
66
+ - [\@Link](arkts-link.md):\@Link装饰的变量可以和父组件建立双向同步关系,子组件中\@Link装饰变量的修改会同步给父组件中建立双向数据绑定的数据源,父组件的更新也会同步给\@Link装饰的变量。
67
+
68
+ - [\@Provide/\@Consume](arkts-provide-and-consume.md):\@Provide/\@Consume装饰的变量用于跨组件层级(多层组件)同步状态变量,可以不需要通过参数命名机制传递,通过alias(别名)或者属性名绑定。
69
+
70
+ - [\@Observed](arkts-observed-and-objectlink.md):\@Observed装饰class,需要观察多层嵌套场景的class需要被\@Observed装饰。单独使用\@Observed没有任何作用,需要和\@ObjectLink、\@Prop联用。
71
+
72
+ - [\@ObjectLink](arkts-observed-and-objectlink.md):\@ObjectLink装饰的变量接收\@Observed装饰的class的实例,应用于观察多层嵌套场景,和父组件的数据源构建双向同步。
73
+
74
+ > **说明:**
75
+ >
76
+ > 仅[\@Observed/\@ObjectLink](arkts-observed-and-objectlink.md)可以观察嵌套场景,其他的状态变量仅能观察第一层,详情见各个装饰器章节的“观察变化和行为表现”小节。
77
+
78
+
79
+ <!--RP2-->[管理应用拥有的状态](arkts-application-state-management-overview.md)<!--RP2End-->,即图中Application级别的状态管理:
80
+
81
+
82
+ - [AppStorage](arkts-appstorage.md)是应用程序中的一个特殊的单例[LocalStorage](arkts-localstorage.md)对象,是应用级的数据库,和进程绑定,通过[@StorageProp](arkts-appstorage.md#storageprop)和[@StorageLink](arkts-appstorage.md#storagelink)装饰器可以和组件联动。
83
+
84
+ - AppStorage是应用状态的“中枢”,将需要与组件(UI)交互的数据存入AppStorage,比如持久化数据[PersistentStorage](arkts-persiststorage.md)和环境变量[Environment](arkts-environment.md)。UI再通过AppStorage提供的装饰器或API接口访问这些数据。
85
+
86
+ - 框架还提供了LocalStorage,AppStorage是LocalStorage特殊的单例。LocalStorage是应用程序声明的应用状态的内存“数据库”,通常用于页面级的状态共享,通过[@LocalStorageProp](arkts-localstorage.md#localstorageprop)和[@LocalStorageLink](arkts-localstorage.md#localstoragelink)装饰器可以和UI联动。
87
+
88
+
89
+ ### 其他状态管理V1功能
90
+
91
+ [\@Watch](arkts-watch.md)用于监听状态变量的变化。
92
+
93
+
94
+ [$$运算符](arkts-two-way-sync.md):给系统组件提供TS变量的引用,使得TS变量和系统组件的内部状态保持同步。
95
+
96
+ ### 相关实例
97
+
98
+ 针对页面状态管理,有以下相关实例可供参考:
99
+
100
+ - [状态管理(ArkTS)(API9)](https://gitcode.com/openharmony/applications_app_samples/tree/master/code/UI/ArkTsComponentCollection/StateManagement)
101
+
102
+ - [目标管理(ArkTS)(API9)](https://gitcode.com/openharmony/codelabs/tree/master/ETSUI/TargetManagement)
103
+
104
+ ## 状态管理(V2)
105
+
106
+ 为了增强状态管理V1版本的部分能力,例如深度观察、属性级更新等,ArkUI推出状态管理V2供开发者使用。
107
+
108
+ ### 状态管理V1现状以及V2优点
109
+
110
+ 状态管理V1使用代理观察数据,创建状态变量时,会同时创建一个数据代理观察者。该观察者可以感知代理变化,但无法感知实际数据变化,因此存在以下限制:
111
+
112
+ - 状态变量不能独立于UI存在,同一个数据被多个视图代理时,其中一个视图的更改不会通知其他视图更新。
113
+ - 只能感知对象属性第一层的变化,无法做到深度观测和深度监听。
114
+ - 在更改对象中属性以及更改数组中元素的场景下存在冗余更新的问题。
115
+ - 装饰器间配合使用限制多,不易用。组件中没有明确状态变量的输入与输出,不利于组件化。
116
+
117
+ ![arkts-old-state-management](figures/arkts-old-state-management.png)
118
+
119
+ 状态管理V2增强了数据的观察能力,使数据本身可观察。更改数据时,会触发相应视图的更新。相较于状态管理V1,状态管理V2有如下优点:
120
+
121
+ - 状态变量独立于UI,更改数据会触发相应视图的更新。
122
+
123
+ - 支持对象的深度观测和深度监听,且深度观测机制不影响观测性能。
124
+
125
+ - 支持对象中属性级精准更新及数组中元素的最小化更新。
126
+
127
+ - 装饰器易用性高、拓展性强,在组件中明确输入与输出,有利于组件化。
128
+
129
+ ![arkts-new-state-management](figures/arkts-new-state-management.png)
130
+
131
+ ### 装饰器总览
132
+
133
+ 状态管理(V2)提供了一套全新的装饰器。
134
+
135
+ - [\@ObservedV2](arkts-new-observedV2-and-trace.md):\@ObservedV2装饰器装饰class,使得被装饰的class具有深度监听的能力。\@ObservedV2和\@Trace配合使用可以使class中的属性具有深度观测的能力。
136
+
137
+ - [\@Trace](arkts-new-observedV2-and-trace.md):\@Trace装饰器装饰被\@ObservedV2装饰的class中的属性,被装饰的属性具有深度观测的能力。
138
+
139
+ - [\@ComponentV2](arkts-create-custom-components.md#componentv2):使用\@ComponentV2装饰的struct中能使用新的装饰器。例如:\@Local、\@Param、\@Event、\@Once、\@Monitor、\@Provider、\@Consumer。
140
+
141
+ - [\@Local](arkts-new-local.md):\@Local装饰的变量为组件内部状态,无法从外部初始化。
142
+
143
+ - [\@Param](arkts-new-param.md):\@Param装饰的变量作为组件的输入,可以接受从外部传入初始化并同步。
144
+
145
+ - [\@Once](arkts-new-once.md):\@Once装饰的变量仅初始化时同步一次,需要与\@Param一起使用。
146
+
147
+ - [\@Event](arkts-new-event.md):\@Event装饰方法类型,作为组件输出,可以通过该方法影响父组件中变量。
148
+
149
+ - [\@Monitor](arkts-new-monitor.md):\@Monitor装饰器用于\@ComponentV2装饰的自定义组件或\@ObservedV2装饰的类中,能够对状态变量进行深度监听。
150
+
151
+ - [\@Provider和\@Consumer](arkts-new-provider-and-consumer.md):用于跨组件层级双向同步。
152
+
153
+ - [\@Computed](arkts-new-computed.md):计算属性,在被计算的值变化的时候,只会计算一次。主要应用于解决UI多次重用该属性从而重复计算导致的性能问题。
154
+
155
+ - [!!语法](arkts-new-binding.md):双向绑定语法糖。
156
+
157
+ ### 状态管理V1与V2能力对比
158
+
159
+ | V1能力 | V2能力 | 说明 |
160
+ | ------------ | ------------------------------------------------------ | ------------------------------------------------------------ |
161
+ | \@Observed | \@ObservedV2 | 表明当前对象为可观察对象。但两者能力并不相同。<br/>\@Observed可观察第一层的属性,需要搭配\@ObjectLink使用才能生效。 <br/>\@ObservedV2本身无观察能力,仅代表当前class可被观察,如果要观察其属性,需要搭配\@Trace使用。 |
162
+ | \@Track | \@Trace | V1装饰器\@Track为精确观察,可以不依赖@Observed单独使用。不使用则无法做到类属性的精准观察。<br/>V2\@Trace装饰的属性可以被精确跟踪观察。 |
163
+ | \@Component | \@ComponentV2 | \@Component为搭配V1状态变量使用的自定义组件装饰器。<br/>\@ComponentV2为搭配V2状态变量使用的自定义组件装饰器。 |
164
+ | \@State | 无外部初始化:\@Local<br/>外部初始化一次:\@Param\@Once | \@State和\@Local类似都是数据源的概念,区别是\@State可以外部传入初始化,而\@Local无法外部传入初始化。 |
165
+ | \@Prop | \@Param | \@Prop和\@Param类似都是自定义组件参数的概念。当输入参数为复杂类型时,\@Prop为深拷贝,\@Param为引用。 |
166
+ | \@Link | \@Param\@Event | \@Link是框架自己封装实现的双向同步,对于V2开发者可以通过\@Param\@Event自己实现双向同步。 |
167
+ | \@ObjectLink | \@Param | 直接兼容,\@ObjectLink需要被\@Observed装饰的class的实例初始化,\@Param没有此限制。 |
168
+ | \@Provide | \@Provider | 兼容。 |
169
+ | \@Consume | \@Consumer | 兼容。 |
170
+ | \@Watch | \@Monitor | \@Watch用于监听V1状态变量的变化,具有监听状态变量本身和其第一层属性变化的能力。状态变量可观察到的变化会触发其\@Watch监听事件。<br/>\@Monitor用于监听V2状态变量的变化,搭配\@Trace使用,可有深层监听的能力。状态变量在一次事件中多次变化时,仅会以最终的结果判断是否触发\@Monitor监听事件。 |
171
+ | LocalStorage | 全局\@ObservedV2\@Trace | 兼容。 |
172
+ | AppStorage | AppStorageV2 | 兼容。 |
173
+ | Environment | 调用Ability接口获取系统环境变量 | Environment获取环境变量能力和AppStorage耦合。在V2中可直接调用Ability接口获取系统环境变量。 |
174
+ | PersistentStorage | PersistenceV2 | PersistentStorage持久化能力和AppStorage耦合,PersistenceV2持久化能力可独立使用。 |
175
+ | 自定义组件生命周期 | 自定义组件生命周期 | 均支持。[aboutToAppear](../../reference/apis-arkui/arkui-ts/ts-custom-component-lifecycle.md#abouttoappear)、[onDidBuild](../../reference/apis-arkui/arkui-ts/ts-custom-component-lifecycle.md#ondidbuild12)、[aboutToDisappear](../../reference/apis-arkui/arkui-ts/ts-custom-component-lifecycle.md#abouttodisappear)。 |
176
+ | 页面生命周期 | 页面生命周期 | 均支持。[onPageShow](../../reference/apis-arkui/arkui-ts/ts-custom-component-lifecycle.md#onpageshow)、[onPageHide](../../reference/apis-arkui/arkui-ts/ts-custom-component-lifecycle.md#onpagehide)、[onBackPress](../../reference/apis-arkui/arkui-ts/ts-custom-component-lifecycle.md#onbackpress)。 |
177
+ | \@Reusable | \@ReusableV2 | 组件复用。包括:[aboutToReuse](../../reference/apis-arkui/arkui-ts/ts-custom-component-lifecycle.md#abouttoreuse10)、[aboutToRecycle](../../reference/apis-arkui/arkui-ts/ts-custom-component-lifecycle.md#abouttorecycle10)。 |
178
+ | $$ | !! | 双向绑定。V2建议使用!!实现双向绑定。 |
179
+ | \@CustomDialog | [openCustomDialog](../../../application-dev/reference/apis-arkui/arkts-apis-uicontext-promptaction.md#opencustomdialog12)接口 | 自定义弹窗。V2建议使用openCustomDialog实现自定义弹窗功能。 |
180
+ | WithTheme | WithTheme | 主题。用于设置应用局部页面自定义主题风格。包括:[onWillApplyTheme](../../reference/apis-arkui/arkui-ts/ts-custom-component-lifecycle.md#onwillapplytheme12)。<br>从API version 18开始,该接口支持在状态管理V2组件中使用。 |
181
+ | 系统预置UI组件库 | 系统预置UI组件库 | 系统预置UI组件库 。支持V1的系统预置UI组件,例如:[Dialog](../../../application-dev/reference/apis-arkui/arkui-ts/ohos-arkui-advanced-Dialog.md)、[ProgressButton](../../../application-dev/reference/apis-arkui/arkui-ts/ohos-arkui-advanced-ProgressButton.md)、[SegmentButton](../../../application-dev/reference/apis-arkui/arkui-ts/ohos-arkui-advanced-SegmentButton.md)。<br>从API version 18开始,系统预置UI组件支持在状态管理V2组件中使用,例如:[DialogV2](../../../application-dev/reference/apis-arkui/arkui-ts/ohos-arkui-advanced-DialogV2.md)、[ProgressButtonV2](../../../application-dev/reference/apis-arkui/arkui-ts/ohos-arkui-advanced-ProgressButtonV2.md)、[SegmentButtonV2](../../../application-dev/reference/apis-arkui/arkui-ts/ohos-arkui-advanced-SegmentButtonV2.md)。 |
182
+ | animateTo | 部分场景不支持 | 当前某些场景下,在状态管理V2中使用animateTo动画,会产生异常效果,详见:[在状态管理V2中使用animateTo动画效果异常](./arkts-new-local.md#在状态管理v2中使用animateto动画效果异常)。 |
183
+
184
+ 有关V1向V2的迁移可参考[迁移指导](./arkts-v1-v2-migration.md),<!--RP3-->有关V1与V2的混用可参考[状态管理V1和V2混用场景](./arkts-v1-v2-mixusage-before-api-version.md)<!--RP3End-->。
@@ -0,0 +1,431 @@
1
+ # ArkUI Component Cookbook
2
+
3
+ Verified constructors, modifiers, enums, and callback signatures for high-frequency ArkUI components. Use these shapes instead of guessing — wrong signatures surface as `No overload matches this call.` and wrong enum members as `Property 'X' does not exist on type 'typeof Y'.` Prefer project-local code style for naming and structure.
4
+
5
+ > Verified against the SDK component `.d.ts` files, OpenHarmony **API 23** (6.1.0.105). When the project targets an older API, confirm availability in `<DEVECO_PATH>/sdk/default/openharmony/ets/component/` (`DEVECO_PATH` from the clone root `conf.yaml`).
6
+
7
+ ## Component constructors (quick reference)
8
+
9
+ | Component | Constructor | Notes |
10
+ |-----------|-------------|-------|
11
+ | `Column` / `Row` | `Column({ space: 12 })` | spacing goes in the constructor |
12
+ | `Flex` | `Flex({ direction, justifyContent, alignItems })` | `alignItems` takes `ItemAlign` (not HorizontalAlign); `space` exists but is `{ main: LengthMetrics.vp(8) }`, NOT a plain number — when unsure use margins on children |
13
+ | `Stack` | `Stack({ alignContent: Alignment.TopStart })` | alignment via `alignContent`, not row/column methods |
14
+ | `List` | `List({ space: 8 })` | children must be `ListItem` / `ListItemGroup` |
15
+ | `Grid` | `Grid()` + `.columnsTemplate('1fr 1fr')` | children must be `GridItem` |
16
+ | `Tabs` | `Tabs({ barPosition: BarPosition.End, controller })` | children must be `TabContent` |
17
+ | `TabContent` | `TabContent()` | NO object parameter; label via `.tabBar(...)` |
18
+ | `Swiper` | `Swiper()` | `.autoPlay(true)`, `.indicator(true)`, `.onChange((index: number) => {})` |
19
+ | `TextInput` | `TextInput({ placeholder: '...', text: this.value })` | `.onChange((value: string) => {})` |
20
+ | `DatePicker` | `DatePicker({ start: new Date('1970-1-1'), end: new Date('2100-12-31'), selected: this.date })` | see DatePicker section |
21
+ | `Progress` | `Progress({ value: 30, total: 100, type: ProgressType.Linear })` | |
22
+ | `Canvas` | `Canvas(this.context)` | takes ONE positional `CanvasRenderingContext2D` — no options object. Declare in the struct: `private settings: RenderingContextSettings = new RenderingContextSettings(true)` and `private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)`; draw in `.onReady(() => { this.context.fillRect(...) })` |
23
+
24
+ ## Kit ownership for imports (exact — wrong kit = compile error)
25
+
26
+ All imports use `@kit.*`; `@ohos.*` paths are legacy. Symbols AI most often mis-assigns:
27
+
28
+ | Symbol | Correct kit | Common wrong guess |
29
+ |--------|------------|--------------------|
30
+ | `router`, `promptAction`, `window`, `ComponentContent` | `@kit.ArkUI` | `@ohos.router` |
31
+ | `BusinessError` | `@kit.BasicServicesKit` | `@ohos.base`, `@kit.ArkUI` |
32
+ | `hilog` | `@kit.PerformanceAnalysisKit` | `@kit.ArkUI` |
33
+ | `UIAbility`, `AbilityConstant`, `Want` | `@kit.AbilityKit` | `@kit.ArkUI` |
34
+ | `image` | `@kit.ImageKit` | `@kit.ArkUI` |
35
+ | `preferences` | `@kit.ArkData` | `@ohos.data.preferences` |
36
+ | `NavPathStack`, UI component types/enums | **global, no import needed** | imported from `@kit.ArkUI` (compiles to "module has no exported member") |
37
+
38
+ If a symbol is not in this table and you are not certain of its kit, search the docs — do not guess kit ownership.
39
+
40
+ ## Modifier ownership
41
+
42
+ Use full ArkUI modifier names — no CSS/web shorthand, no foreign-framework layout constants for width/height.
43
+
44
+ - `Text` owns `.fontSize()`, `.fontColor()`, `.fontWeight()`, `.textAlign()`, `.maxLines()`, `.textOverflow({ overflow: TextOverflow.Ellipsis })` (pair with `.maxLines`)
45
+ - `Image` owns `.objectFit(ImageFit.Cover)`
46
+ - `Column`: `.alignItems(HorizontalAlign.X)` + `.justifyContent(FlexAlign.X)`
47
+ - `Row`: `.alignItems(VerticalAlign.X)` + `.justifyContent(FlexAlign.X)` — the cross-axis enum differs from Column's
48
+ - Universal: `.width()`, `.height()`, `.backgroundColor()`, `.borderRadius()`, `.padding()`, `.margin()`, `.onClick()`
49
+ - `margin`/`padding` take a number, string, or `{ top, bottom, left, right }` object — NOT multi-value CSS shorthand strings
50
+
51
+ Fabricated modifier names that DO NOT exist (frequent AI inventions):
52
+
53
+ | ❌ Invented | ✅ Real modifier |
54
+ |------------|-----------------|
55
+ | `.bgColor()` | `.backgroundColor()` |
56
+ | `.textSize()` / `.textColor()` | `.fontSize()` / `.fontColor()` |
57
+ | `.radius()` | `.borderRadius()` |
58
+ | `List({ gap: 10 })` | `List({ space: 10 })` |
59
+ | `.width('match_parent')` / `.height('wrap_content')` | `.width('100%')` / omit height |
60
+ | `.onClick((e: GestureEvent) => ...)` | param type is `ClickEvent` |
61
+
62
+ ## Enum members (exact names — do not guess)
63
+
64
+ | Enum | Valid members |
65
+ |------|---------------|
66
+ | `GradientDirection` | `Left` `Top` `Right` `Bottom` `LeftTop` `LeftBottom` `RightTop` `RightBottom` `None` — there is NO `BottomRight`/`TopLeft`; the order is horizontal-then-vertical |
67
+ | `Alignment` | `TopStart` `Top` `TopEnd` `Start` `Center` `End` `BottomStart` `Bottom` `BottomEnd` |
68
+ | `HorizontalAlign` | `Start` `Center` `End` |
69
+ | `VerticalAlign` | `Top` `Center` `Bottom` |
70
+ | `FlexAlign` | `Start` `Center` `End` `SpaceBetween` `SpaceAround` `SpaceEvenly` |
71
+ | `TextAlign` | `Start` `Center` `End` `JUSTIFY` `LEFT` `RIGHT` — note the mixed casing |
72
+ | `ItemAlign` (Flex/List cross-axis) | `Auto` `Start` `Center` `End` `Baseline` `Stretch` |
73
+ | `FontWeight` | `Lighter` `Normal` `Regular` `Medium` `Bold` `Bolder` (or a number 100–900) |
74
+ | `BarPosition` | `Start` `End` |
75
+ | `ImageFit` | `Contain` `Cover` `Auto` `Fill` `ScaleDown` `None` |
76
+ | `TextOverflow` | `None` `Clip` `Ellipsis` `MARQUEE` |
77
+ | `FlexDirection` | `Row` `RowReverse` `Column` `ColumnReverse` |
78
+ | `Visibility` | `Visible` `Hidden` `None` |
79
+ | `Curve` | `Linear` `Ease` `EaseIn` `EaseOut` `EaseInOut` `FastOutSlowIn` `Friction` `Sharp` `Smooth` — prefer the enum; a string (e.g. a cubic-bezier) is also legal since the type is `Curve \| string \| ICurve`, but uncommon in this project |
80
+ | `ButtonType` | `Normal` `Capsule` `Circle` |
81
+ | `ToggleType` | `Checkbox` `Switch` `Button` |
82
+ | `ProgressType` | `Linear` `Ring` `Eclipse` `ScaleRing` `Capsule` |
83
+ | `InputType` | `Normal` `Password` `Email` `Number` `PhoneNumber` |
84
+ | `EdgeEffect` | `Spring` `Fade` `None` |
85
+ | `BarState` | `Off` `Auto` `On` |
86
+ | `BarMode` (Tabs) | `Scrollable` `Fixed` |
87
+ | `NavigationMode` | `Stack` `Split` `Auto` |
88
+ | `ScrollDirection` | `Vertical` `Horizontal` `None` |
89
+ | `Axis` | `Vertical` `Horizontal` |
90
+ | `ImageRepeat` | `NoRepeat` `X` `Y` `XY` |
91
+ | `BorderStyle` | `Dotted` `Dashed` `Solid` |
92
+ | `PlayMode` | `Normal` `Reverse` `Alternate` `AlternateReverse` |
93
+
94
+ Known traps (enums/members that look right but don't exist):
95
+
96
+ - `.renderMode()` takes `ImageRenderMode` — NOT `ImageRenderingMode`
97
+ - `DataPanelType` members are `Circle`/`Line` — NOT `Close`/`Ring`
98
+ - `Sticky.Normal` — `StickyStyle` enum does not exist
99
+ - `TextInputStyle` has no `Normal` member — do not write `.style(TextInputStyle.Normal)`
100
+
101
+ Do not pass strings where an enum is expected. Do not pass enum values where the API expects a different enum (e.g. Flex `alignItems` takes `ItemAlign`, not `HorizontalAlign`).
102
+
103
+ ## System resource names (`$r('sys.…')`) — never guess
104
+
105
+ Plausible-looking system resource names usually do not exist: `$r('sys.media.ohos_ic_public_home')`, `$r('sys.symbol.forward_fill')`, etc. all fail with `resource-name-check: Unknown resource name 'X'. No matching sys.media/sys.symbol resource found in SDK.` (observed 7 such failures in a single run, across 3 apps).
106
+
107
+ - Default to text/emoji glyphs (`Text('🏠')`) or app resources you actually create (`$r('app.media.icon_home')` + a file under `resources/base/media/`) — never invent a `sys.media.*`/`sys.symbol.*` name
108
+ - Only use a `sys.*` name you have personally verified in this SDK; there is no memorizable "safe subset"
109
+ - The same applies to system colors (`$r('sys.color.…')`) and `SymbolGlyph` names
110
+
111
+ ## Tabs and TabContent
112
+
113
+ `Tabs` direct children must be `TabContent`; the label goes in `.tabBar(...)`, never as a `TabContent` parameter.
114
+
115
+ ```ets
116
+ Tabs({ barPosition: BarPosition.End }) {
117
+ TabContent() {
118
+ Column() {
119
+ Text('Home')
120
+ }
121
+ }
122
+ .tabBar('Home')
123
+
124
+ TabContent() {
125
+ Column() {
126
+ Text('Discover')
127
+ }
128
+ }
129
+ .tabBar('Discover')
130
+ }
131
+ .onChange((index: number) => {
132
+ this.currentTab = index
133
+ })
134
+ ```
135
+
136
+ - `TabContent()` has no object parameter — `TabContent({ builder: ... })` is wrong.
137
+ - Do not place non-`TabContent` components directly under `Tabs`.
138
+ - For a custom tab bar, pass a `@Builder` to `.tabBar(this.tabBuilder(0, 'Home'))`.
139
+
140
+ ## List, Grid, and ForEach
141
+
142
+ ```ets
143
+ interface CardItem {
144
+ id: string
145
+ title: string
146
+ }
147
+
148
+ @Component
149
+ struct CardGrid {
150
+ @State cards: CardItem[] = [
151
+ { id: 'card-1', title: 'Card 1' },
152
+ { id: 'card-2', title: 'Card 2' }
153
+ ]
154
+
155
+ build() {
156
+ Grid() {
157
+ ForEach(this.cards, (item: CardItem) => {
158
+ GridItem() {
159
+ Text(item.title)
160
+ }
161
+ }, (item: CardItem) => item.id)
162
+ }
163
+ .columnsTemplate('1fr 1fr')
164
+ }
165
+ }
166
+ ```
167
+
168
+ - The key generator must RETURN a stable string — a block body without `return` produces broken keys; avoid index keys for business data.
169
+ - `ListItem` inside `List`, `GridItem` inside `Grid` — never bare children.
170
+ - `LazyForEach` needs a real `IDataSource` implementation (not a plain array) and a scrollable container; for ordinary in-memory arrays use `ForEach`. Copy this shape — `IDataSource` / `DataChangeListener` are global ArkUI types (no import):
171
+
172
+ ```ets
173
+ // Reusable data source — subclass or seed with your data, then call reload() after mutating.
174
+ class CardDataSource implements IDataSource {
175
+ private items: CardItem[] = []
176
+ private listeners: DataChangeListener[] = []
177
+
178
+ constructor(items: CardItem[]) {
179
+ this.items = items
180
+ }
181
+
182
+ totalCount(): number {
183
+ return this.items.length
184
+ }
185
+
186
+ getData(index: number): CardItem {
187
+ return this.items[index]
188
+ }
189
+
190
+ registerDataChangeListener(listener: DataChangeListener): void {
191
+ if (this.listeners.indexOf(listener) < 0) {
192
+ this.listeners.push(listener)
193
+ }
194
+ }
195
+
196
+ unregisterDataChangeListener(listener: DataChangeListener): void {
197
+ const pos: number = this.listeners.indexOf(listener)
198
+ if (pos >= 0) {
199
+ this.listeners.splice(pos, 1)
200
+ }
201
+ }
202
+
203
+ reload(): void {
204
+ this.listeners.forEach((l: DataChangeListener) => l.onDataReloaded())
205
+ }
206
+ }
207
+
208
+ @Component
209
+ struct CardList {
210
+ private data: CardDataSource = new CardDataSource([
211
+ { id: 'card-1', title: 'Card 1' },
212
+ { id: 'card-2', title: 'Card 2' }
213
+ ])
214
+
215
+ build() {
216
+ List() {
217
+ LazyForEach(this.data, (item: CardItem) => {
218
+ ListItem() {
219
+ Text(item.title)
220
+ }
221
+ }, (item: CardItem) => item.id) // keyGenerator: business ID, not the index
222
+ }
223
+ }
224
+ }
225
+ ```
226
+
227
+ - `getData` returns the element type; the keyGenerator (third arg) must return a stable business ID.
228
+
229
+ ## DatePicker and pickers
230
+
231
+ Two callback generations — do not mix their value types:
232
+
233
+ ```ets
234
+ DatePicker({
235
+ start: new Date('1970-1-1'),
236
+ end: new Date('2100-12-31'),
237
+ selected: this.selectedDate
238
+ })
239
+ .onDateChange((value: Date) => { // value is a real Date
240
+ this.birthYear = value.getFullYear()
241
+ this.birthMonth = value.getMonth() + 1 // getMonth() is 0-based
242
+ this.birthDay = value.getDate()
243
+ })
244
+ ```
245
+
246
+ - `.onDateChange((value: Date) => {})` — use this; the value is `Date`, call `getFullYear()/getMonth()/getDate()` on it.
247
+ - The legacy `.onChange((value: DatePickerResult) => {})` callback delivers OPTIONAL fields (`value.year?: number`) — every access needs `?? 0` narrowing. Prefer `onDateChange`.
248
+ - `TextPicker({ range: this.options, selected: this.index })` + `.onChange((value: string | string[], index: number | number[]) => {})`.
249
+
250
+ ## linearGradient
251
+
252
+ ```ets
253
+ Column()
254
+ .linearGradient({
255
+ angle: 135, // number | string; OR use direction
256
+ colors: [['#0C0C1D', 0.0], ['#1A1A3E', 0.5], ['#252545', 1.0]]
257
+ })
258
+ ```
259
+
260
+ - `colors` is an array of `[color, stop]` pairs with stops in `[0, 1]`.
261
+ - Use `angle` (degrees) OR `direction: GradientDirection.RightBottom` — member names are in the enum table above.
262
+
263
+ ## TextInput, Button, and state refresh
264
+
265
+ ```ets
266
+ @Component
267
+ struct RegisterForm {
268
+ @State userName: string = ''
269
+ @State errorText: string = ''
270
+
271
+ build() {
272
+ Column({ space: 12 }) {
273
+ TextInput({ placeholder: 'Enter username', text: this.userName })
274
+ .onChange((value: string) => {
275
+ this.userName = value
276
+ })
277
+
278
+ Button('Register')
279
+ .onClick(() => {
280
+ this.errorText = this.userName.length === 0 ? 'Complete all fields' : 'Registered'
281
+ })
282
+
283
+ Text(this.errorText)
284
+ .fontColor(this.errorText === 'Registered' ? Color.Green : Color.Red)
285
+ }
286
+ }
287
+ }
288
+ ```
289
+
290
+ - Sync input back to state in `.onChange(...)`. Do NOT use two-way-binding sugar in generated code — `$$this.x` (V1): the standalone type check does not understand it and reports `Cannot find name '$$this'` (observed ×4 in one page); `!!` (V2): same convention applies even though official docs teach it — `.onChange` sync is equivalent, checkable, and always passes.
291
+ - Event callback parameter types must be explicit (`(value: string)`) — inference inside modifiers is limited.
292
+ - Required validation messages must be rendered on the page, not only logged.
293
+ - For a styled button label, place a styled `Text` inside `Button() { Text('...') ... }`.
294
+
295
+ ## Dialog and Toast
296
+
297
+ Button label field is `value` — there is no `text` field on dialog buttons.
298
+
299
+ ```ets
300
+ this.getUIContext().showAlertDialog({
301
+ title: 'Confirm entry?',
302
+ message: 'Confirm entry?',
303
+ primaryButton: {
304
+ value: 'Book seat',
305
+ action: () => {
306
+ this.getUIContext().getPromptAction().showToast({ message: 'Booking opened' })
307
+ }
308
+ },
309
+ secondaryButton: {
310
+ value: 'Reconsider',
311
+ action: () => {}
312
+ }
313
+ })
314
+ ```
315
+
316
+ - `ActionSheet` entries go in `sheets: [{ title: '...', action: () => {} }]`.
317
+ - `promptAction.showActionMenu({ title?, buttons: [{ text: '...', color: '#000000' }] })` — the field is `buttons` (1–6 entries), NOT `items`; each `Button` requires BOTH `text` and `color`. The `.then` result type lives in the `promptAction` namespace — the bare name is not in scope: `import { promptAction } from '@kit.ArkUI'`, then `.then((r: promptAction.ActionMenuSuccessResponse) => { r.index ... })` (NOT `ActionMenuSuccessResult`, NOT unqualified `ActionMenuSuccessResponse`).
318
+ - Keep cancel actions side-effect free unless the requirement says otherwise.
319
+ - Prefer UIContext-based APIs when the project uses them: `this.getUIContext().getPromptAction()`, `.showAlertDialog(...)`, `.getRouter()`, `.animateTo(...)`. If the project has its own dialog/toast/router wrapper, use the wrapper instead of introducing a new pattern.
320
+ - **`CustomDialogController` must be created in `@Component`/`@ComponentV2` struct scope** — declare it as a component field (or `new` it inside a method body and call `.open()` **synchronously**). Creating it inside a model / util / ViewModel class — the **`DialogLauncher`/`DialogManager` model anti-pattern** (a helper class that holds the controller and returns/opens it; a common OOP instinct that this rule forbids) — or **deferring** `.open()` (e.g. `setTimeout(() => controller.open(), 50)`), **silently fails**: `.open()` does nothing — no error, no exception, the dialog never shows. When you must launch a dialog from non-component code, route through `this.getUIContext().getPromptAction().openCustomDialog(...)` instead.
321
+ - **The `builder` of a `CustomDialogController` must be a `@CustomDialog struct`, not a plain `@Component`/`@ComponentV2` content struct.** `new CustomDialogController({ builder: SomeContent() })` where `SomeContent` is a regular component compiles fine but **crashes on device** with `class constructor cannot be called without 'new'`. Wrap the dialog body in a dedicated `@CustomDialog struct` and reference that as the `builder`.
322
+
323
+ ## Navigation and NavDestination
324
+
325
+ Follow the existing navigation architecture — do not replace project routing to add one page. (**New projects**: prefer `Navigation` + `NavPathStack`.) Either way, call routing/global-UI APIs through `this.getUIContext()` — bare `router.*` / `promptAction.*` are deprecated WARNINGs.
326
+
327
+ - Projects on `Navigation`: route to `NavDestination` through the existing `NavPathStack` or the project router wrapper; keep page registration consistent with nearby pages.
328
+ - Projects on `router`: `this.getUIContext().getRouter().pushUrl({ url: 'pages/Detail' })`; the page must be listed in `main_pages.json`.
329
+ - Pass only the parameters the target page declares; verify the first visible screen and the new navigation path.
330
+
331
+ ### Router params (the verified recipe — do NOT improvise here)
332
+
333
+ There is exactly one shape that passes the checker; every "obvious" alternative fails (chain observed in production):
334
+
335
+ ```ets
336
+ // model/RouteParams.ets — the params interface is declared ONCE, in a shared model file
337
+ export interface DetailParams {
338
+ capsuleId: string;
339
+ }
340
+
341
+ // Sender page: import the interface; params must be a NAMED interface instance — not a bare literal, not Record
342
+ import { DetailParams } from '../model/RouteParams';
343
+ const p: DetailParams = { capsuleId: this.id };
344
+ this.getUIContext().getRouter().pushUrl({ url: 'pages/Detail', params: p });
345
+
346
+ // Receiver page: import the SAME interface; getParams() returns Object — `as` cast, then null-safe access
347
+ import { DetailParams } from '../model/RouteParams';
348
+ const params = this.getUIContext().getRouter().getParams() as DetailParams;
349
+ const id: string = params?.capsuleId ?? '';
350
+ ```
351
+
352
+ The params interface lives in ONE shared model file and is imported by both pages. Do NOT re-declare it in each page — two pages each declaring their own `interface DetailParams` fails with `Declaration merging is not supported (arkts-no-decl-merging)`.
353
+
354
+ Known-bad fixes (each just produces the next error in the chain — skip straight to the recipe above):
355
+ - Bare literal `params: { id: ... }` → `arkts-no-untyped-obj-literals`
356
+ - `params: { ... } as Record<string, Object>` → `Argument of type 'Record<string, Object>' is not assignable to parameter of type 'RouterOptions'`
357
+ - Annotating the options object as `RouterOptions` without importing it → `Cannot find name 'RouterOptions'` (it lives in `@kit.ArkUI`, but you never need to name it — the typed `params` variable is sufficient)
358
+ - Assigning `getParams()` directly to a typed variable without `as` → `Type 'Object' is not assignable to ...`
359
+ - Copy-declaring the params interface in both sender and receiver pages → `Declaration merging is not supported (arkts-no-decl-merging)`
360
+
361
+ ## Data model + detail page template (copy this shape)
362
+
363
+ `Object is possibly 'undefined'` is the single largest check-error category, and it concentrates in one shape: a model class full of optional fields (`x?: T`) consumed by a detail page. Kill it at the design level — give fields real initial values and narrow ONCE at the entry point:
364
+
365
+ ```ets
366
+ // Model: real initial values, not `?:` everywhere.
367
+ // Only fields that are GENUINELY absent in some states get `| undefined`.
368
+ export class Capsule {
369
+ id: string = '';
370
+ title: string = '';
371
+ createdAt: number = 0;
372
+ openedAt: number | undefined = undefined; // truly optional state
373
+ }
374
+
375
+ // Detail page: narrow the lookup ONCE into a non-optional local/state,
376
+ // then build() reads plain fields — no `?.`/`!.` chains in UI code.
377
+ @Component
378
+ struct CapsuleDetail {
379
+ @State capsule: Capsule = new Capsule();
380
+
381
+ aboutToAppear(): void {
382
+ const found: Capsule | undefined = DataStore.find(this.capsuleId);
383
+ if (found !== undefined) {
384
+ this.capsule = found;
385
+ }
386
+ }
387
+
388
+ build() {
389
+ Column() {
390
+ Text(this.capsule.title) // no narrowing needed — fields are non-optional
391
+ if (this.capsule.openedAt !== undefined) {
392
+ Text(formatTime(this.capsule.openedAt))
393
+ }
394
+ }
395
+ }
396
+ }
397
+ ```
398
+
399
+ Anti-pattern that produces the error storm: `capsule?: Capsule` (or `capsule: Capsule | undefined`) as `@State`, then `this.capsule?.title`, `this.capsule!.x`, `this.capsule.items[i].y` sprinkled through `build()` — every access site becomes a potential `possibly 'undefined'` error (observed: 10 errors across 2 pages from this one shape).
400
+
401
+ ### Creating instances with data (seed/mock data — the template's other half)
402
+
403
+ The template above shows the class and the empty `new Capsule()`. When you create instances **with data** (seed lists, mock stores, a new item from form input), one rule applies:
404
+
405
+ **Class-body defaults do NOT make fields optional in an object literal.** A literal assigned to a class type must list **every** field — including the ones whose default you'd just be repeating — or it fails with `Type '{...}' is missing the following properties from type 'Capsule': tags, openedAt` (observed: 7 errors from one omission copy-pasted across a seed list).
406
+
407
+ ```ets
408
+ // ❌ relies on class defaults for tags/openedAt — checker requires them anyway
409
+ const seed: Capsule[] = [
410
+ { id: '1', title: 'First', createdAt: 0 },
411
+ ];
412
+
413
+ // ✅ Option A (small data sets): list every field, repeating defaults explicitly
414
+ const seed: Capsule[] = [
415
+ { id: '1', title: 'First', createdAt: 0, tags: [], openedAt: undefined },
416
+ ];
417
+
418
+ // ✅ Option B (preferred for seed lists): a static factory — adding a field later
419
+ // means one change here, not a fix in every literal
420
+ export class Capsule {
421
+ // ...fields as above...
422
+ static of(id: string, title: string, createdAt: number): Capsule {
423
+ const c = new Capsule();
424
+ c.id = id;
425
+ c.title = title;
426
+ c.createdAt = createdAt;
427
+ return c;
428
+ }
429
+ }
430
+ const seed: Capsule[] = [Capsule.of('1', 'First', 0), Capsule.of('2', 'Second', 1)];
431
+ ```