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,20 +1,112 @@
1
+ import { resolveIdlePolicy } from "./idle-profiles.js";
2
+ const EARLY_BAIL_FRAME_CHANGES = 2;
3
+ const POST_FALLBACK_MIN_STABLE = 2;
4
+ /**
5
+ * Once frame stats showed no rendering for `stablePolls` polls, the
6
+ * structural phase only has to confirm the hierarchy did not change between
7
+ * two captures taken during this wait: one empty diff after at least two
8
+ * structural samples. Each capture costs a full hierarchy dump.
9
+ */
10
+ const POST_FRAME_STABLE_CONFIRMATIONS = 1;
11
+ const POST_FRAME_STABLE_MIN_SAMPLES = 2;
12
+ function isEditableWidgetChange(change) {
13
+ if (typeof change !== "object" || change === null) {
14
+ return false;
15
+ }
16
+ const record = change;
17
+ const interactions = record.interactions;
18
+ if (Array.isArray(interactions) && interactions.includes("EDITABLE")) {
19
+ return true;
20
+ }
21
+ const cls = record.class;
22
+ return typeof cls === "string" && cls.endsWith("EditText");
23
+ }
24
+ function meaningfulChanges(changes, ignoreCursorBlink) {
25
+ if (!ignoreCursorBlink) {
26
+ return changes;
27
+ }
28
+ return changes.filter((change) => !isEditableWidgetChange(change));
29
+ }
30
+ const EMPTY_SEMANTIC_KEY = "||";
31
+ function semanticKeys(change) {
32
+ if (typeof change !== "object" || change === null) {
33
+ return JSON.stringify(change);
34
+ }
35
+ const record = change;
36
+ const cls = typeof record.class === "string" ? record.class : "";
37
+ const resourceId = typeof record["resource-id"] === "string"
38
+ ? record["resource-id"]
39
+ : "";
40
+ const text = typeof record.text === "string" ? record.text : "";
41
+ return `${cls}|${resourceId}|${text}`;
42
+ }
43
+ /**
44
+ * A structural sample from an opaque backend is one `{layoutSha256}` change
45
+ * that names no element, so every such change collapses to the same empty
46
+ * key. Suppressing a repeated empty key set would report a screen that keeps
47
+ * changing as idle, so drift suppression only applies to identified changes.
48
+ */
49
+ function identifiesElements(keys) {
50
+ return keys.every((key) => key !== EMPTY_SEMANTIC_KEY);
51
+ }
52
+ function sameKeySet(left, right) {
53
+ if (left.length !== right.length)
54
+ return false;
55
+ const sortedLeft = [...left].sort();
56
+ const sortedRight = [...right].sort();
57
+ return sortedLeft.every((key, index) => key === sortedRight[index]);
58
+ }
1
59
  function isAborted(signal) {
2
60
  return signal?.aborted === true;
3
61
  }
62
+ function normalizeObservation(result) {
63
+ return Array.isArray(result)
64
+ ? { changes: result }
65
+ : result;
66
+ }
67
+ function telemetry(strategy, backend, fallbackUsed, frameActivityDetected, samplingDurationMs) {
68
+ return {
69
+ strategy,
70
+ ...(backend === undefined ? {} : { backend }),
71
+ fallbackUsed,
72
+ frameActivityDetected,
73
+ samplingDurationMs
74
+ };
75
+ }
4
76
  export class IdleWaiter {
5
- androidCli;
77
+ stability;
6
78
  clock;
7
79
  deviceSerial;
8
- constructor(androidCli, clock, deviceSerial) {
9
- this.androidCli = androidCli;
80
+ packageName;
81
+ resolveDeviceIdentity;
82
+ transientKeys;
83
+ constructor(stability, clock, deviceSerial, packageName, resolveDeviceIdentity) {
84
+ this.stability = stability;
10
85
  this.clock = clock;
11
86
  this.deviceSerial = deviceSerial;
87
+ this.packageName = packageName;
88
+ this.resolveDeviceIdentity = resolveDeviceIdentity;
12
89
  }
13
- async waitUntilIdle(config, signal) {
90
+ async waitUntilIdle(input, signal) {
91
+ this.stability.reset();
92
+ this.transientKeys = undefined;
93
+ const config = await this.effectiveConfig(input);
94
+ const strategy = config.strategy ?? "hybrid";
14
95
  const startedAt = this.clock.now();
15
96
  let polls = 0;
16
97
  let consecutiveEmpty = 0;
98
+ let consecutiveFrameChanges = 0;
17
99
  let lastDiff = [];
100
+ let lastLayout;
101
+ let backend;
102
+ let fallbackUsed = false;
103
+ let frameStable = false;
104
+ let structuralSamples = 0;
105
+ let frameActivityDetected = false;
106
+ let samplingDurationMs = 0;
107
+ let useStructuralBackend = strategy === "layoutDiff"
108
+ || strategy === "structural"
109
+ || (strategy === "hybrid" && this.packageName === undefined);
18
110
  for (;;) {
19
111
  if (isAborted(signal)) {
20
112
  return {
@@ -25,13 +117,21 @@ export class IdleWaiter {
25
117
  }
26
118
  const elapsedBeforePoll = this.clock.now() - startedAt;
27
119
  polls += 1;
28
- let diff;
120
+ let observation;
29
121
  try {
30
- diff = await this.androidCli.layoutDiff({
122
+ observation = normalizeObservation(await this.stability.sample({
31
123
  deviceSerial: this.deviceSerial,
124
+ ...(useStructuralBackend
125
+ ? { stabilityBackend: "uiautomator" }
126
+ : this.packageName === undefined
127
+ ? {}
128
+ : {
129
+ packageName: this.packageName,
130
+ stabilityBackend: "frameStats"
131
+ }),
32
132
  ...(signal === undefined ? {} : { signal }),
33
133
  timeoutMs: Math.max(1, config.timeoutMs - elapsedBeforePoll)
34
- });
134
+ }));
35
135
  }
36
136
  catch (error) {
37
137
  const elapsed = this.clock.now() - startedAt;
@@ -44,36 +144,110 @@ export class IdleWaiter {
44
144
  code: "IDLE_TIMEOUT",
45
145
  polls,
46
146
  durationMs: elapsed,
47
- lastDiff
147
+ lastDiff,
148
+ ...telemetry(strategy, backend, fallbackUsed, frameActivityDetected, samplingDurationMs)
48
149
  };
49
150
  }
50
151
  throw error;
51
152
  }
52
- if (diff.length === 0) {
153
+ const diff = observation.changes;
154
+ samplingDurationMs += observation.durationMs ?? 0;
155
+ lastLayout = observation.layout ?? lastLayout;
156
+ backend = observation.backend ?? backend;
157
+ if (observation.backend === "gfxFrameStats" && diff.length > 0) {
158
+ frameActivityDetected = true;
159
+ consecutiveFrameChanges += 1;
160
+ }
161
+ else {
162
+ consecutiveFrameChanges = 0;
163
+ }
164
+ if (strategy === "hybrid"
165
+ && !useStructuralBackend
166
+ && consecutiveFrameChanges >= EARLY_BAIL_FRAME_CHANGES) {
167
+ useStructuralBackend = true;
168
+ fallbackUsed = true;
169
+ consecutiveEmpty = 0;
170
+ }
171
+ else if (useStructuralBackend) {
172
+ structuralSamples += 1;
173
+ let visibleChanges = meaningfulChanges(diff, config.ignoreCursorBlink === true);
174
+ if (config.ignoreLayoutDrift === true && visibleChanges.length > 0) {
175
+ const keys = visibleChanges.map(semanticKeys);
176
+ const identified = identifiesElements(keys);
177
+ if (identified
178
+ && this.transientKeys !== undefined
179
+ && sameKeySet(this.transientKeys, keys)) {
180
+ visibleChanges = [];
181
+ }
182
+ else {
183
+ this.transientKeys = identified ? keys : undefined;
184
+ }
185
+ }
186
+ else if (config.ignoreLayoutDrift === true) {
187
+ this.transientKeys = undefined;
188
+ }
189
+ consecutiveEmpty = visibleChanges.length === 0
190
+ ? consecutiveEmpty + 1
191
+ : 0;
192
+ if (visibleChanges.length > 0)
193
+ lastDiff = visibleChanges;
194
+ }
195
+ else if (diff.length === 0) {
53
196
  consecutiveEmpty += 1;
54
197
  }
55
198
  else {
56
199
  consecutiveEmpty = 0;
57
200
  lastDiff = diff;
58
201
  }
59
- if (consecutiveEmpty >= config.stablePolls) {
202
+ const isPostFallback = fallbackUsed && strategy === "hybrid";
203
+ const requiredStableObservations = useStructuralBackend
204
+ ? (frameStable
205
+ ? POST_FRAME_STABLE_CONFIRMATIONS
206
+ : isPostFallback
207
+ ? Math.max(POST_FALLBACK_MIN_STABLE, config.stablePolls - 1)
208
+ : Math.max(2, config.stablePolls))
209
+ : config.stablePolls;
210
+ if (consecutiveEmpty >= requiredStableObservations
211
+ && (!frameStable || structuralSamples >= POST_FRAME_STABLE_MIN_SAMPLES)) {
212
+ if (strategy === "hybrid" && !useStructuralBackend) {
213
+ useStructuralBackend = true;
214
+ frameStable = true;
215
+ consecutiveEmpty = 0;
216
+ }
217
+ else {
218
+ return {
219
+ status: "stable",
220
+ polls,
221
+ durationMs: this.clock.now() - startedAt,
222
+ ...(lastLayout === undefined ? {} : { layout: lastLayout }),
223
+ ...telemetry(strategy, backend, fallbackUsed, frameActivityDetected, samplingDurationMs)
224
+ };
225
+ }
226
+ }
227
+ if (this.clock.now() - startedAt >= config.timeoutMs) {
60
228
  return {
61
- status: "stable",
229
+ status: "timeout",
230
+ code: "IDLE_TIMEOUT",
62
231
  polls,
63
- durationMs: this.clock.now() - startedAt
232
+ durationMs: this.clock.now() - startedAt,
233
+ lastDiff,
234
+ ...telemetry(strategy, backend, fallbackUsed, frameActivityDetected, samplingDurationMs)
64
235
  };
65
236
  }
66
- if (this.clock.now() - startedAt >= config.timeoutMs) {
237
+ const remainingMs = config.timeoutMs
238
+ - (this.clock.now() - startedAt);
239
+ if (remainingMs <= 0) {
67
240
  return {
68
241
  status: "timeout",
69
242
  code: "IDLE_TIMEOUT",
70
243
  polls,
71
244
  durationMs: this.clock.now() - startedAt,
72
- lastDiff
245
+ lastDiff,
246
+ ...telemetry(strategy, backend, fallbackUsed, frameActivityDetected, samplingDurationMs)
73
247
  };
74
248
  }
75
249
  try {
76
- await this.clock.sleep(config.pollIntervalMs, signal);
250
+ await this.clock.sleep(Math.min(config.pollIntervalMs, remainingMs), signal);
77
251
  }
78
252
  catch (error) {
79
253
  if (isAborted(signal)) {
@@ -87,4 +261,16 @@ export class IdleWaiter {
87
261
  }
88
262
  }
89
263
  }
264
+ async effectiveConfig(input) {
265
+ if (this.resolveDeviceIdentity === undefined
266
+ || input.deviceProfiles === undefined
267
+ || input.deviceProfiles.length === 0) {
268
+ return input;
269
+ }
270
+ const identity = await this.resolveDeviceIdentity();
271
+ if (identity === undefined) {
272
+ return input;
273
+ }
274
+ return resolveIdlePolicy(input, identity);
275
+ }
90
276
  }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ import type { CliDependencies } from "../dependencies.js";
3
+ export declare function createAlignCommand(dependencies: CliDependencies): Command;
@@ -0,0 +1,124 @@
1
+ import { resolve } from "node:path";
2
+ import { Command } from "commander";
3
+ import { TapHoundConfigSchema } from "../../domain/config.js";
4
+ import { assertArtifactDirectory, CONFIG_PATH } from "../../domain/workspace.js";
5
+ import { exitCodeForFailure, failureCodeFromUnknown } from "../../domain/failure.js";
6
+ import { AlignError } from "../../application/align/align-service.js";
7
+ import { AlignPromptCancelledError } from "../../ports/align-prompt.js";
8
+ import { errorMessage, failureOutput, writeJson, writeLine } from "../output.js";
9
+ import { prepareWorkspace } from "../workspace-guard.js";
10
+ function alignCameraText(result) {
11
+ if (result.status === "cancelled") {
12
+ return "Cancelled — no flow written.";
13
+ }
14
+ const { flow, probe } = result;
15
+ const confirmLine = probe.confirmResourceId !== undefined
16
+ ? ` Confirm button: ${probe.confirmResourceId}`
17
+ : " Confirm button: (none — camera auto-accepts)";
18
+ const reviewActivityLine = probe.confirmActivityName === undefined
19
+ ? []
20
+ : [` Review activity: ${probe.confirmActivityName}`];
21
+ return [
22
+ "Probing camera...",
23
+ ` Camera package: ${probe.packageName}`,
24
+ ` Camera activity: ${probe.activityName}`,
25
+ ...reviewActivityLine,
26
+ ` Shutter button: ${probe.shutterResourceId}`,
27
+ confirmLine,
28
+ "",
29
+ `Wrote ${flow.name} flow (${String(flow.steps)} steps)`,
30
+ ` Path: ${flow.path}`
31
+ ].join("\n");
32
+ }
33
+ export function createAlignCommand(dependencies) {
34
+ const align = new Command("align")
35
+ .description("Align device-specific External Flows");
36
+ align
37
+ .command("camera")
38
+ .description("Probe the device camera and write a project External Flow")
39
+ .option("--project <path>", "Android project root", dependencies.cwd())
40
+ .option("--config <path>", "TapHound config path", CONFIG_PATH)
41
+ .option("--device <serial>", "Select an online Android device")
42
+ .option("--force", "Overwrite an existing project flow")
43
+ .option("--json", "Emit machine-readable JSON")
44
+ .action(async (options) => {
45
+ try {
46
+ try {
47
+ const config = await TapHoundConfigSchema.parseAsync(await dependencies.readJson(resolve(options.project, options.config)));
48
+ assertArtifactDirectory(options.project, config.artifactsDir);
49
+ await prepareWorkspace(dependencies, options.project);
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
+ const result = await dependencies.align.alignCamera({
63
+ projectRoot: options.project,
64
+ ...(options.device === undefined ? {} : { deviceSerial: options.device }),
65
+ ...(options.force === undefined ? {} : { force: options.force }),
66
+ json: options.json === true,
67
+ ...(dependencies.signal === undefined ? {} : { signal: dependencies.signal })
68
+ });
69
+ if (options.json === true) {
70
+ writeJson(dependencies.stdout, result);
71
+ }
72
+ else {
73
+ writeLine(dependencies.stdout, alignCameraText(result));
74
+ }
75
+ dependencies.setExitCode(result.exitCode);
76
+ }
77
+ catch (error) {
78
+ if (error instanceof AlignPromptCancelledError) {
79
+ const cancelled = { status: "cancelled", exitCode: 2 };
80
+ if (options.json === true) {
81
+ writeJson(dependencies.stdout, cancelled);
82
+ }
83
+ else {
84
+ writeLine(dependencies.stdout, alignCameraText(cancelled));
85
+ }
86
+ dependencies.setExitCode(2);
87
+ return;
88
+ }
89
+ if (error instanceof AlignError) {
90
+ const output = failureOutput(2, error.code, error.message);
91
+ if (options.json === true) {
92
+ writeJson(dependencies.stdout, output);
93
+ }
94
+ else {
95
+ writeLine(dependencies.stderr, output.failure.message);
96
+ }
97
+ dependencies.setExitCode(2);
98
+ return;
99
+ }
100
+ const failureCode = failureCodeFromUnknown(error);
101
+ if (failureCode !== undefined) {
102
+ const exitCode = exitCodeForFailure(failureCode);
103
+ const output = failureOutput(exitCode, failureCode, errorMessage(error));
104
+ if (options.json === true) {
105
+ writeJson(dependencies.stdout, output);
106
+ }
107
+ else {
108
+ writeLine(dependencies.stderr, output.failure.message);
109
+ }
110
+ dependencies.setExitCode(exitCode);
111
+ return;
112
+ }
113
+ const output = failureOutput(4, "INTERNAL_ERROR", errorMessage(error));
114
+ if (options.json === true) {
115
+ writeJson(dependencies.stdout, output);
116
+ }
117
+ else {
118
+ writeLine(dependencies.stderr, output.failure.message);
119
+ }
120
+ dependencies.setExitCode(4);
121
+ }
122
+ });
123
+ return align;
124
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ import type { CliDependencies } from "../dependencies.js";
3
+ export declare function createBaselineCommand(dependencies: CliDependencies): Command;
@@ -0,0 +1,130 @@
1
+ import { Command } from "commander";
2
+ import { exitCodeForFailure, failureCodeFromUnknown } from "../../domain/failure.js";
3
+ import { BASELINES_DIR, BUILD_DIR, assertProjectPathUnder } from "../../domain/workspace.js";
4
+ import { failureOutput, writeJson, writeLine } from "../output.js";
5
+ import { prepareWorkspace } from "../workspace-guard.js";
6
+ function writeFailure(dependencies, json, code, message) {
7
+ const exitCode = exitCodeForFailure(code);
8
+ const output = failureOutput(exitCode, code, message);
9
+ if (json) {
10
+ writeJson(dependencies.stdout, output);
11
+ }
12
+ else {
13
+ writeLine(dependencies.stderr, output.failure.message);
14
+ }
15
+ dependencies.setExitCode(exitCode);
16
+ }
17
+ export function createBaselineCommand(dependencies) {
18
+ const command = new Command("baseline")
19
+ .description("Capture and compare behavior Baselines against Verification reports")
20
+ .addCommand(createCaptureCommand(dependencies))
21
+ .addCommand(createCompareCommand(dependencies));
22
+ return command;
23
+ }
24
+ function createCaptureCommand(dependencies) {
25
+ return new Command("capture")
26
+ .description("Capture a Baseline from a passing Verification report (offline)")
27
+ .option("--project <path>", "Android project root", dependencies.cwd())
28
+ .requiredOption("--report <path>", "Verification report.json path")
29
+ .option("--id <name>", "Baseline id (defaults to the report runId)")
30
+ .option("--journey-sha256 <sha256>", "Assert the source report's Journey sha256")
31
+ .option("--contract-sha256 <sha256>", "Assert the passing Verdict's Contract sha256")
32
+ .option("--verdict <path>", "Passing Contract verdict.json for the source report")
33
+ .option("--no-screen-facts", "Exclude Screen facts from this Baseline")
34
+ .requiredOption("--out <path>", "Baseline output under .taphound/baselines")
35
+ .option("--json", "Emit one machine-readable JSON value")
36
+ .action(async (options) => {
37
+ const json = options.json === true;
38
+ if (dependencies.baselineService === undefined) {
39
+ writeFailure(dependencies, json, "CONFIG_INVALID", "TapHound baseline capture is not configured");
40
+ return;
41
+ }
42
+ try {
43
+ await prepareWorkspace(dependencies, options.project);
44
+ }
45
+ catch (error) {
46
+ writeFailure(dependencies, json, failureCodeFromUnknown(error) ?? "CONFIG_INVALID", error instanceof Error ? error.message : String(error));
47
+ return;
48
+ }
49
+ try {
50
+ const reportPath = assertProjectPathUnder(options.project, options.report, BUILD_DIR, "Verification report");
51
+ const verdictPath = options.verdict === undefined
52
+ ? undefined
53
+ : assertProjectPathUnder(options.project, options.verdict, BUILD_DIR, "Contract verdict");
54
+ const outputPath = assertProjectPathUnder(options.project, options.out, BASELINES_DIR, "Baseline output");
55
+ const baseline = await dependencies.baselineService.captureFromReport(reportPath, {
56
+ id: options.id,
57
+ journeySha256: options.journeySha256,
58
+ contractSha256: options.contractSha256,
59
+ ...(verdictPath === undefined ? {} : { verdictPath }),
60
+ includeScreenFacts: options.screenFacts
61
+ });
62
+ await dependencies.baselineService.write({
63
+ path: outputPath,
64
+ baseline
65
+ });
66
+ if (json) {
67
+ writeJson(dependencies.stdout, baseline);
68
+ }
69
+ else {
70
+ writeLine(dependencies.stdout, `Baseline ${baseline.id} captured (${String(baseline.activities.length)} activity facts, ${String(baseline.elements.length)} element facts, ${String(baseline.checkpoints?.length ?? 0)} Checkpoint facts)`);
71
+ }
72
+ dependencies.setExitCode(0);
73
+ }
74
+ catch (error) {
75
+ writeFailure(dependencies, json, failureCodeFromUnknown(error) ?? "CONFIG_INVALID", error instanceof Error ? error.message : String(error));
76
+ }
77
+ });
78
+ }
79
+ function createCompareCommand(dependencies) {
80
+ return new Command("compare")
81
+ .description("Compare a Verification report against a stored Baseline")
82
+ .option("--project <path>", "Android project root", dependencies.cwd())
83
+ .requiredOption("--baseline <path>", "Baseline JSON path")
84
+ .requiredOption("--report <path>", "Verification report.json path")
85
+ .option("--journey-sha256 <sha256>", "Assert the current report's Journey sha256")
86
+ .option("--verdict <path>", "Contract verdict.json for this report (defaults beside report.json)")
87
+ .option("--json", "Emit one machine-readable JSON value")
88
+ .action(async (options) => {
89
+ const json = options.json === true;
90
+ if (dependencies.baselineService === undefined) {
91
+ writeFailure(dependencies, json, "CONFIG_INVALID", "TapHound regression comparison is not configured");
92
+ return;
93
+ }
94
+ try {
95
+ await prepareWorkspace(dependencies, options.project);
96
+ }
97
+ catch (error) {
98
+ writeFailure(dependencies, json, failureCodeFromUnknown(error) ?? "CONFIG_INVALID", error instanceof Error ? error.message : String(error));
99
+ return;
100
+ }
101
+ try {
102
+ const baselinePath = assertProjectPathUnder(options.project, options.baseline, BASELINES_DIR, "Baseline");
103
+ const reportPath = assertProjectPathUnder(options.project, options.report, BUILD_DIR, "Verification report");
104
+ const verdictPath = options.verdict === undefined
105
+ ? undefined
106
+ : assertProjectPathUnder(options.project, options.verdict, BUILD_DIR, "Contract verdict");
107
+ const result = await dependencies.baselineService.compare({
108
+ baselinePath,
109
+ reportPath,
110
+ journeySha256: options.journeySha256,
111
+ ...(verdictPath === undefined ? {} : { verdictPath })
112
+ });
113
+ if (json) {
114
+ writeJson(dependencies.stdout, result);
115
+ }
116
+ else {
117
+ writeLine(dependencies.stdout, result.equivalent
118
+ ? `Regression compare: equivalent (${String(result.regressions.length)} diffs)`
119
+ : `Regression compare: ${String(result.regressions.length)} diff(s)`);
120
+ for (const diff of result.regressions) {
121
+ writeLine(dependencies.stdout, `- ${diff.kind}${diff.checkpointId === undefined ? "" : ` checkpoint=${diff.checkpointId}`}${diff.stepIndex === undefined ? "" : ` step=${String(diff.stepIndex)}`}: expected ${diff.expected}, actual ${diff.actual}`);
122
+ }
123
+ }
124
+ dependencies.setExitCode(result.equivalent ? 0 : 1);
125
+ }
126
+ catch (error) {
127
+ writeFailure(dependencies, json, failureCodeFromUnknown(error) ?? "CONFIG_INVALID", error instanceof Error ? error.message : String(error));
128
+ }
129
+ });
130
+ }