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,529 @@
1
+ function object(value) {
2
+ return value !== null && typeof value === "object" && !Array.isArray(value)
3
+ ? value
4
+ : undefined;
5
+ }
6
+ function text(record, key) {
7
+ const value = record.data[key];
8
+ return typeof value === "string" && value.trim().length > 0
9
+ ? value.trim()
10
+ : undefined;
11
+ }
12
+ function expression(binding) {
13
+ return object(binding.data.expression) ?? {};
14
+ }
15
+ function expressionText(binding, key) {
16
+ const value = expression(binding)[key];
17
+ return typeof value === "string" && value.trim().length > 0
18
+ ? value.trim()
19
+ : undefined;
20
+ }
21
+ function sourceApiName(record) {
22
+ return text(record, "targetName")?.replace(/-.*$/u, "");
23
+ }
24
+ function normalizedSource(value) {
25
+ if (typeof value !== "string") return undefined;
26
+ const normalized = value.replace(/\s+/gu, " ").trim();
27
+ return normalized.length > 0 ? normalized : undefined;
28
+ }
29
+ function bindingParameterName(binding) {
30
+ return (
31
+ text(binding, "parameterName") ??
32
+ (typeof expression(binding).namedArgument === "string"
33
+ ? String(expression(binding).namedArgument).trim() || undefined
34
+ : undefined)
35
+ );
36
+ }
37
+ function callbackLike(binding) {
38
+ return (
39
+ binding.data.isLambda === true ||
40
+ expressionText(binding, "callableRef") !== undefined ||
41
+ expressionText(binding, "callableReferenceRef") !== undefined
42
+ );
43
+ }
44
+ function append(map, key, value) {
45
+ const records = map.get(key) ?? [];
46
+ records.push(value);
47
+ map.set(key, records);
48
+ }
49
+ function isComposableDeclaration(record) {
50
+ if (record.kind !== "method-declaration") return false;
51
+ if (record.data.composable === true) return true;
52
+ return (
53
+ Array.isArray(record.data.annotations) &&
54
+ record.data.annotations.includes("androidx.compose.runtime.Composable")
55
+ );
56
+ }
57
+ function composableQualifiedName(record) {
58
+ const owner = text(record, "ownerQualifiedName");
59
+ const name = text(record, "name");
60
+ return name ? (owner ? `${owner}#${name}` : name) : undefined;
61
+ }
62
+ function buildIndex(jvm) {
63
+ const recordsById = new Map();
64
+ const calls = [];
65
+ const mutableBindings = new Map();
66
+ const callableParent = new Map();
67
+ const methodsBySignature = new Map();
68
+ const mutableByName = new Map();
69
+ for (const record of jvm.body) {
70
+ recordsById.set(record.id, record);
71
+ if (record.kind === "resolved-call") calls.push(record);
72
+ if (record.kind === "call-argument-binding") {
73
+ const callRef = text(record, "callRef");
74
+ if (callRef) append(mutableBindings, callRef, record);
75
+ }
76
+ if (
77
+ record.kind === "method-declaration" ||
78
+ record.kind === "lambda-declaration"
79
+ ) {
80
+ const parent = text(record, "enclosingCallableRef");
81
+ if (parent) callableParent.set(record.id, parent);
82
+ }
83
+ }
84
+ for (const record of jvm.body) {
85
+ if (!isComposableDeclaration(record)) continue;
86
+ const qualifiedName = composableQualifiedName(record);
87
+ const signature = text(record, "signature") ?? qualifiedName;
88
+ if (!qualifiedName || !signature) continue;
89
+ const method = { record, signature, qualifiedName };
90
+ methodsBySignature.set(signature, method);
91
+ const candidates = mutableByName.get(qualifiedName) ?? [];
92
+ candidates.push(method);
93
+ mutableByName.set(qualifiedName, candidates);
94
+ }
95
+ return {
96
+ recordsById,
97
+ calls: calls.sort((left, right) => left.id.localeCompare(right.id, "en")),
98
+ bindingsByCall: new Map(
99
+ [...mutableBindings].map(([key, values]) => [
100
+ key,
101
+ values.sort((left, right) => left.id.localeCompare(right.id, "en")),
102
+ ]),
103
+ ),
104
+ callableParent,
105
+ methodsBySignature,
106
+ methodsByQualifiedName: new Map(
107
+ [...mutableByName].map(([key, values]) => [
108
+ key,
109
+ values.sort((left, right) =>
110
+ left.signature.localeCompare(right.signature, "en"),
111
+ ),
112
+ ]),
113
+ ),
114
+ };
115
+ }
116
+ function bindingsFor(index, callRef) {
117
+ return index.bindingsByCall.get(callRef) ?? [];
118
+ }
119
+ function bindingForParameter(index, callRef, parameterName) {
120
+ const candidates = bindingsFor(index, callRef).filter(
121
+ (binding) => bindingParameterName(binding) === parameterName,
122
+ );
123
+ return candidates.length === 1 ? candidates[0] : undefined;
124
+ }
125
+ function targetForCall(index, call) {
126
+ const signature = text(call, "targetSignature");
127
+ const exact = signature ? index.methodsBySignature.get(signature) : undefined;
128
+ if (exact) return exact;
129
+ if (!signature?.includes("androidx.compose.runtime.Composer")) {
130
+ return undefined;
131
+ }
132
+ const owner = text(call, "targetOwnerQualifiedName");
133
+ const name = sourceApiName(call);
134
+ if (!owner || !name) return undefined;
135
+ const candidates = index.methodsByQualifiedName.get(`${owner}#${name}`) ?? [];
136
+ return candidates.length === 1 ? candidates[0] : undefined;
137
+ }
138
+ function scopeIsWithin(index, candidate, ancestor) {
139
+ const visited = new Set();
140
+ let current = candidate;
141
+ while (current && !visited.has(current)) {
142
+ if (current === ancestor) return true;
143
+ visited.add(current);
144
+ current = index.callableParent.get(current);
145
+ }
146
+ return false;
147
+ }
148
+ function enclosingComposable(index, callableRef) {
149
+ const visited = new Set();
150
+ let current = callableRef;
151
+ while (current && !visited.has(current)) {
152
+ visited.add(current);
153
+ const record = index.recordsById.get(current);
154
+ if (record && isComposableDeclaration(record)) {
155
+ const signature = text(record, "signature");
156
+ return signature ? index.methodsBySignature.get(signature) : undefined;
157
+ }
158
+ current = index.callableParent.get(current);
159
+ }
160
+ return undefined;
161
+ }
162
+ function declaredParameterNames(record) {
163
+ const parameters = Array.isArray(record.data.parameters)
164
+ ? record.data.parameters
165
+ : [];
166
+ return new Set(
167
+ parameters.flatMap((value) => {
168
+ const parameter = object(value);
169
+ const name = parameter?.name;
170
+ return typeof name === "string" && name.trim().length > 0
171
+ ? [name.trim()]
172
+ : [];
173
+ }),
174
+ );
175
+ }
176
+ function nearestParameterDeclaration(index, callableRef, parameterName) {
177
+ const visited = new Set();
178
+ let current = callableRef;
179
+ while (current && !visited.has(current)) {
180
+ visited.add(current);
181
+ const declaration = index.recordsById.get(current);
182
+ if (!declaration) return undefined;
183
+ if (declaredParameterNames(declaration).has(parameterName)) {
184
+ return declaration;
185
+ }
186
+ current = index.callableParent.get(current);
187
+ }
188
+ return undefined;
189
+ }
190
+ function exactParameterName(index, summary, callableRef, method) {
191
+ const symbol = object(summary.resolvedSymbol);
192
+ const name = typeof symbol?.name === "string" ? symbol.name.trim() : "";
193
+ if (symbol?.kind !== "parameter" || !name) return undefined;
194
+ return nearestParameterDeclaration(index, callableRef, name)?.id ===
195
+ method.record.id
196
+ ? name
197
+ : undefined;
198
+ }
199
+ function initializerCall(index, summary) {
200
+ if (!summary) return undefined;
201
+ const directRef =
202
+ typeof summary.callRef === "string" ? summary.callRef.trim() : "";
203
+ const direct = directRef ? index.recordsById.get(directRef) : undefined;
204
+ if (direct?.kind === "resolved-call") return direct;
205
+ const symbol = object(summary.resolvedSymbol);
206
+ const initializer =
207
+ object(symbol?.initializer) ?? object(summary.initializer);
208
+ const nestedRef =
209
+ typeof initializer?.callRef === "string" ? initializer.callRef.trim() : "";
210
+ const nested = nestedRef ? index.recordsById.get(nestedRef) : undefined;
211
+ return nested?.kind === "resolved-call" ? nested : undefined;
212
+ }
213
+ function isEnumEntries(call, summary) {
214
+ const types = [
215
+ text(call, "receiverType"),
216
+ typeof summary.expressionType === "string"
217
+ ? summary.expressionType.trim()
218
+ : undefined,
219
+ ];
220
+ if (types.some((type) => type?.startsWith("kotlin.enums.EnumEntries<"))) {
221
+ return true;
222
+ }
223
+ const selector = object(summary.selectorExpression);
224
+ const selectorSymbol = object(selector?.resolvedSymbol);
225
+ return (
226
+ (selectorSymbol?.name === "entries" ||
227
+ selectorSymbol?.name === "getEntries") &&
228
+ object(summary.receiverExpression)?.resolvedSymbol !== undefined
229
+ );
230
+ }
231
+ const knownStaticCollectionFactories = new Set([
232
+ "arrayListOf",
233
+ "listOf",
234
+ "mutableListOf",
235
+ "mutableSetOf",
236
+ "setOf",
237
+ ]);
238
+ const knownEmptyCollectionFactories = new Set(["emptyList", "emptySet"]);
239
+ function staticPopulation(index, summary) {
240
+ const initializer = initializerCall(index, summary);
241
+ if (!initializer) return undefined;
242
+ const owner = text(initializer, "targetOwnerQualifiedName") ?? "";
243
+ const name = sourceApiName(initializer);
244
+ if (!name || !owner.startsWith("kotlin.collections.")) return undefined;
245
+ if (knownEmptyCollectionFactories.has(name)) return "impossible";
246
+ if (!knownStaticCollectionFactories.has(name)) return undefined;
247
+ const count = initializer.data.argumentCount;
248
+ return typeof count === "number" && Number.isInteger(count)
249
+ ? count > 0
250
+ ? "unconditional"
251
+ : "impossible"
252
+ : undefined;
253
+ }
254
+ function availabilityFor(record, summary, fallback) {
255
+ const source =
256
+ normalizedSource(summary.source) ??
257
+ normalizedSource(record.data.receiverSource) ??
258
+ normalizedSource(record.data.argumentSource) ??
259
+ fallback;
260
+ return {
261
+ record,
262
+ expressionAnchor: `${source}.isNotEmpty()`,
263
+ plainLanguage: "列表中至少包含一个可操作项目",
264
+ };
265
+ }
266
+ function fixedTerm(population, record, summary, support, keyPrefix) {
267
+ const availability =
268
+ population === "conditional"
269
+ ? availabilityFor(record, summary, `collection:${record.id}`)
270
+ : undefined;
271
+ return {
272
+ key: availability
273
+ ? `dynamic:${availability.expressionAnchor}`
274
+ : `${keyPrefix}:${population}:${record.id}`,
275
+ population,
276
+ support,
277
+ ...(availability ? { availability } : {}),
278
+ };
279
+ }
280
+ function receiverTerm(index, call, method, support) {
281
+ const summary = object(call.data.receiverExpression) ?? {};
282
+ if (isEnumEntries(call, summary)) return undefined;
283
+ const parameter = exactParameterName(
284
+ index,
285
+ summary,
286
+ text(call, "enclosingCallableRef"),
287
+ method,
288
+ );
289
+ if (parameter) {
290
+ return {
291
+ key: `parameter:${method.record.id}:${parameter}`,
292
+ population: "conditional",
293
+ support,
294
+ parameter: { methodRef: method.record.id, name: parameter },
295
+ availability: availabilityFor(
296
+ call,
297
+ summary,
298
+ `parameter:${method.record.id}:${parameter}`,
299
+ ),
300
+ };
301
+ }
302
+ const population = staticPopulation(index, summary) ?? "conditional";
303
+ return fixedTerm(population, call, summary, support, "receiver");
304
+ }
305
+ function isResolvedCollectionIteration(call) {
306
+ if (call.kind !== "resolved-call") return false;
307
+ const name = sourceApiName(call);
308
+ if (name !== "forEach" && name !== "forEachIndexed") return false;
309
+ const owner = text(call, "targetOwnerQualifiedName") ?? "";
310
+ const signature = text(call, "targetSignature") ?? "";
311
+ return (
312
+ owner.startsWith("kotlin.collections.") &&
313
+ /(?:java\.lang\.)?Iterable/iu.test(signature)
314
+ );
315
+ }
316
+ function loopActionScope(index, call) {
317
+ const binding = bindingForParameter(index, call.id, "action");
318
+ const scope = binding ? expressionText(binding, "callableRef") : undefined;
319
+ return binding &&
320
+ binding.data.isLambda === true &&
321
+ text(binding, "bindingStatus") === "resolved" &&
322
+ scope &&
323
+ index.recordsById.has(scope)
324
+ ? { binding, scope }
325
+ : undefined;
326
+ }
327
+ function hasActionCallback(index, call) {
328
+ return bindingsFor(index, call.id).some((binding) => {
329
+ const name = bindingParameterName(binding);
330
+ return (
331
+ name !== undefined &&
332
+ /^on[A-Z][A-Za-z0-9]*$/u.test(name) &&
333
+ callbackLike(binding)
334
+ );
335
+ });
336
+ }
337
+ function uniqueRecords(records) {
338
+ return [
339
+ ...new Map(records.map((record) => [record.id, record])).values(),
340
+ ].sort((left, right) => left.id.localeCompare(right.id, "en"));
341
+ }
342
+ function uniqueTerms(terms) {
343
+ return [...new Map(terms.map((term) => [term.key, term])).values()].sort(
344
+ (left, right) => left.key.localeCompare(right.key, "en"),
345
+ );
346
+ }
347
+ function termsKey(terms) {
348
+ return uniqueTerms(terms)
349
+ .map((term) => term.key)
350
+ .join("\u0000");
351
+ }
352
+ function instantiateTerm(index, call, caller, term) {
353
+ if (!term.parameter) return term;
354
+ const binding = bindingForParameter(index, call.id, term.parameter.name);
355
+ if (!binding) return undefined;
356
+ const summary = expression(binding);
357
+ const directParameter = exactParameterName(
358
+ index,
359
+ summary,
360
+ text(call, "enclosingCallableRef"),
361
+ caller,
362
+ );
363
+ const support = uniqueRecords([...term.support, binding]);
364
+ if (directParameter) {
365
+ return {
366
+ key: `parameter:${caller.record.id}:${directParameter}`,
367
+ population: "conditional",
368
+ support,
369
+ parameter: {
370
+ methodRef: caller.record.id,
371
+ name: directParameter,
372
+ },
373
+ availability: availabilityFor(
374
+ binding,
375
+ summary,
376
+ `parameter:${caller.record.id}:${directParameter}`,
377
+ ),
378
+ };
379
+ }
380
+ const syntheticCall = {
381
+ ...call,
382
+ data: {
383
+ ...call.data,
384
+ receiverType: summary.expressionType,
385
+ receiverSource: binding.data.argumentSource,
386
+ receiverExpression: summary,
387
+ },
388
+ };
389
+ if (isEnumEntries(syntheticCall, summary)) return undefined;
390
+ const population = staticPopulation(index, summary) ?? "conditional";
391
+ return fixedTerm(population, binding, summary, support, "argument");
392
+ }
393
+ function aggregateContext(terms) {
394
+ const unique = uniqueTerms(terms);
395
+ if (unique.length === 0) return undefined;
396
+ const population = unique.some((term) => term.population === "impossible")
397
+ ? "impossible"
398
+ : unique.some((term) => term.population === "conditional")
399
+ ? "conditional"
400
+ : "unconditional";
401
+ return {
402
+ population,
403
+ support: uniqueRecords(unique.flatMap((term) => term.support)),
404
+ availabilities:
405
+ population === "conditional"
406
+ ? [
407
+ ...new Map(
408
+ unique.flatMap((term) =>
409
+ term.availability
410
+ ? [[term.availability.expressionAnchor, term.availability]]
411
+ : [],
412
+ ),
413
+ ).values(),
414
+ ].sort((left, right) =>
415
+ left.expressionAnchor.localeCompare(right.expressionAnchor, "en"),
416
+ )
417
+ : [],
418
+ };
419
+ }
420
+ /**
421
+ * Proves repeated local-Composable invocations from resolved Kotlin
422
+ * collection iteration. Recognition never depends on product symbols or
423
+ * variable names. A wrapper declaration is summarized only when every
424
+ * action-bearing call in that declaration carries the same repeated
425
+ * requirement, preventing one mixed-use helper from becoming globally
426
+ * conditional.
427
+ */
428
+ export function dynamicRepeatedCallSiteContexts(jvm) {
429
+ const index = buildIndex(jvm);
430
+ const loops = index.calls.flatMap((call) => {
431
+ if (!isResolvedCollectionIteration(call)) return [];
432
+ const action = loopActionScope(index, call);
433
+ const method = enclosingComposable(
434
+ index,
435
+ text(call, "enclosingCallableRef"),
436
+ );
437
+ if (!action || !method) return [];
438
+ const term = receiverTerm(
439
+ index,
440
+ call,
441
+ method,
442
+ uniqueRecords([call, action.binding]),
443
+ );
444
+ return term ? [{ call, action, method, term }] : [];
445
+ });
446
+ const localCalls = index.calls.flatMap((call) => {
447
+ const target = targetForCall(index, call);
448
+ const caller = enclosingComposable(
449
+ index,
450
+ text(call, "enclosingCallableRef"),
451
+ );
452
+ return target && caller && hasActionCallback(index, call)
453
+ ? [{ call, target, caller }]
454
+ : [];
455
+ });
456
+ const methodsWithExternalActions = new Set(
457
+ index.calls.flatMap((call) => {
458
+ if (!hasActionCallback(index, call) || targetForCall(index, call))
459
+ return [];
460
+ const caller = enclosingComposable(
461
+ index,
462
+ text(call, "enclosingCallableRef"),
463
+ );
464
+ return caller ? [caller.record.id] : [];
465
+ }),
466
+ );
467
+ const callsByMethod = new Map();
468
+ for (const item of localCalls) {
469
+ const calls = callsByMethod.get(item.caller.record.id) ?? [];
470
+ calls.push(item);
471
+ callsByMethod.set(item.caller.record.id, calls);
472
+ }
473
+ const directTerms = new Map();
474
+ for (const item of localCalls) {
475
+ const enclosing = loops.filter(
476
+ (loop) =>
477
+ loop.method.record.id === item.caller.record.id &&
478
+ scopeIsWithin(
479
+ index,
480
+ text(item.call, "enclosingCallableRef"),
481
+ loop.action.scope,
482
+ ),
483
+ );
484
+ if (enclosing.length > 0) {
485
+ directTerms.set(
486
+ item.call.id,
487
+ uniqueTerms(enclosing.map((loop) => loop.term)),
488
+ );
489
+ }
490
+ }
491
+ const summaries = new Map();
492
+ const termsForCall = (item) => {
493
+ const terms = [...(directTerms.get(item.call.id) ?? [])];
494
+ const targetSummary = summaries.get(item.target.record.id) ?? [];
495
+ for (const term of targetSummary) {
496
+ const instantiated = instantiateTerm(index, item.call, item.caller, term);
497
+ if (instantiated) terms.push(instantiated);
498
+ }
499
+ return uniqueTerms(terms);
500
+ };
501
+ for (let pass = 0; pass <= index.methodsBySignature.size; pass += 1) {
502
+ let changed = false;
503
+ for (const method of index.methodsBySignature.values()) {
504
+ // A call-site condition is attached to every cloned control from the
505
+ // target. Do not summarize a mixed wrapper when it also owns a direct
506
+ // framework control whose availability cannot be proved here.
507
+ if (methodsWithExternalActions.has(method.record.id)) continue;
508
+ const calls = callsByMethod.get(method.record.id) ?? [];
509
+ if (calls.length === 0) continue;
510
+ const perCall = calls.map((item) => termsForCall(item));
511
+ if (perCall.some((terms) => terms.length === 0)) continue;
512
+ const keys = new Set(perCall.map((terms) => termsKey(terms)));
513
+ if (keys.size !== 1) continue;
514
+ const next = uniqueTerms(perCall[0]);
515
+ if (termsKey(summaries.get(method.record.id) ?? []) === termsKey(next)) {
516
+ continue;
517
+ }
518
+ summaries.set(method.record.id, next);
519
+ changed = true;
520
+ }
521
+ if (!changed) break;
522
+ }
523
+ return new Map(
524
+ localCalls.flatMap((item) => {
525
+ const context = aggregateContext(termsForCall(item));
526
+ return context ? [[item.call.id, context]] : [];
527
+ }),
528
+ );
529
+ }
@@ -0,0 +1 @@
1
+ export { buildSourceFacts } from "./normalize.js";