taphound 0.2.0-dev.1 → 0.2.0-dev.12

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 (467) hide show
  1. package/README.md +49 -149
  2. package/README.zh-CN.md +47 -147
  3. package/assets/skills/taphound-case-suite/SKILL.md +363 -0
  4. package/assets/skills/taphound-case-suite/schemas/base-flow-record.schema.json +22 -0
  5. package/assets/skills/taphound-case-suite/schemas/case-catalog.schema.json +26 -0
  6. package/assets/skills/taphound-case-suite/schemas/case-ledger.schema.json +158 -0
  7. package/assets/skills/taphound-case-suite/schemas/suite-input.schema.json +41 -0
  8. package/assets/skills/taphound-case-suite/schemas/transition.schema.json +61 -0
  9. package/assets/skills/taphound-case-suite/scripts/ledger.mjs +1207 -0
  10. package/assets/skills/taphound-case-suite/templates/base-flow-record.example.json +20 -0
  11. package/assets/skills/taphound-case-suite/templates/suite-input.example.json +27 -0
  12. package/assets/skills/taphound-case-suite/templates/transition.example.json +8 -0
  13. package/assets/skills/taphound-flash/SKILL.md +115 -0
  14. package/assets/skills/taphound-flash/scripts/flash.mjs +585 -0
  15. package/assets/skills/taphound-flash/templates/flash-plan.example.json +15 -0
  16. package/assets/skills/taphound-journey-brief-author/CONTEXT-GUIDE.md +471 -0
  17. package/assets/skills/taphound-journey-brief-author/SKILL.md +494 -0
  18. package/assets/skills/taphound-journey-brief-author/prompts/brief-author-role.md +96 -0
  19. package/assets/skills/taphound-journey-brief-author/prompts/brief-author-role.zh-CN.md +80 -0
  20. package/assets/skills/taphound-journey-brief-author/prompts/context-analyze-project.md +309 -0
  21. package/assets/skills/taphound-journey-brief-author/schemas/context-refresh-result.json +123 -0
  22. package/assets/skills/taphound-journey-brief-author/schemas/project-context-module.json +192 -0
  23. package/assets/skills/taphound-journey-brief-author/schemas/project-context.json +152 -0
  24. package/assets/skills/taphound-journey-brief-author/templates/project-context-module.example.json +58 -0
  25. package/assets/skills/taphound-journey-brief-author/templates/project-context.example.json +51 -0
  26. package/assets/skills/taphound-journey-brief-author/templates/taphound-journey-brief.template.md +63 -0
  27. package/assets/skills/taphound-journey-generator/SKILL.md +507 -0
  28. package/assets/skills/{taphound-ai-journey → taphound-journey-generator}/prompts/check-completion.md +3 -0
  29. package/assets/skills/taphound-journey-generator/prompts/consume-journey-brief.md +52 -0
  30. package/assets/skills/taphound-journey-generator/prompts/generate-step.md +211 -0
  31. package/assets/skills/taphound-journey-generator/prompts/select-flow.md +91 -0
  32. package/assets/skills/taphound-journey-generator/references/bridge.md +35 -0
  33. package/assets/skills/taphound-journey-generator/references/mid-session.md +44 -0
  34. package/assets/skills/taphound-journey-generator/schemas/external-flow.json +37 -0
  35. package/assets/skills/taphound-journey-generator/schemas/flow.json +28 -0
  36. package/assets/skills/taphound-journey-generator/schemas/journey-source.json +25 -0
  37. package/assets/skills/{taphound-ai-journey → taphound-journey-generator}/schemas/observe-output.json +13 -4
  38. package/assets/skills/{taphound-ai-journey → taphound-journey-generator}/schemas/proposed-step-envelope.json +127 -5
  39. package/assets/skills/taphound-journey-generator/scripts/envelope.mjs +578 -0
  40. package/assets/skills/taphound-journey-generator/templates/external-flow.example.json +22 -0
  41. package/assets/skills/taphound-journey-generator/templates/flow.example.json +22 -0
  42. package/assets/skills/taphound-journey-generator/templates/journey-source.example.json +17 -0
  43. package/assets/skills/taphound-journey-generator/templates/taphound-journey-brief.example.md +70 -0
  44. package/assets/skills/taphound-verify-change/SKILL.md +91 -0
  45. package/assets/skills/taphound-verify-change/references/accept.md +38 -0
  46. package/assets/skills/taphound-verify-change/references/preserve.md +357 -0
  47. package/assets/skills/taphound-verify-change/schemas/workflow-manifest.schema.json +295 -0
  48. package/assets/skills/taphound-verify-change/scripts/handoff.mjs +482 -0
  49. package/assets/skills/taphound-verify-change/scripts/ui-refactor.mjs +505 -0
  50. package/dist/adapters/adb/adb-adapter.d.ts +16 -2
  51. package/dist/adapters/adb/adb-adapter.js +199 -0
  52. package/dist/adapters/adb/system-uiautomator-snapshot-provider.d.ts +13 -0
  53. package/dist/adapters/adb/system-uiautomator-snapshot-provider.js +122 -0
  54. package/dist/adapters/adb/ui-automator-parser.d.ts +3 -0
  55. package/dist/adapters/adb/ui-automator-parser.js +160 -0
  56. package/dist/adapters/adb/window-topology-parser.d.ts +2 -0
  57. package/dist/adapters/adb/window-topology-parser.js +101 -0
  58. package/dist/adapters/android-cli/android-cli-adapter.d.ts +16 -8
  59. package/dist/adapters/android-cli/android-cli-adapter.js +137 -15
  60. package/dist/adapters/android-cli/android-cli-snapshot-provider.d.ts +9 -0
  61. package/dist/adapters/android-cli/android-cli-snapshot-provider.js +99 -0
  62. package/dist/adapters/android-cli/layout-parser.js +12 -8
  63. package/dist/adapters/appium/appium-doctor.d.ts +7 -0
  64. package/dist/adapters/appium/appium-doctor.js +128 -0
  65. package/dist/adapters/appium/appium-ui-snapshot-provider.d.ts +42 -0
  66. package/dist/adapters/appium/appium-ui-snapshot-provider.js +309 -0
  67. package/dist/adapters/camera/camera-probe-adapter.d.ts +18 -0
  68. package/dist/adapters/camera/camera-probe-adapter.js +286 -0
  69. package/dist/adapters/filesystem/artifact-store.js +40 -1
  70. package/dist/adapters/filesystem/context-document-writer.d.ts +15 -0
  71. package/dist/adapters/filesystem/context-document-writer.js +112 -0
  72. package/dist/adapters/filesystem/diagnostics-journal.d.ts +17 -0
  73. package/dist/adapters/filesystem/diagnostics-journal.js +130 -0
  74. package/dist/adapters/filesystem/external-flow-registry.d.ts +17 -0
  75. package/dist/adapters/filesystem/external-flow-registry.js +325 -0
  76. package/dist/adapters/filesystem/generation-session-store.d.ts +17 -11
  77. package/dist/adapters/filesystem/generation-session-store.js +281 -855
  78. package/dist/adapters/filesystem/generation-store/session-lock.d.ts +29 -0
  79. package/dist/adapters/filesystem/generation-store/session-lock.js +202 -0
  80. package/dist/adapters/filesystem/generation-store/session-transitions.d.ts +24 -0
  81. package/dist/adapters/filesystem/generation-store/session-transitions.js +340 -0
  82. package/dist/adapters/filesystem/generation-store/store-files.d.ts +50 -0
  83. package/dist/adapters/filesystem/generation-store/store-files.js +363 -0
  84. package/dist/adapters/filesystem/journey-composition-store.d.ts +23 -0
  85. package/dist/adapters/filesystem/journey-composition-store.js +151 -0
  86. package/dist/adapters/filesystem/knowledge-registry.d.ts +12 -0
  87. package/dist/adapters/filesystem/knowledge-registry.js +223 -0
  88. package/dist/adapters/filesystem/project-bound-file.js +3 -5
  89. package/dist/adapters/filesystem/project-file-inspector.d.ts +2 -0
  90. package/dist/adapters/filesystem/project-file-inspector.js +57 -28
  91. package/dist/adapters/filesystem/project-identity-inspector.d.ts +7 -0
  92. package/dist/adapters/filesystem/project-identity-inspector.js +215 -0
  93. package/dist/adapters/filesystem/project-inventory-inspector.d.ts +8 -0
  94. package/dist/adapters/filesystem/project-inventory-inspector.js +93 -0
  95. package/dist/adapters/filesystem/project-module-discoverer.d.ts +6 -0
  96. package/dist/adapters/filesystem/project-module-discoverer.js +158 -0
  97. package/dist/adapters/filesystem/skill-installer.d.ts +7 -2
  98. package/dist/adapters/filesystem/skill-installer.js +40 -11
  99. package/dist/adapters/filesystem/workspace-layout.d.ts +7 -0
  100. package/dist/adapters/filesystem/workspace-layout.js +57 -0
  101. package/dist/adapters/git/node-git-diff.d.ts +17 -0
  102. package/dist/adapters/git/node-git-diff.js +114 -0
  103. package/dist/adapters/process/node-detached-process-launcher.d.ts +6 -0
  104. package/dist/adapters/process/node-detached-process-launcher.js +96 -0
  105. package/dist/adapters/process/node-process-runner.js +11 -2
  106. package/dist/adapters/prompt/inquirer-align-prompt.d.ts +27 -0
  107. package/dist/adapters/prompt/inquirer-align-prompt.js +65 -0
  108. package/dist/adapters/prompt/inquirer-generation-prompt.js +3 -0
  109. package/dist/adapters/prompt/inquirer-recorder-prompt.d.ts +9 -1
  110. package/dist/adapters/prompt/inquirer-recorder-prompt.js +63 -0
  111. package/dist/adapters/runtime/adb-runtime-backend.d.ts +67 -0
  112. package/dist/adapters/runtime/adb-runtime-backend.js +206 -0
  113. package/dist/adapters/runtime/fake-runtime-backend.d.ts +87 -0
  114. package/dist/adapters/runtime/fake-runtime-backend.js +240 -0
  115. package/dist/adapters/runtime/mobile-mcp/mcp-tool-client.d.ts +45 -0
  116. package/dist/adapters/runtime/mobile-mcp/mcp-tool-client.js +153 -0
  117. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-errors.d.ts +23 -0
  118. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-errors.js +39 -0
  119. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-responses.d.ts +20 -0
  120. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-responses.js +180 -0
  121. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-runtime-backend.d.ts +78 -0
  122. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-runtime-backend.js +379 -0
  123. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-tools.d.ts +46 -0
  124. package/dist/adapters/runtime/session-adb-view.d.ts +53 -0
  125. package/dist/adapters/runtime/session-adb-view.js +193 -0
  126. package/dist/adapters/runtime/session-backed-ports.d.ts +21 -0
  127. package/dist/adapters/runtime/session-backed-ports.js +43 -0
  128. package/dist/adapters/runtime/shared-session-runtime-backend.d.ts +12 -0
  129. package/dist/adapters/runtime/shared-session-runtime-backend.js +64 -0
  130. package/dist/adapters/ui/auto-ui-snapshot-provider.d.ts +8 -0
  131. package/dist/adapters/ui/auto-ui-snapshot-provider.js +48 -0
  132. package/dist/adapters/ui/device-layout-temp.d.ts +6 -0
  133. package/dist/adapters/ui/device-layout-temp.js +18 -0
  134. package/dist/adapters/ui/device-ui-environment.d.ts +13 -0
  135. package/dist/adapters/ui/device-ui-environment.js +81 -0
  136. package/dist/adapters/ui/layout-normalization.d.ts +9 -0
  137. package/dist/adapters/ui/layout-normalization.js +44 -0
  138. package/dist/adapters/ui/ui-snapshot-error.d.ts +11 -0
  139. package/dist/adapters/ui/ui-snapshot-error.js +12 -0
  140. package/dist/adapters/ui/ui-snapshot-support.d.ts +15 -0
  141. package/dist/adapters/ui/ui-snapshot-support.js +12 -0
  142. package/dist/application/align/align-service.d.ts +42 -0
  143. package/dist/application/align/align-service.js +106 -0
  144. package/dist/application/assertion/expectation-evaluator.d.ts +18 -5
  145. package/dist/application/assertion/expectation-evaluator.js +156 -18
  146. package/dist/application/assertion/guarded-expectation.d.ts +45 -0
  147. package/dist/application/assertion/guarded-expectation.js +74 -0
  148. package/dist/application/checkpoint/baseline-capturer.d.ts +26 -0
  149. package/dist/application/checkpoint/baseline-capturer.js +163 -0
  150. package/dist/application/checkpoint/baseline-error.d.ts +5 -0
  151. package/dist/application/checkpoint/baseline-error.js +8 -0
  152. package/dist/application/checkpoint/baseline-service.d.ts +31 -0
  153. package/dist/application/checkpoint/baseline-service.js +147 -0
  154. package/dist/application/checkpoint/checkpoint-evaluator.d.ts +35 -0
  155. package/dist/application/checkpoint/checkpoint-evaluator.js +415 -0
  156. package/dist/application/checkpoint/regression-comparator.d.ts +18 -0
  157. package/dist/application/checkpoint/regression-comparator.js +192 -0
  158. package/dist/application/collector/logcat-collector.d.ts +22 -1
  159. package/dist/application/collector/logcat-collector.js +103 -15
  160. package/dist/application/collector/logcat-event.d.ts +8 -0
  161. package/dist/application/collector/logcat-event.js +79 -0
  162. package/dist/application/collector/logcat-stop.d.ts +2 -0
  163. package/dist/application/collector/logcat-stop.js +11 -0
  164. package/dist/application/context/context-generator.d.ts +45 -0
  165. package/dist/application/context/context-generator.js +228 -0
  166. package/dist/application/context/context-loader.d.ts +40 -0
  167. package/dist/application/context/context-loader.js +223 -0
  168. package/dist/application/context/context-refresher.d.ts +59 -0
  169. package/dist/application/context/context-refresher.js +349 -0
  170. package/dist/application/context/context-rehasher.d.ts +36 -0
  171. package/dist/application/context/context-rehasher.js +110 -0
  172. package/dist/application/context/context-validator.d.ts +23 -1
  173. package/dist/application/context/context-validator.js +116 -9
  174. package/dist/application/context/evidence-hash.d.ts +1 -0
  175. package/dist/application/context/evidence-hash.js +125 -0
  176. package/dist/application/context/evidence-match.d.ts +9 -0
  177. package/dist/application/context/evidence-match.js +8 -0
  178. package/dist/application/context/shard-identity.d.ts +2 -0
  179. package/dist/application/context/shard-identity.js +7 -0
  180. package/dist/application/contract/contract-loader.d.ts +25 -0
  181. package/dist/application/contract/contract-loader.js +68 -0
  182. package/dist/application/contract/contract-review.d.ts +25 -0
  183. package/dist/application/contract/contract-review.js +51 -0
  184. package/dist/application/contract/contract-verifier.d.ts +53 -0
  185. package/dist/application/contract/contract-verifier.js +645 -0
  186. package/dist/application/devices/resolve-device-assignments.d.ts +21 -0
  187. package/dist/application/devices/resolve-device-assignments.js +60 -0
  188. package/dist/application/diagnosis/failure-classifier.d.ts +23 -0
  189. package/dist/application/diagnosis/failure-classifier.js +179 -0
  190. package/dist/application/diagnostics/diagnostics-exporter.d.ts +29 -0
  191. package/dist/application/diagnostics/diagnostics-exporter.js +283 -0
  192. package/dist/application/diagnostics/ui-capture-telemetry.d.ts +16 -0
  193. package/dist/application/diagnostics/ui-capture-telemetry.js +81 -0
  194. package/dist/application/doctor/doctor-service.d.ts +36 -3
  195. package/dist/application/doctor/doctor-service.js +255 -25
  196. package/dist/application/generation/generation-app-preparer.d.ts +20 -0
  197. package/dist/application/generation/generation-app-preparer.js +28 -0
  198. package/dist/application/generation/generation-config-service.d.ts +21 -0
  199. package/dist/application/generation/generation-config-service.js +53 -0
  200. package/dist/application/generation/generation-confirmation-service.d.ts +14 -3
  201. package/dist/application/generation/generation-confirmation-service.js +109 -24
  202. package/dist/application/generation/generation-context-snapshot.d.ts +6 -0
  203. package/dist/application/generation/generation-context-snapshot.js +29 -0
  204. package/dist/application/generation/generation-finalizer.d.ts +15 -9
  205. package/dist/application/generation/generation-finalizer.js +167 -70
  206. package/dist/application/generation/generation-publisher.js +12 -8
  207. package/dist/application/generation/generation-recovery-service.d.ts +35 -0
  208. package/dist/application/generation/generation-recovery-service.js +144 -0
  209. package/dist/application/generation/generation-reopen-service.d.ts +15 -0
  210. package/dist/application/generation/generation-reopen-service.js +37 -0
  211. package/dist/application/generation/generation-replace-service.d.ts +32 -0
  212. package/dist/application/generation/generation-replace-service.js +116 -0
  213. package/dist/application/generation/generation-starter.d.ts +44 -4
  214. package/dist/application/generation/generation-starter.js +175 -8
  215. package/dist/application/generation/generation-step-executor.d.ts +67 -5
  216. package/dist/application/generation/generation-step-executor.js +471 -108
  217. package/dist/application/generation/proposed-step-validator.js +96 -30
  218. package/dist/application/generation/replay-policy-loader.d.ts +16 -0
  219. package/dist/application/generation/replay-policy-loader.js +29 -0
  220. package/dist/application/generation/risk-evaluator.d.ts +4 -1
  221. package/dist/application/generation/risk-evaluator.js +118 -3
  222. package/dist/application/generation/runtime-observer.d.ts +39 -7
  223. package/dist/application/generation/runtime-observer.js +193 -24
  224. package/dist/application/impact/impact-resolver.d.ts +32 -0
  225. package/dist/application/impact/impact-resolver.js +160 -0
  226. package/dist/application/init/init-service.js +26 -13
  227. package/dist/application/interaction/action-executor.d.ts +3 -2
  228. package/dist/application/interaction/action-executor.js +11 -1
  229. package/dist/application/interaction/action-target.d.ts +17 -0
  230. package/dist/application/interaction/action-target.js +40 -0
  231. package/dist/application/interaction/external-step-runner.d.ts +153 -0
  232. package/dist/application/interaction/external-step-runner.js +332 -0
  233. package/dist/application/interaction/fallback-resolver.d.ts +6 -3
  234. package/dist/application/interaction/fallback-resolver.js +7 -5
  235. package/dist/application/interaction/scroll-to-executor.d.ts +17 -3
  236. package/dist/application/interaction/scroll-to-executor.js +118 -36
  237. package/dist/application/journey/external-flow-resolver.d.ts +25 -0
  238. package/dist/application/journey/external-flow-resolver.js +22 -0
  239. package/dist/application/journey/journey-check-service.d.ts +54 -0
  240. package/dist/application/journey/journey-check-service.js +207 -0
  241. package/dist/application/journey/journey-promoter.d.ts +26 -0
  242. package/dist/application/journey/journey-promoter.js +123 -0
  243. package/dist/application/journey/journey-resolver.d.ts +42 -0
  244. package/dist/application/journey/journey-resolver.js +239 -0
  245. package/dist/application/journey/journey-retirer.d.ts +25 -0
  246. package/dist/application/journey/journey-retirer.js +87 -0
  247. package/dist/application/knowledge/anchor-resolver.d.ts +36 -0
  248. package/dist/application/knowledge/anchor-resolver.js +110 -0
  249. package/dist/application/knowledge/knowledge-loader.d.ts +16 -0
  250. package/dist/application/knowledge/knowledge-loader.js +36 -0
  251. package/dist/application/locator/layout-failure-summary.d.ts +2 -0
  252. package/dist/application/locator/layout-failure-summary.js +67 -0
  253. package/dist/application/locator/layout-traversal.d.ts +11 -0
  254. package/dist/application/locator/layout-traversal.js +18 -0
  255. package/dist/application/locator/locator-resolver.d.ts +13 -1
  256. package/dist/application/locator/locator-resolver.js +182 -18
  257. package/dist/application/observe/observe-service.d.ts +20 -0
  258. package/dist/application/observe/observe-service.js +91 -0
  259. package/dist/application/project/project-describer.d.ts +14 -6
  260. package/dist/application/project/project-describer.js +38 -5
  261. package/dist/application/recognition/screen-detector.d.ts +28 -0
  262. package/dist/application/recognition/screen-detector.js +111 -0
  263. package/dist/application/recorder/locator-selector.js +151 -17
  264. package/dist/application/recorder/recorder-service.d.ts +16 -4
  265. package/dist/application/recorder/recorder-service.js +420 -128
  266. package/dist/application/report/report-writer.d.ts +5 -0
  267. package/dist/application/report/report-writer.js +17 -1
  268. package/dist/application/runtime/cold-launch.d.ts +28 -0
  269. package/dist/application/runtime/cold-launch.js +59 -0
  270. package/dist/application/runtime/step-runner.d.ts +49 -4
  271. package/dist/application/runtime/step-runner.js +721 -130
  272. package/dist/application/runtime/verify-runtime.d.ts +57 -7
  273. package/dist/application/runtime/verify-runtime.js +577 -175
  274. package/dist/application/ui/cached-ui-snapshot-provider.d.ts +45 -0
  275. package/dist/application/ui/cached-ui-snapshot-provider.js +111 -0
  276. package/dist/application/ui/observed-ui-snapshot-provider.d.ts +15 -0
  277. package/dist/application/ui/observed-ui-snapshot-provider.js +66 -0
  278. package/dist/application/ui/ui-snapshot-lifecycle.d.ts +2 -0
  279. package/dist/application/ui/ui-snapshot-lifecycle.js +8 -0
  280. package/dist/application/ui/ui-stability-probe.d.ts +9 -0
  281. package/dist/application/ui/ui-stability-probe.js +24 -0
  282. package/dist/application/wait/idle-advice.d.ts +6 -0
  283. package/dist/application/wait/idle-advice.js +27 -0
  284. package/dist/application/wait/idle-profiles.d.ts +15 -0
  285. package/dist/application/wait/idle-profiles.js +75 -0
  286. package/dist/application/wait/idle-waiter.d.ts +28 -4
  287. package/dist/application/wait/idle-waiter.js +201 -15
  288. package/dist/cli/commands/align.d.ts +3 -0
  289. package/dist/cli/commands/align.js +124 -0
  290. package/dist/cli/commands/baseline.d.ts +3 -0
  291. package/dist/cli/commands/baseline.js +130 -0
  292. package/dist/cli/commands/context.js +300 -27
  293. package/dist/cli/commands/contract.d.ts +3 -0
  294. package/dist/cli/commands/contract.js +120 -0
  295. package/dist/cli/commands/diagnose.d.ts +3 -0
  296. package/dist/cli/commands/diagnose.js +84 -0
  297. package/dist/cli/commands/doctor.js +16 -9
  298. package/dist/cli/commands/failure.d.ts +3 -0
  299. package/dist/cli/commands/failure.js +63 -0
  300. package/dist/cli/commands/generation/lifecycle-commands.d.ts +5 -0
  301. package/dist/cli/commands/generation/lifecycle-commands.js +211 -0
  302. package/dist/cli/commands/generation/session-commands.d.ts +11 -0
  303. package/dist/cli/commands/generation/session-commands.js +472 -0
  304. package/dist/cli/commands/generation/shared.d.ts +1414 -0
  305. package/dist/cli/commands/generation/shared.js +291 -0
  306. package/dist/cli/commands/generation/step-commands.d.ts +8 -0
  307. package/dist/cli/commands/generation/step-commands.js +315 -0
  308. package/dist/cli/commands/generation.js +10 -507
  309. package/dist/cli/commands/impact.d.ts +3 -0
  310. package/dist/cli/commands/impact.js +87 -0
  311. package/dist/cli/commands/init.js +13 -6
  312. package/dist/cli/commands/journey.d.ts +3 -0
  313. package/dist/cli/commands/journey.js +382 -0
  314. package/dist/cli/commands/knowledge.d.ts +3 -0
  315. package/dist/cli/commands/knowledge.js +93 -0
  316. package/dist/cli/commands/observe.d.ts +3 -0
  317. package/dist/cli/commands/observe.js +127 -0
  318. package/dist/cli/commands/project.js +2 -1
  319. package/dist/cli/commands/record.js +18 -5
  320. package/dist/cli/commands/verify.js +326 -64
  321. package/dist/cli/dependencies.d.ts +136 -1
  322. package/dist/cli/dependencies.js +504 -52
  323. package/dist/cli/diagnostics-recorder.d.ts +31 -0
  324. package/dist/cli/diagnostics-recorder.js +82 -0
  325. package/dist/cli/diff-verification.d.ts +41 -0
  326. package/dist/cli/diff-verification.js +192 -0
  327. package/dist/cli/main.d.ts +1 -1
  328. package/dist/cli/main.js +107 -2
  329. package/dist/cli/output.d.ts +5 -3
  330. package/dist/cli/output.js +12 -0
  331. package/dist/cli/program.js +21 -1
  332. package/dist/cli/project-root.d.ts +1 -0
  333. package/dist/cli/project-root.js +6 -0
  334. package/dist/cli/runtime-selection.d.ts +22 -0
  335. package/dist/cli/runtime-selection.js +92 -0
  336. package/dist/cli/version.d.ts +1 -0
  337. package/dist/cli/version.js +14 -0
  338. package/dist/cli/workspace-guard.d.ts +2 -0
  339. package/dist/cli/workspace-guard.js +3 -0
  340. package/dist/domain/binding-reference.d.ts +4 -0
  341. package/dist/domain/binding-reference.js +23 -0
  342. package/dist/domain/checkpoint.d.ts +404 -0
  343. package/dist/domain/checkpoint.js +297 -0
  344. package/dist/domain/config.d.ts +107 -1
  345. package/dist/domain/config.js +52 -6
  346. package/dist/domain/contract.d.ts +413 -0
  347. package/dist/domain/contract.js +196 -0
  348. package/dist/domain/diagnostics.d.ts +1396 -0
  349. package/dist/domain/diagnostics.js +193 -0
  350. package/dist/domain/external-flow.d.ts +493 -0
  351. package/dist/domain/external-flow.js +15 -0
  352. package/dist/domain/failure-classification.d.ts +176 -0
  353. package/dist/domain/failure-classification.js +169 -0
  354. package/dist/domain/failure.d.ts +2 -1
  355. package/dist/domain/failure.js +123 -0
  356. package/dist/domain/generation.d.ts +1671 -132
  357. package/dist/domain/generation.js +202 -13
  358. package/dist/domain/geometry.d.ts +13 -0
  359. package/dist/domain/geometry.js +16 -0
  360. package/dist/domain/impact.d.ts +71 -0
  361. package/dist/domain/impact.js +76 -0
  362. package/dist/domain/init.d.ts +12 -4
  363. package/dist/domain/init.js +24 -18
  364. package/dist/domain/journey-composition.d.ts +2285 -0
  365. package/dist/domain/journey-composition.js +85 -0
  366. package/dist/domain/journey-lifecycle.d.ts +10 -0
  367. package/dist/domain/journey-lifecycle.js +9 -0
  368. package/dist/domain/journey.d.ts +2419 -212
  369. package/dist/domain/journey.js +384 -14
  370. package/dist/domain/knowledge.d.ts +165 -0
  371. package/dist/domain/knowledge.js +188 -0
  372. package/dist/domain/layout.d.ts +34 -5
  373. package/dist/domain/layout.js +64 -6
  374. package/dist/domain/locator-evidence.d.ts +3 -0
  375. package/dist/domain/locator-evidence.js +36 -0
  376. package/dist/domain/logcat-event.d.ts +54 -0
  377. package/dist/domain/logcat-event.js +40 -0
  378. package/dist/domain/observation.d.ts +33 -0
  379. package/dist/domain/observation.js +18 -0
  380. package/dist/domain/project-context.d.ts +219 -1
  381. package/dist/domain/project-context.js +209 -6
  382. package/dist/domain/proposed-step.d.ts +340 -60
  383. package/dist/domain/proposed-step.js +23 -3
  384. package/dist/domain/report.d.ts +1455 -28
  385. package/dist/domain/report.js +211 -14
  386. package/dist/domain/runtime-snapshot.d.ts +58 -1
  387. package/dist/domain/runtime-snapshot.js +14 -3
  388. package/dist/domain/runtime.d.ts +50 -0
  389. package/dist/domain/runtime.js +36 -0
  390. package/dist/domain/system-app-profiles.d.ts +6 -0
  391. package/dist/domain/system-app-profiles.js +43 -0
  392. package/dist/domain/ui-backend.d.ts +28 -0
  393. package/dist/domain/ui-backend.js +33 -0
  394. package/dist/domain/ui-cache.d.ts +11 -0
  395. package/dist/domain/ui-cache.js +10 -0
  396. package/dist/domain/verify-receipt.d.ts +17 -0
  397. package/dist/domain/verify-receipt.js +17 -0
  398. package/dist/domain/window-hierarchy.d.ts +84 -0
  399. package/dist/domain/window-hierarchy.js +172 -0
  400. package/dist/domain/workflow-manifest.d.ts +77 -0
  401. package/dist/domain/workflow-manifest.js +136 -0
  402. package/dist/domain/workspace.d.ts +30 -0
  403. package/dist/domain/workspace.js +74 -0
  404. package/dist/ports/adb.d.ts +34 -1
  405. package/dist/ports/align-prompt.d.ts +11 -0
  406. package/dist/ports/align-prompt.js +6 -0
  407. package/dist/ports/anchor-resolver.d.ts +30 -0
  408. package/dist/ports/anchor-resolver.js +1 -0
  409. package/dist/ports/annotated-screen-resolver.d.ts +4 -0
  410. package/dist/ports/annotated-screen-resolver.js +1 -0
  411. package/dist/ports/camera-probe.d.ts +23 -0
  412. package/dist/ports/camera-probe.js +8 -0
  413. package/dist/ports/context-document-writer.d.ts +24 -0
  414. package/dist/ports/context-document-writer.js +1 -0
  415. package/dist/ports/detached-process-launcher.d.ts +12 -0
  416. package/dist/ports/detached-process-launcher.js +1 -0
  417. package/dist/ports/diagnostics.d.ts +15 -0
  418. package/dist/ports/diagnostics.js +1 -0
  419. package/dist/ports/external-flow-registry.d.ts +37 -0
  420. package/dist/ports/external-flow-registry.js +1 -0
  421. package/dist/ports/generation-prompt.d.ts +2 -1
  422. package/dist/ports/generation-session-store.d.ts +12 -2
  423. package/dist/ports/git-diff.d.ts +9 -0
  424. package/dist/ports/git-diff.js +1 -0
  425. package/dist/ports/journey-composition-store.d.ts +17 -0
  426. package/dist/ports/journey-composition-store.js +1 -0
  427. package/dist/ports/knowledge-registry.d.ts +20 -0
  428. package/dist/ports/knowledge-registry.js +1 -0
  429. package/dist/ports/process-runner.d.ts +7 -0
  430. package/dist/ports/project-file-inspector.d.ts +1 -0
  431. package/dist/ports/project-identity-inspector.d.ts +24 -0
  432. package/dist/ports/project-identity-inspector.js +1 -0
  433. package/dist/ports/project-inventory-inspector.d.ts +21 -0
  434. package/dist/ports/project-inventory-inspector.js +1 -0
  435. package/dist/ports/project-module-discoverer.d.ts +26 -0
  436. package/dist/ports/project-module-discoverer.js +1 -0
  437. package/dist/ports/recorder-prompt.d.ts +10 -1
  438. package/dist/ports/runtime-backend.d.ts +89 -0
  439. package/dist/ports/runtime-backend.js +13 -0
  440. package/dist/ports/runtime-capability.d.ts +12 -0
  441. package/dist/ports/runtime-capability.js +20 -0
  442. package/dist/ports/runtime-session-ports.d.ts +25 -0
  443. package/dist/ports/runtime-session-ports.js +1 -0
  444. package/dist/ports/screenshot.d.ts +11 -0
  445. package/dist/ports/screenshot.js +1 -0
  446. package/dist/ports/skill-installer.d.ts +2 -2
  447. package/dist/ports/ui-snapshot.d.ts +35 -0
  448. package/dist/ports/ui-snapshot.js +1 -0
  449. package/dist/ports/ui-stability.d.ts +19 -0
  450. package/dist/ports/ui-stability.js +1 -0
  451. package/dist/ports/workspace-layout.d.ts +4 -0
  452. package/dist/ports/workspace-layout.js +1 -0
  453. package/dist/shared/errors.d.ts +2 -0
  454. package/dist/shared/errors.js +22 -0
  455. package/dist/shared/paths.d.ts +2 -0
  456. package/dist/shared/paths.js +24 -0
  457. package/dist/shared/strings.d.ts +2 -0
  458. package/dist/shared/strings.js +16 -0
  459. package/package.json +7 -2
  460. package/assets/skills/taphound-ai-journey/GUIDE.md +0 -862
  461. package/assets/skills/taphound-ai-journey/SKILL.md +0 -377
  462. package/assets/skills/taphound-ai-journey/prompts/analyze-project.md +0 -526
  463. package/assets/skills/taphound-ai-journey/prompts/generate-step.md +0 -109
  464. package/assets/skills/taphound-ai-journey/schemas/project-context.json +0 -81
  465. package/assets/skills/taphound-ai-journey/templates/project-context.example.json +0 -49
  466. package/dist/ports/android-cli.d.ts +0 -21
  467. /package/dist/{ports/android-cli.js → adapters/runtime/mobile-mcp/mobile-mcp-tools.js} +0 -0
@@ -0,0 +1,45 @@
1
+ import type { CaptureUiSnapshotOptions, UiSnapshot, UiSnapshotProvider, UiSnapshotProviderFactory, OpenUiSnapshotProviderOptions } from "../../ports/ui-snapshot.js";
2
+ import type { UiStabilityProbe, UiStabilitySampleOptions, UiStabilitySampleResult } from "../../ports/ui-stability.js";
3
+ type InvalidationReason = Parameters<NonNullable<UiSnapshotProvider["invalidate"]>>[0];
4
+ export declare class CachedUiSnapshotProviderFactory implements UiSnapshotProviderFactory {
5
+ private readonly source;
6
+ private readonly now;
7
+ private readonly ttlMs;
8
+ constructor(source: UiSnapshotProviderFactory, now?: () => number, ttlMs?: number);
9
+ open(options: OpenUiSnapshotProviderOptions): Promise<UiSnapshotProvider>;
10
+ }
11
+ export declare class CachedUiSnapshotProvider implements UiSnapshotProvider, Partial<UiStabilityProbe> {
12
+ private readonly source;
13
+ private readonly now;
14
+ private readonly ttlMs;
15
+ readonly descriptor: {
16
+ id: "system-uiautomator" | "android-cli" | "appium-uiautomator2" | "mobile-mcp";
17
+ adapterVersion: string;
18
+ configSha256: string;
19
+ engineVersion?: string | undefined;
20
+ };
21
+ readonly supportsStability: boolean;
22
+ private mutationEpoch;
23
+ private cached;
24
+ private inFlight;
25
+ private closed;
26
+ private closePromise;
27
+ private hits;
28
+ private misses;
29
+ private capturesSaved;
30
+ constructor(source: UiSnapshotProvider, now?: () => number, ttlMs?: number);
31
+ reset(): void;
32
+ sample(options: UiStabilitySampleOptions): Promise<UiStabilitySampleResult>;
33
+ capture(options: CaptureUiSnapshotOptions): Promise<UiSnapshot>;
34
+ invalidate(reason: InvalidationReason): void;
35
+ close(): Promise<void>;
36
+ cacheTelemetry(): {
37
+ hits: number;
38
+ misses: number;
39
+ stale: number;
40
+ relearns: number;
41
+ capturesSaved: number;
42
+ validationDurationMs: number;
43
+ };
44
+ }
45
+ export {};
@@ -0,0 +1,111 @@
1
+ export class CachedUiSnapshotProviderFactory {
2
+ source;
3
+ now;
4
+ ttlMs;
5
+ constructor(source, now = () => Date.now(), ttlMs = 300) {
6
+ this.source = source;
7
+ this.now = now;
8
+ this.ttlMs = ttlMs;
9
+ }
10
+ async open(options) {
11
+ const provider = await this.source.open(options);
12
+ return options.cacheEnabled === false
13
+ ? provider
14
+ : new CachedUiSnapshotProvider(provider, this.now, this.ttlMs);
15
+ }
16
+ }
17
+ export class CachedUiSnapshotProvider {
18
+ source;
19
+ now;
20
+ ttlMs;
21
+ descriptor;
22
+ supportsStability;
23
+ mutationEpoch = 0;
24
+ cached;
25
+ inFlight;
26
+ closed = false;
27
+ closePromise;
28
+ hits = 0;
29
+ misses = 0;
30
+ capturesSaved = 0;
31
+ constructor(source, now = () => Date.now(), ttlMs = 300) {
32
+ this.source = source;
33
+ this.now = now;
34
+ this.ttlMs = ttlMs;
35
+ this.descriptor = source.descriptor;
36
+ const sourceProbe = source;
37
+ this.supportsStability = typeof sourceProbe.sample === "function"
38
+ && typeof sourceProbe.reset === "function";
39
+ }
40
+ reset() {
41
+ const sourceProbe = this.source;
42
+ sourceProbe.reset?.();
43
+ }
44
+ sample(options) {
45
+ const sourceProbe = this.source;
46
+ const sample = sourceProbe.sample;
47
+ if (sample === undefined) {
48
+ return Promise.reject(new Error("Underlying UI snapshot provider does not support stability sampling"));
49
+ }
50
+ return sample.call(sourceProbe, options);
51
+ }
52
+ capture(options) {
53
+ if (this.closed) {
54
+ return Promise.reject(new Error("UI snapshot provider is closed"));
55
+ }
56
+ const freshness = options.freshness ?? "forceFresh";
57
+ const epoch = this.mutationEpoch;
58
+ if (freshness === "sameMutationEpoch") {
59
+ if (this.cached?.epoch === epoch
60
+ && this.now() - this.cached.storedAtMs <= this.ttlMs) {
61
+ this.hits += 1;
62
+ this.capturesSaved += 1;
63
+ return Promise.resolve(this.cached.snapshot);
64
+ }
65
+ if (this.inFlight?.epoch === epoch) {
66
+ this.hits += 1;
67
+ this.capturesSaved += 1;
68
+ return this.inFlight.promise;
69
+ }
70
+ }
71
+ this.misses += 1;
72
+ const promise = this.source.capture(options).then((snapshot) => {
73
+ if (!this.closed && this.mutationEpoch === epoch) {
74
+ this.cached = { epoch, storedAtMs: this.now(), snapshot };
75
+ }
76
+ return snapshot;
77
+ }).finally(() => {
78
+ if (this.inFlight?.promise === promise) {
79
+ this.inFlight = undefined;
80
+ }
81
+ });
82
+ if (freshness === "sameMutationEpoch") {
83
+ this.inFlight = { epoch, promise };
84
+ }
85
+ return promise;
86
+ }
87
+ invalidate(reason) {
88
+ void reason;
89
+ this.mutationEpoch += 1;
90
+ this.cached = undefined;
91
+ this.inFlight = undefined;
92
+ }
93
+ close() {
94
+ if (this.closePromise !== undefined)
95
+ return this.closePromise;
96
+ this.closed = true;
97
+ this.invalidate("providerClosed");
98
+ this.closePromise = this.source.close();
99
+ return this.closePromise;
100
+ }
101
+ cacheTelemetry() {
102
+ return {
103
+ hits: this.hits,
104
+ misses: this.misses,
105
+ stale: 0,
106
+ relearns: 0,
107
+ capturesSaved: this.capturesSaved,
108
+ validationDurationMs: 0
109
+ };
110
+ }
111
+ }
@@ -0,0 +1,15 @@
1
+ import type { UiCaptureObserver } from "../../ports/diagnostics.js";
2
+ import type { OpenUiSnapshotProviderOptions, UiSnapshotProvider, UiSnapshotProviderFactory } from "../../ports/ui-snapshot.js";
3
+ /**
4
+ * Reports the duration and outcome of every UI backend read (captures and
5
+ * stability samples) to an observer. It sits under the snapshot cache, so a
6
+ * cache hit is not counted as a device read.
7
+ */
8
+ export declare class ObservedUiSnapshotProviderFactory implements UiSnapshotProviderFactory {
9
+ private readonly source;
10
+ private readonly observer;
11
+ private readonly now;
12
+ constructor(source: UiSnapshotProviderFactory, observer: UiCaptureObserver, now: () => number);
13
+ open(options: OpenUiSnapshotProviderOptions): Promise<UiSnapshotProvider>;
14
+ }
15
+ export declare function observeProvider(provider: UiSnapshotProvider, observer: UiCaptureObserver, now: () => number): UiSnapshotProvider;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Reports the duration and outcome of every UI backend read (captures and
3
+ * stability samples) to an observer. It sits under the snapshot cache, so a
4
+ * cache hit is not counted as a device read.
5
+ */
6
+ export class ObservedUiSnapshotProviderFactory {
7
+ source;
8
+ observer;
9
+ now;
10
+ constructor(source, observer, now) {
11
+ this.source = source;
12
+ this.observer = observer;
13
+ this.now = now;
14
+ }
15
+ async open(options) {
16
+ return observeProvider(await this.source.open(options), this.observer, this.now);
17
+ }
18
+ }
19
+ export function observeProvider(provider, observer, now) {
20
+ const source = provider;
21
+ const timed = async (read) => {
22
+ const startedAt = now();
23
+ try {
24
+ const value = await read();
25
+ observer.captured(source.descriptor.id, now() - startedAt);
26
+ return value;
27
+ }
28
+ catch (error) {
29
+ observer.captured(source.descriptor.id, now() - startedAt, error);
30
+ throw error;
31
+ }
32
+ };
33
+ const cacheTelemetry = source.cacheTelemetry;
34
+ const invalidate = source.invalidate;
35
+ const observed = {
36
+ descriptor: source.descriptor,
37
+ capture: (options) => timed(() => source.capture(options)),
38
+ close: () => source.close(),
39
+ ...(cacheTelemetry === undefined
40
+ ? {}
41
+ : { cacheTelemetry: () => cacheTelemetry.call(source) }),
42
+ ...(invalidate === undefined
43
+ ? {}
44
+ : {
45
+ invalidate: (reason) => {
46
+ invalidate.call(source, reason);
47
+ }
48
+ })
49
+ };
50
+ const sample = source.sample;
51
+ const reset = source.reset;
52
+ if (typeof sample === "function" && typeof reset === "function") {
53
+ observed.sample = (options) => timed(() => sample.call(source, options));
54
+ observed.reset = () => {
55
+ reset.call(source);
56
+ };
57
+ }
58
+ const withSupport = source;
59
+ if (withSupport.supportsStability !== undefined) {
60
+ Object.defineProperty(observed, "supportsStability", {
61
+ value: withSupport.supportsStability,
62
+ enumerable: true
63
+ });
64
+ }
65
+ return observed;
66
+ }
@@ -0,0 +1,2 @@
1
+ import type { UiSnapshotProvider } from "../../ports/ui-snapshot.js";
2
+ export declare function closeUiSnapshotProvider(provider: UiSnapshotProvider, onFailure?: (error: unknown) => void): Promise<void>;
@@ -0,0 +1,8 @@
1
+ export async function closeUiSnapshotProvider(provider, onFailure) {
2
+ try {
3
+ await provider.close();
4
+ }
5
+ catch (error) {
6
+ onFailure?.(error);
7
+ }
8
+ }
@@ -0,0 +1,9 @@
1
+ import type { UiSnapshotProvider } from "../../ports/ui-snapshot.js";
2
+ import type { UiStabilityProbe } from "../../ports/ui-stability.js";
3
+ /**
4
+ * A snapshot provider that samples stability itself (Appium) answers every
5
+ * structural sample, but frame-stat samples still go to the runtime probe:
6
+ * the provider only knows page sources, so it would answer a cheap
7
+ * `dumpsys gfxinfo` request with a full hierarchy capture.
8
+ */
9
+ export declare function uiStabilityProbe(provider: UiSnapshotProvider, fallback: UiStabilityProbe): UiStabilityProbe;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * A snapshot provider that samples stability itself (Appium) answers every
3
+ * structural sample, but frame-stat samples still go to the runtime probe:
4
+ * the provider only knows page sources, so it would answer a cheap
5
+ * `dumpsys gfxinfo` request with a full hierarchy capture.
6
+ */
7
+ export function uiStabilityProbe(provider, fallback) {
8
+ const withCapability = provider;
9
+ if (withCapability.supportsStability === false
10
+ || typeof withCapability.sample !== "function"
11
+ || typeof withCapability.reset !== "function") {
12
+ return fallback;
13
+ }
14
+ const structural = withCapability;
15
+ return {
16
+ reset: () => {
17
+ structural.reset();
18
+ fallback.reset();
19
+ },
20
+ sample: (options) => (options.stabilityBackend === "frameStats"
21
+ ? fallback.sample(options)
22
+ : structural.sample(options))
23
+ };
24
+ }
@@ -0,0 +1,6 @@
1
+ import type { IdleResult } from "./idle-waiter.js";
2
+ export type IdleTimeoutResult = Extract<IdleResult, {
3
+ status: "timeout";
4
+ }>;
5
+ export declare function idleTimeoutAdvice(idle: IdleTimeoutResult): string;
6
+ export declare function withIdleAdvice(message: string, idle: IdleTimeoutResult): string;
@@ -0,0 +1,27 @@
1
+ const SLOW_CAPTURE_BUDGET_RATIO = 0.8;
2
+ export function idleTimeoutAdvice(idle) {
3
+ if (idle.frameActivityDetected) {
4
+ return `frame activity never settled under idle.strategy "${idle.strategy}"; `
5
+ + "if the screen animates continuously, set idle.strategy to "
6
+ + "\"layoutDiff\" in .taphound/config.json";
7
+ }
8
+ if (idle.lastDiff.length > 0) {
9
+ return "layout differences kept appearing (see lastDiff in the step "
10
+ + "report); raise idle.timeoutMs in .taphound/config.json if the "
11
+ + "change is expected to settle, or set idle.strategy to "
12
+ + "\"layoutDiff\" if the screen animates continuously";
13
+ }
14
+ if (idle.durationMs > 0
15
+ && idle.samplingDurationMs >= idle.durationMs * SLOW_CAPTURE_BUDGET_RATIO) {
16
+ return "UI snapshot captures consumed most of the idle budget; raise "
17
+ + "idle.timeoutMs in .taphound/config.json so idle.stablePolls "
18
+ + "consecutive polls fit, and raise ui.snapshotTimeoutMs if "
19
+ + "individual dumps are slow";
20
+ }
21
+ return "no layout change was detected but the idle budget ended before "
22
+ + "idle.stablePolls consecutive stable polls; raise idle.timeoutMs or "
23
+ + "lower idle.stablePolls/pollIntervalMs in .taphound/config.json";
24
+ }
25
+ export function withIdleAdvice(message, idle) {
26
+ return `${message} (${idleTimeoutAdvice(idle)})`;
27
+ }
@@ -0,0 +1,15 @@
1
+ import type { DeviceIdleProfile } from "../../domain/config.js";
2
+ import type { AdbPort, AppIdentity, DeviceIdentity } from "../../ports/adb.js";
3
+ export type IdleStrategyName = "hybrid" | "layoutDiff" | "frameStats" | "structural";
4
+ export interface IdleSettings {
5
+ strategy?: IdleStrategyName | undefined;
6
+ pollIntervalMs: number;
7
+ stablePolls: number;
8
+ timeoutMs: number;
9
+ ignoreCursorBlink?: boolean | undefined;
10
+ ignoreLayoutDrift?: boolean | undefined;
11
+ }
12
+ export declare function resolveIdlePolicy(idle: IdleSettings & {
13
+ deviceProfiles?: readonly DeviceIdleProfile[] | undefined;
14
+ }, identity: DeviceIdentity | undefined): IdleSettings;
15
+ export declare function deviceIdentityResolver(adb: Pick<AdbPort, "deviceIdentity">, identity: Omit<AppIdentity, "signal">): () => Promise<DeviceIdentity | undefined>;
@@ -0,0 +1,75 @@
1
+ function matchesDevice(profile, identity) {
2
+ const match = profile.match;
3
+ if (match.manufacturer !== undefined
4
+ && match.manufacturer.toLowerCase() !== identity.manufacturer.toLowerCase()) {
5
+ return false;
6
+ }
7
+ if (match.model !== undefined
8
+ && match.model.toLowerCase() !== identity.model.toLowerCase()) {
9
+ return false;
10
+ }
11
+ if (match.sdkLevel !== undefined && match.sdkLevel !== identity.sdkLevel) {
12
+ return false;
13
+ }
14
+ return true;
15
+ }
16
+ export function resolveIdlePolicy(idle, identity) {
17
+ if (identity === undefined || idle.deviceProfiles === undefined) {
18
+ return idle;
19
+ }
20
+ const matches = idle.deviceProfiles.filter((profile) => matchesDevice(profile, identity));
21
+ if (matches.length === 0) {
22
+ return idle;
23
+ }
24
+ const merged = {
25
+ strategy: idle.strategy,
26
+ pollIntervalMs: idle.pollIntervalMs,
27
+ stablePolls: idle.stablePolls,
28
+ timeoutMs: idle.timeoutMs,
29
+ ...(idle.ignoreCursorBlink === undefined
30
+ ? {}
31
+ : { ignoreCursorBlink: idle.ignoreCursorBlink }),
32
+ ...(idle.ignoreLayoutDrift === undefined
33
+ ? {}
34
+ : { ignoreLayoutDrift: idle.ignoreLayoutDrift })
35
+ };
36
+ for (const profile of matches) {
37
+ if (profile.ignoreCursorBlink !== undefined) {
38
+ merged.ignoreCursorBlink = profile.ignoreCursorBlink;
39
+ }
40
+ if (profile.ignoreLayoutDrift !== undefined) {
41
+ merged.ignoreLayoutDrift = profile.ignoreLayoutDrift;
42
+ }
43
+ if (profile.strategy !== undefined) {
44
+ merged.strategy = profile.strategy;
45
+ }
46
+ if (profile.pollIntervalMs !== undefined) {
47
+ merged.pollIntervalMs = profile.pollIntervalMs;
48
+ }
49
+ if (profile.stablePolls !== undefined) {
50
+ merged.stablePolls = profile.stablePolls;
51
+ }
52
+ if (profile.timeoutMs !== undefined) {
53
+ merged.timeoutMs = profile.timeoutMs;
54
+ }
55
+ }
56
+ return merged;
57
+ }
58
+ export function deviceIdentityResolver(adb, identity) {
59
+ // Device identity is immutable for a run; only a successful lookup is
60
+ // memoized so a transient getprop failure is retried on the next wait.
61
+ let resolved;
62
+ return async () => {
63
+ if (resolved !== undefined) {
64
+ return resolved;
65
+ }
66
+ const current = adb.deviceIdentity;
67
+ if (current === undefined) {
68
+ return undefined;
69
+ }
70
+ const requested = { ...identity };
71
+ resolved = await current.call(adb, requested)
72
+ .catch(() => undefined);
73
+ return resolved;
74
+ };
75
+ }
@@ -1,30 +1,54 @@
1
1
  import type { FailureCode } from "../../domain/failure.js";
2
- import type { AndroidCliPort } from "../../ports/android-cli.js";
2
+ import type { LayoutElement } from "../../domain/layout.js";
3
+ import type { DeviceIdleProfile } from "../../domain/config.js";
4
+ import type { DeviceIdentity } from "../../ports/adb.js";
5
+ import type { UiStabilityProbe } from "../../ports/ui-stability.js";
3
6
  import type { Clock } from "../../ports/clock.js";
7
+ export type IdleStrategy = "hybrid" | "layoutDiff" | "frameStats" | "structural";
8
+ export type IdleBackend = "uiautomator" | "androidCli" | "gfxFrameStats" | "mobileMcp";
4
9
  export interface IdleConfig {
10
+ strategy?: IdleStrategy | undefined;
5
11
  pollIntervalMs: number;
6
12
  stablePolls: number;
7
13
  timeoutMs: number;
14
+ ignoreCursorBlink?: boolean | undefined;
15
+ ignoreLayoutDrift?: boolean | undefined;
16
+ deviceProfiles?: readonly DeviceIdleProfile[] | undefined;
8
17
  }
9
18
  export type IdleResult = {
10
19
  status: "stable";
11
20
  polls: number;
12
21
  durationMs: number;
22
+ layout?: readonly LayoutElement[] | undefined;
23
+ backend?: IdleBackend | undefined;
24
+ strategy: IdleStrategy;
25
+ fallbackUsed: boolean;
26
+ frameActivityDetected: boolean;
27
+ samplingDurationMs: number;
13
28
  } | {
14
29
  status: "timeout";
15
30
  code: Extract<FailureCode, "IDLE_TIMEOUT">;
16
31
  polls: number;
17
32
  durationMs: number;
18
33
  lastDiff: readonly unknown[];
34
+ backend?: IdleBackend | undefined;
35
+ strategy: IdleStrategy;
36
+ fallbackUsed: boolean;
37
+ frameActivityDetected: boolean;
38
+ samplingDurationMs: number;
19
39
  } | {
20
40
  status: "cancelled";
21
41
  polls: number;
22
42
  durationMs: number;
23
43
  };
24
44
  export declare class IdleWaiter {
25
- private readonly androidCli;
45
+ private readonly stability;
26
46
  private readonly clock;
27
47
  private readonly deviceSerial;
28
- constructor(androidCli: AndroidCliPort, clock: Clock, deviceSerial: string);
29
- waitUntilIdle(config: IdleConfig, signal?: AbortSignal): Promise<IdleResult>;
48
+ private readonly packageName?;
49
+ private readonly resolveDeviceIdentity?;
50
+ private transientKeys;
51
+ constructor(stability: UiStabilityProbe, clock: Clock, deviceSerial: string, packageName?: string | undefined, resolveDeviceIdentity?: (() => Promise<DeviceIdentity | undefined>) | undefined);
52
+ waitUntilIdle(input: IdleConfig, signal?: AbortSignal): Promise<IdleResult>;
53
+ private effectiveConfig;
30
54
  }