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
@@ -0,0 +1,382 @@
1
+ import { extname, resolve } from "node:path";
2
+ import { Command } from "commander";
3
+ import { z } from "zod";
4
+ import { JourneyCheckError, JourneyCheckService } from "../../application/journey/journey-check-service.js";
5
+ import { JourneyPromotionError, JourneyPromoter } from "../../application/journey/journey-promoter.js";
6
+ import { JourneyRetireError, JourneyRetirer } from "../../application/journey/journey-retirer.js";
7
+ import { JourneyCompositionError } from "../../application/journey/journey-resolver.js";
8
+ import { ContextLoadError } from "../../application/context/context-loader.js";
9
+ import { TapHoundConfigSchema } from "../../domain/config.js";
10
+ import { JourneyResolutionManifestSchema, ResolvedJourneyPathSchema } from "../../domain/journey-composition.js";
11
+ import { JourneySchema } from "../../domain/journey.js";
12
+ import { assertArtifactDirectory, CONFIG_PATH, CONTEXT_INDEX_PATH } from "../../domain/workspace.js";
13
+ import { contextLoadHint, errorMessage, writeJson, writeLine } from "../output.js";
14
+ import { prepareWorkspace } from "../workspace-guard.js";
15
+ import { canonicalProjectRoot } from "../project-root.js";
16
+ function manifestPath(outputPath) {
17
+ const extension = extname(outputPath);
18
+ return extension.toLowerCase() === ".json"
19
+ ? `${outputPath.slice(0, -extension.length)}.resolve.json`
20
+ : `${outputPath}.resolve.json`;
21
+ }
22
+ function serialize(value) {
23
+ return `${JSON.stringify(value, null, 2)}\n`;
24
+ }
25
+ function requireComposition(dependencies) {
26
+ if (dependencies.journeyResolver === undefined
27
+ || dependencies.journeyCompositionStore === undefined) {
28
+ throw new Error("Journey composition runtime is unavailable");
29
+ }
30
+ return {
31
+ resolver: dependencies.journeyResolver,
32
+ store: dependencies.journeyCompositionStore
33
+ };
34
+ }
35
+ function writeFailure(dependencies, options, error) {
36
+ const known = error instanceof JourneyCompositionError
37
+ || error instanceof JourneyCheckError
38
+ || error instanceof JourneyPromotionError
39
+ || error instanceof JourneyRetireError
40
+ || error instanceof ContextLoadError
41
+ || error instanceof z.ZodError;
42
+ const hint = error instanceof ContextLoadError
43
+ ? contextLoadHint(error)
44
+ : undefined;
45
+ const output = {
46
+ status: "error",
47
+ exitCode: known ? 2 : 4,
48
+ failure: {
49
+ code: error instanceof JourneyCompositionError
50
+ ? error.code
51
+ : error instanceof JourneyCheckError
52
+ ? error.code
53
+ : error instanceof JourneyPromotionError
54
+ ? error.code
55
+ : error instanceof JourneyRetireError
56
+ ? error.code
57
+ : error instanceof ContextLoadError
58
+ ? error.code
59
+ : error instanceof z.ZodError
60
+ ? "CONFIG_INVALID"
61
+ : "INTERNAL_ERROR",
62
+ message: errorMessage(error),
63
+ ...(hint === undefined ? {} : { hint })
64
+ }
65
+ };
66
+ if (options.json === true) {
67
+ writeJson(dependencies.stdout, output);
68
+ }
69
+ else {
70
+ writeLine(dependencies.stderr, output.failure.message);
71
+ }
72
+ dependencies.setExitCode(output.exitCode);
73
+ }
74
+ function lifecycleSummary(entries) {
75
+ const counts = {
76
+ draft: 0,
77
+ verified: 0,
78
+ promoted: 0,
79
+ suspect: 0,
80
+ stale: 0,
81
+ retired: 0
82
+ };
83
+ for (const entry of entries) {
84
+ if (entry.lifecycle !== undefined) {
85
+ counts[entry.lifecycle] += 1;
86
+ }
87
+ }
88
+ return counts;
89
+ }
90
+ function createResolveCommand(dependencies) {
91
+ return new Command("resolve")
92
+ .description("Resolve a composed Journey source into Journey v1")
93
+ .option("--project <path>", "Android project root", dependencies.cwd())
94
+ .requiredOption("--source <path>", "Project-relative Journey source path")
95
+ .requiredOption("--output <path>", "Project-relative Journey v1 output path")
96
+ .option("--json", "Emit one machine-readable JSON value")
97
+ .action(async (options) => {
98
+ try {
99
+ await prepareWorkspace(dependencies, options.project);
100
+ const composition = requireComposition(dependencies);
101
+ const resolution = await composition.resolver.resolve({
102
+ projectRoot: options.project,
103
+ sourcePath: options.source
104
+ });
105
+ const journey = JourneySchema.parse(resolution.journey);
106
+ const manifest = JourneyResolutionManifestSchema.parse(resolution.manifest);
107
+ const journeyPath = ResolvedJourneyPathSchema.parse(options.output);
108
+ const sidecarPath = manifestPath(journeyPath);
109
+ await composition.store.writeText({
110
+ projectRoot: options.project,
111
+ relativePath: journeyPath,
112
+ content: serialize(journey)
113
+ });
114
+ await composition.store.writeText({
115
+ projectRoot: options.project,
116
+ relativePath: sidecarPath,
117
+ content: serialize(manifest)
118
+ });
119
+ const output = {
120
+ status: "resolved",
121
+ exitCode: 0,
122
+ journeyPath,
123
+ manifestPath: sidecarPath,
124
+ journeySha256: manifest.journey.sha256,
125
+ resolutionSha256: manifest.resolutionSha256,
126
+ stepCount: journey.steps.length,
127
+ flows: manifest.expansion
128
+ };
129
+ if (options.json === true) {
130
+ writeJson(dependencies.stdout, output);
131
+ }
132
+ else {
133
+ writeLine(dependencies.stdout, `Resolved ${journey.name}: ${journeyPath}`);
134
+ }
135
+ dependencies.setExitCode(0);
136
+ }
137
+ catch (error) {
138
+ writeFailure(dependencies, options, error);
139
+ }
140
+ });
141
+ }
142
+ function createListFlowsCommand(dependencies) {
143
+ return new Command("list-flows")
144
+ .description("List and validate reusable local Flows")
145
+ .option("--project <path>", "Android project root", dependencies.cwd())
146
+ .option("--json", "Emit one machine-readable JSON value")
147
+ .option("--include-external", "Also list External Flows")
148
+ .action(async (options) => {
149
+ try {
150
+ await prepareWorkspace(dependencies, options.project);
151
+ const entries = await requireComposition(dependencies).resolver.listFlows(options.project);
152
+ const output = {
153
+ status: "listed",
154
+ exitCode: 0,
155
+ flows: entries
156
+ };
157
+ if (options.includeExternal === true) {
158
+ if (dependencies.externalFlowResolver === undefined) {
159
+ throw new Error("External Flow resolver is unavailable");
160
+ }
161
+ const externalEntries = await dependencies.externalFlowResolver.list(options.project);
162
+ output.externalFlows = [...externalEntries];
163
+ }
164
+ if (options.json === true) {
165
+ writeJson(dependencies.stdout, output);
166
+ }
167
+ else if (entries.length === 0
168
+ && output.externalFlows === undefined) {
169
+ writeLine(dependencies.stdout, "No reusable Flows found");
170
+ }
171
+ else {
172
+ const lines = entries.map((entry) => `${entry.name}: ${entry.status}`);
173
+ if (output.externalFlows !== undefined) {
174
+ if (output.externalFlows.length === 0) {
175
+ lines.push("No External Flows found");
176
+ }
177
+ else {
178
+ for (const entry of output.externalFlows) {
179
+ const external = entry;
180
+ lines.push(`${external.name}: ${external.status} (external, ${external.source})`);
181
+ }
182
+ }
183
+ }
184
+ writeLine(dependencies.stdout, lines.join("\n"));
185
+ }
186
+ dependencies.setExitCode(0);
187
+ }
188
+ catch (error) {
189
+ writeFailure(dependencies, options, error);
190
+ }
191
+ });
192
+ }
193
+ function checkEntryLine(entry) {
194
+ if (entry.reasons.length === 0) {
195
+ return `${entry.name}: ${entry.status}`;
196
+ }
197
+ const detail = entry.reasons.map((reason) => {
198
+ if (reason === "module-drift" || reason === "module-missing") {
199
+ const ids = entry.driftedModules
200
+ .filter((module) => (reason === "module-drift"
201
+ ? module.reason === "sha256"
202
+ : module.reason === "missing"))
203
+ .map((module) => module.id);
204
+ return `${reason}: ${ids.join(", ")}`;
205
+ }
206
+ return reason;
207
+ });
208
+ return `${entry.name}: ${entry.status} (${detail.join(", ")})`;
209
+ }
210
+ function createCheckCommand(dependencies) {
211
+ return new Command("check")
212
+ .description("Check committed Journeys against live project bindings")
213
+ .option("--project <path>", "Android project root", dependencies.cwd())
214
+ .option("--config <path>", "TapHound config path", CONFIG_PATH)
215
+ .option("--context <path>", "Project Context index path")
216
+ .option("--json", "Emit one machine-readable JSON value")
217
+ .option("--strict", "Exit non-zero when any Journey is not fresh")
218
+ .action(async (options) => {
219
+ try {
220
+ const projectRoot = await canonicalProjectRoot(dependencies.cwd(), options.project);
221
+ await prepareWorkspace(dependencies, projectRoot);
222
+ const composition = requireComposition(dependencies);
223
+ let config;
224
+ try {
225
+ config = TapHoundConfigSchema.parse(await dependencies.readJson(resolve(projectRoot, options.config)));
226
+ assertArtifactDirectory(projectRoot, config.artifactsDir);
227
+ }
228
+ catch (error) {
229
+ throw new JourneyCheckError("CONFIG_INVALID", error instanceof Error ? error.message : String(error), { cause: error });
230
+ }
231
+ const index = await dependencies.contextLoader.readIndex({
232
+ projectRoot,
233
+ contextPath: resolve(projectRoot, options.context ?? CONTEXT_INDEX_PATH)
234
+ });
235
+ const project = await dependencies.projectDescriber.describe({
236
+ projectRoot,
237
+ config,
238
+ ...(dependencies.signal === undefined
239
+ ? {}
240
+ : { signal: dependencies.signal })
241
+ });
242
+ const result = await new JourneyCheckService({
243
+ store: composition.store
244
+ }).check({
245
+ projectRoot,
246
+ config,
247
+ project,
248
+ bundle: index.bundle
249
+ });
250
+ const notFresh = result.summary.total - result.summary.fresh;
251
+ const exitCode = options.strict === true && notFresh > 0 ? 1 : 0;
252
+ const lifecycleCounts = lifecycleSummary(result.entries);
253
+ const output = {
254
+ status: "checked",
255
+ exitCode,
256
+ strict: options.strict === true,
257
+ summary: result.summary,
258
+ lifecycle: lifecycleCounts,
259
+ journeys: result.entries
260
+ };
261
+ if (options.json === true) {
262
+ writeJson(dependencies.stdout, output);
263
+ }
264
+ else if (result.entries.length === 0) {
265
+ writeLine(dependencies.stdout, "No Journeys found");
266
+ }
267
+ else {
268
+ const lines = result.entries.map(checkEntryLine);
269
+ for (const entry of result.entries) {
270
+ if (entry.status === "invalid" && entry.message !== undefined) {
271
+ lines.push(` ${entry.message}`);
272
+ }
273
+ }
274
+ lines.push(`Checked ${String(result.summary.total)} Journeys: `
275
+ + `${String(result.summary.fresh)} fresh, `
276
+ + `${String(result.summary.stale)} stale, `
277
+ + `${String(result.summary.noMeta)} no-meta, `
278
+ + `${String(result.summary.invalid)} invalid`);
279
+ lines.push(`Lifecycle: `
280
+ + Object.entries(lifecycleCounts)
281
+ .filter(([, count]) => count > 0)
282
+ .map(([state, count]) => `${state} ${String(count)}`)
283
+ .join(", "));
284
+ writeLine(dependencies.stdout, lines.join("\n"));
285
+ }
286
+ dependencies.setExitCode(exitCode);
287
+ }
288
+ catch (error) {
289
+ writeFailure(dependencies, options, error);
290
+ }
291
+ });
292
+ }
293
+ function createPromoteCommand(dependencies) {
294
+ return new Command("promote")
295
+ .description("Promote a replay-verified Journey into a durable asset")
296
+ .option("--project <path>", "Android project root", dependencies.cwd())
297
+ .requiredOption("--journey <path>", "Project-relative Journey path")
298
+ .requiredOption("--reason <text>", "Why this Journey is worth keeping")
299
+ .option("--json", "Emit one machine-readable JSON value")
300
+ .action(async (options) => {
301
+ try {
302
+ const projectRoot = options.project;
303
+ await prepareWorkspace(dependencies, projectRoot);
304
+ const composition = requireComposition(dependencies);
305
+ const result = await new JourneyPromoter({
306
+ store: composition.store
307
+ }).promote({
308
+ projectRoot,
309
+ journeyPath: options.journey,
310
+ reason: options.reason,
311
+ now: new Date()
312
+ });
313
+ const output = {
314
+ status: "promoted",
315
+ exitCode: 0,
316
+ journeyPath: result.journeyPath,
317
+ metaPath: result.metaPath,
318
+ generationId: result.generationId,
319
+ promotedAt: result.promotedAt
320
+ };
321
+ if (options.json === true) {
322
+ writeJson(dependencies.stdout, output);
323
+ }
324
+ else {
325
+ writeLine(dependencies.stdout, `Promoted ${result.journeyPath} (${result.generationId})`);
326
+ }
327
+ dependencies.setExitCode(0);
328
+ }
329
+ catch (error) {
330
+ writeFailure(dependencies, options, error);
331
+ }
332
+ });
333
+ }
334
+ function createRetireCommand(dependencies) {
335
+ return new Command("retire")
336
+ .description("Retire a Journey; its replay can no longer be trusted")
337
+ .option("--project <path>", "Android project root", dependencies.cwd())
338
+ .requiredOption("--journey <path>", "Project-relative Journey path")
339
+ .requiredOption("--reason <text>", "Why this Journey is retired")
340
+ .option("--json", "Emit one machine-readable JSON value")
341
+ .action(async (options) => {
342
+ try {
343
+ const projectRoot = options.project;
344
+ await prepareWorkspace(dependencies, projectRoot);
345
+ const composition = requireComposition(dependencies);
346
+ const result = await new JourneyRetirer({
347
+ store: composition.store
348
+ }).retire({
349
+ projectRoot,
350
+ journeyPath: options.journey,
351
+ reason: options.reason,
352
+ now: new Date()
353
+ });
354
+ const output = {
355
+ status: "retired",
356
+ exitCode: 0,
357
+ journeyPath: result.journeyPath,
358
+ metaPath: result.metaPath,
359
+ retiredAt: result.retiredAt
360
+ };
361
+ if (options.json === true) {
362
+ writeJson(dependencies.stdout, output);
363
+ }
364
+ else {
365
+ writeLine(dependencies.stdout, `Retired ${result.journeyPath}`);
366
+ }
367
+ dependencies.setExitCode(0);
368
+ }
369
+ catch (error) {
370
+ writeFailure(dependencies, options, error);
371
+ }
372
+ });
373
+ }
374
+ export function createJourneyCommand(dependencies) {
375
+ return new Command("journey")
376
+ .description("Compose reusable Flows into runnable Journeys")
377
+ .addCommand(createResolveCommand(dependencies))
378
+ .addCommand(createListFlowsCommand(dependencies))
379
+ .addCommand(createCheckCommand(dependencies))
380
+ .addCommand(createPromoteCommand(dependencies))
381
+ .addCommand(createRetireCommand(dependencies));
382
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ import type { CliDependencies } from "../dependencies.js";
3
+ export declare function createKnowledgeCommand(dependencies: CliDependencies): Command;
@@ -0,0 +1,93 @@
1
+ import { resolve } from "node:path";
2
+ import { Command } from "commander";
3
+ import { TapHoundConfigSchema } from "../../domain/config.js";
4
+ import { CONFIG_PATH } from "../../domain/workspace.js";
5
+ import { errorMessage, writeJson, writeLine } from "../output.js";
6
+ function requireKnowledge(dependencies) {
7
+ if (dependencies.knowledge === undefined) {
8
+ throw new Error("Knowledge services are unavailable");
9
+ }
10
+ return dependencies.knowledge;
11
+ }
12
+ function failure(dependencies, options, error) {
13
+ const output = {
14
+ status: "failed",
15
+ exitCode: 2,
16
+ code: "KNOWLEDGE_INVALID",
17
+ message: errorMessage(error)
18
+ };
19
+ if (options.json === true) {
20
+ writeJson(dependencies.stdout, output);
21
+ }
22
+ else {
23
+ writeLine(dependencies.stderr, `${output.code}: ${output.message}`);
24
+ }
25
+ dependencies.setExitCode(2);
26
+ }
27
+ function statusCommand(dependencies) {
28
+ return new Command("status")
29
+ .description("Validate and hash the committed Knowledge Registry")
30
+ .option("--project <path>", "Android project root", dependencies.cwd())
31
+ .option("--json", "Emit one machine-readable JSON value")
32
+ .action(async (options) => {
33
+ try {
34
+ const bundle = await requireKnowledge(dependencies).load({
35
+ projectRoot: options.project
36
+ });
37
+ const output = {
38
+ status: "valid",
39
+ exitCode: 0,
40
+ knowledgeHash: bundle.knowledgeHash,
41
+ revision: bundle.index.revision,
42
+ packageName: bundle.index.packageName,
43
+ counts: {
44
+ anchors: bundle.anchors.length,
45
+ screens: bundle.screens.length
46
+ }
47
+ };
48
+ if (options.json === true)
49
+ writeJson(dependencies.stdout, output);
50
+ else
51
+ writeLine(dependencies.stdout, `Knowledge ${bundle.knowledgeHash} (${String(bundle.anchors.length)} Anchors, ${String(bundle.screens.length)} Screens)`);
52
+ dependencies.setExitCode(0);
53
+ }
54
+ catch (error) {
55
+ failure(dependencies, options, error);
56
+ }
57
+ });
58
+ }
59
+ function rehashCommand(dependencies) {
60
+ return new Command("rehash")
61
+ .description("Rebuild the Knowledge index from committed Anchor and Screen documents")
62
+ .option("--project <path>", "Android project root", dependencies.cwd())
63
+ .option("--config <path>", "TapHound config path", CONFIG_PATH)
64
+ .option("--json", "Emit one machine-readable JSON value")
65
+ .action(async (options) => {
66
+ try {
67
+ const config = TapHoundConfigSchema.parse(await dependencies.readJson(resolve(options.project, options.config)));
68
+ const result = await requireKnowledge(dependencies).rehash({
69
+ projectRoot: options.project,
70
+ packageName: config.run.packageName
71
+ });
72
+ const output = {
73
+ status: result.changed ? "rehashed" : "unchanged",
74
+ exitCode: 0,
75
+ ...result
76
+ };
77
+ if (options.json === true)
78
+ writeJson(dependencies.stdout, output);
79
+ else
80
+ writeLine(dependencies.stdout, `Knowledge ${output.status} at revision ${String(result.revision)} (${String(result.anchors)} Anchors, ${String(result.screens)} Screens)`);
81
+ dependencies.setExitCode(0);
82
+ }
83
+ catch (error) {
84
+ failure(dependencies, options, error);
85
+ }
86
+ });
87
+ }
88
+ export function createKnowledgeCommand(dependencies) {
89
+ return new Command("knowledge")
90
+ .description("Validate and index committed semantic Anchors and Screens")
91
+ .addCommand(statusCommand(dependencies))
92
+ .addCommand(rehashCommand(dependencies));
93
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ import type { CliDependencies } from "../dependencies.js";
3
+ export declare function createObserveCommand(dependencies: CliDependencies): Command;
@@ -0,0 +1,127 @@
1
+ import { resolve } from "node:path";
2
+ import { Command } from "commander";
3
+ import { TapHoundConfigSchema } from "../../domain/config.js";
4
+ import { CONFIG_PATH } from "../../domain/workspace.js";
5
+ import { exitCodeForFailure, failureCodeFromUnknown } from "../../domain/failure.js";
6
+ import { errorMessage, failureOutput, writeJson, writeLine } from "../output.js";
7
+ function summarize(report) {
8
+ const logcatLine = report.logcat === undefined
9
+ ? "logcat: omitted"
10
+ : `logcat: ${String(report.logcat.length)} line(s)`;
11
+ return [
12
+ `TapHound observe: ${report.packageName} on ${report.deviceSerial}`,
13
+ `activity: ${report.activity ?? "(unavailable)"}`,
14
+ `foreground: ${report.foreground.packageName}/${report.foreground.activity}`,
15
+ `ui backend: ${report.uiBackend.id}`,
16
+ `ui capture: ${String(report.uiCaptureDurationMs)}ms`,
17
+ ...(report.uiCache === undefined
18
+ ? []
19
+ : [`ui cache: ${String(report.uiCache.hits)} hit(s), ${String(report.uiCache.misses)} miss(es), ${String(report.uiCache.capturesSaved)} capture(s) saved`]),
20
+ `layout: ${String(report.layout.length)} element(s)`,
21
+ logcatLine
22
+ ].join("\n");
23
+ }
24
+ export function createObserveCommand(dependencies) {
25
+ return new Command("observe")
26
+ .description("Capture a point-in-time device snapshot for the configured package")
27
+ .option("--project <path>", "Android project root", dependencies.cwd())
28
+ .option("--config <path>", "TapHound config path", CONFIG_PATH)
29
+ .option("--device <serial>", "Select an online Android device")
30
+ .option("--logcat-lines <n>", "Dump the last N logcat lines into the report", (value) => Number.parseInt(value, 10))
31
+ .option("--json", "Emit one machine-readable JSON value")
32
+ .action(async (options) => {
33
+ if (options.logcatLines !== undefined
34
+ && (!Number.isFinite(options.logcatLines) || options.logcatLines < 0
35
+ || !Number.isInteger(options.logcatLines))) {
36
+ const output = failureOutput(2, "CONFIG_INVALID", "--logcat-lines must be a non-negative integer");
37
+ if (options.json === true) {
38
+ writeJson(dependencies.stdout, output);
39
+ }
40
+ else {
41
+ writeLine(dependencies.stderr, output.failure.message);
42
+ }
43
+ dependencies.setExitCode(2);
44
+ return;
45
+ }
46
+ let config;
47
+ try {
48
+ const rawConfig = await dependencies.readJson(resolve(options.project, options.config));
49
+ config = TapHoundConfigSchema.parse(rawConfig);
50
+ }
51
+ catch (error) {
52
+ const output = failureOutput(2, "CONFIG_INVALID", errorMessage(error));
53
+ if (options.json === true) {
54
+ writeJson(dependencies.stdout, output);
55
+ }
56
+ else {
57
+ writeLine(dependencies.stderr, output.failure.message);
58
+ }
59
+ dependencies.setExitCode(2);
60
+ return;
61
+ }
62
+ try {
63
+ const doctor = await dependencies.doctor.run({
64
+ packageName: config.run.packageName,
65
+ ...(config.ui?.backend === undefined
66
+ ? {}
67
+ : { requestedUiBackend: config.ui.backend }),
68
+ ...(options.device === undefined
69
+ ? {}
70
+ : { requestedDevice: options.device }),
71
+ ...(dependencies.signal === undefined
72
+ ? {}
73
+ : { signal: dependencies.signal })
74
+ });
75
+ if (doctor.status === "failed") {
76
+ const output = failureOutput(3, doctor.failureCode ?? "ENVIRONMENT_MISSING_TOOL", doctor.checks.find((check) => check.status === "failed")?.message
77
+ ?? "TapHound environment preflight failed");
78
+ if (options.json === true) {
79
+ writeJson(dependencies.stdout, output);
80
+ }
81
+ else {
82
+ writeLine(dependencies.stderr, output.failure.message);
83
+ }
84
+ dependencies.setExitCode(3);
85
+ return;
86
+ }
87
+ const deviceSerial = options.device ?? doctor.deviceSerial;
88
+ if (deviceSerial === undefined) {
89
+ throw new Error("Doctor did not select a device");
90
+ }
91
+ const observer = dependencies.observer(config.ui?.snapshotTimeoutMs ?? config.idle.timeoutMs, config.ui?.backend ?? "auto", config.ui?.cacheEnabled ?? true);
92
+ const report = await observer.observe({
93
+ packageName: config.run.packageName,
94
+ deviceSerial,
95
+ ...(options.logcatLines === undefined
96
+ ? {}
97
+ : { logcatLines: options.logcatLines }),
98
+ ...(dependencies.signal === undefined
99
+ ? {}
100
+ : { signal: dependencies.signal })
101
+ });
102
+ if (options.json === true) {
103
+ writeJson(dependencies.stdout, {
104
+ status: "observed",
105
+ exitCode: 0,
106
+ report
107
+ });
108
+ }
109
+ else {
110
+ writeLine(dependencies.stdout, summarize(report));
111
+ }
112
+ dependencies.setExitCode(0);
113
+ }
114
+ catch (error) {
115
+ const code = failureCodeFromUnknown(error) ?? "INTERNAL_ERROR";
116
+ const exitCode = exitCodeForFailure(code);
117
+ const output = failureOutput(exitCode, code, errorMessage(error));
118
+ if (options.json === true) {
119
+ writeJson(dependencies.stdout, output);
120
+ }
121
+ else {
122
+ writeLine(dependencies.stderr, output.failure.message);
123
+ }
124
+ dependencies.setExitCode(exitCode);
125
+ }
126
+ });
127
+ }
@@ -1,6 +1,7 @@
1
1
  import { resolve } from "node:path";
2
2
  import { Command } from "commander";
3
3
  import { TapHoundConfigSchema } from "../../domain/config.js";
4
+ import { CONFIG_PATH } from "../../domain/workspace.js";
4
5
  import { errorMessage, failureOutput, writeJson, writeLine } from "../output.js";
5
6
  function writeFailure(dependencies, options, exitCode, error) {
6
7
  const output = failureOutput(exitCode, exitCode === 2 ? "CONFIG_INVALID" : "INTERNAL_ERROR", errorMessage(error));
@@ -16,7 +17,7 @@ export function createProjectCommand(dependencies) {
16
17
  const describe = new Command("describe")
17
18
  .description("Describe stable Android project facts")
18
19
  .option("--project <path>", "Android project root", dependencies.cwd())
19
- .option("--config <path>", "TapHound config path", "taphound.config.json")
20
+ .option("--config <path>", "TapHound config path", CONFIG_PATH)
20
21
  .option("--json", "Emit one machine-readable JSON value")
21
22
  .action(async (options) => {
22
23
  let config;