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,891 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { mkdir, mkdtemp, rm } from "node:fs/promises";
3
+ import { basename, dirname, join, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import {
6
+ buildAreaGraph,
7
+ CallbackIterationBudgetExceededError,
8
+ CallDepthBudgetExceededError,
9
+ DEFAULT_MAX_CALLBACK_ITERATIONS,
10
+ DEFAULT_MAX_CALL_DEPTH,
11
+ DEFAULT_MAX_GRAPH_STATES,
12
+ GraphStateBudgetExceededError,
13
+ } from "../analysis/graph/index.js";
14
+ import {
15
+ buildGapAudit,
16
+ diagnosticsForGapAudit,
17
+ } from "../analysis/gap-audit/index.js";
18
+ import { buildReqModel } from "../analysis/req-model/index.js";
19
+ import { buildSourceFacts } from "../analysis/source-facts/index.js";
20
+ import { extractAndroidXml } from "../android/index.js";
21
+ import {
22
+ defineDiagnostic,
23
+ RUN_CONTRACT_VERSION,
24
+ STAGE1_COVERAGE_VERSION,
25
+ } from "../contracts/index.js";
26
+ import { deriveCaseId } from "../core/stable-id.js";
27
+ import { AnalysisFailure, hardFailure } from "../diagnostics.js";
28
+ import { buildJvmAnalyzer, runJvmAnalysis } from "../jvm/index.js";
29
+ import {
30
+ loadGradleProjectModel,
31
+ prepareMergedManifest,
32
+ selectCompatibleModuleVariant,
33
+ selectGradleVariant,
34
+ } from "../project/gradle-model.js";
35
+ import { writeDeterministicGenerationArtifacts } from "../generation/index.js";
36
+ import { validateAreaGraph, validateReqModel } from "../validation/index.js";
37
+ import { publishStagedArtifacts, writeJsonArtifact } from "./output.js";
38
+ const PACKAGE_ROOT = resolve(
39
+ dirname(fileURLToPath(import.meta.url)),
40
+ "..",
41
+ "..",
42
+ );
43
+ export const DEFAULT_ANALYSIS_LIMITS = {
44
+ maxCallDepth: DEFAULT_MAX_CALL_DEPTH,
45
+ maxCallbackIterations: DEFAULT_MAX_CALLBACK_ITERATIONS,
46
+ maxGraphStates: DEFAULT_MAX_GRAPH_STATES,
47
+ };
48
+ const SUCCESS_FILENAMES = [
49
+ "source-facts.json",
50
+ "area-graph.json",
51
+ "req-model.json",
52
+ "gap-audit.json",
53
+ "diagnostics.json",
54
+ "coverage.json",
55
+ "generation",
56
+ "run-report.json",
57
+ ];
58
+ const FAILURE_FILENAMES = [
59
+ "gap-audit.json",
60
+ "diagnostics.json",
61
+ "coverage.json",
62
+ "run-report.json",
63
+ ];
64
+ const STRUCTURED_FILENAMES = [
65
+ "source-facts.json",
66
+ "area-graph.json",
67
+ "req-model.json",
68
+ ];
69
+ const STAGE1_PROGRESS_TOTAL = 7;
70
+ const STAGE1_PROGRESS = {
71
+ projectModel: {
72
+ stage: "project-model",
73
+ index: 1,
74
+ label: "Load Gradle project model",
75
+ },
76
+ androidXml: {
77
+ stage: "android-xml",
78
+ index: 2,
79
+ label: "Merge Manifest and extract Android XML",
80
+ },
81
+ analyzerBuild: {
82
+ stage: "analyzer-build",
83
+ index: 3,
84
+ label: "Build JVM analyzer",
85
+ },
86
+ jvmAnalysis: {
87
+ stage: "jvm-analysis",
88
+ index: 4,
89
+ label: "Run JVM source analysis",
90
+ },
91
+ normalize: {
92
+ stage: "normalize",
93
+ index: 5,
94
+ label: "Normalize source facts",
95
+ },
96
+ graph: {
97
+ stage: "graph",
98
+ index: 6,
99
+ label: "Build Area graph and paths",
100
+ },
101
+ reqModel: {
102
+ stage: "req-model",
103
+ index: 7,
104
+ label: "Build, validate, and publish REQ model and draft",
105
+ },
106
+ };
107
+ const defaultDependencies = {
108
+ loadGradleProjectModel,
109
+ selectGradleVariant,
110
+ prepareMergedManifest,
111
+ extractAndroidXml,
112
+ buildJvmAnalyzer,
113
+ runJvmAnalysis,
114
+ buildSourceFacts,
115
+ buildAreaGraph,
116
+ buildReqModel,
117
+ validateAreaGraph,
118
+ validateReqModel,
119
+ createRunId: randomUUID,
120
+ now: () => new Date(),
121
+ };
122
+ function nonBlank(value, field) {
123
+ const result = value.trim();
124
+ if (result.length === 0) {
125
+ throw new Error(`${field} must not be blank`);
126
+ }
127
+ return result;
128
+ }
129
+ function requireNormalLauncher(android, selected) {
130
+ const hasNormalLauncher = android.manifest.entries.some(
131
+ (entry) => entry.kind === "launcher" && entry.category === "normal",
132
+ );
133
+ if (hasNormalLauncher) return;
134
+ throw hardFailure(
135
+ "NORMAL_LAUNCHER_MISSING",
136
+ "manifest",
137
+ `Selected application variant ${selected.applicationModule.gradlePath}:${selected.variant.name} has no normal Launcher entry in its merged manifest.`,
138
+ "Select an application variant whose merged manifest declares ACTION_MAIN with CATEGORY_LAUNCHER.",
139
+ {
140
+ applicationModule: selected.applicationModule.gradlePath,
141
+ buildVariant: selected.variant.name,
142
+ manifestPackage: android.manifest.packageName ?? "",
143
+ requiredEntryKind: "launcher",
144
+ requiredCategory: "normal",
145
+ },
146
+ );
147
+ }
148
+ function sortedCounts(values) {
149
+ const counts = {};
150
+ for (const value of values) {
151
+ counts[value] = (counts[value] ?? 0) + 1;
152
+ }
153
+ return Object.fromEntries(
154
+ Object.entries(counts).sort(([left], [right]) =>
155
+ left.localeCompare(right, "en"),
156
+ ),
157
+ );
158
+ }
159
+ function emptyStages() {
160
+ return {
161
+ projectModel: { complete: false },
162
+ androidXml: { complete: false },
163
+ jvm: { complete: false },
164
+ normalize: { complete: false },
165
+ graph: { complete: false },
166
+ reqModel: { complete: false },
167
+ };
168
+ }
169
+ function emptyCounts() {
170
+ return {
171
+ rawJvmEvents: 0,
172
+ rawJvmEventsByKind: {},
173
+ evidence: 0,
174
+ facts: 0,
175
+ factsByKind: {},
176
+ areas: 0,
177
+ controls: 0,
178
+ actions: 0,
179
+ effects: 0,
180
+ edges: 0,
181
+ entries: 0,
182
+ unresolved: 0,
183
+ };
184
+ }
185
+ function diagnosticId(code, stage, identity) {
186
+ const digest = createHash("sha256")
187
+ .update(JSON.stringify({ code, stage, identity }))
188
+ .digest("hex")
189
+ .slice(0, 20);
190
+ return `diagnostic:stage1/${digest}`;
191
+ }
192
+ function unexpectedDiagnostic(error, stage) {
193
+ const message = error instanceof Error ? error.message : String(error);
194
+ return defineDiagnostic({
195
+ id: diagnosticId("STAGE1_UNEXPECTED_FAILURE", stage, message),
196
+ code: "STAGE1_UNEXPECTED_FAILURE",
197
+ stage,
198
+ message: `Stage 1 failed: ${message}`,
199
+ remediation:
200
+ "Resolve the reported source or analyzer failure and run Stage 1 again.",
201
+ disposition: "fail-run",
202
+ severity: "error",
203
+ category:
204
+ stage === "normalize" ||
205
+ stage === "graph" ||
206
+ stage === "paths" ||
207
+ stage === "req-model" ||
208
+ stage === "validate"
209
+ ? "invariant"
210
+ : "infrastructure",
211
+ });
212
+ }
213
+ function graphStateBudgetDiagnostic(error) {
214
+ return defineDiagnostic({
215
+ id: diagnosticId(
216
+ error.code,
217
+ error.stage,
218
+ JSON.stringify({
219
+ maxGraphStates: error.maxGraphStates,
220
+ statesUsed: error.statesUsed,
221
+ }),
222
+ ),
223
+ code: error.code,
224
+ stage: error.stage,
225
+ message: error.message,
226
+ remediation:
227
+ "Increase maxGraphStates or reduce the reachable Area path graph before running Stage 1 again.",
228
+ details: {
229
+ maxGraphStates: error.maxGraphStates,
230
+ statesUsed: error.statesUsed,
231
+ attemptedState: error.attemptedState,
232
+ },
233
+ disposition: "fail-run",
234
+ severity: "error",
235
+ category: "infrastructure",
236
+ });
237
+ }
238
+ function callDepthBudgetDiagnostic(error) {
239
+ return defineDiagnostic({
240
+ id: diagnosticId(
241
+ error.code,
242
+ error.stage,
243
+ JSON.stringify({
244
+ maxCallDepth: error.maxCallDepth,
245
+ bindingRef: error.bindingRef,
246
+ callbackRef: error.callbackRef,
247
+ }),
248
+ ),
249
+ code: error.code,
250
+ stage: error.stage,
251
+ message: error.message,
252
+ remediation:
253
+ "Increase maxCallDepth or reduce the callback-flow chain before running Stage 1 again.",
254
+ details: {
255
+ maxCallDepth: error.maxCallDepth,
256
+ depthReached: error.depthReached,
257
+ attemptedDepth: error.attemptedDepth,
258
+ bindingRef: error.bindingRef,
259
+ callbackRef: error.callbackRef,
260
+ },
261
+ disposition: "fail-run",
262
+ severity: "error",
263
+ category: "infrastructure",
264
+ });
265
+ }
266
+ function callbackIterationBudgetDiagnostic(error) {
267
+ return defineDiagnostic({
268
+ id: diagnosticId(
269
+ error.code,
270
+ error.stage,
271
+ JSON.stringify({
272
+ maxCallbackIterations: error.maxCallbackIterations,
273
+ bindingRef: error.bindingRef,
274
+ callbackRef: error.callbackRef,
275
+ }),
276
+ ),
277
+ code: error.code,
278
+ stage: error.stage,
279
+ message: error.message,
280
+ remediation:
281
+ "Increase maxCallbackIterations or reduce callback-flow fan-out before running Stage 1 again.",
282
+ details: {
283
+ maxCallbackIterations: error.maxCallbackIterations,
284
+ iterationsUsed: error.iterationsUsed,
285
+ attemptedIteration: error.attemptedIteration,
286
+ bindingRef: error.bindingRef,
287
+ callbackRef: error.callbackRef,
288
+ },
289
+ disposition: "fail-run",
290
+ severity: "error",
291
+ category: "infrastructure",
292
+ });
293
+ }
294
+ function diagnosticsForUnresolved(graph, source) {
295
+ const sourceIds = new Set(source.unresolved.map((item) => item.id));
296
+ return graph.unresolved
297
+ .map((item) => {
298
+ const stage = sourceIds.has(item.id) ? "normalize" : "graph";
299
+ return defineDiagnostic({
300
+ id: diagnosticId(item.reasonCode, stage, item.id),
301
+ code: item.reasonCode,
302
+ stage,
303
+ message: item.message,
304
+ entityKey: item.ownerRef,
305
+ details: {
306
+ unresolvedRef: item.id,
307
+ evidenceRefs: item.evidenceRefs,
308
+ impact: item.impact,
309
+ },
310
+ disposition: "continue",
311
+ severity: "warning",
312
+ category: "intrinsic-unknown",
313
+ });
314
+ })
315
+ .sort((left, right) => left.id.localeCompare(right.id, "en"));
316
+ }
317
+ function contextsEqual(left, right) {
318
+ return (
319
+ left.caseId === right.caseId &&
320
+ JSON.stringify(left.analysisContext) ===
321
+ JSON.stringify(right.analysisContext)
322
+ );
323
+ }
324
+ function validateArtifactSet(
325
+ source,
326
+ graph,
327
+ reqModel,
328
+ graphValidation,
329
+ reqValidation,
330
+ ) {
331
+ const issues = [...graphValidation.issues, ...reqValidation.issues];
332
+ if (!contextsEqual(source, graph)) {
333
+ issues.push({
334
+ code: "SOURCE_GRAPH_CONTEXT_MISMATCH",
335
+ path: "/analysisContext",
336
+ message: "Source facts and Area graph use different analysis contexts.",
337
+ });
338
+ }
339
+ return issues;
340
+ }
341
+ function updateCounts(counts, input) {
342
+ return {
343
+ ...counts,
344
+ ...(input.jvm
345
+ ? {
346
+ rawJvmEvents: input.jvm.document.body.length,
347
+ rawJvmEventsByKind: input.jvm.document.countsByKind,
348
+ }
349
+ : {}),
350
+ ...(input.source
351
+ ? {
352
+ evidence: input.source.evidence.length,
353
+ facts: input.source.facts.length,
354
+ factsByKind: sortedCounts(
355
+ input.source.facts.map((fact) => fact.kind),
356
+ ),
357
+ unresolved: input.source.unresolved.length,
358
+ }
359
+ : {}),
360
+ ...(input.graph
361
+ ? {
362
+ areas: input.graph.areas.length,
363
+ controls: input.graph.controls.length,
364
+ actions: input.graph.actions.length,
365
+ effects: input.graph.effects.length,
366
+ edges: input.graph.edges.length,
367
+ entries: input.graph.entryPoints.length,
368
+ unresolved: input.graph.unresolved.length,
369
+ }
370
+ : {}),
371
+ };
372
+ }
373
+ function coverageValue(input) {
374
+ return {
375
+ contractVersion: STAGE1_COVERAGE_VERSION,
376
+ runId: input.runId,
377
+ caseId: input.caseId,
378
+ ...(input.target ? { target: input.target } : {}),
379
+ stages: input.stages,
380
+ counts: input.counts,
381
+ budget: {
382
+ limits: input.limits,
383
+ exhausted: input.budgetExhausted ?? false,
384
+ },
385
+ limitations: [
386
+ "Only the selected Application Module, Build Variant, and Resource Configuration are represented.",
387
+ "Runtime-only behavior is outside this static-analysis run.",
388
+ "Gap audit is a conservative source census; possible-gap is the legacy count, while critical unresolved candidates drive semantic publishability.",
389
+ ],
390
+ };
391
+ }
392
+ async function writeCompletedOutput(outputDirectory, values) {
393
+ const staging = await mkdtemp(join(outputDirectory, ".stage1-publish-"));
394
+ try {
395
+ const artifacts = [];
396
+ artifacts.push(
397
+ await writeJsonArtifact(
398
+ staging,
399
+ "source-facts.json",
400
+ "source-facts",
401
+ values.source,
402
+ ),
403
+ );
404
+ artifacts.push(
405
+ await writeJsonArtifact(
406
+ staging,
407
+ "area-graph.json",
408
+ "area-graph",
409
+ values.graph,
410
+ ),
411
+ );
412
+ artifacts.push(
413
+ await writeJsonArtifact(
414
+ staging,
415
+ "req-model.json",
416
+ "req-model",
417
+ values.reqModel,
418
+ ),
419
+ );
420
+ artifacts.push(
421
+ await writeJsonArtifact(
422
+ staging,
423
+ "gap-audit.json",
424
+ "gap-audit",
425
+ values.gapAudit,
426
+ ),
427
+ );
428
+ artifacts.push(
429
+ await writeJsonArtifact(
430
+ staging,
431
+ "diagnostics.json",
432
+ "diagnostics",
433
+ values.diagnostics,
434
+ ),
435
+ );
436
+ artifacts.push(
437
+ await writeJsonArtifact(
438
+ staging,
439
+ "coverage.json",
440
+ "coverage",
441
+ values.coverage,
442
+ ),
443
+ );
444
+ const generated = await writeDeterministicGenerationArtifacts(
445
+ join(staging, "generation"),
446
+ {
447
+ source: values.source,
448
+ graph: values.graph,
449
+ reqModel: values.reqModel,
450
+ },
451
+ );
452
+ artifacts.push(
453
+ ...generated.artifacts.map((artifact) => ({
454
+ ...artifact,
455
+ relativePath: `generation/${artifact.relativePath}`,
456
+ })),
457
+ );
458
+ const report = {
459
+ ...values.reportBase,
460
+ completedAt: values.completedAt,
461
+ artifacts,
462
+ };
463
+ await writeJsonArtifact(staging, "run-report.json", "run-report", report);
464
+ await publishStagedArtifacts(staging, outputDirectory, SUCCESS_FILENAMES);
465
+ return report;
466
+ } finally {
467
+ await rm(staging, { recursive: true, force: true });
468
+ }
469
+ }
470
+ async function writeFailedOutput(outputDirectory, values) {
471
+ const staging = await mkdtemp(join(outputDirectory, ".stage1-failure-"));
472
+ try {
473
+ const artifacts = [];
474
+ const retainedStructuredFilenames = [];
475
+ if (values.source) {
476
+ artifacts.push(
477
+ await writeJsonArtifact(
478
+ staging,
479
+ "source-facts.json",
480
+ "source-facts",
481
+ values.source,
482
+ ),
483
+ );
484
+ retainedStructuredFilenames.push("source-facts.json");
485
+ }
486
+ if (values.graph) {
487
+ artifacts.push(
488
+ await writeJsonArtifact(
489
+ staging,
490
+ "area-graph.json",
491
+ "area-graph",
492
+ values.graph,
493
+ ),
494
+ );
495
+ retainedStructuredFilenames.push("area-graph.json");
496
+ }
497
+ if (values.reqModel) {
498
+ artifacts.push(
499
+ await writeJsonArtifact(
500
+ staging,
501
+ "req-model.json",
502
+ "req-model",
503
+ values.reqModel,
504
+ ),
505
+ );
506
+ retainedStructuredFilenames.push("req-model.json");
507
+ }
508
+ artifacts.push(
509
+ await writeJsonArtifact(
510
+ staging,
511
+ "gap-audit.json",
512
+ "gap-audit",
513
+ values.gapAudit,
514
+ ),
515
+ );
516
+ artifacts.push(
517
+ await writeJsonArtifact(
518
+ staging,
519
+ "diagnostics.json",
520
+ "diagnostics",
521
+ values.diagnostics,
522
+ ),
523
+ );
524
+ artifacts.push(
525
+ await writeJsonArtifact(
526
+ staging,
527
+ "coverage.json",
528
+ "coverage",
529
+ values.coverage,
530
+ ),
531
+ );
532
+ const report = {
533
+ ...values.reportBase,
534
+ completedAt: values.completedAt,
535
+ artifacts,
536
+ };
537
+ await writeJsonArtifact(staging, "run-report.json", "run-report", report);
538
+ await publishStagedArtifacts(
539
+ staging,
540
+ outputDirectory,
541
+ [...retainedStructuredFilenames, ...FAILURE_FILENAMES],
542
+ [
543
+ ...STRUCTURED_FILENAMES.filter(
544
+ (filename) => !retainedStructuredFilenames.includes(filename),
545
+ ),
546
+ "generation",
547
+ ],
548
+ );
549
+ return report;
550
+ } finally {
551
+ await rm(staging, { recursive: true, force: true });
552
+ }
553
+ }
554
+ /**
555
+ * Run the model-free static-analysis stage. Heavy environment boundaries are
556
+ * dependencies so unit tests can exercise orchestration without Gradle,
557
+ * Android SDKs, fixtures, a model, or a network.
558
+ */
559
+ export async function runStage1(options, injected = {}) {
560
+ const dependencies = {
561
+ ...defaultDependencies,
562
+ ...injected,
563
+ };
564
+ const projectRoot = resolve(nonBlank(options.projectRoot, "projectRoot"));
565
+ const outputDirectory = resolve(
566
+ nonBlank(options.outputDirectory, "outputDirectory"),
567
+ );
568
+ const runId = nonBlank(options.runId ?? dependencies.createRunId(), "runId");
569
+ const caseId = nonBlank(
570
+ options.caseId ?? deriveCaseId(basename(projectRoot)),
571
+ "caseId",
572
+ );
573
+ const limits = options.limits ?? DEFAULT_ANALYSIS_LIMITS;
574
+ const startedAt = dependencies.now().toISOString();
575
+ const stages = emptyStages();
576
+ let counts = emptyCounts();
577
+ let target;
578
+ let completedStage = "configure";
579
+ let activeStage = "project-model";
580
+ let analyzerVersion = "unknown";
581
+ let workDirectory;
582
+ let androidForAudit;
583
+ let jvmForAudit;
584
+ let sourceForAudit;
585
+ let graphForAudit;
586
+ let reqModelForAudit;
587
+ let activeProgress;
588
+ const startProgress = (definition) => {
589
+ activeProgress = {
590
+ definition,
591
+ startedAtMs: Date.now(),
592
+ };
593
+ options.onProgress?.({
594
+ ...definition,
595
+ status: "started",
596
+ total: STAGE1_PROGRESS_TOTAL,
597
+ });
598
+ };
599
+ const finishProgress = (status) => {
600
+ if (!activeProgress) return;
601
+ const { definition, startedAtMs } = activeProgress;
602
+ activeProgress = undefined;
603
+ options.onProgress?.({
604
+ ...definition,
605
+ status,
606
+ total: STAGE1_PROGRESS_TOTAL,
607
+ elapsedMs: Date.now() - startedAtMs,
608
+ });
609
+ };
610
+ await mkdir(outputDirectory, { recursive: true });
611
+ try {
612
+ workDirectory = await mkdtemp(join(outputDirectory, ".stage1-work-"));
613
+ startProgress(STAGE1_PROGRESS.projectModel);
614
+ const projectModel = await dependencies.loadGradleProjectModel(
615
+ projectRoot,
616
+ {
617
+ initScript: resolve(
618
+ options.initScriptPath ??
619
+ join(PACKAGE_ROOT, "gradle", "reqgen-model.init.gradle"),
620
+ ),
621
+ outputPath: join(workDirectory, "gradle-project-model.json"),
622
+ ...(options.projectGradle ? { runner: options.projectGradle } : {}),
623
+ },
624
+ );
625
+ const selected = dependencies.selectGradleVariant(
626
+ projectModel,
627
+ options.applicationModulePath,
628
+ options.variantName,
629
+ );
630
+ const nonAndroidLocalModules = selected.reachableModules
631
+ .filter((module) => module.kind === "non-android-library")
632
+ .map((module) => module.gradlePath);
633
+ target = {
634
+ applicationModule: selected.applicationModule.gradlePath,
635
+ buildVariant: selected.variant.name,
636
+ resourceConfiguration: options.resourceConfiguration,
637
+ ...(nonAndroidLocalModules.length > 0 ? { nonAndroidLocalModules } : {}),
638
+ };
639
+ stages.projectModel.complete = true;
640
+ completedStage = "project-model";
641
+ finishProgress("completed");
642
+ activeStage = "extract";
643
+ startProgress(STAGE1_PROGRESS.androidXml);
644
+ const mergedManifestPath = await dependencies.prepareMergedManifest(
645
+ selected,
646
+ options.projectGradle,
647
+ );
648
+ const android = dependencies.extractAndroidXml({
649
+ selected,
650
+ resourceConfiguration: options.resourceConfiguration,
651
+ mergedManifestPath,
652
+ });
653
+ androidForAudit = android;
654
+ stages.androidXml.complete = true;
655
+ requireNormalLauncher(android, selected);
656
+ finishProgress("completed");
657
+ startProgress(STAGE1_PROGRESS.analyzerBuild);
658
+ const builtAnalyzer = await dependencies.buildJvmAnalyzer({
659
+ analyzerProjectRoot: resolve(
660
+ options.analyzerProjectRoot ?? join(PACKAGE_ROOT, "analyzer-jvm"),
661
+ ),
662
+ ...(options.analyzerArtifactPath
663
+ ? { artifactPath: options.analyzerArtifactPath }
664
+ : {}),
665
+ ...(options.analyzerGradle ? { gradle: options.analyzerGradle } : {}),
666
+ });
667
+ finishProgress("completed");
668
+ startProgress(STAGE1_PROGRESS.jvmAnalysis);
669
+ const jvm = await dependencies.runJvmAnalysis({
670
+ target: {
671
+ projectRoot,
672
+ applicationModulePath: selected.applicationModule.gradlePath,
673
+ variantName: selected.variant.name,
674
+ sourceRoot: projectRoot,
675
+ },
676
+ // non-android-library modules have no lintAnalyze task (no AGP applied)
677
+ // and contribute no source to JVM analysis — see gradle-model.ts.
678
+ moduleTargets: selected.reachableModules
679
+ .filter((module) => module.kind !== "non-android-library")
680
+ .map((module) => ({
681
+ projectRoot,
682
+ applicationModulePath: module.gradlePath,
683
+ variantName: selectCompatibleModuleVariant(module, selected.variant)
684
+ .name,
685
+ sourceRoot: projectRoot,
686
+ })),
687
+ analyzerJarPath: builtAnalyzer.jarPath,
688
+ outputDirectory: workDirectory,
689
+ ...(options.projectGradle ? { gradle: options.projectGradle } : {}),
690
+ });
691
+ jvmForAudit = jvm;
692
+ analyzerVersion = jvm.document.header.data.engineVersion;
693
+ stages.jvm.complete = true;
694
+ completedStage = "extract";
695
+ counts = updateCounts(counts, { jvm });
696
+ finishProgress("completed");
697
+ activeStage = "normalize";
698
+ startProgress(STAGE1_PROGRESS.normalize);
699
+ const sourceBase = dependencies.buildSourceFacts({
700
+ caseId,
701
+ android,
702
+ jvm: jvm.document,
703
+ });
704
+ sourceForAudit = sourceBase;
705
+ stages.normalize.complete = true;
706
+ completedStage = "normalize";
707
+ counts = updateCounts(counts, { source: sourceBase });
708
+ finishProgress("completed");
709
+ activeStage = "graph";
710
+ startProgress(STAGE1_PROGRESS.graph);
711
+ const graphBase = dependencies.buildAreaGraph(sourceBase, {
712
+ maxCallDepth: limits.maxCallDepth,
713
+ maxCallbackIterations: limits.maxCallbackIterations,
714
+ maxGraphStates: limits.maxGraphStates,
715
+ });
716
+ stages.graph.complete = true;
717
+ completedStage = "paths";
718
+ counts = updateCounts(counts, { graph: graphBase });
719
+ graphForAudit = graphBase;
720
+ finishProgress("completed");
721
+ activeStage = "req-model";
722
+ startProgress(STAGE1_PROGRESS.reqModel);
723
+ const gapAudit = buildGapAudit({
724
+ runId,
725
+ caseId,
726
+ target,
727
+ android,
728
+ jvm: jvm.document,
729
+ source: sourceBase,
730
+ });
731
+ const semanticFields = {
732
+ semanticCompleteness: gapAudit.semanticCompleteness,
733
+ limitations: gapAudit.semanticLimitations,
734
+ };
735
+ const source = {
736
+ ...sourceBase,
737
+ ...semanticFields,
738
+ };
739
+ const graph = {
740
+ ...graphBase,
741
+ ...semanticFields,
742
+ };
743
+ sourceForAudit = source;
744
+ graphForAudit = graph;
745
+ const reqModel = {
746
+ ...dependencies.buildReqModel(graph, source),
747
+ ...semanticFields,
748
+ };
749
+ reqModelForAudit = reqModel;
750
+ stages.reqModel.complete = true;
751
+ completedStage = "req-model";
752
+ activeStage = "validate";
753
+ const validationIssues = validateArtifactSet(
754
+ source,
755
+ graph,
756
+ reqModel,
757
+ dependencies.validateAreaGraph(graph),
758
+ dependencies.validateReqModel(reqModel, graph, source),
759
+ );
760
+ if (validationIssues.length > 0) {
761
+ throw new AnalysisFailure("Stage 1 artifact validation failed.", [
762
+ defineDiagnostic({
763
+ id: diagnosticId(
764
+ "STAGE1_ARTIFACT_VALIDATION_FAILED",
765
+ "validate",
766
+ JSON.stringify(validationIssues),
767
+ ),
768
+ code: "STAGE1_ARTIFACT_VALIDATION_FAILED",
769
+ stage: "validate",
770
+ message: "Stage 1 artifact invariants failed.",
771
+ remediation:
772
+ "Fix the analyzer or normalization invariant before publishing artifacts.",
773
+ details: {
774
+ issues: validationIssues.map((issue) => ({
775
+ code: issue.code,
776
+ path: issue.path,
777
+ message: issue.message,
778
+ })),
779
+ },
780
+ disposition: "fail-run",
781
+ severity: "error",
782
+ category: "invariant",
783
+ }),
784
+ ]);
785
+ }
786
+ completedStage = "validate";
787
+ const diagnostics = [
788
+ ...diagnosticsForUnresolved(graph, source),
789
+ ...diagnosticsForGapAudit(gapAudit),
790
+ ];
791
+ const coverage = coverageValue({
792
+ runId,
793
+ caseId,
794
+ target,
795
+ stages,
796
+ counts,
797
+ limits,
798
+ });
799
+ const completedAt = dependencies.now().toISOString();
800
+ const publishable = gapAudit.semanticCompleteness !== "incomplete-known";
801
+ const report = await writeCompletedOutput(outputDirectory, {
802
+ source,
803
+ graph,
804
+ reqModel,
805
+ gapAudit,
806
+ diagnostics,
807
+ coverage,
808
+ completedAt,
809
+ reportBase: {
810
+ contractVersion: RUN_CONTRACT_VERSION,
811
+ runId,
812
+ caseId,
813
+ target,
814
+ analyzerVersion,
815
+ startedAt,
816
+ diagnostics,
817
+ semanticCompleteness: gapAudit.semanticCompleteness,
818
+ status: "succeeded",
819
+ publishable,
820
+ completedStage: "validate",
821
+ },
822
+ });
823
+ finishProgress("completed");
824
+ return { report, coverage, outputDirectory };
825
+ } catch (error) {
826
+ finishProgress("failed");
827
+ const budgetExhausted =
828
+ error instanceof GraphStateBudgetExceededError ||
829
+ error instanceof CallDepthBudgetExceededError ||
830
+ error instanceof CallbackIterationBudgetExceededError;
831
+ const failureDiagnostics =
832
+ error instanceof GraphStateBudgetExceededError
833
+ ? [graphStateBudgetDiagnostic(error)]
834
+ : error instanceof CallDepthBudgetExceededError
835
+ ? [callDepthBudgetDiagnostic(error)]
836
+ : error instanceof CallbackIterationBudgetExceededError
837
+ ? [callbackIterationBudgetDiagnostic(error)]
838
+ : error instanceof AnalysisFailure
839
+ ? error.diagnostics
840
+ : [unexpectedDiagnostic(error, activeStage)];
841
+ const gapAudit = buildGapAudit({
842
+ runId,
843
+ caseId,
844
+ ...(target ? { target } : {}),
845
+ ...(androidForAudit ? { android: androidForAudit } : {}),
846
+ ...(jvmForAudit ? { jvm: jvmForAudit.document } : {}),
847
+ ...(sourceForAudit ? { source: sourceForAudit } : {}),
848
+ });
849
+ const diagnostics = [
850
+ ...failureDiagnostics,
851
+ ...diagnosticsForGapAudit(gapAudit),
852
+ ];
853
+ const coverage = coverageValue({
854
+ runId,
855
+ caseId,
856
+ ...(target ? { target } : {}),
857
+ stages,
858
+ counts,
859
+ limits,
860
+ budgetExhausted,
861
+ });
862
+ const completedAt = dependencies.now().toISOString();
863
+ const report = await writeFailedOutput(outputDirectory, {
864
+ ...(sourceForAudit ? { source: sourceForAudit } : {}),
865
+ ...(graphForAudit ? { graph: graphForAudit } : {}),
866
+ ...(reqModelForAudit ? { reqModel: reqModelForAudit } : {}),
867
+ gapAudit,
868
+ diagnostics,
869
+ coverage,
870
+ completedAt,
871
+ reportBase: {
872
+ contractVersion: RUN_CONTRACT_VERSION,
873
+ runId,
874
+ caseId,
875
+ ...(target ? { target } : {}),
876
+ analyzerVersion,
877
+ startedAt,
878
+ diagnostics,
879
+ semanticCompleteness: "incomplete-known",
880
+ status: "failed",
881
+ publishable: false,
882
+ ...(completedStage ? { completedStage } : {}),
883
+ },
884
+ });
885
+ return { report, coverage, outputDirectory };
886
+ } finally {
887
+ if (workDirectory) {
888
+ await rm(workDirectory, { recursive: true, force: true });
889
+ }
890
+ }
891
+ }