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,472 @@
1
+ // `generation` subcommands that create, observe, inspect, list, archive, and configure sessions.
2
+ import { resolve } from "node:path";
3
+ import { createHash } from "node:crypto";
4
+ import { Command } from "commander";
5
+ import { z } from "zod";
6
+ import { GenerationOperationError, flowReplayFailureDetails } from "../../../application/generation/generation-starter.js";
7
+ import { GenerationSessionIdSchema, verificationPhaseLabel } from "../../../domain/generation.js";
8
+ import { DEFAULT_DEVICE_ROLE } from "../../../domain/journey.js";
9
+ import { ProjectRelativePathSchema } from "../../../domain/project-context.js";
10
+ import { CONFIG_PATH, CONTEXT_INDEX_PATH } from "../../../domain/workspace.js";
11
+ import { GenerationSessionStoreError } from "../../../ports/generation-session-store.js";
12
+ import { errorMessage, writeJson, writeLine } from "../../output.js";
13
+ import { canonicalProjectRoot } from "../../project-root.js";
14
+ import { addCommonOptions, assertRuntimeConfig, generationConfig, generationStatusText, loadConfig, mappedFailure, requireRuntime, tools, writeFailure, writeSuccess } from "./shared.js";
15
+ export function createStartCommand(dependencies) {
16
+ return new Command("start")
17
+ .description("Start a Core-owned generation session")
18
+ .option("--project <path>", "Android project root", dependencies.cwd())
19
+ .option("--config <path>", "TapHound config path", CONFIG_PATH)
20
+ .option("--context <path>", "Project Context path")
21
+ .option("--module <id...>", "Select Context modules for this session")
22
+ .option("--device <serial>", "Select an online Android device")
23
+ .option("--base-flow <name>", "Replay a reusable Flow before AI step generation")
24
+ .option("--external-flow <name...>", "Bind external app flow(s) for deterministic bridge replay")
25
+ .option("--brief <path>", "Bind a project-relative Journey Brief by Core-computed content hash")
26
+ .option("--allow-evidence-drift", "Allow changed source evidence; replay remains mandatory")
27
+ .option("--compact", "Summarize contextSelection as indexHash plus module ids instead of per-module binding hashes")
28
+ .option("--json", "Emit one machine-readable JSON value")
29
+ .action(async (options) => {
30
+ try {
31
+ const projectRoot = await canonicalProjectRoot(dependencies.cwd(), options.project);
32
+ const config = await loadConfig(dependencies, {
33
+ project: projectRoot,
34
+ config: options.config
35
+ });
36
+ const contextPath = resolve(projectRoot, options.context ?? CONTEXT_INDEX_PATH);
37
+ const loaded = await dependencies.contextLoader.load({
38
+ projectRoot,
39
+ contextPath,
40
+ allowIncomplete: true,
41
+ ...(options.module === undefined ? {} : { moduleIds: options.module })
42
+ });
43
+ const context = loaded.context;
44
+ const briefRequest = options.brief;
45
+ const sourceBrief = briefRequest === undefined
46
+ ? undefined
47
+ : await (async () => {
48
+ let briefPath;
49
+ try {
50
+ briefPath = ProjectRelativePathSchema.parse(briefRequest);
51
+ }
52
+ catch (error) {
53
+ throw new GenerationOperationError("BRIEF_INVALID", `Journey Brief path must stay within the project: ${briefRequest} (${error instanceof Error ? error.message : String(error)})`);
54
+ }
55
+ let bytes;
56
+ try {
57
+ bytes = await dependencies.readFile(resolve(projectRoot, briefPath));
58
+ }
59
+ catch (error) {
60
+ throw new GenerationOperationError("BRIEF_INVALID", `Journey Brief is not readable: ${briefPath} (${error instanceof Error ? error.message : String(error)})`);
61
+ }
62
+ return {
63
+ path: briefPath,
64
+ sha256: createHash("sha256").update(bytes).digest("hex")
65
+ };
66
+ })();
67
+ const doctor = await dependencies.doctor.run({
68
+ packageName: config.run.packageName,
69
+ ...(config.ui?.backend === undefined
70
+ ? {}
71
+ : { requestedUiBackend: config.ui.backend }),
72
+ ...(options.device === undefined
73
+ ? {}
74
+ : { requestedDevice: options.device }),
75
+ ...(dependencies.signal === undefined
76
+ ? {}
77
+ : { signal: dependencies.signal })
78
+ });
79
+ if (doctor.status === "failed") {
80
+ writeFailure(dependencies, options, 3, doctor.failureCode ?? "ENVIRONMENT_MISSING_TOOL", doctor.checks.find((check) => check.status === "failed")?.message
81
+ ?? "TapHound environment preflight failed");
82
+ return;
83
+ }
84
+ const deviceSerial = options.device ?? doctor.deviceSerial;
85
+ if (deviceSerial === undefined) {
86
+ throw new Error("Doctor did not select a device");
87
+ }
88
+ const project = await dependencies.projectDescriber.describe({
89
+ projectRoot,
90
+ config,
91
+ ...(dependencies.signal === undefined
92
+ ? {}
93
+ : { signal: dependencies.signal })
94
+ });
95
+ const baseFlow = options.baseFlow === undefined
96
+ ? undefined
97
+ : await (async () => {
98
+ if (dependencies.journeyResolver === undefined) {
99
+ throw new GenerationOperationError("FLOW_INVALID", "Journey Flow resolver is unavailable");
100
+ }
101
+ const resolution = await dependencies.journeyResolver.resolveFlow({
102
+ projectRoot,
103
+ name: options.baseFlow
104
+ }).catch((error) => {
105
+ throw new GenerationOperationError("FLOW_INVALID", errorMessage(error));
106
+ });
107
+ writeLine(dependencies.stderr, `TapHound: replaying base Flow ${options.baseFlow}`);
108
+ const verification = await dependencies.verifier.verify({
109
+ config,
110
+ journey: resolution.journey,
111
+ projectRoot,
112
+ devices: [{
113
+ role: resolution.journey.devices[0]?.role ?? DEFAULT_DEVICE_ROLE,
114
+ deviceSerial
115
+ }],
116
+ toolVersions: tools(doctor.checks),
117
+ requireFocusedInput: true,
118
+ generatedReplayPolicy: true,
119
+ ...(dependencies.signal === undefined
120
+ ? {}
121
+ : { signal: dependencies.signal })
122
+ });
123
+ if (verification.status !== "passed"
124
+ || verification.exitCode !== 0) {
125
+ throw new GenerationOperationError("FLOW_REPLAY_FAILED", verification.report.primaryFailure?.message
126
+ ?? `Base Flow ${options.baseFlow} did not replay cleanly`, flowReplayFailureDetails({
127
+ flowName: options.baseFlow,
128
+ reportPath: verification.reportPath,
129
+ journey: resolution.journey,
130
+ report: verification.report
131
+ }));
132
+ }
133
+ return {
134
+ name: options.baseFlow,
135
+ resolutionSha256: resolution.manifest.resolutionSha256,
136
+ journey: resolution.journey,
137
+ verificationReport: verification.report,
138
+ verificationReportPath: verification.reportPath
139
+ };
140
+ })();
141
+ const externalFlows = options.externalFlow === undefined
142
+ ? undefined
143
+ : await (async () => {
144
+ if (dependencies.externalFlowResolver === undefined) {
145
+ throw new GenerationOperationError("FLOW_INVALID", "External Flow resolver is unavailable");
146
+ }
147
+ const flowNames = options.externalFlow;
148
+ const resolved = [];
149
+ for (const name of flowNames) {
150
+ const resolution = await dependencies.externalFlowResolver
151
+ .resolve({ projectRoot, name })
152
+ .catch((error) => {
153
+ throw new GenerationOperationError("FLOW_INVALID", `External Flow ${name}: ${errorMessage(error)}`);
154
+ });
155
+ resolved.push({
156
+ name,
157
+ flowSha256: resolution.flowSha256,
158
+ escapedPackageName: resolution.flow.escapedPackageName,
159
+ stepCount: resolution.stepCount
160
+ });
161
+ }
162
+ return resolved;
163
+ })();
164
+ const session = await dependencies.generationStarter.start({
165
+ projectRoot,
166
+ config,
167
+ context,
168
+ project,
169
+ deviceSerial,
170
+ ...(dependencies.signal === undefined
171
+ ? {}
172
+ : { signal: dependencies.signal }),
173
+ ...(baseFlow === undefined ? {} : { baseFlow }),
174
+ ...(externalFlows === undefined ? {} : { externalFlows }),
175
+ ...(sourceBrief === undefined ? {} : { sourceBrief }),
176
+ ...(options.allowEvidenceDrift === true
177
+ ? { allowEvidenceDrift: true }
178
+ : {})
179
+ });
180
+ const output = {
181
+ status: "started",
182
+ exitCode: 0,
183
+ generationId: session.id,
184
+ revision: session.revision,
185
+ bindings: session.bindings,
186
+ ...(options.compact === true
187
+ ? {
188
+ contextSelection: {
189
+ bundleVersion: session.contextSelection.bundleVersion,
190
+ indexHash: session.contextSelection.indexHash,
191
+ moduleIds: session.contextSelection.modules.map((module) => module.id)
192
+ }
193
+ }
194
+ : { contextSelection: session.contextSelection }),
195
+ ...(options.allowEvidenceDrift === true
196
+ ? { evidenceDriftAllowed: true }
197
+ : {}),
198
+ variables: session.variables,
199
+ target: session.target,
200
+ ...(session.baseFlow === undefined
201
+ ? {}
202
+ : { baseFlow: session.baseFlow }),
203
+ ...(session.sourceBrief === undefined
204
+ ? {}
205
+ : { sourceBrief: session.sourceBrief }),
206
+ ...(session.externalFlows.length === 0
207
+ ? {}
208
+ : { externalFlows: session.externalFlows })
209
+ };
210
+ if (options.json === true) {
211
+ writeJson(dependencies.stdout, output);
212
+ }
213
+ else {
214
+ writeLine(dependencies.stdout, `Generation started: ${session.id}`);
215
+ }
216
+ dependencies.setExitCode(0);
217
+ }
218
+ catch (error) {
219
+ mappedFailure(dependencies, options, error);
220
+ }
221
+ });
222
+ }
223
+ export function createObserveCommand(dependencies) {
224
+ return new Command("observe")
225
+ .description("Observe and bind authoritative runtime state")
226
+ .option("--project <path>", "Android project root", dependencies.cwd())
227
+ .option("--config <path>", "TapHound config path", CONFIG_PATH)
228
+ .requiredOption("--session <id>", "Generation session id")
229
+ .option("--compact", "Emit binding plus authoritative snapshotRef instead of the full snapshot")
230
+ .option("--json", "Emit one machine-readable JSON value")
231
+ .action(async (options) => {
232
+ try {
233
+ const generationId = GenerationSessionIdSchema.parse(options.session);
234
+ const { projectRoot, config } = await generationConfig(dependencies, options);
235
+ const observation = dependencies.generationRuntime === undefined
236
+ ? await dependencies.runtimeObserver.observe({
237
+ projectRoot,
238
+ generationId,
239
+ idle: config.idle,
240
+ ...(dependencies.signal === undefined
241
+ ? {}
242
+ : { signal: dependencies.signal })
243
+ })
244
+ : await (async () => {
245
+ const runtime = requireRuntime(dependencies, projectRoot, config);
246
+ await assertRuntimeConfig(runtime, generationId);
247
+ return runtime.observer.observe({
248
+ generationId,
249
+ idle: config.idle,
250
+ ...(dependencies.signal === undefined
251
+ ? {}
252
+ : { signal: dependencies.signal })
253
+ });
254
+ })();
255
+ const output = {
256
+ status: "observed",
257
+ exitCode: 0,
258
+ ...observation.binding,
259
+ snapshotRef: observation.snapshotRef,
260
+ ...(options.compact === true
261
+ ? {}
262
+ : { snapshot: observation.snapshot })
263
+ };
264
+ if (options.json === true) {
265
+ writeJson(dependencies.stdout, output);
266
+ }
267
+ else {
268
+ writeLine(dependencies.stdout, `Generation observed at revision ${String(observation.binding.baseRevision)}`);
269
+ }
270
+ dependencies.setExitCode(0);
271
+ }
272
+ catch (error) {
273
+ if (error instanceof GenerationOperationError) {
274
+ mappedFailure(dependencies, options, error);
275
+ return;
276
+ }
277
+ if (error instanceof GenerationSessionStoreError
278
+ && (error.code === "REVISION_CONFLICT"
279
+ || error.code === "INVALID_TRANSITION")) {
280
+ writeFailure(dependencies, options, 1, "SNAPSHOT_STALE", error);
281
+ return;
282
+ }
283
+ mappedFailure(dependencies, options, error);
284
+ }
285
+ });
286
+ }
287
+ export function createStatusCommand(dependencies) {
288
+ return addCommonOptions(new Command("status")
289
+ .description("Inspect durable generation session state")
290
+ .option("--wait", "Wait until generation reaches a terminal state")
291
+ .option("--timeout-ms <milliseconds>", "Maximum status wait time", "900000"), dependencies).action(async (options) => {
292
+ try {
293
+ const generationId = GenerationSessionIdSchema.parse(options.session);
294
+ const { projectRoot, config } = await generationConfig(dependencies, options);
295
+ const runtime = requireRuntime(dependencies, projectRoot, config);
296
+ await assertRuntimeConfig(runtime, generationId);
297
+ const timeoutMs = z.coerce.number().int().positive().parse(options.timeoutMs ?? "900000");
298
+ const deadline = Date.now() + timeoutMs;
299
+ let status = await runtime.recovery.status(generationId);
300
+ let reportedPhase = null;
301
+ const reportPhaseProgress = (current) => {
302
+ if (options.wait !== true) {
303
+ return;
304
+ }
305
+ const phase = current.verification.status === "running"
306
+ ? current.verification.phase
307
+ : undefined;
308
+ if (phase === undefined) {
309
+ return;
310
+ }
311
+ const label = verificationPhaseLabel(phase);
312
+ if (label !== reportedPhase) {
313
+ reportedPhase = label;
314
+ writeLine(dependencies.stderr, `TapHound verification: ${label}`);
315
+ }
316
+ };
317
+ reportPhaseProgress(status);
318
+ while (options.wait === true
319
+ && status.publication.status !== "published"
320
+ && status.verification.status !== "failed"
321
+ && status.state !== "recoveryRequired"
322
+ && !(status.verification.status === "running"
323
+ && status.recovery.available)) {
324
+ if (dependencies.signal?.aborted === true) {
325
+ throw new GenerationOperationError("RECOVERY_REQUIRED", "Generation status wait was cancelled");
326
+ }
327
+ if (Date.now() >= deadline) {
328
+ throw new GenerationOperationError("FINALIZATION_IN_PROGRESS", "Generation did not reach a terminal state before status timeout");
329
+ }
330
+ await new Promise((resolveWait) => {
331
+ setTimeout(resolveWait, Math.min(500, deadline - Date.now()));
332
+ });
333
+ status = await runtime.recovery.status(generationId);
334
+ reportPhaseProgress(status);
335
+ }
336
+ if (options.json === true) {
337
+ writeJson(dependencies.stdout, {
338
+ status: "inspected",
339
+ exitCode: 0,
340
+ ...status
341
+ });
342
+ }
343
+ else {
344
+ writeLine(dependencies.stdout, generationStatusText(status));
345
+ }
346
+ dependencies.setExitCode(0);
347
+ }
348
+ catch (error) {
349
+ mappedFailure(dependencies, options, error);
350
+ }
351
+ });
352
+ }
353
+ export function createArchiveCommand(dependencies) {
354
+ return addCommonOptions(new Command("archive")
355
+ .description("Mark an idle generation session as archived"), dependencies).action(async (options) => {
356
+ try {
357
+ const generationId = GenerationSessionIdSchema.parse(options.session);
358
+ const { projectRoot, config } = await generationConfig(dependencies, options);
359
+ const runtime = requireRuntime(dependencies, projectRoot, config);
360
+ await assertRuntimeConfig(runtime, generationId);
361
+ const session = await runtime.archive(generationId);
362
+ writeSuccess(dependencies, options, {
363
+ status: "archived",
364
+ exitCode: 0,
365
+ generationId,
366
+ revision: session.revision
367
+ }, `Generation ${generationId} archived`);
368
+ }
369
+ catch (error) {
370
+ mappedFailure(dependencies, options, error);
371
+ }
372
+ });
373
+ }
374
+ export function idlePolicyText(policy) {
375
+ return `strategy ${policy.strategy}, poll ${String(policy.pollIntervalMs)}ms x${String(policy.stablePolls)}, timeout ${String(policy.timeoutMs)}ms`;
376
+ }
377
+ export function createConfigCommand(dependencies) {
378
+ return new Command("config")
379
+ .description("Adjust session-scoped generation settings")
380
+ .addCommand(addCommonOptions(new Command("idle")
381
+ .description("Hot-adjust the idle policy bound to a generation session")
382
+ .option("--strategy <strategy>", "Idle strategy: hybrid, layoutDiff, frameStats, or structural")
383
+ .option("--poll-interval-ms <milliseconds>", "Idle poll interval in milliseconds")
384
+ .option("--stable-polls <count>", "Consecutive stable polls required before idle")
385
+ .option("--timeout-ms <milliseconds>", "Idle timeout in milliseconds"), dependencies).action(async (options) => {
386
+ try {
387
+ const generationId = GenerationSessionIdSchema.parse(options.session);
388
+ const { projectRoot, config } = await generationConfig(dependencies, options);
389
+ const runtime = requireRuntime(dependencies, projectRoot, config);
390
+ await assertRuntimeConfig(runtime, generationId);
391
+ const strategy = options.strategy === undefined
392
+ ? undefined
393
+ : z
394
+ .enum(["hybrid", "layoutDiff", "frameStats", "structural"])
395
+ .parse(options.strategy);
396
+ const pollIntervalMs = options.pollIntervalMs === undefined
397
+ ? undefined
398
+ : z.coerce.number().int().positive().parse(options.pollIntervalMs);
399
+ const stablePolls = options.stablePolls === undefined
400
+ ? undefined
401
+ : z.coerce.number().int().positive().parse(options.stablePolls);
402
+ const timeoutMs = options.timeoutMs === undefined
403
+ ? undefined
404
+ : z.coerce.number().int().positive().parse(options.timeoutMs);
405
+ if (strategy === undefined
406
+ && pollIntervalMs === undefined
407
+ && stablePolls === undefined
408
+ && timeoutMs === undefined) {
409
+ throw new GenerationOperationError("CONFIG_INVALID", "Generation idle policy update requires at least one setting");
410
+ }
411
+ const session = await runtime.updateIdlePolicy(generationId, {
412
+ ...(strategy === undefined ? {} : { strategy }),
413
+ ...(pollIntervalMs === undefined ? {} : { pollIntervalMs }),
414
+ ...(stablePolls === undefined ? {} : { stablePolls }),
415
+ ...(timeoutMs === undefined ? {} : { timeoutMs })
416
+ });
417
+ const policy = session.idlePolicy;
418
+ writeSuccess(dependencies, options, {
419
+ status: "updated",
420
+ exitCode: 0,
421
+ generationId,
422
+ revision: session.revision,
423
+ ...(policy === undefined ? {} : { idlePolicy: policy })
424
+ }, policy === undefined
425
+ ? `Generation idle policy updated (revision ${String(session.revision)})`
426
+ : `Generation idle policy updated (revision ${String(session.revision)}): ${idlePolicyText(policy)}`);
427
+ }
428
+ catch (error) {
429
+ mappedFailure(dependencies, options, error);
430
+ }
431
+ }));
432
+ }
433
+ export function generationListText(sessions) {
434
+ if (sessions.length === 0) {
435
+ return "No generation sessions found.";
436
+ }
437
+ const lines = sessions.map((session) => {
438
+ const verification = session.verification.status;
439
+ const publication = session.publication.status;
440
+ const steps = String(session.candidateSteps.length);
441
+ return ` ${session.id} ${session.state.padEnd(14)} revision ${String(session.revision).padStart(3)} steps ${steps.padStart(3)} verification ${verification} publication ${publication}`;
442
+ });
443
+ return `Generation sessions (${String(sessions.length)}):\n${lines.join("\n")}`;
444
+ }
445
+ export function createListCommand(dependencies) {
446
+ return new Command("list")
447
+ .description("List generation sessions in the project workspace")
448
+ .option("--project <path>", "Android project root", dependencies.cwd())
449
+ .option("--config <path>", "TapHound config path", CONFIG_PATH)
450
+ .option("--json", "Emit one machine-readable JSON value")
451
+ .action(async (options) => {
452
+ try {
453
+ const { projectRoot, config } = await generationConfig(dependencies, options);
454
+ const runtime = requireRuntime(dependencies, projectRoot, config);
455
+ const sessions = await runtime.list();
456
+ if (options.json === true) {
457
+ writeJson(dependencies.stdout, {
458
+ status: "listed",
459
+ exitCode: 0,
460
+ sessions
461
+ });
462
+ }
463
+ else {
464
+ writeLine(dependencies.stdout, generationListText(sessions));
465
+ }
466
+ dependencies.setExitCode(0);
467
+ }
468
+ catch (error) {
469
+ mappedFailure(dependencies, options, error);
470
+ }
471
+ });
472
+ }