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