taphound 0.2.0-dev.1 → 0.2.0-dev.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (467) hide show
  1. package/README.md +49 -149
  2. package/README.zh-CN.md +47 -147
  3. package/assets/skills/taphound-case-suite/SKILL.md +363 -0
  4. package/assets/skills/taphound-case-suite/schemas/base-flow-record.schema.json +22 -0
  5. package/assets/skills/taphound-case-suite/schemas/case-catalog.schema.json +26 -0
  6. package/assets/skills/taphound-case-suite/schemas/case-ledger.schema.json +158 -0
  7. package/assets/skills/taphound-case-suite/schemas/suite-input.schema.json +41 -0
  8. package/assets/skills/taphound-case-suite/schemas/transition.schema.json +61 -0
  9. package/assets/skills/taphound-case-suite/scripts/ledger.mjs +1207 -0
  10. package/assets/skills/taphound-case-suite/templates/base-flow-record.example.json +20 -0
  11. package/assets/skills/taphound-case-suite/templates/suite-input.example.json +27 -0
  12. package/assets/skills/taphound-case-suite/templates/transition.example.json +8 -0
  13. package/assets/skills/taphound-flash/SKILL.md +115 -0
  14. package/assets/skills/taphound-flash/scripts/flash.mjs +585 -0
  15. package/assets/skills/taphound-flash/templates/flash-plan.example.json +15 -0
  16. package/assets/skills/taphound-journey-brief-author/CONTEXT-GUIDE.md +471 -0
  17. package/assets/skills/taphound-journey-brief-author/SKILL.md +494 -0
  18. package/assets/skills/taphound-journey-brief-author/prompts/brief-author-role.md +96 -0
  19. package/assets/skills/taphound-journey-brief-author/prompts/brief-author-role.zh-CN.md +80 -0
  20. package/assets/skills/taphound-journey-brief-author/prompts/context-analyze-project.md +309 -0
  21. package/assets/skills/taphound-journey-brief-author/schemas/context-refresh-result.json +123 -0
  22. package/assets/skills/taphound-journey-brief-author/schemas/project-context-module.json +192 -0
  23. package/assets/skills/taphound-journey-brief-author/schemas/project-context.json +152 -0
  24. package/assets/skills/taphound-journey-brief-author/templates/project-context-module.example.json +58 -0
  25. package/assets/skills/taphound-journey-brief-author/templates/project-context.example.json +51 -0
  26. package/assets/skills/taphound-journey-brief-author/templates/taphound-journey-brief.template.md +63 -0
  27. package/assets/skills/taphound-journey-generator/SKILL.md +507 -0
  28. package/assets/skills/{taphound-ai-journey → taphound-journey-generator}/prompts/check-completion.md +3 -0
  29. package/assets/skills/taphound-journey-generator/prompts/consume-journey-brief.md +52 -0
  30. package/assets/skills/taphound-journey-generator/prompts/generate-step.md +211 -0
  31. package/assets/skills/taphound-journey-generator/prompts/select-flow.md +91 -0
  32. package/assets/skills/taphound-journey-generator/references/bridge.md +35 -0
  33. package/assets/skills/taphound-journey-generator/references/mid-session.md +44 -0
  34. package/assets/skills/taphound-journey-generator/schemas/external-flow.json +37 -0
  35. package/assets/skills/taphound-journey-generator/schemas/flow.json +28 -0
  36. package/assets/skills/taphound-journey-generator/schemas/journey-source.json +25 -0
  37. package/assets/skills/{taphound-ai-journey → taphound-journey-generator}/schemas/observe-output.json +13 -4
  38. package/assets/skills/{taphound-ai-journey → taphound-journey-generator}/schemas/proposed-step-envelope.json +127 -5
  39. package/assets/skills/taphound-journey-generator/scripts/envelope.mjs +578 -0
  40. package/assets/skills/taphound-journey-generator/templates/external-flow.example.json +22 -0
  41. package/assets/skills/taphound-journey-generator/templates/flow.example.json +22 -0
  42. package/assets/skills/taphound-journey-generator/templates/journey-source.example.json +17 -0
  43. package/assets/skills/taphound-journey-generator/templates/taphound-journey-brief.example.md +70 -0
  44. package/assets/skills/taphound-verify-change/SKILL.md +91 -0
  45. package/assets/skills/taphound-verify-change/references/accept.md +38 -0
  46. package/assets/skills/taphound-verify-change/references/preserve.md +357 -0
  47. package/assets/skills/taphound-verify-change/schemas/workflow-manifest.schema.json +295 -0
  48. package/assets/skills/taphound-verify-change/scripts/handoff.mjs +482 -0
  49. package/assets/skills/taphound-verify-change/scripts/ui-refactor.mjs +505 -0
  50. package/dist/adapters/adb/adb-adapter.d.ts +16 -2
  51. package/dist/adapters/adb/adb-adapter.js +199 -0
  52. package/dist/adapters/adb/system-uiautomator-snapshot-provider.d.ts +13 -0
  53. package/dist/adapters/adb/system-uiautomator-snapshot-provider.js +122 -0
  54. package/dist/adapters/adb/ui-automator-parser.d.ts +3 -0
  55. package/dist/adapters/adb/ui-automator-parser.js +160 -0
  56. package/dist/adapters/adb/window-topology-parser.d.ts +2 -0
  57. package/dist/adapters/adb/window-topology-parser.js +101 -0
  58. package/dist/adapters/android-cli/android-cli-adapter.d.ts +16 -8
  59. package/dist/adapters/android-cli/android-cli-adapter.js +137 -15
  60. package/dist/adapters/android-cli/android-cli-snapshot-provider.d.ts +9 -0
  61. package/dist/adapters/android-cli/android-cli-snapshot-provider.js +99 -0
  62. package/dist/adapters/android-cli/layout-parser.js +12 -8
  63. package/dist/adapters/appium/appium-doctor.d.ts +7 -0
  64. package/dist/adapters/appium/appium-doctor.js +128 -0
  65. package/dist/adapters/appium/appium-ui-snapshot-provider.d.ts +42 -0
  66. package/dist/adapters/appium/appium-ui-snapshot-provider.js +309 -0
  67. package/dist/adapters/camera/camera-probe-adapter.d.ts +18 -0
  68. package/dist/adapters/camera/camera-probe-adapter.js +286 -0
  69. package/dist/adapters/filesystem/artifact-store.js +40 -1
  70. package/dist/adapters/filesystem/context-document-writer.d.ts +15 -0
  71. package/dist/adapters/filesystem/context-document-writer.js +112 -0
  72. package/dist/adapters/filesystem/diagnostics-journal.d.ts +17 -0
  73. package/dist/adapters/filesystem/diagnostics-journal.js +130 -0
  74. package/dist/adapters/filesystem/external-flow-registry.d.ts +17 -0
  75. package/dist/adapters/filesystem/external-flow-registry.js +325 -0
  76. package/dist/adapters/filesystem/generation-session-store.d.ts +17 -11
  77. package/dist/adapters/filesystem/generation-session-store.js +281 -855
  78. package/dist/adapters/filesystem/generation-store/session-lock.d.ts +29 -0
  79. package/dist/adapters/filesystem/generation-store/session-lock.js +202 -0
  80. package/dist/adapters/filesystem/generation-store/session-transitions.d.ts +24 -0
  81. package/dist/adapters/filesystem/generation-store/session-transitions.js +340 -0
  82. package/dist/adapters/filesystem/generation-store/store-files.d.ts +50 -0
  83. package/dist/adapters/filesystem/generation-store/store-files.js +363 -0
  84. package/dist/adapters/filesystem/journey-composition-store.d.ts +23 -0
  85. package/dist/adapters/filesystem/journey-composition-store.js +151 -0
  86. package/dist/adapters/filesystem/knowledge-registry.d.ts +12 -0
  87. package/dist/adapters/filesystem/knowledge-registry.js +223 -0
  88. package/dist/adapters/filesystem/project-bound-file.js +3 -5
  89. package/dist/adapters/filesystem/project-file-inspector.d.ts +2 -0
  90. package/dist/adapters/filesystem/project-file-inspector.js +57 -28
  91. package/dist/adapters/filesystem/project-identity-inspector.d.ts +7 -0
  92. package/dist/adapters/filesystem/project-identity-inspector.js +215 -0
  93. package/dist/adapters/filesystem/project-inventory-inspector.d.ts +8 -0
  94. package/dist/adapters/filesystem/project-inventory-inspector.js +93 -0
  95. package/dist/adapters/filesystem/project-module-discoverer.d.ts +6 -0
  96. package/dist/adapters/filesystem/project-module-discoverer.js +158 -0
  97. package/dist/adapters/filesystem/skill-installer.d.ts +7 -2
  98. package/dist/adapters/filesystem/skill-installer.js +40 -11
  99. package/dist/adapters/filesystem/workspace-layout.d.ts +7 -0
  100. package/dist/adapters/filesystem/workspace-layout.js +57 -0
  101. package/dist/adapters/git/node-git-diff.d.ts +17 -0
  102. package/dist/adapters/git/node-git-diff.js +114 -0
  103. package/dist/adapters/process/node-detached-process-launcher.d.ts +6 -0
  104. package/dist/adapters/process/node-detached-process-launcher.js +96 -0
  105. package/dist/adapters/process/node-process-runner.js +11 -2
  106. package/dist/adapters/prompt/inquirer-align-prompt.d.ts +27 -0
  107. package/dist/adapters/prompt/inquirer-align-prompt.js +65 -0
  108. package/dist/adapters/prompt/inquirer-generation-prompt.js +3 -0
  109. package/dist/adapters/prompt/inquirer-recorder-prompt.d.ts +9 -1
  110. package/dist/adapters/prompt/inquirer-recorder-prompt.js +63 -0
  111. package/dist/adapters/runtime/adb-runtime-backend.d.ts +67 -0
  112. package/dist/adapters/runtime/adb-runtime-backend.js +206 -0
  113. package/dist/adapters/runtime/fake-runtime-backend.d.ts +87 -0
  114. package/dist/adapters/runtime/fake-runtime-backend.js +240 -0
  115. package/dist/adapters/runtime/mobile-mcp/mcp-tool-client.d.ts +45 -0
  116. package/dist/adapters/runtime/mobile-mcp/mcp-tool-client.js +153 -0
  117. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-errors.d.ts +23 -0
  118. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-errors.js +39 -0
  119. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-responses.d.ts +20 -0
  120. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-responses.js +180 -0
  121. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-runtime-backend.d.ts +78 -0
  122. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-runtime-backend.js +379 -0
  123. package/dist/adapters/runtime/mobile-mcp/mobile-mcp-tools.d.ts +46 -0
  124. package/dist/adapters/runtime/session-adb-view.d.ts +53 -0
  125. package/dist/adapters/runtime/session-adb-view.js +193 -0
  126. package/dist/adapters/runtime/session-backed-ports.d.ts +21 -0
  127. package/dist/adapters/runtime/session-backed-ports.js +43 -0
  128. package/dist/adapters/runtime/shared-session-runtime-backend.d.ts +12 -0
  129. package/dist/adapters/runtime/shared-session-runtime-backend.js +64 -0
  130. package/dist/adapters/ui/auto-ui-snapshot-provider.d.ts +8 -0
  131. package/dist/adapters/ui/auto-ui-snapshot-provider.js +48 -0
  132. package/dist/adapters/ui/device-layout-temp.d.ts +6 -0
  133. package/dist/adapters/ui/device-layout-temp.js +18 -0
  134. package/dist/adapters/ui/device-ui-environment.d.ts +13 -0
  135. package/dist/adapters/ui/device-ui-environment.js +81 -0
  136. package/dist/adapters/ui/layout-normalization.d.ts +9 -0
  137. package/dist/adapters/ui/layout-normalization.js +44 -0
  138. package/dist/adapters/ui/ui-snapshot-error.d.ts +11 -0
  139. package/dist/adapters/ui/ui-snapshot-error.js +12 -0
  140. package/dist/adapters/ui/ui-snapshot-support.d.ts +15 -0
  141. package/dist/adapters/ui/ui-snapshot-support.js +12 -0
  142. package/dist/application/align/align-service.d.ts +42 -0
  143. package/dist/application/align/align-service.js +106 -0
  144. package/dist/application/assertion/expectation-evaluator.d.ts +18 -5
  145. package/dist/application/assertion/expectation-evaluator.js +156 -18
  146. package/dist/application/assertion/guarded-expectation.d.ts +45 -0
  147. package/dist/application/assertion/guarded-expectation.js +74 -0
  148. package/dist/application/checkpoint/baseline-capturer.d.ts +26 -0
  149. package/dist/application/checkpoint/baseline-capturer.js +163 -0
  150. package/dist/application/checkpoint/baseline-error.d.ts +5 -0
  151. package/dist/application/checkpoint/baseline-error.js +8 -0
  152. package/dist/application/checkpoint/baseline-service.d.ts +31 -0
  153. package/dist/application/checkpoint/baseline-service.js +147 -0
  154. package/dist/application/checkpoint/checkpoint-evaluator.d.ts +35 -0
  155. package/dist/application/checkpoint/checkpoint-evaluator.js +415 -0
  156. package/dist/application/checkpoint/regression-comparator.d.ts +18 -0
  157. package/dist/application/checkpoint/regression-comparator.js +192 -0
  158. package/dist/application/collector/logcat-collector.d.ts +22 -1
  159. package/dist/application/collector/logcat-collector.js +103 -15
  160. package/dist/application/collector/logcat-event.d.ts +8 -0
  161. package/dist/application/collector/logcat-event.js +79 -0
  162. package/dist/application/collector/logcat-stop.d.ts +2 -0
  163. package/dist/application/collector/logcat-stop.js +11 -0
  164. package/dist/application/context/context-generator.d.ts +45 -0
  165. package/dist/application/context/context-generator.js +228 -0
  166. package/dist/application/context/context-loader.d.ts +40 -0
  167. package/dist/application/context/context-loader.js +223 -0
  168. package/dist/application/context/context-refresher.d.ts +59 -0
  169. package/dist/application/context/context-refresher.js +349 -0
  170. package/dist/application/context/context-rehasher.d.ts +36 -0
  171. package/dist/application/context/context-rehasher.js +110 -0
  172. package/dist/application/context/context-validator.d.ts +23 -1
  173. package/dist/application/context/context-validator.js +116 -9
  174. package/dist/application/context/evidence-hash.d.ts +1 -0
  175. package/dist/application/context/evidence-hash.js +125 -0
  176. package/dist/application/context/evidence-match.d.ts +9 -0
  177. package/dist/application/context/evidence-match.js +8 -0
  178. package/dist/application/context/shard-identity.d.ts +2 -0
  179. package/dist/application/context/shard-identity.js +7 -0
  180. package/dist/application/contract/contract-loader.d.ts +25 -0
  181. package/dist/application/contract/contract-loader.js +68 -0
  182. package/dist/application/contract/contract-review.d.ts +25 -0
  183. package/dist/application/contract/contract-review.js +51 -0
  184. package/dist/application/contract/contract-verifier.d.ts +53 -0
  185. package/dist/application/contract/contract-verifier.js +645 -0
  186. package/dist/application/devices/resolve-device-assignments.d.ts +21 -0
  187. package/dist/application/devices/resolve-device-assignments.js +60 -0
  188. package/dist/application/diagnosis/failure-classifier.d.ts +23 -0
  189. package/dist/application/diagnosis/failure-classifier.js +179 -0
  190. package/dist/application/diagnostics/diagnostics-exporter.d.ts +29 -0
  191. package/dist/application/diagnostics/diagnostics-exporter.js +283 -0
  192. package/dist/application/diagnostics/ui-capture-telemetry.d.ts +16 -0
  193. package/dist/application/diagnostics/ui-capture-telemetry.js +81 -0
  194. package/dist/application/doctor/doctor-service.d.ts +36 -3
  195. package/dist/application/doctor/doctor-service.js +255 -25
  196. package/dist/application/generation/generation-app-preparer.d.ts +20 -0
  197. package/dist/application/generation/generation-app-preparer.js +28 -0
  198. package/dist/application/generation/generation-config-service.d.ts +21 -0
  199. package/dist/application/generation/generation-config-service.js +53 -0
  200. package/dist/application/generation/generation-confirmation-service.d.ts +14 -3
  201. package/dist/application/generation/generation-confirmation-service.js +109 -24
  202. package/dist/application/generation/generation-context-snapshot.d.ts +6 -0
  203. package/dist/application/generation/generation-context-snapshot.js +29 -0
  204. package/dist/application/generation/generation-finalizer.d.ts +15 -9
  205. package/dist/application/generation/generation-finalizer.js +167 -70
  206. package/dist/application/generation/generation-publisher.js +12 -8
  207. package/dist/application/generation/generation-recovery-service.d.ts +35 -0
  208. package/dist/application/generation/generation-recovery-service.js +144 -0
  209. package/dist/application/generation/generation-reopen-service.d.ts +15 -0
  210. package/dist/application/generation/generation-reopen-service.js +37 -0
  211. package/dist/application/generation/generation-replace-service.d.ts +32 -0
  212. package/dist/application/generation/generation-replace-service.js +116 -0
  213. package/dist/application/generation/generation-starter.d.ts +44 -4
  214. package/dist/application/generation/generation-starter.js +175 -8
  215. package/dist/application/generation/generation-step-executor.d.ts +67 -5
  216. package/dist/application/generation/generation-step-executor.js +471 -108
  217. package/dist/application/generation/proposed-step-validator.js +96 -30
  218. package/dist/application/generation/replay-policy-loader.d.ts +16 -0
  219. package/dist/application/generation/replay-policy-loader.js +29 -0
  220. package/dist/application/generation/risk-evaluator.d.ts +4 -1
  221. package/dist/application/generation/risk-evaluator.js +118 -3
  222. package/dist/application/generation/runtime-observer.d.ts +39 -7
  223. package/dist/application/generation/runtime-observer.js +193 -24
  224. package/dist/application/impact/impact-resolver.d.ts +32 -0
  225. package/dist/application/impact/impact-resolver.js +160 -0
  226. package/dist/application/init/init-service.js +26 -13
  227. package/dist/application/interaction/action-executor.d.ts +3 -2
  228. package/dist/application/interaction/action-executor.js +11 -1
  229. package/dist/application/interaction/action-target.d.ts +17 -0
  230. package/dist/application/interaction/action-target.js +40 -0
  231. package/dist/application/interaction/external-step-runner.d.ts +153 -0
  232. package/dist/application/interaction/external-step-runner.js +332 -0
  233. package/dist/application/interaction/fallback-resolver.d.ts +6 -3
  234. package/dist/application/interaction/fallback-resolver.js +7 -5
  235. package/dist/application/interaction/scroll-to-executor.d.ts +17 -3
  236. package/dist/application/interaction/scroll-to-executor.js +118 -36
  237. package/dist/application/journey/external-flow-resolver.d.ts +25 -0
  238. package/dist/application/journey/external-flow-resolver.js +22 -0
  239. package/dist/application/journey/journey-check-service.d.ts +54 -0
  240. package/dist/application/journey/journey-check-service.js +207 -0
  241. package/dist/application/journey/journey-promoter.d.ts +26 -0
  242. package/dist/application/journey/journey-promoter.js +123 -0
  243. package/dist/application/journey/journey-resolver.d.ts +42 -0
  244. package/dist/application/journey/journey-resolver.js +239 -0
  245. package/dist/application/journey/journey-retirer.d.ts +25 -0
  246. package/dist/application/journey/journey-retirer.js +87 -0
  247. package/dist/application/knowledge/anchor-resolver.d.ts +36 -0
  248. package/dist/application/knowledge/anchor-resolver.js +110 -0
  249. package/dist/application/knowledge/knowledge-loader.d.ts +16 -0
  250. package/dist/application/knowledge/knowledge-loader.js +36 -0
  251. package/dist/application/locator/layout-failure-summary.d.ts +2 -0
  252. package/dist/application/locator/layout-failure-summary.js +67 -0
  253. package/dist/application/locator/layout-traversal.d.ts +11 -0
  254. package/dist/application/locator/layout-traversal.js +18 -0
  255. package/dist/application/locator/locator-resolver.d.ts +13 -1
  256. package/dist/application/locator/locator-resolver.js +182 -18
  257. package/dist/application/observe/observe-service.d.ts +20 -0
  258. package/dist/application/observe/observe-service.js +91 -0
  259. package/dist/application/project/project-describer.d.ts +14 -6
  260. package/dist/application/project/project-describer.js +38 -5
  261. package/dist/application/recognition/screen-detector.d.ts +28 -0
  262. package/dist/application/recognition/screen-detector.js +111 -0
  263. package/dist/application/recorder/locator-selector.js +151 -17
  264. package/dist/application/recorder/recorder-service.d.ts +16 -4
  265. package/dist/application/recorder/recorder-service.js +420 -128
  266. package/dist/application/report/report-writer.d.ts +5 -0
  267. package/dist/application/report/report-writer.js +17 -1
  268. package/dist/application/runtime/cold-launch.d.ts +28 -0
  269. package/dist/application/runtime/cold-launch.js +59 -0
  270. package/dist/application/runtime/step-runner.d.ts +49 -4
  271. package/dist/application/runtime/step-runner.js +721 -130
  272. package/dist/application/runtime/verify-runtime.d.ts +57 -7
  273. package/dist/application/runtime/verify-runtime.js +577 -175
  274. package/dist/application/ui/cached-ui-snapshot-provider.d.ts +45 -0
  275. package/dist/application/ui/cached-ui-snapshot-provider.js +111 -0
  276. package/dist/application/ui/observed-ui-snapshot-provider.d.ts +15 -0
  277. package/dist/application/ui/observed-ui-snapshot-provider.js +66 -0
  278. package/dist/application/ui/ui-snapshot-lifecycle.d.ts +2 -0
  279. package/dist/application/ui/ui-snapshot-lifecycle.js +8 -0
  280. package/dist/application/ui/ui-stability-probe.d.ts +9 -0
  281. package/dist/application/ui/ui-stability-probe.js +24 -0
  282. package/dist/application/wait/idle-advice.d.ts +6 -0
  283. package/dist/application/wait/idle-advice.js +27 -0
  284. package/dist/application/wait/idle-profiles.d.ts +15 -0
  285. package/dist/application/wait/idle-profiles.js +75 -0
  286. package/dist/application/wait/idle-waiter.d.ts +28 -4
  287. package/dist/application/wait/idle-waiter.js +201 -15
  288. package/dist/cli/commands/align.d.ts +3 -0
  289. package/dist/cli/commands/align.js +124 -0
  290. package/dist/cli/commands/baseline.d.ts +3 -0
  291. package/dist/cli/commands/baseline.js +130 -0
  292. package/dist/cli/commands/context.js +300 -27
  293. package/dist/cli/commands/contract.d.ts +3 -0
  294. package/dist/cli/commands/contract.js +120 -0
  295. package/dist/cli/commands/diagnose.d.ts +3 -0
  296. package/dist/cli/commands/diagnose.js +84 -0
  297. package/dist/cli/commands/doctor.js +16 -9
  298. package/dist/cli/commands/failure.d.ts +3 -0
  299. package/dist/cli/commands/failure.js +63 -0
  300. package/dist/cli/commands/generation/lifecycle-commands.d.ts +5 -0
  301. package/dist/cli/commands/generation/lifecycle-commands.js +211 -0
  302. package/dist/cli/commands/generation/session-commands.d.ts +11 -0
  303. package/dist/cli/commands/generation/session-commands.js +472 -0
  304. package/dist/cli/commands/generation/shared.d.ts +1414 -0
  305. package/dist/cli/commands/generation/shared.js +291 -0
  306. package/dist/cli/commands/generation/step-commands.d.ts +8 -0
  307. package/dist/cli/commands/generation/step-commands.js +315 -0
  308. package/dist/cli/commands/generation.js +10 -507
  309. package/dist/cli/commands/impact.d.ts +3 -0
  310. package/dist/cli/commands/impact.js +87 -0
  311. package/dist/cli/commands/init.js +13 -6
  312. package/dist/cli/commands/journey.d.ts +3 -0
  313. package/dist/cli/commands/journey.js +382 -0
  314. package/dist/cli/commands/knowledge.d.ts +3 -0
  315. package/dist/cli/commands/knowledge.js +93 -0
  316. package/dist/cli/commands/observe.d.ts +3 -0
  317. package/dist/cli/commands/observe.js +127 -0
  318. package/dist/cli/commands/project.js +2 -1
  319. package/dist/cli/commands/record.js +18 -5
  320. package/dist/cli/commands/verify.js +326 -64
  321. package/dist/cli/dependencies.d.ts +136 -1
  322. package/dist/cli/dependencies.js +504 -52
  323. package/dist/cli/diagnostics-recorder.d.ts +31 -0
  324. package/dist/cli/diagnostics-recorder.js +82 -0
  325. package/dist/cli/diff-verification.d.ts +41 -0
  326. package/dist/cli/diff-verification.js +192 -0
  327. package/dist/cli/main.d.ts +1 -1
  328. package/dist/cli/main.js +107 -2
  329. package/dist/cli/output.d.ts +5 -3
  330. package/dist/cli/output.js +12 -0
  331. package/dist/cli/program.js +21 -1
  332. package/dist/cli/project-root.d.ts +1 -0
  333. package/dist/cli/project-root.js +6 -0
  334. package/dist/cli/runtime-selection.d.ts +22 -0
  335. package/dist/cli/runtime-selection.js +92 -0
  336. package/dist/cli/version.d.ts +1 -0
  337. package/dist/cli/version.js +14 -0
  338. package/dist/cli/workspace-guard.d.ts +2 -0
  339. package/dist/cli/workspace-guard.js +3 -0
  340. package/dist/domain/binding-reference.d.ts +4 -0
  341. package/dist/domain/binding-reference.js +23 -0
  342. package/dist/domain/checkpoint.d.ts +404 -0
  343. package/dist/domain/checkpoint.js +297 -0
  344. package/dist/domain/config.d.ts +107 -1
  345. package/dist/domain/config.js +52 -6
  346. package/dist/domain/contract.d.ts +413 -0
  347. package/dist/domain/contract.js +196 -0
  348. package/dist/domain/diagnostics.d.ts +1396 -0
  349. package/dist/domain/diagnostics.js +193 -0
  350. package/dist/domain/external-flow.d.ts +493 -0
  351. package/dist/domain/external-flow.js +15 -0
  352. package/dist/domain/failure-classification.d.ts +176 -0
  353. package/dist/domain/failure-classification.js +169 -0
  354. package/dist/domain/failure.d.ts +2 -1
  355. package/dist/domain/failure.js +123 -0
  356. package/dist/domain/generation.d.ts +1671 -132
  357. package/dist/domain/generation.js +202 -13
  358. package/dist/domain/geometry.d.ts +13 -0
  359. package/dist/domain/geometry.js +16 -0
  360. package/dist/domain/impact.d.ts +71 -0
  361. package/dist/domain/impact.js +76 -0
  362. package/dist/domain/init.d.ts +12 -4
  363. package/dist/domain/init.js +24 -18
  364. package/dist/domain/journey-composition.d.ts +2285 -0
  365. package/dist/domain/journey-composition.js +85 -0
  366. package/dist/domain/journey-lifecycle.d.ts +10 -0
  367. package/dist/domain/journey-lifecycle.js +9 -0
  368. package/dist/domain/journey.d.ts +2419 -212
  369. package/dist/domain/journey.js +384 -14
  370. package/dist/domain/knowledge.d.ts +165 -0
  371. package/dist/domain/knowledge.js +188 -0
  372. package/dist/domain/layout.d.ts +34 -5
  373. package/dist/domain/layout.js +64 -6
  374. package/dist/domain/locator-evidence.d.ts +3 -0
  375. package/dist/domain/locator-evidence.js +36 -0
  376. package/dist/domain/logcat-event.d.ts +54 -0
  377. package/dist/domain/logcat-event.js +40 -0
  378. package/dist/domain/observation.d.ts +33 -0
  379. package/dist/domain/observation.js +18 -0
  380. package/dist/domain/project-context.d.ts +219 -1
  381. package/dist/domain/project-context.js +209 -6
  382. package/dist/domain/proposed-step.d.ts +340 -60
  383. package/dist/domain/proposed-step.js +23 -3
  384. package/dist/domain/report.d.ts +1455 -28
  385. package/dist/domain/report.js +211 -14
  386. package/dist/domain/runtime-snapshot.d.ts +58 -1
  387. package/dist/domain/runtime-snapshot.js +14 -3
  388. package/dist/domain/runtime.d.ts +50 -0
  389. package/dist/domain/runtime.js +36 -0
  390. package/dist/domain/system-app-profiles.d.ts +6 -0
  391. package/dist/domain/system-app-profiles.js +43 -0
  392. package/dist/domain/ui-backend.d.ts +28 -0
  393. package/dist/domain/ui-backend.js +33 -0
  394. package/dist/domain/ui-cache.d.ts +11 -0
  395. package/dist/domain/ui-cache.js +10 -0
  396. package/dist/domain/verify-receipt.d.ts +17 -0
  397. package/dist/domain/verify-receipt.js +17 -0
  398. package/dist/domain/window-hierarchy.d.ts +84 -0
  399. package/dist/domain/window-hierarchy.js +172 -0
  400. package/dist/domain/workflow-manifest.d.ts +77 -0
  401. package/dist/domain/workflow-manifest.js +136 -0
  402. package/dist/domain/workspace.d.ts +30 -0
  403. package/dist/domain/workspace.js +74 -0
  404. package/dist/ports/adb.d.ts +34 -1
  405. package/dist/ports/align-prompt.d.ts +11 -0
  406. package/dist/ports/align-prompt.js +6 -0
  407. package/dist/ports/anchor-resolver.d.ts +30 -0
  408. package/dist/ports/anchor-resolver.js +1 -0
  409. package/dist/ports/annotated-screen-resolver.d.ts +4 -0
  410. package/dist/ports/annotated-screen-resolver.js +1 -0
  411. package/dist/ports/camera-probe.d.ts +23 -0
  412. package/dist/ports/camera-probe.js +8 -0
  413. package/dist/ports/context-document-writer.d.ts +24 -0
  414. package/dist/ports/context-document-writer.js +1 -0
  415. package/dist/ports/detached-process-launcher.d.ts +12 -0
  416. package/dist/ports/detached-process-launcher.js +1 -0
  417. package/dist/ports/diagnostics.d.ts +15 -0
  418. package/dist/ports/diagnostics.js +1 -0
  419. package/dist/ports/external-flow-registry.d.ts +37 -0
  420. package/dist/ports/external-flow-registry.js +1 -0
  421. package/dist/ports/generation-prompt.d.ts +2 -1
  422. package/dist/ports/generation-session-store.d.ts +12 -2
  423. package/dist/ports/git-diff.d.ts +9 -0
  424. package/dist/ports/git-diff.js +1 -0
  425. package/dist/ports/journey-composition-store.d.ts +17 -0
  426. package/dist/ports/journey-composition-store.js +1 -0
  427. package/dist/ports/knowledge-registry.d.ts +20 -0
  428. package/dist/ports/knowledge-registry.js +1 -0
  429. package/dist/ports/process-runner.d.ts +7 -0
  430. package/dist/ports/project-file-inspector.d.ts +1 -0
  431. package/dist/ports/project-identity-inspector.d.ts +24 -0
  432. package/dist/ports/project-identity-inspector.js +1 -0
  433. package/dist/ports/project-inventory-inspector.d.ts +21 -0
  434. package/dist/ports/project-inventory-inspector.js +1 -0
  435. package/dist/ports/project-module-discoverer.d.ts +26 -0
  436. package/dist/ports/project-module-discoverer.js +1 -0
  437. package/dist/ports/recorder-prompt.d.ts +10 -1
  438. package/dist/ports/runtime-backend.d.ts +89 -0
  439. package/dist/ports/runtime-backend.js +13 -0
  440. package/dist/ports/runtime-capability.d.ts +12 -0
  441. package/dist/ports/runtime-capability.js +20 -0
  442. package/dist/ports/runtime-session-ports.d.ts +25 -0
  443. package/dist/ports/runtime-session-ports.js +1 -0
  444. package/dist/ports/screenshot.d.ts +11 -0
  445. package/dist/ports/screenshot.js +1 -0
  446. package/dist/ports/skill-installer.d.ts +2 -2
  447. package/dist/ports/ui-snapshot.d.ts +35 -0
  448. package/dist/ports/ui-snapshot.js +1 -0
  449. package/dist/ports/ui-stability.d.ts +19 -0
  450. package/dist/ports/ui-stability.js +1 -0
  451. package/dist/ports/workspace-layout.d.ts +4 -0
  452. package/dist/ports/workspace-layout.js +1 -0
  453. package/dist/shared/errors.d.ts +2 -0
  454. package/dist/shared/errors.js +22 -0
  455. package/dist/shared/paths.d.ts +2 -0
  456. package/dist/shared/paths.js +24 -0
  457. package/dist/shared/strings.d.ts +2 -0
  458. package/dist/shared/strings.js +16 -0
  459. package/package.json +7 -2
  460. package/assets/skills/taphound-ai-journey/GUIDE.md +0 -862
  461. package/assets/skills/taphound-ai-journey/SKILL.md +0 -377
  462. package/assets/skills/taphound-ai-journey/prompts/analyze-project.md +0 -526
  463. package/assets/skills/taphound-ai-journey/prompts/generate-step.md +0 -109
  464. package/assets/skills/taphound-ai-journey/schemas/project-context.json +0 -81
  465. package/assets/skills/taphound-ai-journey/templates/project-context.example.json +0 -49
  466. package/dist/ports/android-cli.d.ts +0 -21
  467. /package/dist/{ports/android-cli.js → adapters/runtime/mobile-mcp/mobile-mcp-tools.js} +0 -0
@@ -0,0 +1,15 @@
1
+ import type { DisplayViewport } from "../../domain/geometry.js";
2
+ import type { LayoutElement } from "../../domain/layout.js";
3
+ import type { UiBackendDescriptor } from "../../domain/ui-backend.js";
4
+ import type { UiSnapshot } from "../../ports/ui-snapshot.js";
5
+ export interface UiSnapshotTiming {
6
+ now?: (() => Date) | undefined;
7
+ createObservationId?: (() => string) | undefined;
8
+ }
9
+ export declare function snapshotFromCapture(input: {
10
+ startedAt: number;
11
+ roots: readonly LayoutElement[];
12
+ backend: UiBackendDescriptor;
13
+ viewport: DisplayViewport;
14
+ timing: UiSnapshotTiming;
15
+ }): UiSnapshot;
@@ -0,0 +1,12 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { performance } from "node:perf_hooks";
3
+ export function snapshotFromCapture(input) {
4
+ return {
5
+ observationId: (input.timing.createObservationId ?? randomUUID)(),
6
+ capturedAt: (input.timing.now ?? (() => new Date()))().toISOString(),
7
+ durationMs: performance.now() - input.startedAt,
8
+ backend: input.backend,
9
+ viewport: input.viewport,
10
+ roots: input.roots
11
+ };
12
+ }
@@ -0,0 +1,42 @@
1
+ import type { FailureCode } from "../../domain/failure.js";
2
+ import type { AdbPort } from "../../ports/adb.js";
3
+ import type { AlignPromptPort } from "../../ports/align-prompt.js";
4
+ import type { CameraProbePort, CameraProbeResult } from "../../ports/camera-probe.js";
5
+ import type { ExternalFlowRegistry, WriteExternalFlowResult } from "../../ports/external-flow-registry.js";
6
+ export declare class AlignError extends Error {
7
+ readonly code: FailureCode;
8
+ constructor(code: FailureCode, message: string);
9
+ }
10
+ export interface AlignServiceDeps {
11
+ adb: Pick<AdbPort, "devices">;
12
+ probe: CameraProbePort;
13
+ prompt: AlignPromptPort;
14
+ registry: ExternalFlowRegistry;
15
+ }
16
+ export interface AlignCameraInput {
17
+ projectRoot: string;
18
+ deviceSerial?: string | undefined;
19
+ force?: boolean | undefined;
20
+ json: boolean;
21
+ signal?: AbortSignal | undefined;
22
+ }
23
+ export interface AlignCameraWrittenResult {
24
+ status: "written";
25
+ exitCode: 0;
26
+ flow: WriteExternalFlowResult & {
27
+ name: string;
28
+ steps: number;
29
+ };
30
+ probe: CameraProbeResult;
31
+ deviceSerial: string;
32
+ }
33
+ export interface AlignCameraCancelledResult {
34
+ status: "cancelled";
35
+ exitCode: 2;
36
+ }
37
+ export type AlignCameraResult = AlignCameraWrittenResult | AlignCameraCancelledResult;
38
+ export declare class AlignService {
39
+ private readonly deps;
40
+ constructor(deps: AlignServiceDeps);
41
+ alignCamera(input: AlignCameraInput): Promise<AlignCameraResult>;
42
+ }
@@ -0,0 +1,106 @@
1
+ import { CameraProbeError } from "../../ports/camera-probe.js";
2
+ export class AlignError extends Error {
3
+ code;
4
+ constructor(code, message) {
5
+ super(message);
6
+ this.name = "AlignError";
7
+ this.code = code;
8
+ }
9
+ }
10
+ const FLOW_NAME = "camera/photo-capture";
11
+ function selectDevice(devices, requested) {
12
+ const online = devices.filter((device) => device.status === "device");
13
+ if (requested !== undefined) {
14
+ return online.find((device) => device.serial === requested)?.serial;
15
+ }
16
+ return online.length === 1 ? online[0]?.serial : undefined;
17
+ }
18
+ function buildFlow(probeResult, deviceSerial) {
19
+ const steps = [
20
+ { action: "wait", expectedActivity: probeResult.activityName },
21
+ {
22
+ action: "click",
23
+ locator: { resourceId: probeResult.shutterResourceId },
24
+ expectedActivity: probeResult.activityName
25
+ }
26
+ ];
27
+ if (probeResult.confirmResourceId !== undefined) {
28
+ steps.push({
29
+ action: "click",
30
+ locator: { resourceId: probeResult.confirmResourceId },
31
+ expectedActivity: probeResult.confirmActivityName
32
+ ?? probeResult.activityName
33
+ });
34
+ }
35
+ return {
36
+ version: 1,
37
+ kind: "externalFlow",
38
+ name: FLOW_NAME,
39
+ description: `Auto-generated by \`taphound align camera\` for ${probeResult.packageName} on ${deviceSerial}`,
40
+ escapedPackageName: probeResult.packageName,
41
+ expectedEscapeActivity: probeResult.activityName,
42
+ includes: [],
43
+ steps
44
+ };
45
+ }
46
+ export class AlignService {
47
+ deps;
48
+ constructor(deps) {
49
+ this.deps = deps;
50
+ }
51
+ async alignCamera(input) {
52
+ const devices = await this.deps.adb.devices(input.signal);
53
+ const deviceSerial = selectDevice(devices, input.deviceSerial);
54
+ if (deviceSerial === undefined) {
55
+ throw new AlignError("ALIGN_DEVICE_UNAVAILABLE", input.deviceSerial === undefined
56
+ ? `Expected exactly one online device, found ${String(devices.filter((d) => d.status === "device").length)}`
57
+ : `Requested device is not online: ${input.deviceSerial}`);
58
+ }
59
+ let probeResult;
60
+ try {
61
+ probeResult = await this.deps.probe.probe({
62
+ deviceSerial,
63
+ ...(input.signal === undefined ? {} : { signal: input.signal })
64
+ });
65
+ }
66
+ catch (error) {
67
+ if (error instanceof CameraProbeError) {
68
+ throw new AlignError(error.code, error.message);
69
+ }
70
+ throw error;
71
+ }
72
+ if (!input.json) {
73
+ const confirmed = await this.deps.prompt.confirmWrite({
74
+ values: probeResult,
75
+ targetPath: `.taphound/flows/external/${FLOW_NAME}.json`
76
+ });
77
+ if (!confirmed) {
78
+ return { status: "cancelled", exitCode: 2 };
79
+ }
80
+ }
81
+ const flow = buildFlow(probeResult, deviceSerial);
82
+ let writeResult;
83
+ try {
84
+ writeResult = await this.deps.registry.write({
85
+ projectRoot: input.projectRoot,
86
+ name: FLOW_NAME,
87
+ flow,
88
+ ...(input.force === undefined ? {} : { force: input.force })
89
+ });
90
+ }
91
+ catch (error) {
92
+ const message = error instanceof Error ? error.message : String(error);
93
+ if (/already exists/i.test(message)) {
94
+ throw new AlignError("ALIGN_FLOW_EXISTS", `External Flow already exists: ${FLOW_NAME} (use --force to overwrite)`);
95
+ }
96
+ throw error;
97
+ }
98
+ return {
99
+ status: "written",
100
+ exitCode: 0,
101
+ flow: { ...writeResult, name: FLOW_NAME, steps: flow.steps.length },
102
+ probe: probeResult,
103
+ deviceSerial
104
+ };
105
+ }
106
+ }
@@ -1,14 +1,17 @@
1
1
  import type { FailureCode } from "../../domain/failure.js";
2
2
  import type { Expectation } from "../../domain/journey.js";
3
+ import type { StepReport } from "../../domain/report.js";
3
4
  import type { LayoutElement } from "../../domain/layout.js";
4
5
  import type { AdbPort } from "../../ports/adb.js";
5
- import type { AndroidCliPort } from "../../ports/android-cli.js";
6
6
  import type { Clock } from "../../ports/clock.js";
7
- import type { LogcatCollector } from "../collector/logcat-collector.js";
7
+ import type { UiSnapshotProvider } from "../../ports/ui-snapshot.js";
8
+ import type { LogcatCollector, LogcatLine } from "../collector/logcat-collector.js";
8
9
  export interface ExpectationContext {
9
10
  packageName: string;
10
11
  deviceSerial: string;
11
12
  stepStartedAt: number;
13
+ runStartedAt?: number | undefined;
14
+ markers?: ReadonlyMap<string, number> | undefined;
12
15
  }
13
16
  export interface ExpectationObservationInput {
14
17
  timeoutMs: number;
@@ -38,24 +41,34 @@ export type ExpectationResult = {
38
41
  durationMs: number;
39
42
  actual?: string | undefined;
40
43
  matchedLine?: string | undefined;
44
+ logcatEvent?: NonNullable<StepReport["expectation"]>["logcatEvent"];
41
45
  } | {
42
46
  status: "failed";
43
47
  type: Expectation["type"];
44
- code: Extract<FailureCode, "EXPECT_ACTIVITY_FAILED" | "EXPECT_ELEMENT_FAILED" | "EXPECT_LOGCAT_FAILED">;
48
+ code: Extract<FailureCode, "EXPECT_ACTIVITY_FAILED" | "EXPECT_ELEMENT_FAILED" | "EXPECT_LOGCAT_FAILED" | "EXPECT_LOGCAT_AMBIGUOUS">;
45
49
  message: string;
46
50
  durationMs: number;
47
51
  actual?: string | undefined;
52
+ logcatEvent?: NonNullable<StepReport["expectation"]>["logcatEvent"];
48
53
  } | {
49
54
  status: "cancelled";
50
55
  type: Expectation["type"];
51
56
  durationMs: number;
52
57
  };
58
+ type ElementExpectation = Extract<Expectation, {
59
+ type: "element";
60
+ }>;
61
+ export declare function elementPredicateMismatch(element: LayoutElement, expectation: ElementExpectation): string | undefined;
53
62
  export declare class ExpectationEvaluator {
54
63
  private readonly adb;
55
- private readonly androidCli;
64
+ private readonly uiSnapshotProvider;
56
65
  private readonly logcat;
57
66
  private readonly clock;
58
67
  private readonly pollIntervalMs;
59
- constructor(adb: AdbPort, androidCli: AndroidCliPort, logcat: LogcatCollector, clock: Clock, pollIntervalMs?: number);
68
+ private readonly matchedEvents;
69
+ constructor(adb: AdbPort, uiSnapshotProvider: UiSnapshotProvider, logcat: LogcatCollector, clock: Clock, pollIntervalMs?: number);
70
+ /** Internal runtime-only evidence, deliberately absent from JSON results. */
71
+ matchedEventFor(result: ExpectationResult): LogcatLine | undefined;
60
72
  evaluate(expectation: Expectation, context: ExpectationContext, signal?: AbortSignal, observations?: ExpectationObservationBoundary): Promise<ExpectationResult>;
61
73
  }
74
+ export {};
@@ -1,7 +1,18 @@
1
+ import { createHash } from "node:crypto";
2
+ import { matchesLogcatEvent, requestErrorClassFor } from "../collector/logcat-event.js";
1
3
  import { resolveLocator } from "../locator/locator-resolver.js";
2
- function hasElement(elements, locator) {
3
- return resolveLocator(elements, locator, { requireEnabled: false }).status
4
- === "found";
4
+ export function elementPredicateMismatch(element, expectation) {
5
+ if (expectation.enabled !== undefined
6
+ && element.enabled !== expectation.enabled) {
7
+ return `element ${element.id} enabled=${element.enabled ? "true" : "false"}`
8
+ + `, expected enabled=${expectation.enabled ? "true" : "false"}`;
9
+ }
10
+ if (expectation.clickable !== undefined
11
+ && (element.clickable === true) !== expectation.clickable) {
12
+ return `element ${element.id} clickable=${element.clickable === true ? "true" : "false"}`
13
+ + `, expected clickable=${expectation.clickable ? "true" : "false"}`;
14
+ }
15
+ return undefined;
5
16
  }
6
17
  function matchesLogcat(line, expectation, pattern) {
7
18
  if (line.tag !== expectation.tag
@@ -19,17 +30,22 @@ function isAborted(signal) {
19
30
  }
20
31
  export class ExpectationEvaluator {
21
32
  adb;
22
- androidCli;
33
+ uiSnapshotProvider;
23
34
  logcat;
24
35
  clock;
25
36
  pollIntervalMs;
26
- constructor(adb, androidCli, logcat, clock, pollIntervalMs = 100) {
37
+ matchedEvents = new WeakMap();
38
+ constructor(adb, uiSnapshotProvider, logcat, clock, pollIntervalMs = 100) {
27
39
  this.adb = adb;
28
- this.androidCli = androidCli;
40
+ this.uiSnapshotProvider = uiSnapshotProvider;
29
41
  this.logcat = logcat;
30
42
  this.clock = clock;
31
43
  this.pollIntervalMs = pollIntervalMs;
32
44
  }
45
+ /** Internal runtime-only evidence, deliberately absent from JSON results. */
46
+ matchedEventFor(result) {
47
+ return this.matchedEvents.get(result);
48
+ }
33
49
  async evaluate(expectation, context, signal, observations = {}) {
34
50
  const startedAt = this.clock.now();
35
51
  const logPattern = expectation.type === "logcat"
@@ -38,6 +54,43 @@ export class ExpectationEvaluator {
38
54
  : expectation.pattern)
39
55
  : undefined;
40
56
  let actual;
57
+ let elementObservation;
58
+ const window = expectation.type === "logcatEvent"
59
+ ? expectation.window
60
+ : undefined;
61
+ const windowStart = window === undefined
62
+ ? undefined
63
+ : window.from === "stepStart"
64
+ ? context.stepStartedAt
65
+ : window.from === "runStart"
66
+ ? context.runStartedAt
67
+ : context.markers?.get(window.markerId);
68
+ if (window !== undefined && windowStart === undefined) {
69
+ return {
70
+ status: "failed",
71
+ type: "logcatEvent",
72
+ code: "EXPECT_LOGCAT_FAILED",
73
+ message: "Logcat event window source is unavailable",
74
+ durationMs: 0
75
+ };
76
+ }
77
+ const eventEvidence = (matched) => window === undefined || windowStart === undefined
78
+ ? undefined
79
+ : {
80
+ matchedCount: matched.length,
81
+ ...(matched.length !== 1 || matched[0] === undefined
82
+ ? {}
83
+ : {
84
+ matchedLineSha256: createHash("sha256")
85
+ .update(matched[0].raw)
86
+ .digest("hex"),
87
+ ...(requestErrorClassFor(matched[0]) === undefined
88
+ ? {} : { requestErrorClass: requestErrorClassFor(matched[0]) })
89
+ }),
90
+ window,
91
+ startedAtMs: windowStart
92
+ };
93
+ let eventMatches = [];
41
94
  for (;;) {
42
95
  if (isAborted(signal)) {
43
96
  return {
@@ -95,11 +148,12 @@ export class ExpectationEvaluator {
95
148
  const observation = observations.layout === undefined
96
149
  ? {
97
150
  status: "observed",
98
- layout: await this.androidCli.layout({
99
- deviceSerial: context.deviceSerial,
151
+ layout: (await this.uiSnapshotProvider.capture({
152
+ reason: "expect",
153
+ freshness: "sameMutationEpoch",
100
154
  ...(signal === undefined ? {} : { signal }),
101
155
  timeoutMs: commandTimeoutMs
102
- })
156
+ })).roots
103
157
  }
104
158
  : await observations.layout({
105
159
  timeoutMs: commandTimeoutMs,
@@ -121,12 +175,34 @@ export class ExpectationEvaluator {
121
175
  durationMs: this.clock.now() - startedAt
122
176
  };
123
177
  }
124
- if (hasElement(observation.layout, expectation.locator)) {
125
- return {
126
- status: "passed",
127
- type: expectation.type,
128
- durationMs: this.clock.now() - startedAt
129
- };
178
+ const resolution = resolveLocator(observation.layout, expectation.locator, { requireEnabled: false });
179
+ if (expectation.absent === true) {
180
+ if (resolution.status === "failed"
181
+ && resolution.code === "LOCATOR_NOT_FOUND"
182
+ && resolution.evidenceMismatch !== true) {
183
+ return {
184
+ status: "passed",
185
+ type: expectation.type,
186
+ durationMs: this.clock.now() - startedAt
187
+ };
188
+ }
189
+ elementObservation = resolution.status === "found"
190
+ ? `expected absent element matched by ${resolution.matchedBy}`
191
+ : `expected absent element still resolvable: ${resolution.message}`;
192
+ }
193
+ else if (resolution.status === "found") {
194
+ const mismatch = elementPredicateMismatch(resolution.element, expectation);
195
+ if (mismatch === undefined) {
196
+ return {
197
+ status: "passed",
198
+ type: expectation.type,
199
+ durationMs: this.clock.now() - startedAt
200
+ };
201
+ }
202
+ elementObservation = mismatch;
203
+ }
204
+ else {
205
+ elementObservation = resolution.message;
130
206
  }
131
207
  break;
132
208
  }
@@ -142,6 +218,45 @@ export class ExpectationEvaluator {
142
218
  matchedLine: matched.raw
143
219
  };
144
220
  }
221
+ if (!this.logcat.completeSince(context.stepStartedAt)) {
222
+ const metadata = this.logcat.metadata();
223
+ return {
224
+ status: "failed",
225
+ type: expectation.type,
226
+ code: "EXPECT_LOGCAT_FAILED",
227
+ message: "Logcat evidence is incomplete in the step window"
228
+ + ` (droppedLines=${String(metadata.droppedLines ?? 0)},`
229
+ + ` droppedBytes=${String(metadata.droppedBytes ?? 0)},`
230
+ + ` lastDroppedAtMs=${String(metadata.lastDroppedAtMs ?? "unknown")})`,
231
+ durationMs: this.clock.now() - startedAt
232
+ };
233
+ }
234
+ break;
235
+ }
236
+ case "logcatEvent": {
237
+ if (windowStart === undefined || !this.logcat.completeSince(windowStart)) {
238
+ return {
239
+ status: "failed",
240
+ type: expectation.type,
241
+ code: "EXPECT_LOGCAT_FAILED",
242
+ message: "Logcat event evidence is incomplete in the declared window",
243
+ durationMs: this.clock.now() - startedAt,
244
+ logcatEvent: eventEvidence(eventMatches)
245
+ };
246
+ }
247
+ eventMatches = this.logcat
248
+ .linesBetween(windowStart, Math.min(this.clock.now(), startedAt + expectation.timeoutMs))
249
+ .filter((line) => matchesLogcatEvent(line, expectation));
250
+ if (eventMatches.length > 1) {
251
+ return {
252
+ status: "failed",
253
+ type: expectation.type,
254
+ code: "EXPECT_LOGCAT_AMBIGUOUS",
255
+ message: "Logcat event appeared more than once in the declared window",
256
+ durationMs: this.clock.now() - startedAt,
257
+ logcatEvent: eventEvidence(eventMatches)
258
+ };
259
+ }
145
260
  break;
146
261
  }
147
262
  }
@@ -159,7 +274,8 @@ export class ExpectationEvaluator {
159
274
  const codes = {
160
275
  activity: "EXPECT_ACTIVITY_FAILED",
161
276
  element: "EXPECT_ELEMENT_FAILED",
162
- logcat: "EXPECT_LOGCAT_FAILED"
277
+ logcat: "EXPECT_LOGCAT_FAILED",
278
+ logcatEvent: "EXPECT_LOGCAT_FAILED"
163
279
  };
164
280
  return {
165
281
  status: "failed",
@@ -177,14 +293,36 @@ export class ExpectationEvaluator {
177
293
  const codes = {
178
294
  activity: "EXPECT_ACTIVITY_FAILED",
179
295
  element: "EXPECT_ELEMENT_FAILED",
180
- logcat: "EXPECT_LOGCAT_FAILED"
296
+ logcat: "EXPECT_LOGCAT_FAILED",
297
+ logcatEvent: "EXPECT_LOGCAT_FAILED"
181
298
  };
299
+ if (expectation.type === "logcatEvent" && eventMatches.length === 1) {
300
+ const result = {
301
+ status: "passed",
302
+ type: expectation.type,
303
+ durationMs: elapsed,
304
+ logcatEvent: eventEvidence(eventMatches)
305
+ };
306
+ if (eventMatches[0] !== undefined) {
307
+ this.matchedEvents.set(result, eventMatches[0]);
308
+ }
309
+ return result;
310
+ }
182
311
  return {
183
312
  status: "failed",
184
313
  type: expectation.type,
185
314
  code: codes[expectation.type],
186
- message: `${expectation.type} Expect did not match before timeout`,
315
+ message: expectation.type === "logcatEvent"
316
+ ? "Logcat event did not appear before timeout"
317
+ : expectation.type === "element"
318
+ ? elementObservation === undefined
319
+ ? "element Expect did not match before timeout"
320
+ : `element Expect did not match before timeout: ${elementObservation}`
321
+ : `${expectation.type} Expect did not match before timeout`,
187
322
  durationMs: elapsed,
323
+ ...(expectation.type === "logcatEvent"
324
+ ? { logcatEvent: eventEvidence(eventMatches) }
325
+ : {}),
188
326
  ...(actual === undefined ? {} : { actual })
189
327
  };
190
328
  }
@@ -0,0 +1,45 @@
1
+ import type { Expectation } from "../../domain/journey.js";
2
+ import type { LayoutElement } from "../../domain/layout.js";
3
+ import type { ExpectationObservationBoundary, ExpectationObservationInput } from "./expectation-evaluator.js";
4
+ /**
5
+ * Engine-specific observation of the App under a bound identity. Each call
6
+ * re-checks the foreground package and process identity and throws when they
7
+ * no longer match; `layout` also re-checks them after the capture.
8
+ */
9
+ export interface GuardedExpectationProbe<TObservation extends {
10
+ layout: readonly LayoutElement[];
11
+ }> {
12
+ activity: (input: ExpectationObservationInput) => Promise<string>;
13
+ layout: (input: ExpectationObservationInput) => Promise<TObservation>;
14
+ /** Errors that must propagate instead of failing the observation. */
15
+ rethrow?: (error: unknown) => boolean;
16
+ }
17
+ /**
18
+ * Expectation observations shared by generated Replay and Generation. A guard
19
+ * violation becomes a failed observation, which the evaluator reports as
20
+ * `EXPECT_ACTIVITY_FAILED` or `EXPECT_ELEMENT_FAILED`. The first Layout
21
+ * observation reuses the settled post-action Layout, which the engine has
22
+ * already guarded, instead of capturing the same screen again.
23
+ */
24
+ export declare class GuardedExpectationObservations<TObservation extends {
25
+ layout: readonly LayoutElement[];
26
+ }> {
27
+ private readonly probe;
28
+ private seed;
29
+ private last;
30
+ constructor(probe: GuardedExpectationProbe<TObservation>, settled?: TObservation);
31
+ boundary(): ExpectationObservationBoundary;
32
+ /** The Layout observation the element expectation last resolved against. */
33
+ lastLayoutObservation(): TObservation | undefined;
34
+ private failed;
35
+ }
36
+ /**
37
+ * The foreground a passing expectation leaves behind. An `element`
38
+ * expectation is proven on the guarded Layout it resolved against and an
39
+ * `activity` expectation on the guarded Activity it matched; log expectations
40
+ * prove nothing about the screen, so the foreground must be re-checked.
41
+ */
42
+ export declare function settledExpectationForeground(expectation: Expectation, afterActivity: string): {
43
+ activity: string;
44
+ proven: boolean;
45
+ };
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Expectation observations shared by generated Replay and Generation. A guard
3
+ * violation becomes a failed observation, which the evaluator reports as
4
+ * `EXPECT_ACTIVITY_FAILED` or `EXPECT_ELEMENT_FAILED`. The first Layout
5
+ * observation reuses the settled post-action Layout, which the engine has
6
+ * already guarded, instead of capturing the same screen again.
7
+ */
8
+ export class GuardedExpectationObservations {
9
+ probe;
10
+ seed;
11
+ last;
12
+ constructor(probe, settled) {
13
+ this.probe = probe;
14
+ this.seed = settled;
15
+ }
16
+ boundary() {
17
+ return {
18
+ activity: async (input) => {
19
+ try {
20
+ return {
21
+ status: "observed",
22
+ activity: await this.probe.activity(input)
23
+ };
24
+ }
25
+ catch (error) {
26
+ return this.failed(error, "Expect Activity observation failed");
27
+ }
28
+ },
29
+ layout: async (input) => {
30
+ if (this.seed !== undefined) {
31
+ this.last = this.seed;
32
+ this.seed = undefined;
33
+ return { status: "observed", layout: this.last.layout };
34
+ }
35
+ try {
36
+ this.last = await this.probe.layout(input);
37
+ return { status: "observed", layout: this.last.layout };
38
+ }
39
+ catch (error) {
40
+ return this.failed(error, "Expect Layout observation failed");
41
+ }
42
+ }
43
+ };
44
+ }
45
+ /** The Layout observation the element expectation last resolved against. */
46
+ lastLayoutObservation() {
47
+ return this.last;
48
+ }
49
+ failed(error, fallback) {
50
+ if (this.probe.rethrow?.(error) === true)
51
+ throw error;
52
+ return {
53
+ status: "failed",
54
+ message: error instanceof Error ? error.message : fallback
55
+ };
56
+ }
57
+ }
58
+ /**
59
+ * The foreground a passing expectation leaves behind. An `element`
60
+ * expectation is proven on the guarded Layout it resolved against and an
61
+ * `activity` expectation on the guarded Activity it matched; log expectations
62
+ * prove nothing about the screen, so the foreground must be re-checked.
63
+ */
64
+ export function settledExpectationForeground(expectation, afterActivity) {
65
+ switch (expectation.type) {
66
+ case "activity":
67
+ return { activity: expectation.value, proven: true };
68
+ case "element":
69
+ return { activity: afterActivity, proven: true };
70
+ case "logcat":
71
+ case "logcatEvent":
72
+ return { activity: afterActivity, proven: false };
73
+ }
74
+ }
@@ -0,0 +1,26 @@
1
+ import { type Baseline } from "../../domain/checkpoint.js";
2
+ import type { VerifyResult } from "../runtime/verify-runtime.js";
3
+ export interface BaselineCaptureInput {
4
+ id: string;
5
+ journeySha256: string;
6
+ contractSha256?: string | undefined;
7
+ includeScreenFacts?: boolean | undefined;
8
+ capturedAt: string;
9
+ runId: string;
10
+ packageName: string;
11
+ result: Pick<VerifyResult, "report" | "hookOutcomes" | "status" | "reportPath">;
12
+ }
13
+ export interface BaselineCapturerDependencies {
14
+ now: () => Date;
15
+ createBaselineId?: (() => string) | undefined;
16
+ }
17
+ /**
18
+ * Captures a Baseline from a completed (passing) verification run. The
19
+ * capture is read-only with respect to the device: it derives deterministic
20
+ * facts from the published report and hook outcomes.
21
+ */
22
+ export declare class BaselineCapturer {
23
+ private readonly dependencies;
24
+ constructor(dependencies: BaselineCapturerDependencies);
25
+ readonly capture: (input: BaselineCaptureInput) => Baseline;
26
+ }