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,123 @@
1
+ import { createHash } from "node:crypto";
2
+ import { GenerationMetaSchema } from "../../domain/generation.js";
3
+ import { ResolvedJourneyPathSchema } from "../../domain/journey-composition.js";
4
+ import { JourneySchema } from "../../domain/journey.js";
5
+ import { TapHoundReportSchema } from "../../domain/report.js";
6
+ import { GENERATIONS_DIR } from "../../domain/workspace.js";
7
+ export class JourneyPromotionError extends Error {
8
+ code;
9
+ name = "JourneyPromotionError";
10
+ constructor(code, message, options) {
11
+ super(message, options);
12
+ this.code = code;
13
+ }
14
+ }
15
+ function sha256(bytes) {
16
+ return createHash("sha256").update(bytes).digest("hex");
17
+ }
18
+ function parseJson(bytes) {
19
+ return JSON.parse(bytes.toString("utf8"));
20
+ }
21
+ function sameJson(left, right) {
22
+ return (JSON.stringify(parseJson(left)) === JSON.stringify(parseJson(right)));
23
+ }
24
+ function serialize(value) {
25
+ return `${JSON.stringify(value, null, 2)}\n`;
26
+ }
27
+ const VERIFIED_JOURNEY_EVIDENCE = "verified/journey.json";
28
+ export class JourneyPromoter {
29
+ dependencies;
30
+ constructor(dependencies) {
31
+ this.dependencies = dependencies;
32
+ }
33
+ promote = async (input) => {
34
+ const journeyPath = ResolvedJourneyPathSchema.parse(input.journeyPath);
35
+ const metaPath = `${journeyPath.slice(0, -".json".length)}.meta.json`;
36
+ let journeyBytes;
37
+ try {
38
+ journeyBytes = await this.dependencies.store.read({
39
+ projectRoot: input.projectRoot,
40
+ relativePath: journeyPath
41
+ });
42
+ }
43
+ catch {
44
+ throw new JourneyPromotionError("JOURNEY_NOT_FOUND", `Journey is not readable: ${journeyPath}`);
45
+ }
46
+ try {
47
+ JourneySchema.parse(parseJson(journeyBytes));
48
+ }
49
+ catch (error) {
50
+ throw new JourneyPromotionError("JOURNEY_INVALID", `Journey does not match the Journey schema: ${journeyPath}`, { cause: error });
51
+ }
52
+ const metaBytes = await this.dependencies.store.readJourneyMeta({
53
+ projectRoot: input.projectRoot,
54
+ journeyPath
55
+ });
56
+ if (metaBytes === null) {
57
+ throw new JourneyPromotionError("META_MISSING", `Journey has no generation meta sidecar: ${metaPath}`);
58
+ }
59
+ let meta;
60
+ try {
61
+ meta = GenerationMetaSchema.parse(parseJson(metaBytes));
62
+ }
63
+ catch (error) {
64
+ throw new JourneyPromotionError("META_INVALID", `Journey meta sidecar is invalid: ${metaPath}`, { cause: error });
65
+ }
66
+ if (meta.status === "promoted") {
67
+ throw new JourneyPromotionError("JOURNEY_ALREADY_PROMOTED", `Journey is already promoted: ${journeyPath}`);
68
+ }
69
+ const bundleRoot = `${GENERATIONS_DIR}/${meta.generationId}`;
70
+ const reportPath = `${bundleRoot}/${meta.verification.reportPath}`;
71
+ let reportBytes;
72
+ try {
73
+ reportBytes = await this.dependencies.store.read({
74
+ projectRoot: input.projectRoot,
75
+ relativePath: reportPath
76
+ });
77
+ }
78
+ catch {
79
+ throw new JourneyPromotionError("EVIDENCE_MISSING", `Verification evidence is missing: ${reportPath}`);
80
+ }
81
+ if (sha256(reportBytes) !== meta.verification.reportSha256) {
82
+ throw new JourneyPromotionError("EVIDENCE_HASH_MISMATCH", `Verification evidence no longer matches the promoted hash: ${reportPath}`);
83
+ }
84
+ const report = TapHoundReportSchema.parse(parseJson(reportBytes));
85
+ if (report.runId !== meta.verification.runId) {
86
+ throw new JourneyPromotionError("EVIDENCE_HASH_MISMATCH", "Verification evidence run does not match the generation meta");
87
+ }
88
+ let verifiedJourneyBytes;
89
+ try {
90
+ verifiedJourneyBytes = await this.dependencies.store.read({
91
+ projectRoot: input.projectRoot,
92
+ relativePath: `${bundleRoot}/${VERIFIED_JOURNEY_EVIDENCE}`
93
+ });
94
+ }
95
+ catch {
96
+ throw new JourneyPromotionError("EVIDENCE_MISSING", `Verified Journey evidence is missing: ${bundleRoot}`);
97
+ }
98
+ if (!sameJson(journeyBytes, verifiedJourneyBytes)) {
99
+ throw new JourneyPromotionError("JOURNEY_MODIFIED", `Journey no longer matches its verified evidence: ${journeyPath}`);
100
+ }
101
+ const promotedAt = input.now.toISOString();
102
+ const promoted = GenerationMetaSchema.parse({
103
+ ...meta,
104
+ status: "promoted",
105
+ promotion: {
106
+ promotedAt,
107
+ reason: input.reason
108
+ }
109
+ });
110
+ await this.dependencies.store.writeText({
111
+ projectRoot: input.projectRoot,
112
+ relativePath: metaPath,
113
+ content: serialize(promoted)
114
+ });
115
+ return {
116
+ status: "promoted",
117
+ journeyPath,
118
+ metaPath,
119
+ generationId: meta.generationId,
120
+ promotedAt
121
+ };
122
+ };
123
+ }
@@ -0,0 +1,42 @@
1
+ import { type JourneyResolutionManifest } from "../../domain/journey-composition.js";
2
+ import { type Journey } from "../../domain/journey.js";
3
+ import type { JourneyCompositionStore } from "../../ports/journey-composition-store.js";
4
+ export type JourneyCompositionErrorCode = "SOURCE_INVALID" | "FLOW_INVALID" | "FLOW_NOT_FOUND" | "FLOW_CYCLE" | "FLOW_DUPLICATE" | "ACTIVITY_BOUNDARY_MISMATCH";
5
+ export declare class JourneyCompositionError extends Error {
6
+ readonly code: JourneyCompositionErrorCode;
7
+ readonly name = "JourneyCompositionError";
8
+ constructor(code: JourneyCompositionErrorCode, message: string, options?: ErrorOptions);
9
+ }
10
+ export interface JourneyResolveInput {
11
+ projectRoot: string;
12
+ sourcePath: string;
13
+ }
14
+ export interface JourneyResolution {
15
+ journey: Journey;
16
+ manifest: JourneyResolutionManifest;
17
+ }
18
+ export interface FlowCatalogEntry {
19
+ name: string;
20
+ path: string;
21
+ status: "valid" | "invalid";
22
+ entryActivity?: string | undefined;
23
+ exitActivity?: string | undefined;
24
+ stepCount?: number | undefined;
25
+ resolutionSha256?: string | undefined;
26
+ failure?: {
27
+ code: string;
28
+ message: string;
29
+ } | undefined;
30
+ }
31
+ export declare class JourneyResolver {
32
+ private readonly store;
33
+ constructor(store: Pick<JourneyCompositionStore, "read" | "listFlowPaths">);
34
+ readonly resolve: (input: JourneyResolveInput) => Promise<JourneyResolution>;
35
+ readonly resolveFlow: (input: {
36
+ projectRoot: string;
37
+ name: string;
38
+ }) => Promise<JourneyResolution>;
39
+ readonly listFlows: (projectRoot: string) => Promise<FlowCatalogEntry[]>;
40
+ private readonly resolveDocument;
41
+ private readonly loadFlow;
42
+ }
@@ -0,0 +1,239 @@
1
+ import { createHash } from "node:crypto";
2
+ import { FlowNameSchema, FlowSchema, JourneySourcePathSchema, JourneyResolutionManifestSchema, JourneySourceSchema } from "../../domain/journey-composition.js";
3
+ import { DEFAULT_DEVICE_ROLE, JourneySchema } from "../../domain/journey.js";
4
+ import { FLOWS_DIR } from "../../domain/workspace.js";
5
+ const MAX_COMPOSITION_BYTES = 1024 * 1024;
6
+ export class JourneyCompositionError extends Error {
7
+ code;
8
+ name = "JourneyCompositionError";
9
+ constructor(code, message, options) {
10
+ super(message, options);
11
+ this.code = code;
12
+ }
13
+ }
14
+ function canonicalize(value) {
15
+ if (Array.isArray(value)) {
16
+ return value.map(canonicalize);
17
+ }
18
+ if (value !== null && typeof value === "object") {
19
+ return Object.fromEntries(Object.entries(value)
20
+ .filter(([, item]) => item !== undefined)
21
+ .sort(([left], [right]) => left.localeCompare(right))
22
+ .map(([key, item]) => [key, canonicalize(item)]));
23
+ }
24
+ return value;
25
+ }
26
+ function sha256(value) {
27
+ return createHash("sha256").update(value).digest("hex");
28
+ }
29
+ function hashCanonical(value) {
30
+ return sha256(JSON.stringify(canonicalize(value)));
31
+ }
32
+ function parseJson(bytes, label) {
33
+ if (bytes.byteLength > MAX_COMPOSITION_BYTES) {
34
+ throw new JourneyCompositionError(label === "Journey source" ? "SOURCE_INVALID" : "FLOW_INVALID", `${label} exceeds ${String(MAX_COMPOSITION_BYTES)} bytes`);
35
+ }
36
+ try {
37
+ return JSON.parse(bytes.toString("utf8"));
38
+ }
39
+ catch (error) {
40
+ throw new JourneyCompositionError(label === "Journey source" ? "SOURCE_INVALID" : "FLOW_INVALID", `${label} is not valid JSON`, { cause: error });
41
+ }
42
+ }
43
+ function flowPath(name) {
44
+ return `${FLOWS_DIR}/${FlowNameSchema.parse(name)}.json`;
45
+ }
46
+ function normalizedSourcePath(path) {
47
+ try {
48
+ return JourneySourcePathSchema.parse(path);
49
+ }
50
+ catch (error) {
51
+ throw new JourneyCompositionError("SOURCE_INVALID", "Journey source must be a normalized JSON file under .taphound/sources", { cause: error });
52
+ }
53
+ }
54
+ function assertActivityBoundaries(steps) {
55
+ for (let index = 1; index < steps.length; index += 1) {
56
+ const previous = steps[index - 1];
57
+ const current = steps[index];
58
+ if (previous !== undefined
59
+ && current !== undefined
60
+ && previous.activity.after !== current.activity.before) {
61
+ throw new JourneyCompositionError("ACTIVITY_BOUNDARY_MISMATCH", `Step ${String(index - 1)} ends at ${previous.activity.after}, but step ${String(index)} starts at ${current.activity.before}`);
62
+ }
63
+ }
64
+ }
65
+ function errorDetails(error) {
66
+ if (error instanceof JourneyCompositionError) {
67
+ return { code: error.code, message: error.message };
68
+ }
69
+ return {
70
+ code: "FLOW_INVALID",
71
+ message: error instanceof Error ? error.message : String(error)
72
+ };
73
+ }
74
+ export class JourneyResolver {
75
+ store;
76
+ constructor(store) {
77
+ this.store = store;
78
+ }
79
+ resolve = async (input) => {
80
+ const sourcePath = normalizedSourcePath(input.sourcePath);
81
+ let sourceBytes;
82
+ try {
83
+ sourceBytes = await this.store.read({
84
+ projectRoot: input.projectRoot,
85
+ relativePath: sourcePath
86
+ });
87
+ }
88
+ catch (error) {
89
+ throw new JourneyCompositionError("SOURCE_INVALID", `Unable to read Journey source ${sourcePath}`, { cause: error });
90
+ }
91
+ let source;
92
+ try {
93
+ source = JourneySourceSchema.parse(parseJson(sourceBytes, "Journey source"));
94
+ }
95
+ catch (error) {
96
+ throw error instanceof JourneyCompositionError
97
+ ? error
98
+ : new JourneyCompositionError("SOURCE_INVALID", `Journey source ${sourcePath} is invalid`, { cause: error });
99
+ }
100
+ return this.resolveDocument(input.projectRoot, sourcePath, sourceBytes, source);
101
+ };
102
+ resolveFlow = async (input) => {
103
+ const name = FlowNameSchema.parse(input.name);
104
+ const path = flowPath(name);
105
+ const loaded = await this.loadFlow(input.projectRoot, name);
106
+ const source = {
107
+ version: 1,
108
+ kind: "journeySource",
109
+ name,
110
+ includes: loaded.flow.includes,
111
+ steps: loaded.flow.steps
112
+ };
113
+ return this.resolveDocument(input.projectRoot, path, loaded.bytes, source, name);
114
+ };
115
+ listFlows = async (projectRoot) => {
116
+ const paths = [...await this.store.listFlowPaths(projectRoot)].sort();
117
+ const entries = [];
118
+ for (const path of paths) {
119
+ try {
120
+ const bytes = await this.store.read({ projectRoot, relativePath: path });
121
+ const flow = FlowSchema.parse(parseJson(bytes, "Flow"));
122
+ const expectedPath = flowPath(flow.name);
123
+ if (path !== expectedPath) {
124
+ throw new JourneyCompositionError("FLOW_INVALID", `Flow ${flow.name} must be stored at ${expectedPath}`);
125
+ }
126
+ const resolution = await this.resolveFlow({
127
+ projectRoot,
128
+ name: flow.name
129
+ });
130
+ entries.push({
131
+ name: flow.name,
132
+ path,
133
+ status: "valid",
134
+ entryActivity: resolution.journey.steps[0]?.activity.before,
135
+ exitActivity: resolution.journey.steps.at(-1)?.activity.after,
136
+ stepCount: resolution.journey.steps.length,
137
+ resolutionSha256: resolution.manifest.resolutionSha256
138
+ });
139
+ }
140
+ catch (error) {
141
+ entries.push({
142
+ name: path.slice(`${FLOWS_DIR}/`.length, -".json".length),
143
+ path,
144
+ status: "invalid",
145
+ failure: errorDetails(error)
146
+ });
147
+ }
148
+ }
149
+ return entries;
150
+ };
151
+ resolveDocument = async (projectRoot, sourcePath, sourceBytes, source, rootFlowName) => {
152
+ const steps = [];
153
+ const dependencies = [];
154
+ const expanded = new Set();
155
+ const stack = [];
156
+ const expand = async (name) => {
157
+ if (stack.includes(name)) {
158
+ throw new JourneyCompositionError("FLOW_CYCLE", `Flow cycle detected: ${[...stack, name].join(" -> ")}`);
159
+ }
160
+ if (expanded.has(name)) {
161
+ throw new JourneyCompositionError("FLOW_DUPLICATE", `Flow ${name} is included more than once`);
162
+ }
163
+ stack.push(name);
164
+ const loaded = await this.loadFlow(projectRoot, name);
165
+ for (const dependency of loaded.flow.includes) {
166
+ await expand(dependency);
167
+ }
168
+ stack.pop();
169
+ expanded.add(name);
170
+ steps.push(...loaded.flow.steps);
171
+ dependencies.push({
172
+ name,
173
+ path: loaded.path,
174
+ sha256: sha256(loaded.bytes),
175
+ stepCount: loaded.flow.steps.length
176
+ });
177
+ };
178
+ if (rootFlowName === undefined) {
179
+ for (const name of source.includes) {
180
+ await expand(name);
181
+ }
182
+ steps.push(...source.steps);
183
+ }
184
+ else {
185
+ await expand(rootFlowName);
186
+ }
187
+ assertActivityBoundaries(steps);
188
+ const journey = JourneySchema.parse({
189
+ version: 2,
190
+ name: source.name,
191
+ devices: [{ role: DEFAULT_DEVICE_ROLE }],
192
+ steps
193
+ });
194
+ const unsignedManifest = {
195
+ version: 1,
196
+ source: {
197
+ path: sourcePath,
198
+ sha256: sha256(sourceBytes)
199
+ },
200
+ flows: dependencies,
201
+ expansion: dependencies.map((dependency) => dependency.name),
202
+ journey: {
203
+ name: journey.name,
204
+ sha256: hashCanonical(journey),
205
+ stepCount: journey.steps.length
206
+ }
207
+ };
208
+ return {
209
+ journey,
210
+ manifest: JourneyResolutionManifestSchema.parse({
211
+ ...unsignedManifest,
212
+ resolutionSha256: hashCanonical(unsignedManifest)
213
+ })
214
+ };
215
+ };
216
+ loadFlow = async (projectRoot, name) => {
217
+ const path = flowPath(name);
218
+ let bytes;
219
+ try {
220
+ bytes = await this.store.read({ projectRoot, relativePath: path });
221
+ }
222
+ catch (error) {
223
+ throw new JourneyCompositionError("FLOW_NOT_FOUND", `Unable to read Flow ${name} at ${path}`, { cause: error });
224
+ }
225
+ let flow;
226
+ try {
227
+ flow = FlowSchema.parse(parseJson(bytes, "Flow"));
228
+ }
229
+ catch (error) {
230
+ throw error instanceof JourneyCompositionError
231
+ ? error
232
+ : new JourneyCompositionError("FLOW_INVALID", `Flow ${name} is invalid`, { cause: error });
233
+ }
234
+ if (flow.name !== name) {
235
+ throw new JourneyCompositionError("FLOW_INVALID", `Flow at ${path} declares name ${flow.name}`);
236
+ }
237
+ return { path, bytes, flow };
238
+ };
239
+ }
@@ -0,0 +1,25 @@
1
+ import type { JourneyCompositionStore } from "../../ports/journey-composition-store.js";
2
+ export type JourneyRetireErrorCode = "JOURNEY_NOT_FOUND" | "JOURNEY_INVALID" | "META_MISSING" | "META_INVALID" | "JOURNEY_ALREADY_RETIRED";
3
+ export declare class JourneyRetireError extends Error {
4
+ readonly code: JourneyRetireErrorCode;
5
+ readonly name = "JourneyRetireError";
6
+ constructor(code: JourneyRetireErrorCode, message: string, options?: ErrorOptions);
7
+ }
8
+ export interface JourneyRetireResult {
9
+ status: "retired";
10
+ journeyPath: string;
11
+ metaPath: string;
12
+ retiredAt: string;
13
+ }
14
+ export declare class JourneyRetirer {
15
+ private readonly dependencies;
16
+ constructor(dependencies: {
17
+ store: Pick<JourneyCompositionStore, "read" | "readJourneyMeta" | "writeText">;
18
+ });
19
+ readonly retire: (input: {
20
+ projectRoot: string;
21
+ journeyPath: string;
22
+ reason: string;
23
+ now: Date;
24
+ }) => Promise<JourneyRetireResult>;
25
+ }
@@ -0,0 +1,87 @@
1
+ import { GenerationMetaSchema } from "../../domain/generation.js";
2
+ import { ResolvedJourneyPathSchema } from "../../domain/journey-composition.js";
3
+ import { JourneySchema } from "../../domain/journey.js";
4
+ export class JourneyRetireError extends Error {
5
+ code;
6
+ name = "JourneyRetireError";
7
+ constructor(code, message, options) {
8
+ super(message, options);
9
+ this.code = code;
10
+ }
11
+ }
12
+ function parseJson(bytes) {
13
+ return JSON.parse(bytes.toString("utf8"));
14
+ }
15
+ function serialize(value) {
16
+ return `${JSON.stringify(value, null, 2)}\n`;
17
+ }
18
+ export class JourneyRetirer {
19
+ dependencies;
20
+ constructor(dependencies) {
21
+ this.dependencies = dependencies;
22
+ }
23
+ retire = async (input) => {
24
+ const journeyPath = ResolvedJourneyPathSchema.parse(input.journeyPath);
25
+ const metaPath = `${journeyPath.slice(0, -".json".length)}.meta.json`;
26
+ let journeyBytes;
27
+ try {
28
+ journeyBytes = await this.dependencies.store.read({
29
+ projectRoot: input.projectRoot,
30
+ relativePath: journeyPath
31
+ });
32
+ }
33
+ catch {
34
+ throw new JourneyRetireError("JOURNEY_NOT_FOUND", `Journey is not readable: ${journeyPath}`);
35
+ }
36
+ try {
37
+ JourneySchema.parse(parseJson(journeyBytes));
38
+ }
39
+ catch (error) {
40
+ throw new JourneyRetireError("JOURNEY_INVALID", `Journey does not match the Journey schema: ${journeyPath}`, { cause: error });
41
+ }
42
+ const metaBytes = await this.dependencies.store.readJourneyMeta({
43
+ projectRoot: input.projectRoot,
44
+ journeyPath
45
+ });
46
+ if (metaBytes === null) {
47
+ throw new JourneyRetireError("META_MISSING", `Journey has no generation meta sidecar: ${metaPath}`);
48
+ }
49
+ let meta;
50
+ try {
51
+ meta = GenerationMetaSchema.parse(parseJson(metaBytes));
52
+ }
53
+ catch (error) {
54
+ throw new JourneyRetireError("META_INVALID", `Journey meta sidecar is invalid: ${metaPath}`, { cause: error });
55
+ }
56
+ if (meta.retired !== undefined) {
57
+ throw new JourneyRetireError("JOURNEY_ALREADY_RETIRED", `Journey is already retired: ${journeyPath}`);
58
+ }
59
+ const retiredAt = input.now.toISOString();
60
+ const updated = {
61
+ ...meta,
62
+ retired: {
63
+ retiredAt,
64
+ reason: input.reason.trim()
65
+ }
66
+ };
67
+ await this.dependencies.store.writeText({
68
+ projectRoot: input.projectRoot,
69
+ relativePath: metaPath,
70
+ content: serialize(updated)
71
+ });
72
+ const written = await this.dependencies.store.readJourneyMeta({
73
+ projectRoot: input.projectRoot,
74
+ journeyPath
75
+ });
76
+ if (written === null) {
77
+ throw new JourneyRetireError("META_INVALID", `Retired meta sidecar is not readable: ${metaPath}`);
78
+ }
79
+ GenerationMetaSchema.parse(parseJson(written));
80
+ return {
81
+ status: "retired",
82
+ journeyPath,
83
+ metaPath,
84
+ retiredAt
85
+ };
86
+ };
87
+ }
@@ -0,0 +1,36 @@
1
+ import type { DisplayViewport } from "../../domain/geometry.js";
2
+ import type { LayoutElement } from "../../domain/layout.js";
3
+ import type { AnchorResolution, AnchorResolverPort } from "../../ports/anchor-resolver.js";
4
+ import type { KnowledgeRegistryPort } from "../../ports/knowledge-registry.js";
5
+ /**
6
+ * Semantic Anchor resolver.
7
+ *
8
+ * An Anchor is a Semantic UI Reference: an ordered candidate chain
9
+ * (composeSemantics → resourceId → contentDescription → visibleText →
10
+ * visualMatch). Resolution walks the chain deterministically:
11
+ *
12
+ * - the first candidate that resolves **uniquely** wins; the win is recorded
13
+ * as `primary` (first candidate) or `fallback` (a later candidate), so a
14
+ * fallback resolution is visible in the report rather than silent;
15
+ * - an **ambiguous** match at any candidate fails closed (matching the fixed
16
+ * locator-priority rule: never select heuristically);
17
+ * - `visualMatch` is never resolved by Core: when nothing before it matched,
18
+ * the resolution is `visualOnly` and the run fails closed —
19
+ * `RUNTIME_CAPABILITY_MISSING` for the caller — leaving the visual layer to
20
+ * an external multimodal reviewer under the Escalation Policy.
21
+ *
22
+ * The legacy single-locator identity remains supported as the primary
23
+ * candidate when no explicit `candidates` chain is present.
24
+ */
25
+ export declare class KnowledgeAnchorResolver implements AnchorResolverPort {
26
+ private readonly registry;
27
+ private readonly projectRoot;
28
+ constructor(registry: Pick<KnowledgeRegistryPort, "load">, projectRoot: string);
29
+ readonly resolve: (input: {
30
+ anchorId: string;
31
+ layout: readonly LayoutElement[];
32
+ viewport?: DisplayViewport | undefined;
33
+ signal?: AbortSignal | undefined;
34
+ }) => Promise<AnchorResolution>;
35
+ private readonly found;
36
+ }
@@ -0,0 +1,110 @@
1
+ import { resolveLocator } from "../locator/locator-resolver.js";
2
+ function candidateKindForLocator(locator) {
3
+ if (locator.resourceId !== undefined) {
4
+ return "resourceId";
5
+ }
6
+ if (locator.contentDescription !== undefined) {
7
+ return "contentDescription";
8
+ }
9
+ if (locator.text !== undefined) {
10
+ return "visibleText";
11
+ }
12
+ return "resourceId";
13
+ }
14
+ function resolveCandidate(layout, candidate, viewport) {
15
+ return resolveLocator(layout, candidate.locator, {
16
+ requireEnabled: true,
17
+ ...(viewport === undefined ? {} : { viewport })
18
+ });
19
+ }
20
+ /**
21
+ * Semantic Anchor resolver.
22
+ *
23
+ * An Anchor is a Semantic UI Reference: an ordered candidate chain
24
+ * (composeSemantics → resourceId → contentDescription → visibleText →
25
+ * visualMatch). Resolution walks the chain deterministically:
26
+ *
27
+ * - the first candidate that resolves **uniquely** wins; the win is recorded
28
+ * as `primary` (first candidate) or `fallback` (a later candidate), so a
29
+ * fallback resolution is visible in the report rather than silent;
30
+ * - an **ambiguous** match at any candidate fails closed (matching the fixed
31
+ * locator-priority rule: never select heuristically);
32
+ * - `visualMatch` is never resolved by Core: when nothing before it matched,
33
+ * the resolution is `visualOnly` and the run fails closed —
34
+ * `RUNTIME_CAPABILITY_MISSING` for the caller — leaving the visual layer to
35
+ * an external multimodal reviewer under the Escalation Policy.
36
+ *
37
+ * The legacy single-locator identity remains supported as the primary
38
+ * candidate when no explicit `candidates` chain is present.
39
+ */
40
+ export class KnowledgeAnchorResolver {
41
+ registry;
42
+ projectRoot;
43
+ constructor(registry, projectRoot) {
44
+ this.registry = registry;
45
+ this.projectRoot = projectRoot;
46
+ }
47
+ resolve = async (input) => {
48
+ void input.signal;
49
+ const bundle = await this.registry.load(this.projectRoot);
50
+ const anchor = bundle.anchors.find((candidate) => candidate.id === input.anchorId);
51
+ if (anchor === undefined) {
52
+ return {
53
+ status: "notFound",
54
+ message: `Knowledge anchor ${input.anchorId} is not defined in ${this.projectRoot}`
55
+ };
56
+ }
57
+ if (anchor.identity.kind !== "element") {
58
+ return {
59
+ status: "notFound",
60
+ message: `Knowledge anchor ${input.anchorId} does not carry an element locator identity`
61
+ };
62
+ }
63
+ const candidates = anchor.candidates ?? [];
64
+ const chain = candidates.length > 0
65
+ ? candidates.map((candidate) => ({ kind: candidate.kind, candidate }))
66
+ : [{
67
+ kind: candidateKindForLocator(anchor.identity.locator),
68
+ candidate: {
69
+ kind: candidateKindForLocator(anchor.identity.locator),
70
+ locator: anchor.identity.locator
71
+ }
72
+ }];
73
+ for (const [index, entry] of chain.entries()) {
74
+ if (entry.kind === "visualMatch") {
75
+ continue;
76
+ }
77
+ const resolution = resolveCandidate(input.layout, entry.candidate, input.viewport);
78
+ if (resolution.status !== "found") {
79
+ continue;
80
+ }
81
+ return this.found(entry.kind, index === 0, resolution);
82
+ }
83
+ const hasVisual = chain.some((entry) => entry.kind === "visualMatch");
84
+ if (hasVisual) {
85
+ return {
86
+ status: "visualOnly",
87
+ message: `Knowledge anchor ${input.anchorId} resolves only via visualMatch, which Core never performs`
88
+ };
89
+ }
90
+ return {
91
+ status: "notFound",
92
+ message: `Knowledge anchor ${input.anchorId} did not resolve through any candidate`
93
+ };
94
+ };
95
+ found = (kind, primary, resolution) => {
96
+ if (resolution.element.bounds === undefined) {
97
+ return {
98
+ status: "ambiguous",
99
+ message: `Knowledge anchor resolved via ${kind} to an element without bounds`
100
+ };
101
+ }
102
+ return {
103
+ status: "found",
104
+ point: resolution.point,
105
+ bounds: resolution.element.bounds,
106
+ element: resolution.element,
107
+ resolvedBy: { kind, confidence: primary ? "primary" : "fallback" }
108
+ };
109
+ };
110
+ }
@@ -0,0 +1,16 @@
1
+ import type { KnowledgeRegistryPort, LoadedKnowledgeBundle } from "../../ports/knowledge-registry.js";
2
+ export type KnowledgeLoadErrorCode = "KNOWLEDGE_INVALID" | "KNOWLEDGE_STALE" | "KNOWLEDGE_NOT_FOUND";
3
+ export declare class KnowledgeLoadError extends Error {
4
+ readonly code: KnowledgeLoadErrorCode;
5
+ readonly name = "KnowledgeLoadError";
6
+ constructor(code: KnowledgeLoadErrorCode, message: string, options?: ErrorOptions);
7
+ }
8
+ export declare class KnowledgeLoader {
9
+ private readonly registry;
10
+ constructor(registry: Pick<KnowledgeRegistryPort, "load">);
11
+ readonly load: (input: {
12
+ projectRoot: string;
13
+ packageName?: string | undefined;
14
+ expectedKnowledgeHash?: string | undefined;
15
+ }) => Promise<LoadedKnowledgeBundle>;
16
+ }