taphound 0.2.0-dev.1 → 0.2.0-dev.11

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 (447) 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 +500 -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 +561 -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 +349 -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 +34 -0
  66. package/dist/adapters/appium/appium-ui-snapshot-provider.js +240 -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/external-flow-registry.d.ts +17 -0
  73. package/dist/adapters/filesystem/external-flow-registry.js +325 -0
  74. package/dist/adapters/filesystem/generation-session-store.d.ts +17 -11
  75. package/dist/adapters/filesystem/generation-session-store.js +281 -855
  76. package/dist/adapters/filesystem/generation-store/session-lock.d.ts +29 -0
  77. package/dist/adapters/filesystem/generation-store/session-lock.js +202 -0
  78. package/dist/adapters/filesystem/generation-store/session-transitions.d.ts +24 -0
  79. package/dist/adapters/filesystem/generation-store/session-transitions.js +340 -0
  80. package/dist/adapters/filesystem/generation-store/store-files.d.ts +50 -0
  81. package/dist/adapters/filesystem/generation-store/store-files.js +363 -0
  82. package/dist/adapters/filesystem/journey-composition-store.d.ts +23 -0
  83. package/dist/adapters/filesystem/journey-composition-store.js +151 -0
  84. package/dist/adapters/filesystem/knowledge-registry.d.ts +12 -0
  85. package/dist/adapters/filesystem/knowledge-registry.js +223 -0
  86. package/dist/adapters/filesystem/project-bound-file.js +3 -5
  87. package/dist/adapters/filesystem/project-file-inspector.d.ts +2 -0
  88. package/dist/adapters/filesystem/project-file-inspector.js +57 -28
  89. package/dist/adapters/filesystem/project-identity-inspector.d.ts +7 -0
  90. package/dist/adapters/filesystem/project-identity-inspector.js +215 -0
  91. package/dist/adapters/filesystem/project-inventory-inspector.d.ts +8 -0
  92. package/dist/adapters/filesystem/project-inventory-inspector.js +93 -0
  93. package/dist/adapters/filesystem/project-module-discoverer.d.ts +6 -0
  94. package/dist/adapters/filesystem/project-module-discoverer.js +158 -0
  95. package/dist/adapters/filesystem/skill-installer.d.ts +7 -2
  96. package/dist/adapters/filesystem/skill-installer.js +40 -11
  97. package/dist/adapters/filesystem/workspace-layout.d.ts +7 -0
  98. package/dist/adapters/filesystem/workspace-layout.js +57 -0
  99. package/dist/adapters/git/node-git-diff.d.ts +17 -0
  100. package/dist/adapters/git/node-git-diff.js +114 -0
  101. package/dist/adapters/process/node-detached-process-launcher.d.ts +6 -0
  102. package/dist/adapters/process/node-detached-process-launcher.js +96 -0
  103. package/dist/adapters/process/node-process-runner.js +11 -2
  104. package/dist/adapters/prompt/inquirer-align-prompt.d.ts +27 -0
  105. package/dist/adapters/prompt/inquirer-align-prompt.js +65 -0
  106. package/dist/adapters/prompt/inquirer-generation-prompt.js +3 -0
  107. package/dist/adapters/prompt/inquirer-recorder-prompt.d.ts +9 -1
  108. package/dist/adapters/prompt/inquirer-recorder-prompt.js +63 -0
  109. package/dist/adapters/runtime/adb-runtime-backend.d.ts +67 -0
  110. package/dist/adapters/runtime/adb-runtime-backend.js +206 -0
  111. package/dist/adapters/runtime/fake-runtime-backend.d.ts +87 -0
  112. package/dist/adapters/runtime/fake-runtime-backend.js +240 -0
  113. package/dist/adapters/runtime/mobile-mcp/mcp-tool-client.d.ts +45 -0
  114. package/dist/adapters/runtime/mobile-mcp/mcp-tool-client.js +153 -0
  115. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-errors.d.ts +23 -0
  116. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-errors.js +39 -0
  117. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-responses.d.ts +20 -0
  118. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-responses.js +180 -0
  119. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-runtime-backend.d.ts +78 -0
  120. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-runtime-backend.js +379 -0
  121. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-tools.d.ts +46 -0
  122. package/dist/adapters/runtime/session-adb-view.d.ts +53 -0
  123. package/dist/adapters/runtime/session-adb-view.js +193 -0
  124. package/dist/adapters/runtime/session-backed-ports.d.ts +21 -0
  125. package/dist/adapters/runtime/session-backed-ports.js +43 -0
  126. package/dist/adapters/runtime/shared-session-runtime-backend.d.ts +12 -0
  127. package/dist/adapters/runtime/shared-session-runtime-backend.js +64 -0
  128. package/dist/adapters/ui/auto-ui-snapshot-provider.d.ts +8 -0
  129. package/dist/adapters/ui/auto-ui-snapshot-provider.js +48 -0
  130. package/dist/adapters/ui/device-layout-temp.d.ts +6 -0
  131. package/dist/adapters/ui/device-layout-temp.js +18 -0
  132. package/dist/adapters/ui/device-ui-environment.d.ts +13 -0
  133. package/dist/adapters/ui/device-ui-environment.js +81 -0
  134. package/dist/adapters/ui/layout-normalization.d.ts +9 -0
  135. package/dist/adapters/ui/layout-normalization.js +44 -0
  136. package/dist/adapters/ui/ui-snapshot-error.d.ts +11 -0
  137. package/dist/adapters/ui/ui-snapshot-error.js +12 -0
  138. package/dist/adapters/ui/ui-snapshot-support.d.ts +15 -0
  139. package/dist/adapters/ui/ui-snapshot-support.js +12 -0
  140. package/dist/application/align/align-service.d.ts +42 -0
  141. package/dist/application/align/align-service.js +106 -0
  142. package/dist/application/assertion/expectation-evaluator.d.ts +18 -5
  143. package/dist/application/assertion/expectation-evaluator.js +156 -18
  144. package/dist/application/assertion/guarded-expectation.d.ts +45 -0
  145. package/dist/application/assertion/guarded-expectation.js +74 -0
  146. package/dist/application/checkpoint/baseline-capturer.d.ts +26 -0
  147. package/dist/application/checkpoint/baseline-capturer.js +163 -0
  148. package/dist/application/checkpoint/baseline-error.d.ts +5 -0
  149. package/dist/application/checkpoint/baseline-error.js +8 -0
  150. package/dist/application/checkpoint/baseline-service.d.ts +31 -0
  151. package/dist/application/checkpoint/baseline-service.js +147 -0
  152. package/dist/application/checkpoint/checkpoint-evaluator.d.ts +35 -0
  153. package/dist/application/checkpoint/checkpoint-evaluator.js +415 -0
  154. package/dist/application/checkpoint/regression-comparator.d.ts +18 -0
  155. package/dist/application/checkpoint/regression-comparator.js +192 -0
  156. package/dist/application/collector/logcat-collector.d.ts +22 -1
  157. package/dist/application/collector/logcat-collector.js +103 -15
  158. package/dist/application/collector/logcat-event.d.ts +8 -0
  159. package/dist/application/collector/logcat-event.js +79 -0
  160. package/dist/application/collector/logcat-stop.d.ts +2 -0
  161. package/dist/application/collector/logcat-stop.js +11 -0
  162. package/dist/application/context/context-generator.d.ts +45 -0
  163. package/dist/application/context/context-generator.js +228 -0
  164. package/dist/application/context/context-loader.d.ts +40 -0
  165. package/dist/application/context/context-loader.js +223 -0
  166. package/dist/application/context/context-refresher.d.ts +59 -0
  167. package/dist/application/context/context-refresher.js +349 -0
  168. package/dist/application/context/context-rehasher.d.ts +36 -0
  169. package/dist/application/context/context-rehasher.js +110 -0
  170. package/dist/application/context/context-validator.d.ts +23 -1
  171. package/dist/application/context/context-validator.js +116 -9
  172. package/dist/application/context/evidence-hash.d.ts +1 -0
  173. package/dist/application/context/evidence-hash.js +125 -0
  174. package/dist/application/context/evidence-match.d.ts +9 -0
  175. package/dist/application/context/evidence-match.js +8 -0
  176. package/dist/application/context/shard-identity.d.ts +2 -0
  177. package/dist/application/context/shard-identity.js +7 -0
  178. package/dist/application/contract/contract-loader.d.ts +25 -0
  179. package/dist/application/contract/contract-loader.js +68 -0
  180. package/dist/application/contract/contract-review.d.ts +25 -0
  181. package/dist/application/contract/contract-review.js +51 -0
  182. package/dist/application/contract/contract-verifier.d.ts +53 -0
  183. package/dist/application/contract/contract-verifier.js +645 -0
  184. package/dist/application/devices/resolve-device-assignments.d.ts +21 -0
  185. package/dist/application/devices/resolve-device-assignments.js +60 -0
  186. package/dist/application/diagnosis/failure-classifier.d.ts +23 -0
  187. package/dist/application/diagnosis/failure-classifier.js +179 -0
  188. package/dist/application/doctor/doctor-service.d.ts +36 -3
  189. package/dist/application/doctor/doctor-service.js +255 -25
  190. package/dist/application/generation/generation-app-preparer.d.ts +20 -0
  191. package/dist/application/generation/generation-app-preparer.js +28 -0
  192. package/dist/application/generation/generation-config-service.d.ts +21 -0
  193. package/dist/application/generation/generation-config-service.js +53 -0
  194. package/dist/application/generation/generation-confirmation-service.d.ts +14 -3
  195. package/dist/application/generation/generation-confirmation-service.js +109 -24
  196. package/dist/application/generation/generation-context-snapshot.d.ts +6 -0
  197. package/dist/application/generation/generation-context-snapshot.js +29 -0
  198. package/dist/application/generation/generation-finalizer.d.ts +15 -9
  199. package/dist/application/generation/generation-finalizer.js +167 -70
  200. package/dist/application/generation/generation-publisher.js +12 -8
  201. package/dist/application/generation/generation-recovery-service.d.ts +35 -0
  202. package/dist/application/generation/generation-recovery-service.js +144 -0
  203. package/dist/application/generation/generation-reopen-service.d.ts +15 -0
  204. package/dist/application/generation/generation-reopen-service.js +37 -0
  205. package/dist/application/generation/generation-replace-service.d.ts +32 -0
  206. package/dist/application/generation/generation-replace-service.js +116 -0
  207. package/dist/application/generation/generation-starter.d.ts +44 -4
  208. package/dist/application/generation/generation-starter.js +175 -8
  209. package/dist/application/generation/generation-step-executor.d.ts +67 -5
  210. package/dist/application/generation/generation-step-executor.js +471 -108
  211. package/dist/application/generation/proposed-step-validator.js +96 -30
  212. package/dist/application/generation/replay-policy-loader.d.ts +16 -0
  213. package/dist/application/generation/replay-policy-loader.js +29 -0
  214. package/dist/application/generation/risk-evaluator.d.ts +4 -1
  215. package/dist/application/generation/risk-evaluator.js +118 -3
  216. package/dist/application/generation/runtime-observer.d.ts +39 -7
  217. package/dist/application/generation/runtime-observer.js +193 -24
  218. package/dist/application/impact/impact-resolver.d.ts +32 -0
  219. package/dist/application/impact/impact-resolver.js +160 -0
  220. package/dist/application/init/init-service.js +26 -13
  221. package/dist/application/interaction/action-executor.d.ts +3 -2
  222. package/dist/application/interaction/action-executor.js +11 -1
  223. package/dist/application/interaction/action-target.d.ts +17 -0
  224. package/dist/application/interaction/action-target.js +40 -0
  225. package/dist/application/interaction/external-step-runner.d.ts +153 -0
  226. package/dist/application/interaction/external-step-runner.js +332 -0
  227. package/dist/application/interaction/fallback-resolver.d.ts +6 -3
  228. package/dist/application/interaction/fallback-resolver.js +7 -5
  229. package/dist/application/interaction/scroll-to-executor.d.ts +17 -3
  230. package/dist/application/interaction/scroll-to-executor.js +118 -36
  231. package/dist/application/journey/external-flow-resolver.d.ts +25 -0
  232. package/dist/application/journey/external-flow-resolver.js +22 -0
  233. package/dist/application/journey/journey-check-service.d.ts +54 -0
  234. package/dist/application/journey/journey-check-service.js +207 -0
  235. package/dist/application/journey/journey-promoter.d.ts +26 -0
  236. package/dist/application/journey/journey-promoter.js +123 -0
  237. package/dist/application/journey/journey-resolver.d.ts +42 -0
  238. package/dist/application/journey/journey-resolver.js +239 -0
  239. package/dist/application/journey/journey-retirer.d.ts +25 -0
  240. package/dist/application/journey/journey-retirer.js +87 -0
  241. package/dist/application/knowledge/anchor-resolver.d.ts +36 -0
  242. package/dist/application/knowledge/anchor-resolver.js +110 -0
  243. package/dist/application/knowledge/knowledge-loader.d.ts +16 -0
  244. package/dist/application/knowledge/knowledge-loader.js +36 -0
  245. package/dist/application/locator/layout-failure-summary.d.ts +2 -0
  246. package/dist/application/locator/layout-failure-summary.js +67 -0
  247. package/dist/application/locator/layout-traversal.d.ts +11 -0
  248. package/dist/application/locator/layout-traversal.js +18 -0
  249. package/dist/application/locator/locator-resolver.d.ts +13 -1
  250. package/dist/application/locator/locator-resolver.js +182 -18
  251. package/dist/application/observe/observe-service.d.ts +20 -0
  252. package/dist/application/observe/observe-service.js +91 -0
  253. package/dist/application/project/project-describer.d.ts +14 -6
  254. package/dist/application/project/project-describer.js +38 -5
  255. package/dist/application/recognition/screen-detector.d.ts +28 -0
  256. package/dist/application/recognition/screen-detector.js +111 -0
  257. package/dist/application/recorder/locator-selector.js +151 -17
  258. package/dist/application/recorder/recorder-service.d.ts +16 -4
  259. package/dist/application/recorder/recorder-service.js +420 -128
  260. package/dist/application/report/report-writer.js +1 -1
  261. package/dist/application/runtime/cold-launch.d.ts +28 -0
  262. package/dist/application/runtime/cold-launch.js +59 -0
  263. package/dist/application/runtime/step-runner.d.ts +49 -4
  264. package/dist/application/runtime/step-runner.js +721 -130
  265. package/dist/application/runtime/verify-runtime.d.ts +57 -7
  266. package/dist/application/runtime/verify-runtime.js +554 -174
  267. package/dist/application/ui/cached-ui-snapshot-provider.d.ts +45 -0
  268. package/dist/application/ui/cached-ui-snapshot-provider.js +111 -0
  269. package/dist/application/ui/ui-snapshot-lifecycle.d.ts +2 -0
  270. package/dist/application/ui/ui-snapshot-lifecycle.js +8 -0
  271. package/dist/application/ui/ui-stability-probe.d.ts +3 -0
  272. package/dist/application/ui/ui-stability-probe.js +8 -0
  273. package/dist/application/wait/idle-advice.d.ts +6 -0
  274. package/dist/application/wait/idle-advice.js +27 -0
  275. package/dist/application/wait/idle-profiles.d.ts +15 -0
  276. package/dist/application/wait/idle-profiles.js +75 -0
  277. package/dist/application/wait/idle-waiter.d.ts +28 -4
  278. package/dist/application/wait/idle-waiter.js +186 -15
  279. package/dist/cli/commands/align.d.ts +3 -0
  280. package/dist/cli/commands/align.js +124 -0
  281. package/dist/cli/commands/baseline.d.ts +3 -0
  282. package/dist/cli/commands/baseline.js +130 -0
  283. package/dist/cli/commands/context.js +300 -27
  284. package/dist/cli/commands/contract.d.ts +3 -0
  285. package/dist/cli/commands/contract.js +120 -0
  286. package/dist/cli/commands/doctor.js +16 -9
  287. package/dist/cli/commands/failure.d.ts +3 -0
  288. package/dist/cli/commands/failure.js +63 -0
  289. package/dist/cli/commands/generation/lifecycle-commands.d.ts +5 -0
  290. package/dist/cli/commands/generation/lifecycle-commands.js +211 -0
  291. package/dist/cli/commands/generation/session-commands.d.ts +11 -0
  292. package/dist/cli/commands/generation/session-commands.js +472 -0
  293. package/dist/cli/commands/generation/shared.d.ts +1414 -0
  294. package/dist/cli/commands/generation/shared.js +291 -0
  295. package/dist/cli/commands/generation/step-commands.d.ts +8 -0
  296. package/dist/cli/commands/generation/step-commands.js +315 -0
  297. package/dist/cli/commands/generation.js +10 -507
  298. package/dist/cli/commands/impact.d.ts +3 -0
  299. package/dist/cli/commands/impact.js +87 -0
  300. package/dist/cli/commands/init.js +13 -6
  301. package/dist/cli/commands/journey.d.ts +3 -0
  302. package/dist/cli/commands/journey.js +382 -0
  303. package/dist/cli/commands/knowledge.d.ts +3 -0
  304. package/dist/cli/commands/knowledge.js +93 -0
  305. package/dist/cli/commands/observe.d.ts +3 -0
  306. package/dist/cli/commands/observe.js +127 -0
  307. package/dist/cli/commands/project.js +2 -1
  308. package/dist/cli/commands/record.js +18 -5
  309. package/dist/cli/commands/verify.js +273 -63
  310. package/dist/cli/dependencies.d.ts +125 -1
  311. package/dist/cli/dependencies.js +450 -51
  312. package/dist/cli/diff-verification.d.ts +41 -0
  313. package/dist/cli/diff-verification.js +192 -0
  314. package/dist/cli/main.js +49 -1
  315. package/dist/cli/output.d.ts +5 -3
  316. package/dist/cli/output.js +12 -0
  317. package/dist/cli/program.js +19 -1
  318. package/dist/cli/project-root.d.ts +1 -0
  319. package/dist/cli/project-root.js +6 -0
  320. package/dist/cli/runtime-selection.d.ts +22 -0
  321. package/dist/cli/runtime-selection.js +92 -0
  322. package/dist/cli/version.d.ts +1 -0
  323. package/dist/cli/version.js +14 -0
  324. package/dist/cli/workspace-guard.d.ts +2 -0
  325. package/dist/cli/workspace-guard.js +3 -0
  326. package/dist/domain/binding-reference.d.ts +4 -0
  327. package/dist/domain/binding-reference.js +23 -0
  328. package/dist/domain/checkpoint.d.ts +404 -0
  329. package/dist/domain/checkpoint.js +297 -0
  330. package/dist/domain/config.d.ts +107 -1
  331. package/dist/domain/config.js +52 -6
  332. package/dist/domain/contract.d.ts +413 -0
  333. package/dist/domain/contract.js +196 -0
  334. package/dist/domain/external-flow.d.ts +493 -0
  335. package/dist/domain/external-flow.js +15 -0
  336. package/dist/domain/failure-classification.d.ts +176 -0
  337. package/dist/domain/failure-classification.js +169 -0
  338. package/dist/domain/failure.d.ts +2 -1
  339. package/dist/domain/failure.js +123 -0
  340. package/dist/domain/generation.d.ts +1671 -132
  341. package/dist/domain/generation.js +202 -13
  342. package/dist/domain/geometry.d.ts +13 -0
  343. package/dist/domain/geometry.js +16 -0
  344. package/dist/domain/impact.d.ts +71 -0
  345. package/dist/domain/impact.js +76 -0
  346. package/dist/domain/init.d.ts +12 -4
  347. package/dist/domain/init.js +24 -18
  348. package/dist/domain/journey-composition.d.ts +2285 -0
  349. package/dist/domain/journey-composition.js +85 -0
  350. package/dist/domain/journey-lifecycle.d.ts +10 -0
  351. package/dist/domain/journey-lifecycle.js +9 -0
  352. package/dist/domain/journey.d.ts +2419 -212
  353. package/dist/domain/journey.js +384 -14
  354. package/dist/domain/knowledge.d.ts +165 -0
  355. package/dist/domain/knowledge.js +188 -0
  356. package/dist/domain/layout.d.ts +34 -5
  357. package/dist/domain/layout.js +64 -6
  358. package/dist/domain/locator-evidence.d.ts +3 -0
  359. package/dist/domain/locator-evidence.js +36 -0
  360. package/dist/domain/logcat-event.d.ts +54 -0
  361. package/dist/domain/logcat-event.js +40 -0
  362. package/dist/domain/observation.d.ts +33 -0
  363. package/dist/domain/observation.js +18 -0
  364. package/dist/domain/project-context.d.ts +219 -1
  365. package/dist/domain/project-context.js +209 -6
  366. package/dist/domain/proposed-step.d.ts +340 -60
  367. package/dist/domain/proposed-step.js +23 -3
  368. package/dist/domain/report.d.ts +1455 -28
  369. package/dist/domain/report.js +211 -14
  370. package/dist/domain/runtime-snapshot.d.ts +58 -1
  371. package/dist/domain/runtime-snapshot.js +14 -3
  372. package/dist/domain/runtime.d.ts +50 -0
  373. package/dist/domain/runtime.js +36 -0
  374. package/dist/domain/system-app-profiles.d.ts +6 -0
  375. package/dist/domain/system-app-profiles.js +43 -0
  376. package/dist/domain/ui-backend.d.ts +28 -0
  377. package/dist/domain/ui-backend.js +33 -0
  378. package/dist/domain/ui-cache.d.ts +11 -0
  379. package/dist/domain/ui-cache.js +10 -0
  380. package/dist/domain/window-hierarchy.d.ts +84 -0
  381. package/dist/domain/window-hierarchy.js +172 -0
  382. package/dist/domain/workflow-manifest.d.ts +77 -0
  383. package/dist/domain/workflow-manifest.js +136 -0
  384. package/dist/domain/workspace.d.ts +28 -0
  385. package/dist/domain/workspace.js +72 -0
  386. package/dist/ports/adb.d.ts +34 -1
  387. package/dist/ports/align-prompt.d.ts +11 -0
  388. package/dist/ports/align-prompt.js +6 -0
  389. package/dist/ports/anchor-resolver.d.ts +30 -0
  390. package/dist/ports/anchor-resolver.js +1 -0
  391. package/dist/ports/annotated-screen-resolver.d.ts +4 -0
  392. package/dist/ports/annotated-screen-resolver.js +1 -0
  393. package/dist/ports/camera-probe.d.ts +23 -0
  394. package/dist/ports/camera-probe.js +8 -0
  395. package/dist/ports/context-document-writer.d.ts +24 -0
  396. package/dist/ports/context-document-writer.js +1 -0
  397. package/dist/ports/detached-process-launcher.d.ts +12 -0
  398. package/dist/ports/detached-process-launcher.js +1 -0
  399. package/dist/ports/external-flow-registry.d.ts +37 -0
  400. package/dist/ports/external-flow-registry.js +1 -0
  401. package/dist/ports/generation-prompt.d.ts +2 -1
  402. package/dist/ports/generation-session-store.d.ts +12 -2
  403. package/dist/ports/git-diff.d.ts +9 -0
  404. package/dist/ports/git-diff.js +1 -0
  405. package/dist/ports/journey-composition-store.d.ts +17 -0
  406. package/dist/ports/journey-composition-store.js +1 -0
  407. package/dist/ports/knowledge-registry.d.ts +20 -0
  408. package/dist/ports/knowledge-registry.js +1 -0
  409. package/dist/ports/process-runner.d.ts +7 -0
  410. package/dist/ports/project-file-inspector.d.ts +1 -0
  411. package/dist/ports/project-identity-inspector.d.ts +24 -0
  412. package/dist/ports/project-identity-inspector.js +1 -0
  413. package/dist/ports/project-inventory-inspector.d.ts +21 -0
  414. package/dist/ports/project-inventory-inspector.js +1 -0
  415. package/dist/ports/project-module-discoverer.d.ts +26 -0
  416. package/dist/ports/project-module-discoverer.js +1 -0
  417. package/dist/ports/recorder-prompt.d.ts +10 -1
  418. package/dist/ports/runtime-backend.d.ts +89 -0
  419. package/dist/ports/runtime-backend.js +13 -0
  420. package/dist/ports/runtime-capability.d.ts +12 -0
  421. package/dist/ports/runtime-capability.js +20 -0
  422. package/dist/ports/runtime-session-ports.d.ts +25 -0
  423. package/dist/ports/runtime-session-ports.js +1 -0
  424. package/dist/ports/screenshot.d.ts +11 -0
  425. package/dist/ports/screenshot.js +1 -0
  426. package/dist/ports/skill-installer.d.ts +2 -2
  427. package/dist/ports/ui-snapshot.d.ts +35 -0
  428. package/dist/ports/ui-snapshot.js +1 -0
  429. package/dist/ports/ui-stability.d.ts +19 -0
  430. package/dist/ports/ui-stability.js +1 -0
  431. package/dist/ports/workspace-layout.d.ts +4 -0
  432. package/dist/ports/workspace-layout.js +1 -0
  433. package/dist/shared/errors.d.ts +2 -0
  434. package/dist/shared/errors.js +22 -0
  435. package/dist/shared/paths.d.ts +2 -0
  436. package/dist/shared/paths.js +24 -0
  437. package/dist/shared/strings.d.ts +2 -0
  438. package/dist/shared/strings.js +16 -0
  439. package/package.json +6 -1
  440. package/assets/skills/taphound-ai-journey/GUIDE.md +0 -862
  441. package/assets/skills/taphound-ai-journey/SKILL.md +0 -377
  442. package/assets/skills/taphound-ai-journey/prompts/analyze-project.md +0 -526
  443. package/assets/skills/taphound-ai-journey/prompts/generate-step.md +0 -109
  444. package/assets/skills/taphound-ai-journey/schemas/project-context.json +0 -81
  445. package/assets/skills/taphound-ai-journey/templates/project-context.example.json +0 -49
  446. package/dist/ports/android-cli.d.ts +0 -21
  447. /package/dist/{ports/android-cli.js → adapters/runtime/mobile-mcp/mobile-mcp-tools.js} +0 -0
@@ -1,56 +1,294 @@
1
1
  import { randomBytes, randomUUID } from "node:crypto";
2
- import { mkdtemp, readFile, rm } from "node:fs/promises";
2
+ import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
3
3
  import { homedir, tmpdir } from "node:os";
4
- import { join } from "node:path";
4
+ import { dirname, join, resolve as resolvePath } from "node:path";
5
+ import { fileURLToPath } from "node:url";
5
6
  import { AdbAdapter } from "../adapters/adb/adb-adapter.js";
7
+ import { AdbRuntimeBackend } from "../adapters/runtime/adb-runtime-backend.js";
8
+ import { SharedSessionRuntimeBackend } from "../adapters/runtime/shared-session-runtime-backend.js";
9
+ import { SessionBackedScreenshotAdapter, SessionBackedUiSnapshotProviderFactory } from "../adapters/runtime/session-backed-ports.js";
10
+ import { runtimeSessionPortViews } from "../adapters/runtime/session-adb-view.js";
11
+ import { MobileMcpRuntimeBackend } from "../adapters/runtime/mobile-mcp/mobile-mcp-runtime-backend.js";
12
+ import { McpToolClient } from "../adapters/runtime/mobile-mcp/mcp-tool-client.js";
13
+ import { isMobileMcpSpawnFailureDetail, mobileMcpServerUnavailableMessage } from "../adapters/runtime/mobile-mcp/mobile-mcp-errors.js";
14
+ import { SystemUiAutomatorSnapshotProviderFactory } from "../adapters/adb/system-uiautomator-snapshot-provider.js";
6
15
  import { AndroidCliAdapter } from "../adapters/android-cli/android-cli-adapter.js";
16
+ import { AndroidCliSnapshotProviderFactory } from "../adapters/android-cli/android-cli-snapshot-provider.js";
17
+ import { AppiumUiSnapshotProviderFactory } from "../adapters/appium/appium-ui-snapshot-provider.js";
18
+ import { checkAppiumUiAutomator2 } from "../adapters/appium/appium-doctor.js";
19
+ import { AutoUiSnapshotProviderFactory } from "../adapters/ui/auto-ui-snapshot-provider.js";
20
+ import { CachedUiSnapshotProviderFactory } from "../application/ui/cached-ui-snapshot-provider.js";
21
+ import { CameraProbeAdapter } from "../adapters/camera/camera-probe-adapter.js";
7
22
  import { SystemClock } from "../adapters/clock/system-clock.js";
8
23
  import { FileSystemArtifactStore } from "../adapters/filesystem/artifact-store.js";
24
+ import { FileSystemContextDocumentWriter } from "../adapters/filesystem/context-document-writer.js";
9
25
  import { FileSystemGenerationMetaWriter } from "../adapters/filesystem/generation-meta-writer.js";
10
26
  import { FileSystemGenerationSessionStore } from "../adapters/filesystem/generation-session-store.js";
11
27
  import { FileSystemJourneyWriter } from "../adapters/filesystem/journey-writer.js";
28
+ import { FileSystemKnowledgeRegistry } from "../adapters/filesystem/knowledge-registry.js";
29
+ import { FileSystemJourneyCompositionStore } from "../adapters/filesystem/journey-composition-store.js";
30
+ import { FileSystemExternalFlowRegistry } from "../adapters/filesystem/external-flow-registry.js";
12
31
  import { NodeProjectFileInspector } from "../adapters/filesystem/project-file-inspector.js";
32
+ import { NodeProjectInventoryInspector } from "../adapters/filesystem/project-inventory-inspector.js";
33
+ import { GradleProjectModuleDiscoverer } from "../adapters/filesystem/project-module-discoverer.js";
34
+ import { AndroidProjectIdentityInspector } from "../adapters/filesystem/project-identity-inspector.js";
13
35
  import { FileSystemSkillInstaller } from "../adapters/filesystem/skill-installer.js";
36
+ import { FileSystemWorkspaceLayout } from "../adapters/filesystem/workspace-layout.js";
14
37
  import { NodeProcessRunner } from "../adapters/process/node-process-runner.js";
38
+ import { NodeDetachedProcessLauncher } from "../adapters/process/node-detached-process-launcher.js";
15
39
  import { InquirerRecorderPrompt } from "../adapters/prompt/inquirer-recorder-prompt.js";
16
40
  import { InquirerGenerationPrompt } from "../adapters/prompt/inquirer-generation-prompt.js";
17
41
  import { InquirerInitPrompt } from "../adapters/prompt/inquirer-init-prompt.js";
42
+ import { InquirerAlignPrompt } from "../adapters/prompt/inquirer-align-prompt.js";
43
+ import { AlignService } from "../application/align/align-service.js";
44
+ import { ObserveService } from "../application/observe/observe-service.js";
45
+ import { ContextGenerator } from "../application/context/context-generator.js";
46
+ import { ContextRehasher } from "../application/context/context-rehasher.js";
18
47
  import { ContextValidator } from "../application/context/context-validator.js";
48
+ import { ContextLoader } from "../application/context/context-loader.js";
49
+ import { ContextRefresher } from "../application/context/context-refresher.js";
19
50
  import { DoctorService } from "../application/doctor/doctor-service.js";
20
51
  import { GenerationConfirmationService } from "../application/generation/generation-confirmation-service.js";
52
+ import { GenerationAppPreparer } from "../application/generation/generation-app-preparer.js";
21
53
  import { GenerationFinalizer } from "../application/generation/generation-finalizer.js";
22
54
  import { GenerationPublisher } from "../application/generation/generation-publisher.js";
55
+ import { GenerationRecoveryService } from "../application/generation/generation-recovery-service.js";
56
+ import { GenerationReopenService } from "../application/generation/generation-reopen-service.js";
57
+ import { GenerationConfigService } from "../application/generation/generation-config-service.js";
58
+ import { GenerationReplaceService } from "../application/generation/generation-replace-service.js";
23
59
  import { GenerationStarter, GenerationOperationError, hashGenerationBinding } from "../application/generation/generation-starter.js";
60
+ import { readGenerationContextSnapshot } from "../application/generation/generation-context-snapshot.js";
24
61
  import { GenerationStepExecutor } from "../application/generation/generation-step-executor.js";
25
62
  import { RuntimeObserver, SnapshotReobservationGuard } from "../application/generation/runtime-observer.js";
26
63
  import { InitService } from "../application/init/init-service.js";
64
+ import { JourneyResolver } from "../application/journey/journey-resolver.js";
65
+ import { ExternalFlowResolver } from "../application/journey/external-flow-resolver.js";
66
+ import { KnowledgeLoadError, KnowledgeLoader } from "../application/knowledge/knowledge-loader.js";
67
+ import { KnowledgeAnchorResolver } from "../application/knowledge/anchor-resolver.js";
68
+ import { ImpactResolver } from "../application/impact/impact-resolver.js";
69
+ import { NodeGitDiff } from "../adapters/git/node-git-diff.js";
27
70
  import { ProjectDescriber } from "../application/project/project-describer.js";
28
71
  import { RecorderService } from "../application/recorder/recorder-service.js";
29
72
  import { ReportWriter } from "../application/report/report-writer.js";
73
+ import { ContractVerifier } from "../application/contract/contract-verifier.js";
74
+ import { ContractLoader } from "../application/contract/contract-loader.js";
75
+ import { ContractReviewMerger } from "../application/contract/contract-review.js";
76
+ import { BaselineService } from "../application/checkpoint/baseline-service.js";
77
+ import { FailureClassifier } from "../application/diagnosis/failure-classifier.js";
78
+ import { TapHoundReportV4Schema } from "../domain/report.js";
30
79
  import { VerifyRuntime } from "../application/runtime/verify-runtime.js";
80
+ import { IdleWaiter } from "../application/wait/idle-waiter.js";
81
+ import { deviceIdentityResolver } from "../application/wait/idle-profiles.js";
82
+ import { resolveRuntimeBackendId } from "../domain/runtime.js";
83
+ import { withRuntimeSession } from "../ports/runtime-backend.js";
84
+ import { verificationPhaseLabel } from "../domain/generation.js";
85
+ import { isErrnoException } from "../shared/errors.js";
86
+ import { readRuntimeBackendChoice } from "./runtime-selection.js";
87
+ import { CONTEXT_INDEX_PATH } from "../domain/workspace.js";
88
+ import { JourneySchema } from "../domain/journey.js";
31
89
  function runId() {
32
90
  return `${new Date().toISOString().replaceAll(":", "-")}-${randomUUID()}`;
33
91
  }
92
+ export function loadKnowledgeResilient(load, input) {
93
+ return load(input).catch((error) => {
94
+ if ((isErrnoException(error) && error.code === "ENOENT")
95
+ || (error instanceof KnowledgeLoadError
96
+ && error.code === "KNOWLEDGE_NOT_FOUND")) {
97
+ return {
98
+ index: {
99
+ version: 1,
100
+ packageName: input.packageName,
101
+ revision: 0,
102
+ anchors: [],
103
+ screens: []
104
+ },
105
+ indexSha256: "0".repeat(64),
106
+ knowledgeHash: "0".repeat(64),
107
+ anchors: [],
108
+ screens: []
109
+ };
110
+ }
111
+ throw error;
112
+ });
113
+ }
34
114
  export function createProductionDependencies(signal, options = {}) {
115
+ const backendId = resolveRuntimeBackendId(options.runtimeBackendChoice ?? readRuntimeBackendChoice(process.env));
35
116
  const runner = new NodeProcessRunner();
36
- const adb = new AdbAdapter(runner);
37
- const androidCli = new AndroidCliAdapter(runner);
38
- const clock = new SystemClock();
117
+ const clock = options.clock ?? new SystemClock();
118
+ const now = () => clock.now();
119
+ const permissionCaptureTimeoutMs = 10_000;
120
+ let backend;
121
+ let screenshots;
122
+ let uiSnapshots;
123
+ let sharedBackend;
124
+ if (options.runtimeBackend !== undefined) {
125
+ backend = options.runtimeBackend;
126
+ screenshots = new SessionBackedScreenshotAdapter(backend);
127
+ uiSnapshots = new CachedUiSnapshotProviderFactory(new SessionBackedUiSnapshotProviderFactory(backend), now);
128
+ }
129
+ else if (backendId === "mobile-mcp") {
130
+ const shared = new SharedSessionRuntimeBackend(new MobileMcpRuntimeBackend({
131
+ createTools: options.mobileMcpToolsFactory
132
+ ?? (() => new McpToolClient())
133
+ }));
134
+ sharedBackend = shared;
135
+ backend = shared;
136
+ screenshots = new SessionBackedScreenshotAdapter(backend);
137
+ uiSnapshots = new CachedUiSnapshotProviderFactory(new SessionBackedUiSnapshotProviderFactory(backend), now);
138
+ }
139
+ else {
140
+ const adbAdapter = new AdbAdapter(runner);
141
+ const androidCli = new AndroidCliAdapter(runner);
142
+ const autoSnapshots = new CachedUiSnapshotProviderFactory(new AutoUiSnapshotProviderFactory(new SystemUiAutomatorSnapshotProviderFactory(runner), new AndroidCliSnapshotProviderFactory(runner), new AppiumUiSnapshotProviderFactory(runner)), now);
143
+ const adbBackend = new AdbRuntimeBackend({
144
+ adb: adbAdapter,
145
+ screenshots: androidCli,
146
+ annotatedScreens: androidCli,
147
+ uiStability: androidCli,
148
+ uiSnapshots: autoSnapshots
149
+ });
150
+ backend = adbBackend;
151
+ screenshots = androidCli;
152
+ uiSnapshots = autoSnapshots;
153
+ }
154
+ const sessions = backend;
155
+ // Device-wide probes (listing, install state) borrow a session per call.
156
+ const devices = {
157
+ devices: (signal) => backend.listDevices(signal),
158
+ isInstalled: (identity) => withRuntimeSession(backend, identity.deviceSerial, identity.signal, (session) => session.isInstalled({
159
+ packageName: identity.packageName,
160
+ ...(identity.signal === undefined ? {} : { signal: identity.signal }),
161
+ ...(identity.timeoutMs === undefined
162
+ ? {}
163
+ : { timeoutMs: identity.timeoutMs })
164
+ }))
165
+ };
166
+ const waitUntilIdle = (deviceSerial, config, signal, packageName, stability, device) => new IdleWaiter(stability, clock, deviceSerial, packageName, deviceIdentityResolver(device, {
167
+ packageName,
168
+ deviceSerial,
169
+ timeoutMs: config.timeoutMs
170
+ })).waitUntilIdle(config, signal);
39
171
  const generationStoreFactory = options.generationStoreFactory
40
172
  ?? ((projectRoot) => (new FileSystemGenerationSessionStore(projectRoot)));
41
- const contextValidator = new ContextValidator(new NodeProjectFileInspector());
173
+ const projectFiles = new NodeProjectFileInspector();
174
+ const projectInventory = new NodeProjectInventoryInspector();
175
+ const moduleDiscoverer = new GradleProjectModuleDiscoverer();
176
+ const identityInspector = new AndroidProjectIdentityInspector();
177
+ const contextWriter = new FileSystemContextDocumentWriter();
178
+ const contextValidator = new ContextValidator(projectFiles, projectInventory);
179
+ const contextLoader = new ContextLoader({
180
+ files: projectFiles,
181
+ inventory: projectInventory,
182
+ readJson: async (path) => JSON.parse(await readFile(path, "utf8"))
183
+ });
184
+ const contextRefresher = new ContextRefresher({
185
+ files: projectFiles,
186
+ inventory: projectInventory,
187
+ loader: contextLoader,
188
+ writer: contextWriter
189
+ });
190
+ const contextGenerator = new ContextGenerator({
191
+ discoverer: moduleDiscoverer,
192
+ identity: identityInspector,
193
+ files: projectFiles,
194
+ inventory: projectInventory,
195
+ writer: contextWriter
196
+ });
197
+ const contextRehasher = new ContextRehasher({
198
+ files: projectFiles,
199
+ loader: contextLoader,
200
+ writer: contextWriter
201
+ });
202
+ const journeyCompositionStore = new FileSystemJourneyCompositionStore();
203
+ const journeyResolver = new JourneyResolver(journeyCompositionStore);
204
+ const builtinFlowsRoot = resolvePath(dirname(fileURLToPath(import.meta.url)), "..", "..", "..", "assets", "external-flows");
205
+ const externalFlowRegistry = new FileSystemExternalFlowRegistry(builtinFlowsRoot);
206
+ const externalFlowResolver = new ExternalFlowResolver({
207
+ registry: externalFlowRegistry
208
+ });
209
+ const knowledgeRegistry = new FileSystemKnowledgeRegistry();
210
+ const knowledgeLoader = new KnowledgeLoader(knowledgeRegistry);
211
+ const productionContractLoader = new ContractLoader({
212
+ readText: (path) => readFile(path, "utf8")
213
+ });
214
+ const productionContractReview = new ContractReviewMerger({
215
+ now: () => new Date()
216
+ });
217
+ const productionBaselineService = new BaselineService({
218
+ readText: (path) => readFile(path, "utf8"),
219
+ writeText: (path, content) => {
220
+ const directory = dirname(path);
221
+ return mkdir(directory, { recursive: true }).then(() => (writeFile(path, content, "utf8")));
222
+ },
223
+ now: () => new Date()
224
+ });
225
+ const productionFailureClassifier = new FailureClassifier({
226
+ now: () => new Date()
227
+ });
228
+ const productionContractVerifier = new ContractVerifier({
229
+ verify: (input) => productionVerifyRuntime.verify(input),
230
+ loadKnowledge: (input) => (knowledgeRegistry.load(input.projectRoot)),
231
+ readText: (path) => readFile(path, "utf8"),
232
+ writeVerdict: async ({ reportPath, verdict }) => {
233
+ const directory = dirname(reportPath);
234
+ await mkdir(directory, { recursive: true });
235
+ await writeFile(join(directory, "verdict.json"), `${JSON.stringify(verdict, null, 2)}\n`, "utf8");
236
+ },
237
+ now: () => new Date()
238
+ });
239
+ const productionVerifyRuntime = new VerifyRuntime({
240
+ sessions,
241
+ sessionPorts: runtimeSessionPortViews,
242
+ clock,
243
+ artifactStore: new FileSystemArtifactStore(),
244
+ reportWriter: new ReportWriter(),
245
+ now: () => new Date(),
246
+ createRunId: runId,
247
+ anchorResolverFor: (projectRoot) => (new KnowledgeAnchorResolver(knowledgeRegistry, projectRoot)),
248
+ loadKnowledge: (input) => (knowledgeRegistry.load(input.projectRoot))
249
+ });
250
+ const gitDiff = new NodeGitDiff(runner);
251
+ const impactResolver = new ImpactResolver({
252
+ loadContext: async (input) => {
253
+ const loaded = await contextLoader.load({
254
+ projectRoot: input.projectRoot,
255
+ contextPath: join(input.projectRoot, CONTEXT_INDEX_PATH),
256
+ allowIncomplete: true
257
+ });
258
+ return { context: loaded.context, modules: loaded.modules };
259
+ },
260
+ loadKnowledge: (input) => loadKnowledgeResilient(knowledgeLoader.load.bind(knowledgeLoader), input),
261
+ listJourneyPaths: (input) => (journeyCompositionStore.listJourneyPaths(input.projectRoot)),
262
+ readJourney: async (input) => {
263
+ const bytes = await journeyCompositionStore.read({
264
+ projectRoot: input.projectRoot,
265
+ relativePath: input.path
266
+ });
267
+ try {
268
+ return JourneySchema.parse(JSON.parse(bytes.toString("utf8")));
269
+ }
270
+ catch {
271
+ return null;
272
+ }
273
+ }
274
+ });
42
275
  return {
43
276
  ...(signal === undefined ? {} : { signal }),
277
+ ...(sharedBackend === undefined
278
+ ? {}
279
+ : { close: () => sharedBackend.close() }),
44
280
  doctor: new DoctorService({
45
281
  runner,
46
- adb,
282
+ adb: devices,
47
283
  nodeVersion: process.version,
284
+ runtimeBackendId: backendId,
48
285
  checkAndroidPermissions: async (deviceSerial, signal) => {
49
286
  const directory = await mkdtemp(join(tmpdir(), "taphound-doctor-"));
50
287
  try {
51
- const result = await androidCli.captureScreen({
288
+ const result = await screenshots.capture({
52
289
  outputPath: join(directory, "screen.png"),
53
290
  deviceSerial,
291
+ timeoutMs: permissionCaptureTimeoutMs,
54
292
  ...(signal === undefined ? {} : { signal })
55
293
  });
56
294
  if (result.exitCode !== 0
@@ -59,9 +297,11 @@ export function createProductionDependencies(signal, options = {}) {
59
297
  || result.timedOut) {
60
298
  return {
61
299
  status: "failed",
62
- message: result.stderr.trim()
63
- || result.spawnError
64
- || "Android screen capture permission probe failed"
300
+ message: result.timedOut
301
+ ? "Android screen capture permission probe timed out after 10 seconds"
302
+ : result.stderr.trim()
303
+ || result.spawnError
304
+ || "Android screen capture permission probe failed"
65
305
  };
66
306
  }
67
307
  return { status: "passed" };
@@ -69,35 +309,121 @@ export function createProductionDependencies(signal, options = {}) {
69
309
  finally {
70
310
  await rm(directory, { recursive: true, force: true });
71
311
  }
312
+ },
313
+ checkAppiumUiAutomator2: async (appiumSignal) => (checkAppiumUiAutomator2(runner, appiumSignal)),
314
+ checkMobileMcpServer: async (mcpSignal) => {
315
+ const result = await runner.run({
316
+ executable: "mcp-server-mobile",
317
+ args: ["--version"],
318
+ ...(mcpSignal === undefined ? {} : { signal: mcpSignal })
319
+ });
320
+ if (result.exitCode !== 0
321
+ || result.spawnError !== undefined
322
+ || result.cancelled
323
+ || result.timedOut) {
324
+ const detail = result.stderr.trim()
325
+ || result.spawnError
326
+ || "mcp-server-mobile check failed";
327
+ return {
328
+ status: "failed",
329
+ message: isMobileMcpSpawnFailureDetail(detail)
330
+ ? mobileMcpServerUnavailableMessage("mcp-server-mobile", detail)
331
+ : detail
332
+ };
333
+ }
334
+ return {
335
+ status: "passed",
336
+ version: result.stdout.trim().split(/\r?\n/, 1)[0] ?? "unknown"
337
+ };
72
338
  }
73
339
  }),
74
340
  recorder: new RecorderService({
75
- androidCli,
76
- adb,
341
+ sessions,
342
+ sessionPorts: runtimeSessionPortViews,
77
343
  clock,
78
- prompt: new InquirerRecorderPrompt(),
344
+ prompt: options.recorderPrompt ?? new InquirerRecorderPrompt(),
79
345
  journeyWriter: new FileSystemJourneyWriter()
80
346
  }),
81
- verifier: new VerifyRuntime({
82
- androidCli,
83
- adb,
84
- clock,
85
- artifactStore: new FileSystemArtifactStore(),
86
- reportWriter: new ReportWriter(),
87
- now: () => new Date(),
88
- createRunId: runId
347
+ verifier: productionVerifyRuntime,
348
+ contractLoader: productionContractLoader,
349
+ contractVerifier: productionContractVerifier,
350
+ baselineService: productionBaselineService,
351
+ failureClassifier: {
352
+ classify: async (reportPath) => {
353
+ const text = await readFile(reportPath, "utf8");
354
+ const report = TapHoundReportV4Schema.parse(JSON.parse(text));
355
+ return productionFailureClassifier.classify({ report });
356
+ }
357
+ },
358
+ contractReview: {
359
+ merge: productionContractReview.merge,
360
+ writeVerdict: async ({ verdictPath, view }) => {
361
+ const directory = dirname(verdictPath);
362
+ await mkdir(directory, { recursive: true });
363
+ await writeFile(verdictPath, `${JSON.stringify(view, null, 2)}\n`, "utf8");
364
+ }
365
+ },
366
+ projectDescriber: new ProjectDescriber({
367
+ discoverer: moduleDiscoverer,
368
+ identity: identityInspector
89
369
  }),
90
- projectDescriber: new ProjectDescriber(),
91
370
  contextValidator,
371
+ contextLoader,
372
+ contextRefresher,
373
+ contextGenerator,
374
+ contextRehasher,
375
+ journeyResolver,
376
+ journeyCompositionStore,
377
+ externalFlowResolver,
92
378
  init: new InitService({
93
379
  installer: new FileSystemSkillInstaller(),
94
380
  cwd: process.cwd(),
95
381
  homedir: homedir()
96
382
  }),
97
383
  initPrompt: new InquirerInitPrompt(),
384
+ align: new AlignService({
385
+ adb: devices,
386
+ probe: new CameraProbeAdapter({
387
+ sessions,
388
+ sessionPorts: runtimeSessionPortViews,
389
+ uiSnapshots,
390
+ now: () => Date.now(),
391
+ sleep: async (ms) => {
392
+ await new Promise((resolve) => setTimeout(resolve, ms));
393
+ }
394
+ }),
395
+ prompt: new InquirerAlignPrompt(),
396
+ registry: externalFlowRegistry
397
+ }),
398
+ observer: (layoutTimeoutMs, backend, cacheEnabled) => {
399
+ const service = new ObserveService({
400
+ sessions,
401
+ layoutTimeoutMs,
402
+ ...(backend === undefined ? {} : { backend }),
403
+ ...(cacheEnabled === undefined ? {} : { cacheEnabled })
404
+ });
405
+ return {
406
+ observe: (input) => service.observe(input)
407
+ };
408
+ },
409
+ workspaceLayout: new FileSystemWorkspaceLayout(),
410
+ impact: {
411
+ resolve: (input) => impactResolver.resolve(input)
412
+ },
413
+ gitDiff,
414
+ knowledge: {
415
+ load: (input) => knowledgeLoader.load(input),
416
+ rehash: (input) => (knowledgeRegistry.rehash(input.projectRoot, input.packageName))
417
+ },
98
418
  generationStarter: {
99
419
  start: async (input) => new GenerationStarter({
100
420
  contextValidator,
421
+ appPreparer: new GenerationAppPreparer({
422
+ sessions,
423
+ sessionPorts: runtimeSessionPortViews,
424
+ clock
425
+ }),
426
+ uiSnapshots,
101
427
  store: generationStoreFactory(input.projectRoot),
102
428
  now: () => new Date(),
103
429
  generateId: randomUUID,
@@ -107,8 +433,9 @@ export function createProductionDependencies(signal, options = {}) {
107
433
  runtimeObserver: {
108
434
  observe: async ({ projectRoot, ...input }) => (new RuntimeObserver({
109
435
  store: generationStoreFactory(projectRoot),
110
- adb,
111
- androidCli,
436
+ sessions,
437
+ sessionPorts: runtimeSessionPortViews,
438
+ waitUntilIdle,
112
439
  now: () => new Date(),
113
440
  createAttemptId: randomUUID
114
441
  }).observe(input))
@@ -118,16 +445,13 @@ export function createProductionDependencies(signal, options = {}) {
118
445
  const prompt = new InquirerGenerationPrompt();
119
446
  const observer = new RuntimeObserver({
120
447
  store,
121
- adb,
122
- androidCli,
448
+ sessions,
449
+ sessionPorts: runtimeSessionPortViews,
450
+ waitUntilIdle,
123
451
  now: () => new Date(),
124
- createAttemptId: randomUUID
125
- });
126
- const freshnessGuard = new SnapshotReobservationGuard({
127
- store,
128
- adb,
129
- androidCli,
130
- now: () => new Date()
452
+ createAttemptId: randomUUID,
453
+ uiCacheEnabled: config.ui?.cacheEnabled ?? true,
454
+ uiSnapshotTimeoutMs: config.ui?.snapshotTimeoutMs
131
455
  });
132
456
  const confirmation = new GenerationConfirmationService({
133
457
  store,
@@ -138,54 +462,129 @@ export function createProductionDependencies(signal, options = {}) {
138
462
  });
139
463
  const executor = new GenerationStepExecutor({
140
464
  store,
141
- freshnessGuard,
142
- adb,
143
- androidCli,
465
+ createFreshnessGuard: (uiSnapshotProvider, views) => (new SnapshotReobservationGuard({
466
+ store,
467
+ adb: views.adb,
468
+ uiSnapshotProvider,
469
+ now: () => new Date(),
470
+ uiSnapshotTimeoutMs: config.ui?.snapshotTimeoutMs
471
+ })),
472
+ sessions,
473
+ sessionPorts: runtimeSessionPortViews,
474
+ uiCacheEnabled: config.ui?.cacheEnabled ?? true,
144
475
  clock,
145
476
  idle: config.idle,
146
477
  now: () => new Date(),
147
478
  generateAttemptId: randomUUID,
479
+ projectRoot,
480
+ externalFlowResolver,
148
481
  clearApprovedConfirmation: async (generationId, challenge) => confirmation.clearApproved({
149
482
  generationId,
150
483
  challenge
151
- })
484
+ }),
485
+ observeNext: (observation) => (observer.observeCollected({
486
+ generationId: observation.generationId,
487
+ runtime: observation.runtime,
488
+ ...(observation.signal === undefined
489
+ ? {}
490
+ : { signal: observation.signal })
491
+ }))
152
492
  });
153
493
  const publisher = new GenerationPublisher({
154
494
  store,
155
495
  journeyWriter: new FileSystemJourneyWriter(),
156
496
  metaWriter: new FileSystemGenerationMetaWriter()
157
497
  });
498
+ const verifyRuntime = new VerifyRuntime({
499
+ sessions,
500
+ sessionPorts: runtimeSessionPortViews,
501
+ clock,
502
+ artifactStore: new FileSystemArtifactStore(),
503
+ reportWriter: new ReportWriter(),
504
+ now: () => new Date(),
505
+ createRunId: runId,
506
+ anchorResolverFor: (projectRoot) => (new KnowledgeAnchorResolver(knowledgeRegistry, projectRoot))
507
+ });
158
508
  const finalizer = new GenerationFinalizer({
159
509
  store,
160
- contextValidator,
161
- adb,
162
- verifyRuntime: new VerifyRuntime({
163
- androidCli,
164
- adb,
165
- clock,
166
- artifactStore: new FileSystemArtifactStore(),
167
- reportWriter: new ReportWriter(),
168
- now: () => new Date(),
169
- createRunId: runId
170
- }),
510
+ verifyRuntime,
171
511
  publisher,
172
- generateAttemptId: randomUUID
512
+ generateAttemptId: randomUUID,
513
+ owner: { pid: process.pid, now: () => new Date() },
514
+ progress: (stage) => {
515
+ process.stderr.write(`TapHound finalize: ${stage}\n`);
516
+ },
517
+ replayProgress: (phase) => {
518
+ process.stderr.write(`TapHound finalize: ${verificationPhaseLabel(phase)}\n`);
519
+ }
520
+ });
521
+ const recovery = new GenerationRecoveryService({
522
+ store,
523
+ now: () => new Date(),
524
+ ownerAlive: (pid) => {
525
+ try {
526
+ process.kill(pid, 0);
527
+ return true;
528
+ }
529
+ catch (error) {
530
+ return !isErrnoException(error) || error.code !== "ESRCH";
531
+ }
532
+ }
533
+ });
534
+ const reopen = new GenerationReopenService({
535
+ store,
536
+ now: () => new Date()
173
537
  });
174
538
  return {
175
539
  confirmation,
176
540
  executor,
177
541
  observer,
178
542
  finalizer,
543
+ recovery,
544
+ reopen,
545
+ archive: async (id) => {
546
+ const current = await store.read(id);
547
+ const next = {
548
+ ...current,
549
+ revision: current.revision + 1,
550
+ state: "archived"
551
+ };
552
+ await store.archive(id, current.revision, next);
553
+ return next;
554
+ },
555
+ list: () => store.list(),
179
556
  readSession: (id) => store.read(id),
557
+ readContextSnapshot: (id) => (readGenerationContextSnapshot({ store }, id)),
180
558
  assertConfigIdentity: async (id) => {
181
559
  const session = await store.read(id);
182
560
  if (hashGenerationBinding(config) !== session.bindings.configHash) {
183
561
  throw new GenerationOperationError("CONFIG_INVALID", "Generation configuration does not match the authoritative session");
184
562
  }
185
- }
563
+ },
564
+ updateIdlePolicy: async (id, patch) => (new GenerationConfigService({ store }).updateIdlePolicy({
565
+ generationId: id,
566
+ config,
567
+ patch
568
+ })),
569
+ replace: (input) => (new GenerationReplaceService({
570
+ store,
571
+ observer,
572
+ verifyRuntime,
573
+ appPreparer: new GenerationAppPreparer({
574
+ sessions,
575
+ sessionPorts: runtimeSessionPortViews,
576
+ clock
577
+ })
578
+ }).replace(input))
186
579
  };
187
580
  },
581
+ detachedProcess: new NodeDetachedProcessLauncher(),
582
+ createDetachedJobId: randomUUID,
583
+ ...(process.argv[1] === undefined
584
+ ? {}
585
+ : { cliEntryPath: process.argv[1] }),
188
586
  readJson: async (path) => JSON.parse(await readFile(path, "utf8")),
587
+ readFile: async (path) => readFile(path),
189
588
  cwd: () => process.cwd(),
190
589
  stdout: {
191
590
  write: (content) => {
@@ -0,0 +1,41 @@
1
+ import type { ImpactSet } from "../domain/impact.js";
2
+ import { CONFIG_PATH } from "../domain/workspace.js";
3
+ import { type FailureCode } from "../domain/failure.js";
4
+ import type { CliDependencies } from "./dependencies.js";
5
+ export interface DiffVerificationOptions {
6
+ project: string;
7
+ config: string;
8
+ base: string;
9
+ head?: string | undefined;
10
+ device?: string | undefined;
11
+ scope?: string | undefined;
12
+ json?: boolean | undefined;
13
+ }
14
+ export interface JourneyVerdict {
15
+ path: string;
16
+ name: string;
17
+ selection: "p0" | "p1" | "p2";
18
+ status: string;
19
+ exitCode: 0 | 1 | 2 | 3 | 4;
20
+ reportPath: string;
21
+ }
22
+ export interface DiffVerificationResult {
23
+ base: string;
24
+ head: string;
25
+ impact: ImpactSet;
26
+ results: JourneyVerdict[];
27
+ overall: "passed" | "failed" | "error";
28
+ exitCode: 0 | 1 | 2 | 3 | 4;
29
+ note?: string | undefined;
30
+ }
31
+ declare function writeFailure(dependencies: CliDependencies, json: boolean, code: FailureCode, message: string): void;
32
+ /**
33
+ * Diff-driven verification: compute the ImpactSet for a Git change, select
34
+ * the affected Journeys by tier (p0/p1/p2), and verify each one on the
35
+ * connected device.
36
+ *
37
+ * This is the Agent-facing entry behind `verify --diff`; it never parses the app's internals — the Coding Agent
38
+ * only sees Journey names + verdicts.
39
+ */
40
+ export declare function runDiffVerification(dependencies: CliDependencies, options: DiffVerificationOptions): Promise<void>;
41
+ export { CONFIG_PATH, writeFailure };