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,28 @@
1
+ import { normalizeActivity } from "../../domain/activity.js";
2
+ import { withRuntimeSession } from "../../ports/runtime-backend.js";
3
+ import { coldLaunchApp } from "../runtime/cold-launch.js";
4
+ export class GenerationAppPreparer {
5
+ dependencies;
6
+ constructor(dependencies) {
7
+ this.dependencies = dependencies;
8
+ }
9
+ prepare(input) {
10
+ return withRuntimeSession(this.dependencies.sessions, input.deviceSerial, input.signal, (session) => this.coldLaunch(this.dependencies.sessionPorts(session).adb, input));
11
+ }
12
+ async coldLaunch(adb, input) {
13
+ const launched = await coldLaunchApp(adb, this.dependencies.clock, {
14
+ packageName: input.config.run.packageName,
15
+ activity: normalizeActivity(input.config.run.packageName, input.config.run.activity),
16
+ deviceSerial: input.deviceSerial,
17
+ pollIntervalMs: input.config.idle.pollIntervalMs,
18
+ timeoutMs: input.config.idle.timeoutMs,
19
+ signal: input.signal
20
+ });
21
+ if (launched.status === "cancelled") {
22
+ throw new Error("App launch was cancelled");
23
+ }
24
+ if (launched.status === "failed") {
25
+ throw new Error(launched.message);
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,21 @@
1
+ import { type GenerationSession } from "../../domain/generation.js";
2
+ import { type TapHoundConfig } from "../../domain/config.js";
3
+ import type { GenerationSessionStore } from "../../ports/generation-session-store.js";
4
+ export interface GenerationIdlePolicyPatch {
5
+ strategy?: TapHoundConfig["idle"]["strategy"] | undefined;
6
+ pollIntervalMs?: number | undefined;
7
+ stablePolls?: number | undefined;
8
+ timeoutMs?: number | undefined;
9
+ }
10
+ export interface GenerationConfigServiceDependencies {
11
+ store: Pick<GenerationSessionStore, "read" | "update">;
12
+ }
13
+ export declare class GenerationConfigService {
14
+ private readonly dependencies;
15
+ constructor(dependencies: GenerationConfigServiceDependencies);
16
+ readonly updateIdlePolicy: (input: {
17
+ generationId: string;
18
+ config: TapHoundConfig;
19
+ patch: GenerationIdlePolicyPatch;
20
+ }) => Promise<GenerationSession>;
21
+ }
@@ -0,0 +1,53 @@
1
+ import { GenerationSessionSchema } from "../../domain/generation.js";
2
+ import { IdlePolicySchema } from "../../domain/config.js";
3
+ import { GenerationOperationError } from "./generation-starter.js";
4
+ function hasPatch(patch) {
5
+ return patch.strategy !== undefined
6
+ || patch.pollIntervalMs !== undefined
7
+ || patch.stablePolls !== undefined
8
+ || patch.timeoutMs !== undefined;
9
+ }
10
+ function assertUpdatable(session) {
11
+ if (session.state !== "active") {
12
+ throw new GenerationOperationError("CONFIG_INVALID", `Generation idle policy can only be updated on an active session (state: ${session.state})`);
13
+ }
14
+ if (session.inFlight !== null) {
15
+ throw new GenerationOperationError("CONFIG_INVALID", "Generation idle policy cannot change while a step is in flight");
16
+ }
17
+ if (session.pendingConfirmation !== null) {
18
+ throw new GenerationOperationError("CONFIG_INVALID", "Generation idle policy cannot change while a confirmation is pending");
19
+ }
20
+ if (session.verification.status !== "notRun") {
21
+ throw new GenerationOperationError("CONFIG_INVALID", "Generation idle policy cannot change once verification has started");
22
+ }
23
+ if (session.publication.status !== "notRun") {
24
+ throw new GenerationOperationError("CONFIG_INVALID", "Generation idle policy cannot change after publication");
25
+ }
26
+ }
27
+ export class GenerationConfigService {
28
+ dependencies;
29
+ constructor(dependencies) {
30
+ this.dependencies = dependencies;
31
+ }
32
+ updateIdlePolicy = async (input) => {
33
+ if (!hasPatch(input.patch)) {
34
+ throw new GenerationOperationError("CONFIG_INVALID", "Generation idle policy update requires at least one setting");
35
+ }
36
+ const session = GenerationSessionSchema.parse(await this.dependencies.store.read(input.generationId));
37
+ assertUpdatable(session);
38
+ const base = session.idlePolicy ?? input.config.idle;
39
+ const idlePolicy = IdlePolicySchema.parse({
40
+ strategy: input.patch.strategy ?? base.strategy,
41
+ pollIntervalMs: input.patch.pollIntervalMs ?? base.pollIntervalMs,
42
+ stablePolls: input.patch.stablePolls ?? base.stablePolls,
43
+ timeoutMs: input.patch.timeoutMs ?? base.timeoutMs
44
+ });
45
+ const next = {
46
+ ...session,
47
+ revision: session.revision + 1,
48
+ idlePolicy
49
+ };
50
+ await this.dependencies.store.update(input.generationId, session.revision, next);
51
+ return next;
52
+ };
53
+ }
@@ -13,18 +13,22 @@ export interface GenerationConfirmationDependencies {
13
13
  export interface ConfirmationRequestInput {
14
14
  generationId: string;
15
15
  proposal: ProposedStep;
16
- snapshot: RuntimeSnapshot;
16
+ snapshot?: RuntimeSnapshot | undefined;
17
+ snapshotRef?: string | undefined;
17
18
  source?: "planner" | "manualOverride" | undefined;
18
19
  }
19
20
  export interface ConfirmationApproveInput extends ConfirmationRequestInput {
20
21
  challengeId: string;
22
+ decision?: ConfirmationDecision | undefined;
21
23
  signal?: AbortSignal | undefined;
22
24
  }
23
25
  export interface StoredConfirmationApproveInput {
24
26
  generationId: string;
25
27
  challengeId: string;
28
+ decision?: ConfirmationDecision | undefined;
26
29
  signal?: AbortSignal | undefined;
27
30
  }
31
+ export type ConfirmationDecision = "approve" | "decline";
28
32
  export interface ManualConfirmationRequestInput {
29
33
  generationId: string;
30
34
  snapshot: RuntimeSnapshot;
@@ -37,18 +41,22 @@ export interface PendingManualConfirmationInput {
37
41
  }
38
42
  export interface ConfirmationRequiredResult {
39
43
  status: "confirmationRequired";
44
+ revision: number;
40
45
  challenge: PendingConfirmation;
41
46
  }
42
47
  export type ConfirmationRequestResult = {
43
48
  status: "approved";
44
49
  proposal: ProposedStep;
50
+ snapshot: RuntimeSnapshot;
45
51
  } | ConfirmationRequiredResult;
46
- export interface StoredConfirmationApproveResult {
52
+ export type StoredConfirmationApproveResult = {
47
53
  status: "approved";
48
54
  proposal: ProposedStep;
49
55
  snapshot: RuntimeSnapshot;
50
56
  source: "planner" | "manualOverride";
51
- }
57
+ } | {
58
+ status: "declined";
59
+ };
52
60
  export declare function summarizeProposedStep(step: ProposedStep): string;
53
61
  export declare function confirmationEvidencePath(challengeId: string): string;
54
62
  export declare class GenerationConfirmationService {
@@ -63,6 +71,8 @@ export declare class GenerationConfirmationService {
63
71
  readonly confirm: (input: ConfirmationApproveInput) => Promise<{
64
72
  status: "approved";
65
73
  proposal: ProposedStep;
74
+ } | {
75
+ status: "declined";
66
76
  }>;
67
77
  readonly clearApproved: (input: {
68
78
  generationId: string;
@@ -73,4 +83,5 @@ export declare class GenerationConfirmationService {
73
83
  private requireExactPendingChallenge;
74
84
  private updateConfirmationReconciled;
75
85
  private readStoredEvidence;
86
+ private resolveSnapshot;
76
87
  }
@@ -1,7 +1,8 @@
1
- import { GenerationConfirmationEvidenceSchema, GenerationSessionIdSchema, GenerationSessionSchema, hashGenerationConfirmationEvidence } from "../../domain/generation.js";
1
+ import { GenerationConfirmationEvidenceSchema, GenerationSessionIdSchema, GenerationSessionSchema, hashGenerationConfirmationEvidence, isGenerationConfirmationExpired } from "../../domain/generation.js";
2
2
  import { ProposedStepSchema, hashProposedStep } from "../../domain/proposed-step.js";
3
3
  import { RuntimeSnapshotSchema, hashRuntimeSnapshot } from "../../domain/runtime-snapshot.js";
4
4
  import { GenerationPromptCancelledError } from "../../ports/generation-prompt.js";
5
+ import { parseSnapshotEvidenceReference } from "../../domain/workspace.js";
5
6
  import { GenerationOperationError } from "./generation-starter.js";
6
7
  import { ProposedStepValidator } from "./proposed-step-validator.js";
7
8
  import { RiskEvaluator } from "./risk-evaluator.js";
@@ -11,6 +12,9 @@ function locatorSummary(step) {
11
12
  || step.action === "wait") {
12
13
  return "";
13
14
  }
15
+ if (step.action === "bridge") {
16
+ return JSON.stringify(step.triggerLocator);
17
+ }
14
18
  return JSON.stringify(step.locator);
15
19
  }
16
20
  export function summarizeProposedStep(step) {
@@ -27,6 +31,9 @@ export function summarizeProposedStep(step) {
27
31
  if (step.action === "scrollTo") {
28
32
  return `Scroll ${step.direction} in ${JSON.stringify(step.container)} to ${locatorSummary(step)} on ${before}`;
29
33
  }
34
+ if (step.action === "bridge") {
35
+ return `Bridge ${step.scenario} via ${locatorSummary(step)} on ${before}`;
36
+ }
30
37
  return `${step.action} ${locatorSummary(step)} on ${before}`;
31
38
  }
32
39
  function bindingFailure(message) {
@@ -47,15 +54,23 @@ export class GenerationConfirmationService {
47
54
  }
48
55
  }
49
56
  request = async (input) => {
57
+ const inputSnapshot = await this.resolveSnapshot(input);
50
58
  const session = GenerationSessionSchema.parse(await this.dependencies.store.read(input.generationId));
51
59
  const submittedEvidence = GenerationConfirmationEvidenceSchema.parse({
52
60
  version: 1,
53
61
  proposal: input.proposal,
54
- snapshot: input.snapshot,
62
+ snapshot: inputSnapshot,
55
63
  source: input.source ?? "planner"
56
64
  });
57
65
  if (session.pendingConfirmation !== null
58
66
  && session.pendingConfirmation.status === "pending") {
67
+ if (isGenerationConfirmationExpired(session.pendingConfirmation, this.dependencies.now())) {
68
+ await this.clearExactChallenge(session.id, {
69
+ expectedRevision: session.revision,
70
+ expectedChallenge: session.pendingConfirmation
71
+ });
72
+ throw bindingFailure("Generation confirmation challenge expired and was cleared; observe again before proposing a step");
73
+ }
59
74
  const storedEvidence = await this.readStoredEvidence({
60
75
  generationId: session.id,
61
76
  challengeId: session.pendingConfirmation.challengeId
@@ -64,19 +79,27 @@ export class GenerationConfirmationService {
64
79
  throw bindingFailure("Pending generation confirmation does not match submitted evidence");
65
80
  }
66
81
  const challenge = this.requireExactPendingChallenge(session, storedEvidence);
67
- return { status: "confirmationRequired", challenge };
82
+ return {
83
+ status: "confirmationRequired",
84
+ revision: session.revision,
85
+ challenge
86
+ };
68
87
  }
69
88
  const proposal = this.validator.validate({
70
89
  session,
71
90
  snapshot: submittedEvidence.snapshot,
72
91
  proposal: submittedEvidence.proposal
73
92
  });
74
- const risk = this.riskEvaluator.evaluate(proposal.action, session.target.interactionPolicy);
93
+ const risk = this.riskEvaluator.evaluate(proposal, session.target.interactionPolicy, submittedEvidence.snapshot);
75
94
  if (risk.effectiveRisk === "forbidden") {
76
95
  throw new GenerationOperationError("ACTION_FORBIDDEN", `${proposal.action} is forbidden by the Core interaction policy`);
77
96
  }
78
97
  if (risk.effectiveRisk === "safe") {
79
- return { status: "approved", proposal };
98
+ return {
99
+ status: "approved",
100
+ proposal,
101
+ snapshot: submittedEvidence.snapshot
102
+ };
80
103
  }
81
104
  if (session.revision === Number.MAX_SAFE_INTEGER) {
82
105
  throw bindingFailure("Generation revision cannot create a challenge");
@@ -94,6 +117,7 @@ export class GenerationConfirmationService {
94
117
  snapshotHash: proposal.binding.snapshotHash,
95
118
  evidenceHash: hashGenerationConfirmationEvidence(evidence),
96
119
  actionSummary: summarizeProposedStep(proposal),
120
+ ...(risk.reason === undefined ? {} : { reason: risk.reason }),
97
121
  expiresAt: new Date(this.dependencies.now().getTime()
98
122
  + this.dependencies.confirmationTtlMs).toISOString(),
99
123
  status: "pending"
@@ -105,7 +129,11 @@ export class GenerationConfirmationService {
105
129
  });
106
130
  await this.dependencies.store.writeEvidence(session.id, confirmationEvidencePath(challenge.challengeId), evidence);
107
131
  await this.updateConfirmationReconciled(session.id, session.revision, next);
108
- return { status: "confirmationRequired", challenge };
132
+ return {
133
+ status: "confirmationRequired",
134
+ revision: next.revision,
135
+ challenge
136
+ };
109
137
  };
110
138
  requestManual = async (input) => {
111
139
  const proposal = await this.dependencies.prompt.buildManualProposal(input.manual, input.signal);
@@ -125,6 +153,13 @@ export class GenerationConfirmationService {
125
153
  if (pending === null || pending.status !== "pending") {
126
154
  return null;
127
155
  }
156
+ if (isGenerationConfirmationExpired(pending, this.dependencies.now())) {
157
+ await this.clearExactChallenge(session.id, {
158
+ expectedRevision: session.revision,
159
+ expectedChallenge: pending
160
+ });
161
+ throw bindingFailure("Generation confirmation challenge expired and was cleared; observe again before manual takeover");
162
+ }
128
163
  const evidence = await this.readStoredEvidence({
129
164
  generationId: session.id,
130
165
  challengeId: pending.challengeId
@@ -134,18 +169,28 @@ export class GenerationConfirmationService {
134
169
  throw bindingFailure("Pending manual confirmation does not match the requested action");
135
170
  }
136
171
  const challenge = this.requireExactPendingChallenge(session, evidence);
137
- return { status: "confirmationRequired", challenge };
172
+ return {
173
+ status: "confirmationRequired",
174
+ revision: session.revision,
175
+ challenge
176
+ };
138
177
  };
139
178
  confirmStored = async (input) => {
140
179
  const evidence = await this.readStoredEvidence(input);
141
- await this.confirm({
180
+ const result = await this.confirm({
142
181
  generationId: input.generationId,
143
182
  challengeId: input.challengeId,
144
183
  proposal: evidence.proposal,
145
184
  snapshot: evidence.snapshot,
146
185
  source: evidence.source,
186
+ ...(input.decision === undefined
187
+ ? {}
188
+ : { decision: input.decision }),
147
189
  signal: input.signal
148
190
  });
191
+ if (result.status === "declined") {
192
+ return result;
193
+ }
149
194
  return {
150
195
  status: "approved",
151
196
  proposal: evidence.proposal,
@@ -174,9 +219,14 @@ export class GenerationConfirmationService {
174
219
  expectedRevision,
175
220
  expectedChallenge: challenge
176
221
  };
177
- const expired = this.dependencies.now().getTime()
178
- >= new Date(challenge.expiresAt).getTime();
222
+ const expired = isGenerationConfirmationExpired(challenge, this.dependencies.now());
179
223
  const challengeMatches = challenge.challengeId === input.challengeId;
224
+ if (input.decision === "decline") {
225
+ if (!challengeMatches || !await this.clearExactChallenge(session.id, cleanupToken)) {
226
+ throw bindingFailure("Generation confirmation binding is no longer authoritative");
227
+ }
228
+ return { status: "declined" };
229
+ }
180
230
  const proposalMatches = challenge.proposalHash
181
231
  === hashProposedStep(proposal);
182
232
  const evidenceMatches = challenge.evidenceHash === evidenceHash;
@@ -227,13 +277,15 @@ export class GenerationConfirmationService {
227
277
  if (challenge.status === "approved") {
228
278
  return { status: "approved", proposal };
229
279
  }
230
- let confirmed;
231
- try {
232
- confirmed = await this.dependencies.prompt.confirm(challenge, input.signal);
233
- }
234
- catch (error) {
235
- await this.clearExactChallenge(session.id, cleanupToken);
236
- throw error;
280
+ let confirmed = input.decision === "approve";
281
+ if (input.decision === undefined) {
282
+ try {
283
+ confirmed = await this.dependencies.prompt.confirm(challenge, input.signal);
284
+ }
285
+ catch (error) {
286
+ await this.clearExactChallenge(session.id, cleanupToken);
287
+ throw error;
288
+ }
237
289
  }
238
290
  if (input.signal?.aborted === true) {
239
291
  await this.cancelPrompt(session.id, cleanupToken);
@@ -249,8 +301,7 @@ export class GenerationConfirmationService {
249
301
  const stillAuthoritative = latest.revision === session.revision
250
302
  && JSON.stringify(latest.pendingConfirmation)
251
303
  === JSON.stringify(challenge)
252
- && this.dependencies.now().getTime()
253
- < new Date(challenge.expiresAt).getTime();
304
+ && !isGenerationConfirmationExpired(challenge, this.dependencies.now());
254
305
  if (!stillAuthoritative) {
255
306
  await this.clearExactChallenge(session.id, cleanupToken);
256
307
  throw bindingFailure("Generation confirmation state changed while prompting");
@@ -267,7 +318,10 @@ export class GenerationConfirmationService {
267
318
  revision: latest.revision + 1,
268
319
  pendingConfirmation: {
269
320
  ...challenge,
270
- status: "approved"
321
+ status: "approved",
322
+ approvalMode: input.decision === "approve"
323
+ ? "delegated"
324
+ : "localTty"
271
325
  }
272
326
  });
273
327
  await this.dependencies.store.updateConfirmation(latest.id, latest.revision, approved);
@@ -292,7 +346,7 @@ export class GenerationConfirmationService {
292
346
  if (latest.revision !== token.expectedRevision
293
347
  || pending === null
294
348
  || JSON.stringify(pending) !== JSON.stringify(token.expectedChallenge)) {
295
- return;
349
+ return false;
296
350
  }
297
351
  if (latest.revision === Number.MAX_SAFE_INTEGER) {
298
352
  throw bindingFailure("Generation revision cannot clear challenge");
@@ -303,6 +357,7 @@ export class GenerationConfirmationService {
303
357
  pendingConfirmation: null
304
358
  });
305
359
  await this.updateConfirmationReconciled(latest.id, latest.revision, cleared);
360
+ return true;
306
361
  }
307
362
  async cancelPrompt(generationId, token) {
308
363
  await this.clearExactChallenge(generationId, token);
@@ -332,7 +387,7 @@ export class GenerationConfirmationService {
332
387
  catch {
333
388
  throw bindingFailure("Pending generation confirmation is no longer authoritative");
334
389
  }
335
- const risk = this.riskEvaluator.evaluate(proposal.action, session.target.interactionPolicy);
390
+ const risk = this.riskEvaluator.evaluate(proposal, session.target.interactionPolicy, snapshot);
336
391
  if (risk.effectiveRisk !== "confirmationRequired"
337
392
  || challenge.stepIndex !== session.candidateSteps.length
338
393
  || challenge.proposalHash !== hashProposedStep(proposal)
@@ -340,8 +395,7 @@ export class GenerationConfirmationService {
340
395
  || challenge.snapshotHash !== proposal.binding.snapshotHash
341
396
  || challenge.evidenceHash !== hashGenerationConfirmationEvidence(evidence)
342
397
  || challenge.actionSummary !== summarizeProposedStep(proposal)
343
- || this.dependencies.now().getTime()
344
- >= new Date(challenge.expiresAt).getTime()) {
398
+ || isGenerationConfirmationExpired(challenge, this.dependencies.now())) {
345
399
  throw bindingFailure("Pending generation confirmation does not match stored evidence");
346
400
  }
347
401
  return challenge;
@@ -380,4 +434,35 @@ export class GenerationConfirmationService {
380
434
  : "Generation confirmation evidence is unavailable");
381
435
  }
382
436
  }
437
+ async resolveSnapshot(input) {
438
+ if ((input.snapshot !== undefined) === (input.snapshotRef !== undefined)) {
439
+ throw new GenerationOperationError("SNAPSHOT_STALE", "Provide exactly one of snapshot or snapshotRef");
440
+ }
441
+ if (input.snapshot !== undefined) {
442
+ return input.snapshot;
443
+ }
444
+ const reference = input.snapshotRef ?? "";
445
+ const evidencePath = parseSnapshotEvidenceReference(reference, input.generationId);
446
+ if (evidencePath === null) {
447
+ throw new GenerationOperationError("SNAPSHOT_STALE", `Snapshot reference is not a valid evidence binding for generation ${input.generationId}: ${reference}`);
448
+ }
449
+ let bytes;
450
+ try {
451
+ bytes = await this.dependencies.store.readEvidence(input.generationId, evidencePath);
452
+ }
453
+ catch (error) {
454
+ throw new GenerationOperationError("SNAPSHOT_STALE", `Referenced snapshot evidence is unavailable: ${reference} (${error instanceof Error ? error.message : "read failed"})`);
455
+ }
456
+ let snapshot;
457
+ try {
458
+ snapshot = RuntimeSnapshotSchema.parse(JSON.parse(bytes.toString("utf8")));
459
+ }
460
+ catch {
461
+ throw new GenerationOperationError("SNAPSHOT_STALE", `Referenced snapshot evidence is not a valid RuntimeSnapshot: ${reference}`);
462
+ }
463
+ if (snapshot.generationId !== input.generationId) {
464
+ throw new GenerationOperationError("SNAPSHOT_STALE", `Referenced snapshot belongs to another generation: ${reference}`);
465
+ }
466
+ return snapshot;
467
+ }
383
468
  }
@@ -0,0 +1,6 @@
1
+ import { type ResolvedProjectContext } from "../../domain/project-context.js";
2
+ import { type GenerationSessionStore } from "../../ports/generation-session-store.js";
3
+ export interface GenerationContextSnapshotDependencies {
4
+ store: Pick<GenerationSessionStore, "read" | "readEvidence">;
5
+ }
6
+ export declare const readGenerationContextSnapshot: (dependencies: GenerationContextSnapshotDependencies, sessionId: string) => Promise<ResolvedProjectContext>;
@@ -0,0 +1,29 @@
1
+ import { ResolvedProjectContextSchema } from "../../domain/project-context.js";
2
+ import { GENERATION_CONTEXT_SNAPSHOT_PATH } from "../../domain/workspace.js";
3
+ import { GenerationSessionStoreError } from "../../ports/generation-session-store.js";
4
+ import { GenerationOperationError, hashGenerationBinding } from "./generation-starter.js";
5
+ export const readGenerationContextSnapshot = async (dependencies, sessionId) => {
6
+ let bytes;
7
+ try {
8
+ bytes = await dependencies.store.readEvidence(sessionId, GENERATION_CONTEXT_SNAPSHOT_PATH);
9
+ }
10
+ catch (error) {
11
+ if (error instanceof GenerationSessionStoreError
12
+ && error.code === "EVIDENCE_NOT_FOUND") {
13
+ throw new GenerationOperationError("CONTEXT_INVALID", "Generation session has no stored context snapshot; start a new session");
14
+ }
15
+ throw error;
16
+ }
17
+ let context;
18
+ try {
19
+ context = ResolvedProjectContextSchema.parse(JSON.parse(bytes.toString("utf8")));
20
+ }
21
+ catch {
22
+ throw new GenerationOperationError("CONTEXT_INVALID", "Stored context snapshot is unreadable");
23
+ }
24
+ const session = await dependencies.store.read(sessionId);
25
+ if (hashGenerationBinding(context) !== session.bindings.contextHash) {
26
+ throw new GenerationOperationError("CONTEXT_INVALID", "Stored context snapshot does not match the session context binding");
27
+ }
28
+ return context;
29
+ };
@@ -1,11 +1,9 @@
1
1
  import { z } from "zod";
2
- import { type GenerationErrorCode, type GenerationMeta } from "../../domain/generation.js";
2
+ import { type GenerationErrorCode, type GenerationMeta, type VerificationPhase } from "../../domain/generation.js";
3
3
  import { type Journey } from "../../domain/journey.js";
4
- import { type ProjectContext } from "../../domain/project-context.js";
4
+ import { type ResolvedProjectContext } from "../../domain/project-context.js";
5
5
  import { type TapHoundConfig } from "../../domain/config.js";
6
- import type { AdbPort } from "../../ports/adb.js";
7
6
  import { type GenerationSessionStore } from "../../ports/generation-session-store.js";
8
- import type { ContextValidator } from "../context/context-validator.js";
9
7
  import type { ProjectDescription } from "../project/project-describer.js";
10
8
  import type { VerifyRuntime } from "../runtime/verify-runtime.js";
11
9
  import { GenerationPublisher } from "./generation-publisher.js";
@@ -15,28 +13,34 @@ export declare class GenerationFinalizationError extends Error {
15
13
  readonly code: GenerationErrorCode;
16
14
  readonly stage: GenerationFinalizationStage;
17
15
  readonly recoverable: boolean;
16
+ readonly details?: unknown | undefined;
18
17
  readonly name = "GenerationFinalizationError";
19
- constructor(code: GenerationErrorCode, stage: GenerationFinalizationStage, recoverable: boolean, message: string, options?: ErrorOptions);
18
+ constructor(code: GenerationErrorCode, stage: GenerationFinalizationStage, recoverable: boolean, message: string, options?: ErrorOptions, details?: unknown | undefined);
20
19
  }
21
20
  export interface GenerationFinalizeInput {
22
21
  generationId: string;
23
22
  projectRoot: string;
24
23
  config: TapHoundConfig;
25
- context: ProjectContext;
24
+ context: ResolvedProjectContext;
26
25
  project: ProjectDescription;
27
26
  outputPath: string;
28
27
  name?: string | undefined;
29
28
  deviceSerial: string;
29
+ manualReplay?: boolean | undefined;
30
30
  toolVersions: Record<string, string>;
31
31
  signal?: AbortSignal | undefined;
32
32
  }
33
33
  export interface GenerationFinalizerDependencies {
34
- store: Pick<GenerationSessionStore, "read" | "beginVerification" | "completeVerification" | "failVerification" | "markBundlePublishable" | "writeTextEvidence" | "readEvidence">;
35
- contextValidator: Pick<ContextValidator, "validate">;
36
- adb: Pick<AdbPort, "forceStop">;
34
+ store: Pick<GenerationSessionStore, "read" | "beginVerification" | "updateVerificationPhase" | "abortVerification" | "completeVerification" | "failVerification" | "markBundlePublishable" | "writeTextEvidence" | "readEvidence">;
37
35
  verifyRuntime: Pick<VerifyRuntime, "verify">;
38
36
  publisher: GenerationPublisher;
39
37
  generateAttemptId: () => string;
38
+ owner?: {
39
+ pid: number;
40
+ now: () => Date;
41
+ } | undefined;
42
+ progress?: ((stage: GenerationFinalizationStage) => void) | undefined;
43
+ replayProgress?: ((phase: VerificationPhase) => void) | undefined;
40
44
  }
41
45
  export interface GenerationFinalizeResult {
42
46
  status: "verified";
@@ -51,6 +55,7 @@ export declare class GenerationFinalizer {
51
55
  private readonly dependencies;
52
56
  constructor(dependencies: GenerationFinalizerDependencies);
53
57
  readonly finalize: (input: GenerationFinalizeInput) => Promise<GenerationFinalizeResult>;
58
+ private bridgeReplayProgress;
54
59
  private assertBindings;
55
60
  private revalidate;
56
61
  private beginVerification;
@@ -60,6 +65,7 @@ export declare class GenerationFinalizer {
60
65
  private receiptMatches;
61
66
  private persistPassedVerification;
62
67
  private reconcilePassedVerification;
68
+ private tryAbortVerification;
63
69
  private persistFailedVerification;
64
70
  private readVerifiedReport;
65
71
  private buildMeta;