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,124 @@
1
+ import { resolve } from "node:path";
2
+ import { Command } from "commander";
3
+ import { TapHoundConfigSchema } from "../../domain/config.js";
4
+ import { assertArtifactDirectory, CONFIG_PATH } from "../../domain/workspace.js";
5
+ import { exitCodeForFailure, failureCodeFromUnknown } from "../../domain/failure.js";
6
+ import { AlignError } from "../../application/align/align-service.js";
7
+ import { AlignPromptCancelledError } from "../../ports/align-prompt.js";
8
+ import { errorMessage, failureOutput, writeJson, writeLine } from "../output.js";
9
+ import { prepareWorkspace } from "../workspace-guard.js";
10
+ function alignCameraText(result) {
11
+ if (result.status === "cancelled") {
12
+ return "Cancelled — no flow written.";
13
+ }
14
+ const { flow, probe } = result;
15
+ const confirmLine = probe.confirmResourceId !== undefined
16
+ ? ` Confirm button: ${probe.confirmResourceId}`
17
+ : " Confirm button: (none — camera auto-accepts)";
18
+ const reviewActivityLine = probe.confirmActivityName === undefined
19
+ ? []
20
+ : [` Review activity: ${probe.confirmActivityName}`];
21
+ return [
22
+ "Probing camera...",
23
+ ` Camera package: ${probe.packageName}`,
24
+ ` Camera activity: ${probe.activityName}`,
25
+ ...reviewActivityLine,
26
+ ` Shutter button: ${probe.shutterResourceId}`,
27
+ confirmLine,
28
+ "",
29
+ `Wrote ${flow.name} flow (${String(flow.steps)} steps)`,
30
+ ` Path: ${flow.path}`
31
+ ].join("\n");
32
+ }
33
+ export function createAlignCommand(dependencies) {
34
+ const align = new Command("align")
35
+ .description("Align device-specific External Flows");
36
+ align
37
+ .command("camera")
38
+ .description("Probe the device camera and write a project External Flow")
39
+ .option("--project <path>", "Android project root", dependencies.cwd())
40
+ .option("--config <path>", "TapHound config path", CONFIG_PATH)
41
+ .option("--device <serial>", "Select an online Android device")
42
+ .option("--force", "Overwrite an existing project flow")
43
+ .option("--json", "Emit machine-readable JSON")
44
+ .action(async (options) => {
45
+ try {
46
+ try {
47
+ const config = await TapHoundConfigSchema.parseAsync(await dependencies.readJson(resolve(options.project, options.config)));
48
+ assertArtifactDirectory(options.project, config.artifactsDir);
49
+ await prepareWorkspace(dependencies, options.project);
50
+ }
51
+ catch (error) {
52
+ const output = failureOutput(2, "CONFIG_INVALID", errorMessage(error));
53
+ if (options.json === true) {
54
+ writeJson(dependencies.stdout, output);
55
+ }
56
+ else {
57
+ writeLine(dependencies.stderr, output.failure.message);
58
+ }
59
+ dependencies.setExitCode(2);
60
+ return;
61
+ }
62
+ const result = await dependencies.align.alignCamera({
63
+ projectRoot: options.project,
64
+ ...(options.device === undefined ? {} : { deviceSerial: options.device }),
65
+ ...(options.force === undefined ? {} : { force: options.force }),
66
+ json: options.json === true,
67
+ ...(dependencies.signal === undefined ? {} : { signal: dependencies.signal })
68
+ });
69
+ if (options.json === true) {
70
+ writeJson(dependencies.stdout, result);
71
+ }
72
+ else {
73
+ writeLine(dependencies.stdout, alignCameraText(result));
74
+ }
75
+ dependencies.setExitCode(result.exitCode);
76
+ }
77
+ catch (error) {
78
+ if (error instanceof AlignPromptCancelledError) {
79
+ const cancelled = { status: "cancelled", exitCode: 2 };
80
+ if (options.json === true) {
81
+ writeJson(dependencies.stdout, cancelled);
82
+ }
83
+ else {
84
+ writeLine(dependencies.stdout, alignCameraText(cancelled));
85
+ }
86
+ dependencies.setExitCode(2);
87
+ return;
88
+ }
89
+ if (error instanceof AlignError) {
90
+ const output = failureOutput(2, error.code, error.message);
91
+ if (options.json === true) {
92
+ writeJson(dependencies.stdout, output);
93
+ }
94
+ else {
95
+ writeLine(dependencies.stderr, output.failure.message);
96
+ }
97
+ dependencies.setExitCode(2);
98
+ return;
99
+ }
100
+ const failureCode = failureCodeFromUnknown(error);
101
+ if (failureCode !== undefined) {
102
+ const exitCode = exitCodeForFailure(failureCode);
103
+ const output = failureOutput(exitCode, failureCode, errorMessage(error));
104
+ if (options.json === true) {
105
+ writeJson(dependencies.stdout, output);
106
+ }
107
+ else {
108
+ writeLine(dependencies.stderr, output.failure.message);
109
+ }
110
+ dependencies.setExitCode(exitCode);
111
+ return;
112
+ }
113
+ const output = failureOutput(4, "INTERNAL_ERROR", errorMessage(error));
114
+ if (options.json === true) {
115
+ writeJson(dependencies.stdout, output);
116
+ }
117
+ else {
118
+ writeLine(dependencies.stderr, output.failure.message);
119
+ }
120
+ dependencies.setExitCode(4);
121
+ }
122
+ });
123
+ return align;
124
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ import type { CliDependencies } from "../dependencies.js";
3
+ export declare function createBaselineCommand(dependencies: CliDependencies): Command;
@@ -0,0 +1,130 @@
1
+ import { Command } from "commander";
2
+ import { exitCodeForFailure, failureCodeFromUnknown } from "../../domain/failure.js";
3
+ import { BASELINES_DIR, BUILD_DIR, assertProjectPathUnder } from "../../domain/workspace.js";
4
+ import { failureOutput, writeJson, writeLine } from "../output.js";
5
+ import { prepareWorkspace } from "../workspace-guard.js";
6
+ function writeFailure(dependencies, json, code, message) {
7
+ const exitCode = exitCodeForFailure(code);
8
+ const output = failureOutput(exitCode, code, message);
9
+ if (json) {
10
+ writeJson(dependencies.stdout, output);
11
+ }
12
+ else {
13
+ writeLine(dependencies.stderr, output.failure.message);
14
+ }
15
+ dependencies.setExitCode(exitCode);
16
+ }
17
+ export function createBaselineCommand(dependencies) {
18
+ const command = new Command("baseline")
19
+ .description("Capture and compare behavior Baselines against Verification reports")
20
+ .addCommand(createCaptureCommand(dependencies))
21
+ .addCommand(createCompareCommand(dependencies));
22
+ return command;
23
+ }
24
+ function createCaptureCommand(dependencies) {
25
+ return new Command("capture")
26
+ .description("Capture a Baseline from a passing Verification report (offline)")
27
+ .option("--project <path>", "Android project root", dependencies.cwd())
28
+ .requiredOption("--report <path>", "Verification report.json path")
29
+ .option("--id <name>", "Baseline id (defaults to the report runId)")
30
+ .option("--journey-sha256 <sha256>", "Assert the source report's Journey sha256")
31
+ .option("--contract-sha256 <sha256>", "Assert the passing Verdict's Contract sha256")
32
+ .option("--verdict <path>", "Passing Contract verdict.json for the source report")
33
+ .option("--no-screen-facts", "Exclude Screen facts from this Baseline")
34
+ .requiredOption("--out <path>", "Baseline output under .taphound/baselines")
35
+ .option("--json", "Emit one machine-readable JSON value")
36
+ .action(async (options) => {
37
+ const json = options.json === true;
38
+ if (dependencies.baselineService === undefined) {
39
+ writeFailure(dependencies, json, "CONFIG_INVALID", "TapHound baseline capture is not configured");
40
+ return;
41
+ }
42
+ try {
43
+ await prepareWorkspace(dependencies, options.project);
44
+ }
45
+ catch (error) {
46
+ writeFailure(dependencies, json, failureCodeFromUnknown(error) ?? "CONFIG_INVALID", error instanceof Error ? error.message : String(error));
47
+ return;
48
+ }
49
+ try {
50
+ const reportPath = assertProjectPathUnder(options.project, options.report, BUILD_DIR, "Verification report");
51
+ const verdictPath = options.verdict === undefined
52
+ ? undefined
53
+ : assertProjectPathUnder(options.project, options.verdict, BUILD_DIR, "Contract verdict");
54
+ const outputPath = assertProjectPathUnder(options.project, options.out, BASELINES_DIR, "Baseline output");
55
+ const baseline = await dependencies.baselineService.captureFromReport(reportPath, {
56
+ id: options.id,
57
+ journeySha256: options.journeySha256,
58
+ contractSha256: options.contractSha256,
59
+ ...(verdictPath === undefined ? {} : { verdictPath }),
60
+ includeScreenFacts: options.screenFacts
61
+ });
62
+ await dependencies.baselineService.write({
63
+ path: outputPath,
64
+ baseline
65
+ });
66
+ if (json) {
67
+ writeJson(dependencies.stdout, baseline);
68
+ }
69
+ else {
70
+ writeLine(dependencies.stdout, `Baseline ${baseline.id} captured (${String(baseline.activities.length)} activity facts, ${String(baseline.elements.length)} element facts, ${String(baseline.checkpoints?.length ?? 0)} Checkpoint facts)`);
71
+ }
72
+ dependencies.setExitCode(0);
73
+ }
74
+ catch (error) {
75
+ writeFailure(dependencies, json, failureCodeFromUnknown(error) ?? "CONFIG_INVALID", error instanceof Error ? error.message : String(error));
76
+ }
77
+ });
78
+ }
79
+ function createCompareCommand(dependencies) {
80
+ return new Command("compare")
81
+ .description("Compare a Verification report against a stored Baseline")
82
+ .option("--project <path>", "Android project root", dependencies.cwd())
83
+ .requiredOption("--baseline <path>", "Baseline JSON path")
84
+ .requiredOption("--report <path>", "Verification report.json path")
85
+ .option("--journey-sha256 <sha256>", "Assert the current report's Journey sha256")
86
+ .option("--verdict <path>", "Contract verdict.json for this report (defaults beside report.json)")
87
+ .option("--json", "Emit one machine-readable JSON value")
88
+ .action(async (options) => {
89
+ const json = options.json === true;
90
+ if (dependencies.baselineService === undefined) {
91
+ writeFailure(dependencies, json, "CONFIG_INVALID", "TapHound regression comparison is not configured");
92
+ return;
93
+ }
94
+ try {
95
+ await prepareWorkspace(dependencies, options.project);
96
+ }
97
+ catch (error) {
98
+ writeFailure(dependencies, json, failureCodeFromUnknown(error) ?? "CONFIG_INVALID", error instanceof Error ? error.message : String(error));
99
+ return;
100
+ }
101
+ try {
102
+ const baselinePath = assertProjectPathUnder(options.project, options.baseline, BASELINES_DIR, "Baseline");
103
+ const reportPath = assertProjectPathUnder(options.project, options.report, BUILD_DIR, "Verification report");
104
+ const verdictPath = options.verdict === undefined
105
+ ? undefined
106
+ : assertProjectPathUnder(options.project, options.verdict, BUILD_DIR, "Contract verdict");
107
+ const result = await dependencies.baselineService.compare({
108
+ baselinePath,
109
+ reportPath,
110
+ journeySha256: options.journeySha256,
111
+ ...(verdictPath === undefined ? {} : { verdictPath })
112
+ });
113
+ if (json) {
114
+ writeJson(dependencies.stdout, result);
115
+ }
116
+ else {
117
+ writeLine(dependencies.stdout, result.equivalent
118
+ ? `Regression compare: equivalent (${String(result.regressions.length)} diffs)`
119
+ : `Regression compare: ${String(result.regressions.length)} diff(s)`);
120
+ for (const diff of result.regressions) {
121
+ writeLine(dependencies.stdout, `- ${diff.kind}${diff.checkpointId === undefined ? "" : ` checkpoint=${diff.checkpointId}`}${diff.stepIndex === undefined ? "" : ` step=${String(diff.stepIndex)}`}: expected ${diff.expected}, actual ${diff.actual}`);
122
+ }
123
+ }
124
+ dependencies.setExitCode(result.equivalent ? 0 : 1);
125
+ }
126
+ catch (error) {
127
+ writeFailure(dependencies, json, failureCodeFromUnknown(error) ?? "CONFIG_INVALID", error instanceof Error ? error.message : String(error));
128
+ }
129
+ });
130
+ }
@@ -1,32 +1,74 @@
1
1
  import { resolve } from "node:path";
2
2
  import { Command } from "commander";
3
+ import { ContextGenerateError } from "../../application/context/context-generator.js";
4
+ import { ContextLoadError } from "../../application/context/context-loader.js";
5
+ import { ContextRehashError } from "../../application/context/context-rehasher.js";
6
+ import { ContextRefreshError } from "../../application/context/context-refresher.js";
3
7
  import { TapHoundConfigSchema } from "../../domain/config.js";
4
- import { ProjectContextSchema } from "../../domain/project-context.js";
8
+ import { assertProjectPathUnder, CONFIG_PATH, CONTEXT_DIR } from "../../domain/workspace.js";
5
9
  import { errorMessage, failureOutput, writeJson, writeLine } from "../output.js";
10
+ function contextPath(root, requested) {
11
+ return assertProjectPathUnder(root, requested, CONTEXT_DIR, "Project Context output");
12
+ }
6
13
  function exitCodeForContext(command, result) {
7
14
  if (result.status === "invalid") {
8
15
  return 2;
9
16
  }
10
17
  return command === "validate" && result.status === "stale" ? 1 : 0;
11
18
  }
19
+ function loadFailureResult(error) {
20
+ return error.code === "CONTEXT_STALE"
21
+ ? {
22
+ status: "stale",
23
+ reason: {
24
+ code: "EVIDENCE_HASH_MISMATCH",
25
+ message: error.message
26
+ }
27
+ }
28
+ : {
29
+ status: "invalid",
30
+ reason: {
31
+ code: "CONTEXT_SCHEMA_INVALID",
32
+ message: error.message
33
+ }
34
+ };
35
+ }
36
+ function writeContextResult(dependencies, options, name, result, details = {}) {
37
+ const exitCode = exitCodeForContext(name, result);
38
+ const output = { ...result, ...details, exitCode };
39
+ if (options.json === true) {
40
+ writeJson(dependencies.stdout, output);
41
+ }
42
+ else {
43
+ writeLine(dependencies.stdout, result.status === "valid"
44
+ ? "Context: valid"
45
+ : `Context: ${result.status} (${result.reason.message})`);
46
+ if (result.status === "valid" && result.divergence !== undefined) {
47
+ writeLine(dependencies.stderr, `identity divergence: evidence package ${result.divergence.evidencePackageName}, configured package ${result.divergence.configuredPackageName} (activity suffix matches)`);
48
+ }
49
+ }
50
+ dependencies.setExitCode(exitCode);
51
+ }
12
52
  function createContextOperation(dependencies, name) {
13
53
  return new Command(name)
14
54
  .description(name === "validate"
15
55
  ? "Validate deterministic Project Context evidence"
16
56
  : "Observe deterministic Project Context status")
17
57
  .option("--project <path>", "Android project root", dependencies.cwd())
18
- .option("--config <path>", "TapHound config path", "taphound.config.json")
19
- .requiredOption("--context <path>", "Project Context path")
58
+ .option("--config <path>", "TapHound config path", CONFIG_PATH)
59
+ .option("--context <path>", "Project Context path under .taphound/context", ".taphound/context/project-context.json")
60
+ .option("--module <id...>", "Select Context modules")
20
61
  .option("--json", "Emit one machine-readable JSON value")
21
62
  .action(async (options) => {
63
+ const json = options.json === true;
64
+ const projectRoot = options.project;
22
65
  let config;
23
- let context;
24
66
  try {
25
- config = TapHoundConfigSchema.parse(await dependencies.readJson(resolve(options.project, options.config)));
67
+ config = TapHoundConfigSchema.parse(await dependencies.readJson(resolve(projectRoot, options.config)));
26
68
  }
27
69
  catch (error) {
28
70
  const output = failureOutput(2, "CONFIG_INVALID", errorMessage(error));
29
- if (options.json === true) {
71
+ if (json) {
30
72
  writeJson(dependencies.stdout, output);
31
73
  }
32
74
  else {
@@ -36,53 +78,280 @@ function createContextOperation(dependencies, name) {
36
78
  return;
37
79
  }
38
80
  try {
39
- context = ProjectContextSchema.parse(await dependencies.readJson(resolve(options.project, options.context)));
81
+ const loaded = await dependencies.contextLoader.load({
82
+ projectRoot,
83
+ contextPath: contextPath(projectRoot, options.context),
84
+ ...(options.module === undefined ? {} : { moduleIds: options.module }),
85
+ allowIncomplete: name === "status"
86
+ });
87
+ const result = await dependencies.contextValidator.validate({
88
+ context: loaded.context,
89
+ projectRoot,
90
+ config,
91
+ ...(name === "status" ? { modules: loaded.modules } : {}),
92
+ ...(name === "status" ? { reportScopes: true } : {})
93
+ });
94
+ writeContextResult(dependencies, options, name, result, {
95
+ contextSelection: loaded.context.selection,
96
+ modules: loaded.modules.map((module) => ({
97
+ id: module.moduleId,
98
+ status: module.status
99
+ }))
100
+ });
40
101
  }
41
102
  catch (error) {
103
+ if (error instanceof ContextLoadError) {
104
+ writeContextResult(dependencies, options, name, loadFailureResult(error));
105
+ return;
106
+ }
107
+ const output = failureOutput(4, "INTERNAL_ERROR", errorMessage(error));
108
+ if (options.json === true) {
109
+ writeJson(dependencies.stdout, output);
110
+ }
111
+ else {
112
+ writeLine(dependencies.stderr, output.failure.message);
113
+ }
114
+ dependencies.setExitCode(4);
115
+ }
116
+ });
117
+ }
118
+ function createContextListCommand(dependencies) {
119
+ return new Command("list")
120
+ .description("List Project Context modules without loading shards")
121
+ .option("--project <path>", "Android project root", dependencies.cwd())
122
+ .option("--context <path>", "Project Context path under .taphound/context", ".taphound/context/project-context.json")
123
+ .option("--json", "Emit one machine-readable JSON value")
124
+ .action(async (options) => {
125
+ try {
126
+ const { bundle, indexHash } = await dependencies.contextLoader.readIndex({
127
+ projectRoot: options.project,
128
+ contextPath: contextPath(options.project, options.context)
129
+ });
42
130
  const output = {
43
- status: "error",
44
- exitCode: 2,
45
- failure: {
46
- code: "CONTEXT_INVALID",
47
- message: errorMessage(error)
48
- }
131
+ status: "listed",
132
+ exitCode: 0,
133
+ version: bundle.version,
134
+ packageName: bundle.packageName,
135
+ launchActivity: bundle.launchActivity,
136
+ indexHash,
137
+ modules: bundle.modules
49
138
  };
50
139
  if (options.json === true) {
51
140
  writeJson(dependencies.stdout, output);
52
141
  }
142
+ else {
143
+ for (const module of bundle.modules) {
144
+ writeLine(dependencies.stdout, `${module.id}: ${module.status} (${module.contextPath})`);
145
+ }
146
+ }
147
+ dependencies.setExitCode(0);
148
+ }
149
+ catch (error) {
150
+ const output = error instanceof ContextLoadError
151
+ ? {
152
+ status: "error",
153
+ exitCode: 2,
154
+ failure: {
155
+ code: error.code,
156
+ message: error.message
157
+ }
158
+ }
159
+ : failureOutput(4, "INTERNAL_ERROR", errorMessage(error));
160
+ if (options.json === true) {
161
+ writeJson(dependencies.stdout, output);
162
+ }
53
163
  else {
54
164
  writeLine(dependencies.stderr, output.failure.message);
55
165
  }
56
- dependencies.setExitCode(2);
57
- return;
166
+ dependencies.setExitCode(output.exitCode);
167
+ }
168
+ });
169
+ }
170
+ function refreshExitCode(result) {
171
+ return result.status === "blocked" ? 1 : 0;
172
+ }
173
+ function writeRefreshText(dependencies, result) {
174
+ writeLine(dependencies.stdout, `Context: ${result.status}`);
175
+ for (const scope of result.scopes) {
176
+ if (scope.semanticBackfilled === 0
177
+ && scope.formattingRehashed === 0
178
+ && scope.semanticChanged.length === 0
179
+ && scope.unresolved.length === 0
180
+ && scope.pruned === 0
181
+ && scope.droppedIneligible === 0
182
+ && !scope.inventoryChanged) {
183
+ continue;
58
184
  }
185
+ writeLine(dependencies.stdout, `${scope.id}: semantic ${String(scope.semanticBackfilled)}`
186
+ + `, rehashed ${String(scope.formattingRehashed)}`
187
+ + `, changed ${String(scope.semanticChanged.length)}`
188
+ + `, unresolved ${String(scope.unresolved.length)}`
189
+ + `, pruned ${String(scope.pruned)}`
190
+ + `, dropped ${String(scope.droppedIneligible)}`
191
+ + (scope.inventoryChanged ? ", inventory changed" : ""));
192
+ }
193
+ for (const block of result.blocked) {
194
+ writeLine(dependencies.stderr, `${block.code} [${block.resolution}]: ${block.message}`);
195
+ }
196
+ }
197
+ function createContextRefreshCommand(dependencies) {
198
+ return new Command("refresh")
199
+ .description("Recompute Project Context evidence hashes without analysis")
200
+ .option("--project <path>", "Android project root", dependencies.cwd())
201
+ .option("--context <path>", "Project Context path under .taphound/context", ".taphound/context/project-context.json")
202
+ .option("--module <id...>", "Refresh only the listed Context modules")
203
+ .option("--accept-source-changes", "Also rehash evidence whose semantics changed")
204
+ .option("--prune-deleted", "Drop evidence entries for files no longer on disk")
205
+ .option("--json", "Emit one machine-readable JSON value")
206
+ .action(async (options) => {
59
207
  try {
60
- const result = await dependencies.contextValidator.validate({
61
- context,
208
+ const result = await dependencies.contextRefresher.refresh({
62
209
  projectRoot: options.project,
63
- config
210
+ contextPath: contextPath(options.project, options.context),
211
+ ...(options.module === undefined ? {} : { moduleIds: options.module }),
212
+ ...(options.acceptSourceChanges === undefined
213
+ ? {}
214
+ : { acceptSourceChanges: options.acceptSourceChanges }),
215
+ ...(options.pruneDeleted === undefined
216
+ ? {}
217
+ : { pruneDeleted: options.pruneDeleted })
64
218
  });
65
- const exitCode = exitCodeForContext(name, result);
66
- const output = { ...result, exitCode };
219
+ const exitCode = refreshExitCode(result);
67
220
  if (options.json === true) {
68
- writeJson(dependencies.stdout, output);
221
+ writeJson(dependencies.stdout, { ...result, exitCode });
69
222
  }
70
223
  else {
71
- writeLine(dependencies.stdout, result.status === "valid"
72
- ? "Context: valid"
73
- : `Context: ${result.status} (${result.reason.message})`);
224
+ writeRefreshText(dependencies, result);
74
225
  }
75
226
  dependencies.setExitCode(exitCode);
76
227
  }
77
228
  catch (error) {
78
- const output = failureOutput(4, "INTERNAL_ERROR", errorMessage(error));
229
+ const output = error instanceof ContextRefreshError
230
+ ? {
231
+ status: "error",
232
+ exitCode: 2,
233
+ failure: { code: error.code, message: error.message }
234
+ }
235
+ : error instanceof ContextLoadError
236
+ ? {
237
+ status: "error",
238
+ exitCode: 2,
239
+ failure: { code: error.code, message: error.message }
240
+ }
241
+ : failureOutput(4, "INTERNAL_ERROR", errorMessage(error));
79
242
  if (options.json === true) {
80
243
  writeJson(dependencies.stdout, output);
81
244
  }
82
245
  else {
83
246
  writeLine(dependencies.stderr, output.failure.message);
84
247
  }
85
- dependencies.setExitCode(4);
248
+ dependencies.setExitCode(output.exitCode);
249
+ }
250
+ });
251
+ }
252
+ function writeGenerateText(dependencies, result) {
253
+ writeLine(dependencies.stdout, `Context: generated (${String(result.modules.length)} modules)`);
254
+ writeLine(dependencies.stdout, `Package: ${result.packageName}`);
255
+ writeLine(dependencies.stdout, `Activity: ${result.launchActivity}`);
256
+ for (const module of result.modules) {
257
+ writeLine(dependencies.stdout, ` ${module.id}: ${module.kind} (${String(module.evidenceCount)} evidence files)`);
258
+ }
259
+ }
260
+ function createContextGenerateCommand(dependencies) {
261
+ return new Command("generate")
262
+ .description("Generate Project Context scaffolding from project source")
263
+ .option("--project <path>", "Android project root", dependencies.cwd())
264
+ .option("--context <path>", "Project Context path under .taphound/context", ".taphound/context/project-context.json")
265
+ .option("--force", "Overwrite an existing Project Context")
266
+ .option("--json", "Emit one machine-readable JSON value")
267
+ .action(async (options) => {
268
+ const json = options.json === true;
269
+ const projectRoot = options.project;
270
+ try {
271
+ const result = await dependencies.contextGenerator.generate({
272
+ projectRoot,
273
+ contextPath: contextPath(projectRoot, options.context),
274
+ ...(options.force === undefined ? {} : { force: options.force })
275
+ });
276
+ const output = { ...result, exitCode: 0 };
277
+ if (json) {
278
+ writeJson(dependencies.stdout, output);
279
+ }
280
+ else {
281
+ writeGenerateText(dependencies, result);
282
+ }
283
+ dependencies.setExitCode(0);
284
+ }
285
+ catch (error) {
286
+ const output = error instanceof ContextGenerateError
287
+ ? {
288
+ status: "error",
289
+ exitCode: 2,
290
+ failure: { code: error.code, message: error.message }
291
+ }
292
+ : failureOutput(4, "INTERNAL_ERROR", errorMessage(error));
293
+ if (json) {
294
+ writeJson(dependencies.stdout, output);
295
+ }
296
+ else {
297
+ writeLine(dependencies.stderr, output.failure.message);
298
+ }
299
+ dependencies.setExitCode(output.exitCode);
300
+ }
301
+ });
302
+ }
303
+ function writeRehashText(dependencies, result) {
304
+ writeLine(dependencies.stdout, `Context: ${result.status}`);
305
+ for (const module of result.modules) {
306
+ if (module.changed) {
307
+ writeLine(dependencies.stdout, ` ${module.id}: ${module.previousSha256} -> ${module.currentSha256}`);
308
+ }
309
+ }
310
+ }
311
+ function createContextRehashCommand(dependencies) {
312
+ return new Command("rehash")
313
+ .description("Recompute Project Context shard and index hashes")
314
+ .option("--project <path>", "Android project root", dependencies.cwd())
315
+ .option("--context <path>", "Project Context path under .taphound/context", ".taphound/context/project-context.json")
316
+ .option("--module <id...>", "Rehash only the listed Context modules")
317
+ .option("--json", "Emit one machine-readable JSON value")
318
+ .action(async (options) => {
319
+ try {
320
+ const result = await dependencies.contextRehasher.rehash({
321
+ projectRoot: options.project,
322
+ contextPath: contextPath(options.project, options.context),
323
+ ...(options.module === undefined ? {} : { moduleIds: options.module })
324
+ });
325
+ const output = { ...result, exitCode: 0 };
326
+ if (options.json === true) {
327
+ writeJson(dependencies.stdout, output);
328
+ }
329
+ else {
330
+ writeRehashText(dependencies, result);
331
+ }
332
+ dependencies.setExitCode(0);
333
+ }
334
+ catch (error) {
335
+ const output = error instanceof ContextRehashError
336
+ ? {
337
+ status: "error",
338
+ exitCode: 2,
339
+ failure: { code: error.code, message: error.message }
340
+ }
341
+ : error instanceof ContextLoadError
342
+ ? {
343
+ status: "error",
344
+ exitCode: 2,
345
+ failure: { code: error.code, message: error.message }
346
+ }
347
+ : failureOutput(4, "INTERNAL_ERROR", errorMessage(error));
348
+ if (options.json === true) {
349
+ writeJson(dependencies.stdout, output);
350
+ }
351
+ else {
352
+ writeLine(dependencies.stderr, output.failure.message);
353
+ }
354
+ dependencies.setExitCode(output.exitCode);
86
355
  }
87
356
  });
88
357
  }
@@ -90,5 +359,9 @@ export function createContextCommand(dependencies) {
90
359
  return new Command("context")
91
360
  .description("Validate or inspect Project Context")
92
361
  .addCommand(createContextOperation(dependencies, "validate"))
93
- .addCommand(createContextOperation(dependencies, "status"));
362
+ .addCommand(createContextOperation(dependencies, "status"))
363
+ .addCommand(createContextListCommand(dependencies))
364
+ .addCommand(createContextRefreshCommand(dependencies))
365
+ .addCommand(createContextGenerateCommand(dependencies))
366
+ .addCommand(createContextRehashCommand(dependencies));
94
367
  }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ import type { CliDependencies } from "../dependencies.js";
3
+ export declare function createContractCommand(dependencies: CliDependencies): Command;