swipium 1.5.0 → 2.0.0

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 (498) hide show
  1. package/CHANGELOG.md +171 -0
  2. package/README.md +173 -280
  3. package/THREAT_MODEL.md +223 -47
  4. package/dist/appMap/automationLink.js +30 -27
  5. package/dist/appMap/automationLink.js.map +1 -1
  6. package/dist/appMap/build.js +47 -21
  7. package/dist/appMap/build.js.map +1 -1
  8. package/dist/appMap/codeIndex.js +2 -2
  9. package/dist/appMap/codeIndex.js.map +1 -1
  10. package/dist/appMap/featureIndex.js +3 -3
  11. package/dist/appMap/featureIndex.js.map +1 -1
  12. package/dist/appMap/featureModel.js +2 -2
  13. package/dist/appMap/featureModel.js.map +1 -1
  14. package/dist/appMap/firstRunApply.js +2 -2
  15. package/dist/appMap/firstRunApply.js.map +1 -1
  16. package/dist/appMap/issues.js +10 -10
  17. package/dist/appMap/issues.js.map +1 -1
  18. package/dist/appMap/migrations.js +5 -5
  19. package/dist/appMap/migrations.js.map +1 -1
  20. package/dist/appMap/prelaunch.js +2 -2
  21. package/dist/appMap/prelaunch.js.map +1 -1
  22. package/dist/appMap/projectRegistry.js +77 -11
  23. package/dist/appMap/projectRegistry.js.map +1 -1
  24. package/dist/appMap/provenance.js +2 -2
  25. package/dist/appMap/provenance.js.map +1 -1
  26. package/dist/appMap/query.js +2 -2
  27. package/dist/appMap/query.js.map +1 -1
  28. package/dist/appMap/runtimeMerge.js +3 -3
  29. package/dist/appMap/runtimeMerge.js.map +1 -1
  30. package/dist/appMap/schema.js +1 -1
  31. package/dist/appMap/schema.js.map +1 -1
  32. package/dist/appMap/screenMatch.js +1 -1
  33. package/dist/appMap/screenMatch.js.map +1 -1
  34. package/dist/appMap/staticScan.js +17 -17
  35. package/dist/appMap/staticScan.js.map +1 -1
  36. package/dist/appMap/store.js +55 -7
  37. package/dist/appMap/store.js.map +1 -1
  38. package/dist/appMap/tsAstScan.js +3 -3
  39. package/dist/appMap/tsAstScan.js.map +1 -1
  40. package/dist/artifacts/bundletool.js +5 -5
  41. package/dist/artifacts/bundletool.js.map +1 -1
  42. package/dist/artifacts/resolve.js +10 -10
  43. package/dist/artifacts/resolve.js.map +1 -1
  44. package/dist/automation/capabilities.js +3 -3
  45. package/dist/automation/capabilities.js.map +1 -1
  46. package/dist/automation/gestures.js +1 -1
  47. package/dist/automation/gestures.js.map +1 -1
  48. package/dist/automation/plan.js +7 -7
  49. package/dist/automation/plan.js.map +1 -1
  50. package/dist/automation/report.js +3 -3
  51. package/dist/automation/report.js.map +1 -1
  52. package/dist/automation/selectors.js +14 -25
  53. package/dist/automation/selectors.js.map +1 -1
  54. package/dist/automation/types.js +1 -1
  55. package/dist/automation/types.js.map +1 -1
  56. package/dist/automation/waits.js +5 -5
  57. package/dist/automation/waits.js.map +1 -1
  58. package/dist/automation/webview.js +2 -2
  59. package/dist/automation/webview.js.map +1 -1
  60. package/dist/automationGen/appiumModel.js +13 -7
  61. package/dist/automationGen/appiumModel.js.map +1 -1
  62. package/dist/automationGen/ciEmitter.js +5 -5
  63. package/dist/automationGen/ciEmitter.js.map +1 -1
  64. package/dist/automationGen/identifiers.js +224 -0
  65. package/dist/automationGen/identifiers.js.map +1 -0
  66. package/dist/automationGen/jsEmitter.js +265 -106
  67. package/dist/automationGen/jsEmitter.js.map +1 -1
  68. package/dist/automationGen/packagePatch.js +2 -2
  69. package/dist/automationGen/packagePatch.js.map +1 -1
  70. package/dist/automationGen/platformResolve.js +36 -0
  71. package/dist/automationGen/platformResolve.js.map +1 -0
  72. package/dist/automationGen/projectProfile.js +71 -26
  73. package/dist/automationGen/projectProfile.js.map +1 -1
  74. package/dist/automationGen/pythonEmitter.js +276 -105
  75. package/dist/automationGen/pythonEmitter.js.map +1 -1
  76. package/dist/automationGen/readmeEmitter.js +7 -6
  77. package/dist/automationGen/readmeEmitter.js.map +1 -1
  78. package/dist/{tools/automationGenerate.js → automationGen/run.js} +72 -113
  79. package/dist/automationGen/run.js.map +1 -0
  80. package/dist/automationGen/suitePlan.js +6 -4
  81. package/dist/automationGen/suitePlan.js.map +1 -1
  82. package/dist/automationGen/validation.js +20 -8
  83. package/dist/automationGen/validation.js.map +1 -1
  84. package/dist/build/parseBuildLog.js +2 -2
  85. package/dist/build/parseBuildLog.js.map +1 -1
  86. package/dist/build/plan.js +7 -7
  87. package/dist/build/plan.js.map +1 -1
  88. package/dist/ci/preflight.js +13 -4
  89. package/dist/ci/preflight.js.map +1 -1
  90. package/dist/cli/gc.js +74 -0
  91. package/dist/cli/gc.js.map +1 -0
  92. package/dist/cli/init.js +217 -26
  93. package/dist/cli/init.js.map +1 -1
  94. package/dist/cli/main.js +50 -0
  95. package/dist/cli/main.js.map +1 -0
  96. package/dist/cli/report.js +218 -0
  97. package/dist/cli/report.js.map +1 -0
  98. package/dist/cli/scan.js +35 -14
  99. package/dist/cli/scan.js.map +1 -1
  100. package/dist/cli/suite.js +6 -6
  101. package/dist/cli/suite.js.map +1 -1
  102. package/dist/cli/verify.js +7 -7
  103. package/dist/cli/verify.js.map +1 -1
  104. package/dist/consent/consent.js +162 -5
  105. package/dist/consent/consent.js.map +1 -1
  106. package/dist/context/detect.js +45 -14
  107. package/dist/context/detect.js.map +1 -1
  108. package/dist/context/findApps.js +6 -6
  109. package/dist/context/findApps.js.map +1 -1
  110. package/dist/context/projectRoot.js +174 -19
  111. package/dist/context/projectRoot.js.map +1 -1
  112. package/dist/context/scan.js +1 -1
  113. package/dist/context/scan.js.map +1 -1
  114. package/dist/core/capabilityGroups.js +90 -0
  115. package/dist/core/capabilityGroups.js.map +1 -0
  116. package/dist/core/target.js +3 -3
  117. package/dist/core/target.js.map +1 -1
  118. package/dist/core/targetPlan.js +65 -62
  119. package/dist/core/targetPlan.js.map +1 -1
  120. package/dist/drivers/DirectDriver.js +300 -36
  121. package/dist/drivers/DirectDriver.js.map +1 -1
  122. package/dist/drivers/SimctlDriver.js +120 -7
  123. package/dist/drivers/SimctlDriver.js.map +1 -1
  124. package/dist/drivers/WdaDriver.js +350 -50
  125. package/dist/drivers/WdaDriver.js.map +1 -1
  126. package/dist/explore/candidates.js +2 -2
  127. package/dist/explore/candidates.js.map +1 -1
  128. package/dist/explore/graph.js +5 -5
  129. package/dist/explore/graph.js.map +1 -1
  130. package/dist/explore/policy.js +5 -5
  131. package/dist/explore/policy.js.map +1 -1
  132. package/dist/explore/runner.js +301 -284
  133. package/dist/explore/runner.js.map +1 -1
  134. package/dist/explore/signatures.js +1 -1
  135. package/dist/featureTesting/executionBootstrap.js +29 -30
  136. package/dist/featureTesting/executionBootstrap.js.map +1 -1
  137. package/dist/featureTesting/featureMap.js +2 -2
  138. package/dist/featureTesting/featureMap.js.map +1 -1
  139. package/dist/featureTesting/featureScope.js +12 -12
  140. package/dist/featureTesting/featureScope.js.map +1 -1
  141. package/dist/featureTesting/mapFeatureScope.js +7 -7
  142. package/dist/featureTesting/mapFeatureScope.js.map +1 -1
  143. package/dist/featureTesting/objectiveModel.js +10 -10
  144. package/dist/featureTesting/objectiveModel.js.map +1 -1
  145. package/dist/featureTesting/resultMerge.js +6 -6
  146. package/dist/featureTesting/resultMerge.js.map +1 -1
  147. package/dist/featureTesting/sources.js +4 -4
  148. package/dist/featureTesting/sources.js.map +1 -1
  149. package/dist/featureTesting/suiteBridge.js +1 -1
  150. package/dist/featureTesting/suiteBridge.js.map +1 -1
  151. package/dist/featureTesting/synonyms.js +1 -1
  152. package/dist/featureTesting/synonyms.js.map +1 -1
  153. package/dist/featureTesting/testCaseFactory.js +11 -11
  154. package/dist/featureTesting/testCaseFactory.js.map +1 -1
  155. package/dist/featureTesting/testPlan.js +3 -3
  156. package/dist/featureTesting/testPlan.js.map +1 -1
  157. package/dist/firstRun/authStateMachine.js +1 -1
  158. package/dist/firstRun/authStateMachine.js.map +1 -1
  159. package/dist/firstRun/classifyScreen.js +5 -5
  160. package/dist/firstRun/classifyScreen.js.map +1 -1
  161. package/dist/firstRun/firstRunPlanner.js +11 -11
  162. package/dist/firstRun/firstRunPlanner.js.map +1 -1
  163. package/dist/firstRun/firstRunRunner.js +8 -8
  164. package/dist/firstRun/firstRunRunner.js.map +1 -1
  165. package/dist/firstRun/generatedDataPolicy.js +9 -9
  166. package/dist/firstRun/generatedDataPolicy.js.map +1 -1
  167. package/dist/firstRun/inputPlanner.js +5 -5
  168. package/dist/firstRun/inputPlanner.js.map +1 -1
  169. package/dist/firstRun/onboardingStateMachine.js +1 -1
  170. package/dist/firstRun/onboardingStateMachine.js.map +1 -1
  171. package/dist/firstRun/paywallPolicy.js +3 -3
  172. package/dist/firstRun/paywallPolicy.js.map +1 -1
  173. package/dist/firstRun/types.js +1 -1
  174. package/dist/firstRun/types.js.map +1 -1
  175. package/dist/fixtures/catalog.js +33 -3
  176. package/dist/fixtures/catalog.js.map +1 -1
  177. package/dist/fixtures/load.js +50 -0
  178. package/dist/fixtures/load.js.map +1 -0
  179. package/dist/flows/discover.js +2 -2
  180. package/dist/flows/discover.js.map +1 -1
  181. package/dist/flows/generate.js +20 -10
  182. package/dist/flows/generate.js.map +1 -1
  183. package/dist/flows/pack.js +3 -3
  184. package/dist/flows/pack.js.map +1 -1
  185. package/dist/flows/paths.js +57 -0
  186. package/dist/flows/paths.js.map +1 -0
  187. package/dist/flows/repair.js +111 -23
  188. package/dist/flows/repair.js.map +1 -1
  189. package/dist/flows/run.js +153 -57
  190. package/dist/flows/run.js.map +1 -1
  191. package/dist/flows/schema.js +50 -5
  192. package/dist/flows/schema.js.map +1 -1
  193. package/dist/flows/seedExec.js +4 -4
  194. package/dist/flows/seedExec.js.map +1 -1
  195. package/dist/flows/templates.js +5 -5
  196. package/dist/index.js +50 -8
  197. package/dist/index.js.map +1 -1
  198. package/dist/issues/classify.js +16 -16
  199. package/dist/issues/classify.js.map +1 -1
  200. package/dist/issues/fingerprint.js +24 -4
  201. package/dist/issues/fingerprint.js.map +1 -1
  202. package/dist/issues/index.js +94 -31
  203. package/dist/issues/index.js.map +1 -1
  204. package/dist/issues/metrics.js +4 -4
  205. package/dist/issues/metrics.js.map +1 -1
  206. package/dist/issues/recurrence.js +35 -8
  207. package/dist/issues/recurrence.js.map +1 -1
  208. package/dist/issues/report.js +4 -4
  209. package/dist/issues/report.js.map +1 -1
  210. package/dist/issues/reportBridge.js +4 -4
  211. package/dist/issues/reportBridge.js.map +1 -1
  212. package/dist/issues/schema.js +2 -2
  213. package/dist/issues/schema.js.map +1 -1
  214. package/dist/issues/sourceRevision.js +2 -2
  215. package/dist/issues/sourceRevision.js.map +1 -1
  216. package/dist/issues/store.js +110 -32
  217. package/dist/issues/store.js.map +1 -1
  218. package/dist/lib/abortScope.js +48 -0
  219. package/dist/lib/abortScope.js.map +1 -0
  220. package/dist/lib/android.js +75 -7
  221. package/dist/lib/android.js.map +1 -1
  222. package/dist/lib/coordSpace.js +1 -1
  223. package/dist/lib/coordSpace.js.map +1 -1
  224. package/dist/lib/device.js +32 -7
  225. package/dist/lib/device.js.map +1 -1
  226. package/dist/lib/gestures.js +141 -0
  227. package/dist/lib/gestures.js.map +1 -0
  228. package/dist/lib/gitignore.js +4 -3
  229. package/dist/lib/gitignore.js.map +1 -1
  230. package/dist/lib/image.js +1 -1
  231. package/dist/lib/image.js.map +1 -1
  232. package/dist/lib/lockfile.js +370 -31
  233. package/dist/lib/lockfile.js.map +1 -1
  234. package/dist/lib/needsInput.js +3 -3
  235. package/dist/lib/needsInput.js.map +1 -1
  236. package/dist/lib/png.js +2 -2
  237. package/dist/lib/png.js.map +1 -1
  238. package/dist/lib/redact.js +170 -9
  239. package/dist/lib/redact.js.map +1 -1
  240. package/dist/lib/result.js +79 -10
  241. package/dist/lib/result.js.map +1 -1
  242. package/dist/lib/schemaHash.js +3 -3
  243. package/dist/lib/schemaHash.js.map +1 -1
  244. package/dist/lib/sensitive.js +3 -2
  245. package/dist/lib/sensitive.js.map +1 -1
  246. package/dist/lib/simctl.js +3 -3
  247. package/dist/lib/simctl.js.map +1 -1
  248. package/dist/lib/spawn.js +52 -10
  249. package/dist/lib/spawn.js.map +1 -1
  250. package/dist/lib/toolAnnotations.js +114 -0
  251. package/dist/lib/toolAnnotations.js.map +1 -0
  252. package/dist/lib/wda.js +294 -15
  253. package/dist/lib/wda.js.map +1 -1
  254. package/dist/mobileAudit/checks.js +12 -12
  255. package/dist/mobileAudit/checks.js.map +1 -1
  256. package/dist/mobileAudit/evidence.js +4 -4
  257. package/dist/mobileAudit/evidence.js.map +1 -1
  258. package/dist/mobileAudit/profiles.js +1 -1
  259. package/dist/mobileAudit/profiles.js.map +1 -1
  260. package/dist/mobileAudit/results.js +3 -3
  261. package/dist/mobileAudit/results.js.map +1 -1
  262. package/dist/mobileAudit/runner.js +72 -18
  263. package/dist/mobileAudit/runner.js.map +1 -1
  264. package/dist/oracle/auth.js +1 -1
  265. package/dist/oracle/auth.js.map +1 -1
  266. package/dist/oracle/failures.js +219 -36
  267. package/dist/oracle/failures.js.map +1 -1
  268. package/dist/oracle/health.js +63 -17
  269. package/dist/oracle/health.js.map +1 -1
  270. package/dist/oracle/locator.js +13 -13
  271. package/dist/oracle/locator.js.map +1 -1
  272. package/dist/oracle/record.js +3 -3
  273. package/dist/oracle/record.js.map +1 -1
  274. package/dist/orchestration/envelope.js +2 -2
  275. package/dist/orchestration/envelope.js.map +1 -1
  276. package/dist/orchestration/goal.js +4 -4
  277. package/dist/orchestration/goal.js.map +1 -1
  278. package/dist/orchestration/testThis/execute.js +62 -21
  279. package/dist/orchestration/testThis/execute.js.map +1 -1
  280. package/dist/orchestration/testThis/pipeline.js +119 -30
  281. package/dist/orchestration/testThis/pipeline.js.map +1 -1
  282. package/dist/orchestration/testThis/plan.js +162 -73
  283. package/dist/orchestration/testThis/plan.js.map +1 -1
  284. package/dist/orchestration/testThis/sessionIntent.js +72 -0
  285. package/dist/orchestration/testThis/sessionIntent.js.map +1 -0
  286. package/dist/orchestration/testThis/terminal.js +34 -16
  287. package/dist/orchestration/testThis/terminal.js.map +1 -1
  288. package/dist/orchestration/testThis/types.js +1 -1
  289. package/dist/orchestration/testThis/types.js.map +1 -1
  290. package/dist/plan/plan.js +9 -9
  291. package/dist/plan/plan.js.map +1 -1
  292. package/dist/prompts/index.js +22 -22
  293. package/dist/prompts/index.js.map +1 -1
  294. package/dist/report/export.js +392 -37
  295. package/dist/report/export.js.map +1 -1
  296. package/dist/report/findingsDedupe.js +41 -0
  297. package/dist/report/findingsDedupe.js.map +1 -0
  298. package/dist/report/policy.js +7 -4
  299. package/dist/report/policy.js.map +1 -1
  300. package/dist/report/qaLevel.js +8 -8
  301. package/dist/report/qaLevel.js.map +1 -1
  302. package/dist/report/sarifSources.js +160 -0
  303. package/dist/report/sarifSources.js.map +1 -0
  304. package/dist/report/summary.js +2 -2
  305. package/dist/report/summary.js.map +1 -1
  306. package/dist/report/testCatalog.js +4 -4
  307. package/dist/report/testCatalog.js.map +1 -1
  308. package/dist/report/toolHealth.js +124 -0
  309. package/dist/report/toolHealth.js.map +1 -0
  310. package/dist/server.js +472 -45
  311. package/dist/server.js.map +1 -1
  312. package/dist/services/automationGenerate.js +8 -2
  313. package/dist/services/automationGenerate.js.map +1 -1
  314. package/dist/services/build.js +2 -2
  315. package/dist/services/build.js.map +1 -1
  316. package/dist/{tools → services}/flowGenerate.js +29 -13
  317. package/dist/services/flowGenerate.js.map +1 -0
  318. package/dist/services/preflight.js +4 -4
  319. package/dist/services/preflight.js.map +1 -1
  320. package/dist/services/prepareAndroid.js +46 -8
  321. package/dist/services/prepareAndroid.js.map +1 -1
  322. package/dist/services/prepareIos.js +24 -9
  323. package/dist/services/prepareIos.js.map +1 -1
  324. package/dist/services/report.js +100 -45
  325. package/dist/services/report.js.map +1 -1
  326. package/dist/services/smoke.js +32 -16
  327. package/dist/services/smoke.js.map +1 -1
  328. package/dist/services/suiteGenerate.js +28 -3
  329. package/dist/services/suiteGenerate.js.map +1 -1
  330. package/dist/services/testSuiteKnowledge.js +40 -27
  331. package/dist/services/testSuiteKnowledge.js.map +1 -1
  332. package/dist/session/attach.js +270 -6
  333. package/dist/session/attach.js.map +1 -1
  334. package/dist/session/processRegistry.js +317 -48
  335. package/dist/session/processRegistry.js.map +1 -1
  336. package/dist/session/progress.js +1 -1
  337. package/dist/session/retention.js +201 -0
  338. package/dist/session/retention.js.map +1 -0
  339. package/dist/session/store.js +275 -48
  340. package/dist/session/store.js.map +1 -1
  341. package/dist/snapshot/overlays.js +53 -8
  342. package/dist/snapshot/overlays.js.map +1 -1
  343. package/dist/snapshot/parse.js +28 -4
  344. package/dist/snapshot/parse.js.map +1 -1
  345. package/dist/snapshot/present.js +11 -5
  346. package/dist/snapshot/present.js.map +1 -1
  347. package/dist/snapshot/settle.js +39 -9
  348. package/dist/snapshot/settle.js.map +1 -1
  349. package/dist/state/consent.js +99 -0
  350. package/dist/state/consent.js.map +1 -0
  351. package/dist/state/profile.js +46 -2
  352. package/dist/state/profile.js.map +1 -1
  353. package/dist/suite/compile.js +9 -5
  354. package/dist/suite/compile.js.map +1 -1
  355. package/dist/suite/lint.js +4 -4
  356. package/dist/suite/lint.js.map +1 -1
  357. package/dist/suite/pom.js +50 -41
  358. package/dist/suite/pom.js.map +1 -1
  359. package/dist/suite/secretGuard.js +266 -0
  360. package/dist/suite/secretGuard.js.map +1 -0
  361. package/dist/suite/testcase.js +9 -7
  362. package/dist/suite/testcase.js.map +1 -1
  363. package/dist/testSuite/exporter.js +4 -4
  364. package/dist/testSuite/exporter.js.map +1 -1
  365. package/dist/testSuite/generator.js +13 -9
  366. package/dist/testSuite/generator.js.map +1 -1
  367. package/dist/testSuite/history.js +1 -1
  368. package/dist/testSuite/history.js.map +1 -1
  369. package/dist/testSuite/issueLinks.js +3 -3
  370. package/dist/testSuite/issueLinks.js.map +1 -1
  371. package/dist/testSuite/lint.js +4 -4
  372. package/dist/testSuite/lint.js.map +1 -1
  373. package/dist/testSuite/merge.js +5 -5
  374. package/dist/testSuite/merge.js.map +1 -1
  375. package/dist/testSuite/schema.js +5 -5
  376. package/dist/testSuite/schema.js.map +1 -1
  377. package/dist/testSuite/store.js +3 -3
  378. package/dist/testSuite/store.js.map +1 -1
  379. package/dist/testSuite/traceability.js +2 -2
  380. package/dist/testSuite/traceability.js.map +1 -1
  381. package/dist/tools/act.js +794 -164
  382. package/dist/tools/act.js.map +1 -1
  383. package/dist/tools/agent.js +451 -128
  384. package/dist/tools/agent.js.map +1 -1
  385. package/dist/tools/appControl.js +69 -19
  386. package/dist/tools/appControl.js.map +1 -1
  387. package/dist/tools/appMap.js +188 -130
  388. package/dist/tools/appMap.js.map +1 -1
  389. package/dist/tools/build.js +32 -42
  390. package/dist/tools/build.js.map +1 -1
  391. package/dist/tools/bundletool.js +21 -31
  392. package/dist/tools/bundletool.js.map +1 -1
  393. package/dist/tools/clearOverlay.js +55 -12
  394. package/dist/tools/clearOverlay.js.map +1 -1
  395. package/dist/tools/device.js +76 -24
  396. package/dist/tools/device.js.map +1 -1
  397. package/dist/tools/doctor.js +68 -28
  398. package/dist/tools/doctor.js.map +1 -1
  399. package/dist/tools/explore.js +41 -47
  400. package/dist/tools/explore.js.map +1 -1
  401. package/dist/tools/featureTesting.js +31 -48
  402. package/dist/tools/featureTesting.js.map +1 -1
  403. package/dist/tools/firstRun.js +34 -41
  404. package/dist/tools/firstRun.js.map +1 -1
  405. package/dist/tools/flow.js +183 -103
  406. package/dist/tools/flow.js.map +1 -1
  407. package/dist/tools/flowRepair.js +25 -13
  408. package/dist/tools/flowRepair.js.map +1 -1
  409. package/dist/tools/generate.js +52 -89
  410. package/dist/tools/generate.js.map +1 -1
  411. package/dist/tools/getArtifact.js +16 -5
  412. package/dist/tools/getArtifact.js.map +1 -1
  413. package/dist/tools/health.js +15 -12
  414. package/dist/tools/health.js.map +1 -1
  415. package/dist/tools/ios.js +45 -223
  416. package/dist/tools/ios.js.map +1 -1
  417. package/dist/tools/issues.js +251 -35
  418. package/dist/tools/issues.js.map +1 -1
  419. package/dist/tools/jobs.js +41 -16
  420. package/dist/tools/jobs.js.map +1 -1
  421. package/dist/tools/metro.js +36 -35
  422. package/dist/tools/metro.js.map +1 -1
  423. package/dist/tools/mobileAudit.js +50 -45
  424. package/dist/tools/mobileAudit.js.map +1 -1
  425. package/dist/tools/network.js +31 -14
  426. package/dist/tools/network.js.map +1 -1
  427. package/dist/tools/note.js +26 -26
  428. package/dist/tools/note.js.map +1 -1
  429. package/dist/tools/prepareIosTarget.js +10 -16
  430. package/dist/tools/prepareIosTarget.js.map +1 -1
  431. package/dist/tools/prepareTarget.js +117 -50
  432. package/dist/tools/prepareTarget.js.map +1 -1
  433. package/dist/tools/report.js +11 -22
  434. package/dist/tools/report.js.map +1 -1
  435. package/dist/tools/resolveArtifact.js +11 -15
  436. package/dist/tools/resolveArtifact.js.map +1 -1
  437. package/dist/tools/resolveTarget.js +78 -24
  438. package/dist/tools/resolveTarget.js.map +1 -1
  439. package/dist/tools/screenRecord.js +23 -21
  440. package/dist/tools/screenRecord.js.map +1 -1
  441. package/dist/tools/screenshot.js +23 -16
  442. package/dist/tools/screenshot.js.map +1 -1
  443. package/dist/tools/smoke.js +20 -16
  444. package/dist/tools/smoke.js.map +1 -1
  445. package/dist/tools/snapshot.js +155 -118
  446. package/dist/tools/snapshot.js.map +1 -1
  447. package/dist/tools/startSession.js +104 -116
  448. package/dist/tools/startSession.js.map +1 -1
  449. package/dist/tools/suite.js +72 -43
  450. package/dist/tools/suite.js.map +1 -1
  451. package/dist/tools/testSuite.js +30 -20
  452. package/dist/tools/testSuite.js.map +1 -1
  453. package/dist/tools/testThis.js +24 -28
  454. package/dist/tools/testThis.js.map +1 -1
  455. package/dist/tools/visual.js +686 -210
  456. package/dist/tools/visual.js.map +1 -1
  457. package/dist/tools/wait.js +9 -38
  458. package/dist/tools/wait.js.map +1 -1
  459. package/dist/tools/wda.js +187 -57
  460. package/dist/tools/wda.js.map +1 -1
  461. package/dist/version.js +31 -22
  462. package/dist/version.js.map +1 -1
  463. package/dist/visual/ocr.js +53 -6
  464. package/dist/visual/ocr.js.map +1 -1
  465. package/dist/visual/provider.js +80 -12
  466. package/dist/visual/provider.js.map +1 -1
  467. package/docs/README.md +24 -10
  468. package/docs/ci-reports.md +328 -0
  469. package/docs/concepts.md +227 -0
  470. package/docs/flows.md +153 -0
  471. package/docs/mcp-server.md +194 -128
  472. package/docs/physical-devices.md +84 -0
  473. package/docs/tools.md +812 -152
  474. package/package.json +3 -2
  475. package/dist/tools/assertVisual.js +0 -84
  476. package/dist/tools/assertVisual.js.map +0 -1
  477. package/dist/tools/automationGenerate.js.map +0 -1
  478. package/dist/tools/capabilities.js +0 -179
  479. package/dist/tools/capabilities.js.map +0 -1
  480. package/dist/tools/detectContext.js +0 -41
  481. package/dist/tools/detectContext.js.map +0 -1
  482. package/dist/tools/flowGenerate.js.map +0 -1
  483. package/dist/tools/history.js +0 -86
  484. package/dist/tools/history.js.map +0 -1
  485. package/dist/tools/locator.js +0 -85
  486. package/dist/tools/locator.js.map +0 -1
  487. package/dist/tools/permissions.js +0 -174
  488. package/dist/tools/permissions.js.map +0 -1
  489. package/dist/tools/plan.js +0 -52
  490. package/dist/tools/plan.js.map +0 -1
  491. package/dist/tools/screenInfo.js +0 -76
  492. package/dist/tools/screenInfo.js.map +0 -1
  493. package/dist/tools/seed.js +0 -133
  494. package/dist/tools/seed.js.map +0 -1
  495. package/dist/tools/state.js +0 -217
  496. package/dist/tools/state.js.map +0 -1
  497. package/dist/tools/visualText.js +0 -106
  498. package/dist/tools/visualText.js.map +0 -1
@@ -1,12 +1,84 @@
1
- // Portable consent state machine (DESIGN §10.2). Works WITHOUT client elicitation:
1
+ // Portable consent state machine. Works WITHOUT client elicitation:
2
2
  // a privileged action returns { requiresConsent, consentId, ... }; the agent surfaces
3
3
  // it, the user approves, and the same tool is re-called with { consentId, approve:true }.
4
+ //
5
+ // THREAT_MODEL: the re-call is made by the client, so a compromised client can self-approve.
6
+ // When the connected client advertises the MCP elicitation capability, server.ts installs an
7
+ // elicitation provider here and routes each pending consent through a REAL out-of-band user
8
+ // prompt (requestConsentDecision) before the envelope ever reaches the model. On such clients a
9
+ // declined, dismissed (`cancel`), timed-out or failed prompt is a REFUSAL. It never falls back
10
+ // to the model-mediated re-call. Which path decided an action is tagged as its
11
+ // ApprovalMechanism and lands in the mutation ledger.
4
12
  import { randomUUID } from 'node:crypto';
13
+ import { AsyncLocalStorage } from 'node:async_hooks';
14
+ // The calling tool invocation's sessionId, set once per call by the server's tool wrapper
15
+ // (src/server.ts) so every consent-gated tool is session-bound with zero per-tool changes.
16
+ const consentScope = new AsyncLocalStorage();
17
+ /** Run `fn` as part of a tool call made in `sessionId` (undefined = no session). */
18
+ export function runWithConsentScope(sessionId, fn) {
19
+ return consentScope.run({ sessionId: typeof sessionId === 'string' && sessionId ? sessionId : undefined }, fn);
20
+ }
21
+ function currentConsentSession() {
22
+ return consentScope.getStore()?.sessionId;
23
+ }
24
+ // Pending challenges are bounded (review §4): a consent that is never resumed must not live
25
+ // forever, and a client minting challenges in a loop must not grow the map without limit.
26
+ // TTL comfortably exceeds the elicitation timeout below so an in-flight prompt never expires.
27
+ export const CONSENT_TTL_MS = 30 * 60_000;
28
+ export const CONSENT_PENDING_CAP = 200;
5
29
  const pending = new Map();
30
+ function prunePending(now = Date.now()) {
31
+ for (const [id, p] of pending) {
32
+ if (now - p.createdAt > CONSENT_TTL_MS)
33
+ forget(id);
34
+ }
35
+ // Map iteration order is insertion order, so the first keys are the oldest challenges.
36
+ while (pending.size > CONSENT_PENDING_CAP) {
37
+ const oldest = pending.keys().next().value;
38
+ if (oldest === undefined)
39
+ break;
40
+ forget(oldest);
41
+ }
42
+ }
43
+ function forget(consentId) {
44
+ pending.delete(consentId);
45
+ elicitationApproved.delete(consentId);
46
+ awaitingElicitation.delete(consentId);
47
+ }
48
+ let elicitationProvider;
49
+ /** Installed once at server construction (src/server.ts); undefined disables elicitation. */
50
+ export function setElicitationProvider(provider) {
51
+ elicitationProvider = provider;
52
+ }
53
+ // consentId > mechanism for approvals already consumed, so the mutation ledger can record
54
+ // HOW each privileged action was approved even at recording sites far from the gate
55
+ // (SessionStore.recordMutation reads this). Bounded like the ledger itself.
56
+ const consumedMechanisms = new Map();
57
+ const elicitationApproved = new Set();
58
+ // Challenges currently routed to (or decided by) an out-of-band prompt: a client re-call can
59
+ // never approve these. Only the elicitation answer can (no approve:true bypass).
60
+ const awaitingElicitation = new Set();
61
+ /** Mechanism that approved an already-consumed consentId (audit trail for the ledger). */
62
+ export function approvalMechanismFor(consentId) {
63
+ return consumedMechanisms.get(consentId);
64
+ }
65
+ /** The still-pending request behind a consentId (read-only; used to ledger a refusal). */
66
+ export function peekConsent(consentId) {
67
+ const p = pending.get(consentId);
68
+ if (!p || Date.now() - p.createdAt > CONSENT_TTL_MS)
69
+ return undefined;
70
+ return p.req;
71
+ }
72
+ /** Burn a pending challenge without approving it (e.g. the routed action changed under a prompt). */
73
+ export function burnConsent(consentId) {
74
+ forget(consentId);
75
+ }
6
76
  /** Build the tool result that asks for consent. */
7
77
  export function requireConsent(req) {
78
+ prunePending();
8
79
  const consentId = randomUUID().slice(0, 8);
9
- pending.set(consentId, req);
80
+ const sessionId = currentConsentSession();
81
+ pending.set(consentId, { req, createdAt: Date.now(), ...(sessionId ? { sessionId } : {}) });
10
82
  const payload = { requiresConsent: true, consentId, ...req };
11
83
  const text = `🔐 Consent required (${req.risk}): ${req.explain}\n` +
12
84
  (req.exactCommand ? `Will run: ${req.exactCommand}\n` : '') +
@@ -16,6 +88,61 @@ export function requireConsent(req) {
16
88
  '\n```';
17
89
  return { content: [{ type: 'text', text }], structuredContent: payload };
18
90
  }
91
+ /**
92
+ * Ask the connected client's HUMAN to decide a freshly-minted consent via MCP elicitation.
93
+ * - approved: the caller re-invokes the tool; consumeConsent tags mechanism 'elicitation'.
94
+ * - declined / cancelled (dismissed, timed out, transport error, aborted call): REFUSAL. The
95
+ * challenge is burned so the client cannot self-approve it afterwards (a re-call of the tool
96
+ * mints a fresh challenge and a fresh prompt).
97
+ * - unavailable (client does not advertise elicitation): portable re-call convention
98
+ * ('client-assertion'), unless SWIPIUM_REQUIRE_ELICITATION=1, in which case EVERY
99
+ * consent-gated action (builds, Metro, installs, data wipes, seeds…) is refused outright.
100
+ */
101
+ export async function requestConsentDecision(consentId, ctx) {
102
+ const req = peekConsent(consentId);
103
+ if (!req)
104
+ return { mechanism: 'client-assertion' };
105
+ let answer = 'unavailable';
106
+ let failure;
107
+ if (elicitationProvider) {
108
+ awaitingElicitation.add(consentId);
109
+ try {
110
+ answer = await elicitationProvider(req, ctx);
111
+ }
112
+ catch (e) {
113
+ // The client advertised elicitation, so a throw here is a timeout / transport failure /
114
+ // aborted call / invalid answer while the prompt was outstanding: fail CLOSED.
115
+ answer = 'cancelled';
116
+ failure = e instanceof Error ? e.message : String(e);
117
+ }
118
+ if (answer === 'unavailable')
119
+ awaitingElicitation.delete(consentId);
120
+ }
121
+ if (answer === 'approved') {
122
+ elicitationApproved.add(consentId);
123
+ return { mechanism: 'elicitation', approved: true };
124
+ }
125
+ if (answer === 'declined' || answer === 'cancelled') {
126
+ forget(consentId);
127
+ return {
128
+ mechanism: 'elicitation',
129
+ approved: false,
130
+ outcome: answer,
131
+ reason: answer === 'declined'
132
+ ? `User declined "${req.action}" in the consent prompt`
133
+ : `Consent prompt for "${req.action}" was dismissed or not answered${failure ? ` (${failure})` : ''}, treated as a refusal`,
134
+ };
135
+ }
136
+ if (process.env.SWIPIUM_REQUIRE_ELICITATION === '1') {
137
+ forget(consentId);
138
+ return {
139
+ mechanism: 'refused',
140
+ reason: `SWIPIUM_REQUIRE_ELICITATION=1: "${req.action}" (risk ${req.risk}) needs an out-of-band user prompt, ` +
141
+ 'but the connected client does not support MCP elicitation.',
142
+ };
143
+ }
144
+ return { mechanism: 'client-assertion' };
145
+ }
19
146
  /**
20
147
  * Validate a resume call. Consent is single-use AND bound to the exact action:
21
148
  * `expected.action`/`expected.affects` must match what was originally requested, so an
@@ -24,9 +151,19 @@ export function requireConsent(req) {
24
151
  export function consumeConsent(consentId, approve, expected) {
25
152
  if (!consentId)
26
153
  return { approved: false, reason: 'no consentId supplied' };
27
- const req = pending.get(consentId);
154
+ const entry = pending.get(consentId);
155
+ if (entry && Date.now() - entry.createdAt > CONSENT_TTL_MS) {
156
+ forget(consentId);
157
+ return { approved: false, reason: 'consent expired; re-call without consentId for a fresh challenge' };
158
+ }
159
+ const req = entry?.req;
28
160
  if (!req)
29
161
  return { approved: false, reason: 'unknown or already-used consentId' };
162
+ // Session binding: checked BEFORE consuming (like the action binding) so a cross-session replay
163
+ // attempt never burns the challenge for its real session.
164
+ if (entry.sessionId !== undefined && entry.sessionId !== currentConsentSession()) {
165
+ return { approved: false, req, reason: 'consent was issued for a different session' };
166
+ }
30
167
  // Bind to the exact action/affects BEFORE consuming, so a mismatched id stays valid
31
168
  // for its real use rather than being silently burned.
32
169
  if (expected?.action && req.action !== expected.action) {
@@ -35,9 +172,29 @@ export function consumeConsent(consentId, approve, expected) {
35
172
  if (expected?.affects && JSON.stringify(req.affects ?? {}) !== JSON.stringify(expected.affects)) {
36
173
  return { approved: false, req, reason: 'consent does not match the affected target' };
37
174
  }
38
- pending.delete(consentId);
175
+ const wasElicited = elicitationApproved.has(consentId);
176
+ const routed = awaitingElicitation.has(consentId);
177
+ forget(consentId);
39
178
  if (!approve)
40
179
  return { approved: false, req, reason: 'user did not approve' };
41
- return { approved: true, req };
180
+ // A challenge routed to an out-of-band prompt can only be approved BY that prompt: a client
181
+ // re-call with approve:true (e.g. racing the dialog) must not bypass the human.
182
+ if (routed && !wasElicited)
183
+ return { approved: false, req, reason: 'consent is awaiting the out-of-band user prompt' };
184
+ const mechanism = wasElicited ? 'elicitation' : 'client-assertion';
185
+ recordMechanism(consentId, mechanism);
186
+ return { approved: true, req, mechanism };
187
+ }
188
+ function recordMechanism(consentId, mechanism) {
189
+ consumedMechanisms.set(consentId, mechanism);
190
+ if (consumedMechanisms.size > 500) {
191
+ const oldest = consumedMechanisms.keys().next().value;
192
+ if (oldest !== undefined)
193
+ consumedMechanisms.delete(oldest);
194
+ }
195
+ }
196
+ /** Test/diagnostic view of the pending-challenge map size (bounded by CONSENT_PENDING_CAP). */
197
+ export function pendingConsentCount() {
198
+ return pending.size;
42
199
  }
43
200
  //# sourceMappingURL=consent.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"consent.js","sourceRoot":"","sources":["../../src/consent/consent.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,sFAAsF;AACtF,0FAA0F;AAE1F,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAazC,MAAM,OAAO,GAAG,IAAI,GAAG,EAA0B,CAAC;AAElD,mDAAmD;AACnD,MAAM,UAAU,cAAc,CAAC,GAAmB;IAChD,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAC5B,MAAM,OAAO,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,GAAG,EAAE,CAAC;IAC7D,MAAM,IAAI,GACR,wBAAwB,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,OAAO,IAAI;QACrD,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,YAAY,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,iDAAiD,SAAS,yBAAyB;QACnF,WAAW;QACX,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAChC,OAAO,CAAC;IACV,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC;AAC3E,CAAC;AAQD;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,SAAkB,EAClB,OAAiB,EACjB,QAAiE;IAEjE,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAC;IAC5E,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACnC,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,mCAAmC,EAAE,CAAC;IAClF,oFAAoF;IACpF,sDAAsD;IACtD,IAAI,QAAQ,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;QACvD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,mBAAmB,GAAG,CAAC,MAAM,WAAW,QAAQ,CAAC,MAAM,GAAG,EAAE,CAAC;IACtG,CAAC;IACD,IAAI,QAAQ,EAAE,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAChG,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,4CAA4C,EAAE,CAAC;IACxF,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC1B,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC;IAC9E,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;AACjC,CAAC"}
1
+ {"version":3,"file":"consent.js","sourceRoot":"","sources":["../../src/consent/consent.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,33 @@
1
- // Detect the mobile project context under a resolved projectRoot (DESIGN §7).
1
+ // Detect the mobile project context under a resolved projectRoot.
2
2
  // Best-effort, file-marker based; never trusts cwd.
3
3
  import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
4
4
  import { join } from 'node:path';
5
5
  import { which, firstLine, adbDevices, listAvds, findAapt2 } from '../lib/android.js';
6
6
  import { resolveArtifact } from '../artifacts/resolve.js';
7
+ import { simctlAvailable, listSimulators } from '../lib/simctl.js';
8
+ /** Booted + available (shut down) iOS simulators. Tolerates absence: non-macOS hosts, no Xcode
9
+ * command-line tools, or a failing simctl all yield empty lists, never an error. */
10
+ export async function detectIosSimulators() {
11
+ if (process.platform !== 'darwin')
12
+ return { iosBooted: [], iosAvailable: [] };
13
+ try {
14
+ if (!(await simctlAvailable()))
15
+ return { iosBooted: [], iosAvailable: [] };
16
+ const sims = await listSimulators();
17
+ const brief = (s) => ({ udid: s.udid, name: s.name, runtime: s.runtime });
18
+ return {
19
+ iosBooted: sims.filter((s) => s.state === 'Booted').map(brief),
20
+ iosAvailable: sims.filter((s) => s.state !== 'Booted').map(brief),
21
+ };
22
+ }
23
+ catch {
24
+ return { iosBooted: [], iosAvailable: [] };
25
+ }
26
+ }
27
+ /** Any usable device at all (online/bootable Android emulator, or a booted/bootable iOS simulator). */
28
+ export function hasAnyDevice(d) {
29
+ return d.androidOnline.length > 0 || d.avds.length > 0 || d.iosBooted.length > 0 || d.iosAvailable.length > 0;
30
+ }
7
31
  function readJson(p) {
8
32
  try {
9
33
  return JSON.parse(readFileSync(p, 'utf8'));
@@ -121,32 +145,39 @@ export async function detectContext(projectRoot) {
121
145
  aapt2: findAapt2() !== null,
122
146
  xcodebuild,
123
147
  };
124
- const devices = {
125
- androidOnline: adb ? await adbDevices() : [],
126
- avds: emulator ? await listAvds() : [],
127
- };
148
+ const [androidOnline, avds, ios] = await Promise.all([
149
+ adb ? adbDevices() : Promise.resolve([]),
150
+ emulator ? listAvds() : Promise.resolve([]),
151
+ detectIosSimulators(),
152
+ ]);
153
+ const devices = { androidOnline, avds, ...ios };
154
+ const iosUsable = ios.iosBooted.length > 0 || ios.iosAvailable.length > 0;
128
155
  const blockers = [];
129
156
  if (framework === 'unknown')
130
- blockers.push('Could not identify a mobile project here — pass an explicit projectRoot, or this is not a supported framework.');
157
+ blockers.push('Could not identify a mobile project here. Pass an explicit projectRoot, or this is not a supported framework.');
131
158
  if (monorepo)
132
- blockers.push('Monorepo detected — specify which app target to use (avoids guessing).');
133
- if (!toolchain.adb)
134
- blockers.push('adb not found — install Android platform-tools.');
159
+ blockers.push('Monorepo detected. Specify which app target to use (avoids guessing).');
160
+ // adb is only a blocker when Android is the only way forward (an iOS project, or any project
161
+ // with a usable iOS simulator, can still be tested without it).
162
+ if (!toolchain.adb && framework !== 'native-ios' && !iosUsable)
163
+ blockers.push('adb not found. Install Android platform-tools.');
135
164
  if (framework === 'native-android' && artifacts.apks.length === 0) {
136
- blockers.push('No prebuilt Android APK found — drop an APK under apps/android, build Gradle output, or pass apk=.');
165
+ blockers.push('No prebuilt Android APK found. Drop an APK under apps/android, build Gradle output, or pass apk=.');
137
166
  }
138
167
  else if (framework === 'native-ios' && artifacts.ipas.length === 0 && artifacts.appBundles.length === 0) {
139
- blockers.push('No prebuilt iOS app artifact found — build a simulator .app or provide an .ipa for a real device lane.');
168
+ blockers.push('No prebuilt iOS app artifact found. Build a simulator .app or provide an .ipa for a real device lane.');
140
169
  }
141
170
  else if (framework !== 'native-android' &&
142
171
  framework !== 'native-ios' &&
143
172
  artifacts.apks.length === 0 &&
144
173
  artifacts.ipas.length === 0 &&
145
174
  artifacts.appBundles.length === 0) {
146
- blockers.push('No prebuilt app artifact found — build an APK for Android or a simulator .app for iOS, then run swipium scan again.');
175
+ blockers.push('No prebuilt app artifact found. Build an APK for Android or a simulator .app for iOS, then run swipium scan again.');
147
176
  }
148
- if (toolchain.adb && devices.androidOnline.length === 0 && devices.avds.length === 0)
149
- blockers.push('No online device and no AVD — create an AVD (see qa_doctor).');
177
+ if (!hasAnyDevice(devices))
178
+ blockers.push(framework === 'native-ios'
179
+ ? 'No iOS simulator booted or available. Create one in Xcode (Settings > Platforms).'
180
+ : 'No online device, no AVD, and no iOS simulator. Create an AVD (see qa_doctor) or an iOS simulator.');
150
181
  return {
151
182
  projectRoot,
152
183
  location,
@@ -1 +1 @@
1
- {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/context/detect.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/context/detect.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- // Mobile app discovery for low-context roots (Developer 1, roadmap §3.1 / §3.7). When a developer
1
+ // Mobile app discovery for low-context roots (Developer 1). When a developer
2
2
  // or agent points Swipium at a monorepo root, a parent directory, or any folder that is not itself
3
3
  // a mobile app, this locates the candidate app(s) so `qa_test_this` can either proceed with the one
4
- // strong candidate (recording a workaround) or ask ONE disambiguation question — instead of failing
4
+ // strong candidate (recording a workaround) or ask ONE disambiguation question, instead of failing
5
5
  // with NOT_MOBILE_PROJECT at a root that does in fact contain an app.
6
6
  //
7
7
  // Pure + bounded + side-effect free: it scans a fixed, shallow set of conventional locations and
@@ -82,7 +82,7 @@ function readdirSafe(dir) {
82
82
  return [];
83
83
  }
84
84
  }
85
- /** Best-effort app id from cheap config markers (no APK badging — that is too heavy here). */
85
+ /** Best-effort app id from cheap config markers (no APK badging; that is too heavy here). */
86
86
  function lightAppId(dir, fw) {
87
87
  if (fw === 'expo') {
88
88
  const cfg = readJson(join(dir, 'app.json'));
@@ -197,9 +197,9 @@ export function findMobileApps(root, nowMs = Date.now()) {
197
197
  }
198
198
  /**
199
199
  * Decide what `qa_test_this` should do with the discovery result.
200
- * - 'adopt' → exactly one recognized app; proceed with it.
201
- * - 'disambiguate' → ≥2 recognized apps; ask one monorepo_target question with ranked choices.
202
- * - 'none' → no recognized app anywhere searched.
200
+ * - 'adopt' > exactly one recognized app; proceed with it.
201
+ * - 'disambiguate' > ≥2 recognized apps; ask one monorepo_target question with ranked choices.
202
+ * - 'none' > no recognized app anywhere searched.
203
203
  */
204
204
  export function classifyDiscovery(result) {
205
205
  const choices = result.candidates;
@@ -1 +1 @@
1
- {"version":3,"file":"findApps.js","sourceRoot":"","sources":["../../src/context/findApps.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"findApps.js","sourceRoot":"","sources":["../../src/context/findApps.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,158 @@
1
- // Resolve the project root WITHOUT trusting the server cwd (DESIGN §2, review #1).
2
- // Order: explicit arg → MCP roots (the proper mechanism) → needs-input.
3
- import { existsSync, statSync } from 'node:fs';
1
+ // Resolve the project root the server should work in.
2
+ // Order (first hit wins):
3
+ // 1. explicit `projectRoot` arg (must be absolute + an existing directory; an invalid explicit
4
+ // value is an error, never silently replaced by a fallback)
5
+ // 2. MCP roots (the client's declared workspace, the proper mechanism)
6
+ // 3. env SWIPIUM_PROJECT_ROOT (user-set in the client's server config)
7
+ // 4. env CLAUDE_PROJECT_DIR (Claude Code sets it for every stdio server it launches)
8
+ // 5. process.cwd(), only when it is a real directory that is NOT the filesystem root and NOT
9
+ // $HOME, AND it contains a project marker (package.json, app.json, pubspec.yaml, Gradle
10
+ // build/settings files, android/, ios/, *.xcodeproj, *.xcworkspace, Podfile). GUI clients
11
+ // often launch servers from `/`, `~` or an arbitrary directory, which must never be treated
12
+ // as an app repo; clients that honor a configured `cwd` (Codex, Gemini, VS Code) land here.
13
+ // Unresolved: failureCode PROJECT_ROOT_UNRESOLVED (see unresolvedProjectRootError).
14
+ import { AsyncLocalStorage } from 'node:async_hooks';
15
+ import { existsSync, readdirSync, statSync } from 'node:fs';
4
16
  import { fileURLToPath } from 'node:url';
5
- import { isAbsolute } from 'node:path';
6
- export async function resolveProjectRoot(server, explicit) {
17
+ import { isAbsolute, join, parse, resolve } from 'node:path';
18
+ import { homedir } from 'node:os';
19
+ import { qaError } from '../lib/result.js';
20
+ export const PROJECT_ROOT_UNRESOLVED = 'PROJECT_ROOT_UNRESOLVED';
21
+ function isDir(p) {
22
+ try {
23
+ return existsSync(p) && statSync(p).isDirectory();
24
+ }
25
+ catch {
26
+ return false;
27
+ }
28
+ }
29
+ /** Files / directories whose presence marks a directory as a mobile (or JS) app project. */
30
+ export const PROJECT_MARKER_FILES = [
31
+ 'package.json',
32
+ 'app.json',
33
+ 'pubspec.yaml',
34
+ 'build.gradle',
35
+ 'build.gradle.kts',
36
+ 'settings.gradle',
37
+ 'settings.gradle.kts',
38
+ 'Podfile',
39
+ ];
40
+ export const PROJECT_MARKER_DIRS = ['android', 'ios'];
41
+ /** Whether `dir` looks like an app project (see PROJECT_MARKER_FILES / _DIRS, *.xcodeproj, *.xcworkspace). */
42
+ export function hasProjectMarker(dir) {
43
+ if (PROJECT_MARKER_FILES.some((f) => existsSync(join(dir, f))))
44
+ return true;
45
+ if (PROJECT_MARKER_DIRS.some((d) => isDir(join(dir, d))))
46
+ return true;
47
+ try {
48
+ return readdirSync(dir).some((e) => /\.(xcodeproj|xcworkspace)$/i.test(e));
49
+ }
50
+ catch {
51
+ return false;
52
+ }
53
+ }
54
+ /** A cwd is a usable project root only if it is a directory other than `/` (or a drive root) and
55
+ * $HOME that contains a project marker (an arbitrary launch directory is never guessed as the app). */
56
+ export function isUsableCwd(cwd, home = homedir()) {
57
+ if (!cwd || !isAbsolute(cwd))
58
+ return false;
59
+ const abs = resolve(cwd);
60
+ if (abs === parse(abs).root)
61
+ return false;
62
+ if (home && abs === resolve(home))
63
+ return false;
64
+ return isDir(abs) && hasProjectMarker(abs);
65
+ }
66
+ /** Steps 3-5 of the chain (env vars, then cwd). Exported for tests and CLI reuse. Env values are
67
+ * explicit user/client configuration and are trusted as-is; only the cwd guess needs a marker. */
68
+ export function resolveFallbackRoot(opts = {}) {
69
+ const env = opts.env ?? process.env;
70
+ for (const key of ['SWIPIUM_PROJECT_ROOT', 'CLAUDE_PROJECT_DIR']) {
71
+ const v = env[key]?.trim();
72
+ if (v && isAbsolute(v) && isDir(v))
73
+ return { root: v, source: `env:${key}` };
74
+ }
75
+ const cwd = opts.cwd ?? process.cwd();
76
+ if (isUsableCwd(cwd, opts.home ?? homedir()))
77
+ return { root: resolve(cwd), source: 'cwd' };
78
+ return null;
79
+ }
80
+ /** Choose among the client's MCP roots (review P2): the first existing file:// root that has a
81
+ * project marker; else the first one that is neither `/` nor $HOME. A client exposing
82
+ * [$HOME, app] must land on the app, not on the home directory. Exported for tests. */
83
+ export function pickMcpRoot(uris, home = homedir()) {
84
+ const dirs = [];
85
+ for (const u of uris) {
86
+ if (typeof u !== 'string' || !u.startsWith('file://'))
87
+ continue;
88
+ try {
89
+ const p = fileURLToPath(u);
90
+ if (isDir(p))
91
+ dirs.push(p);
92
+ }
93
+ catch {
94
+ /* malformed URI, skip */
95
+ }
96
+ }
97
+ const unsafe = (p) => {
98
+ const abs = resolve(p);
99
+ return abs === parse(abs).root || (!!home && abs === resolve(home));
100
+ };
101
+ return dirs.find((p) => !unsafe(p) && hasProjectMarker(p)) ?? dirs.find((p) => !unsafe(p));
102
+ }
103
+ const UNRESOLVED_HINT = 'No project root: the client exposed no MCP roots, SWIPIUM_PROJECT_ROOT / CLAUDE_PROJECT_DIR are unset, and the server cwd is not an app directory (no package.json / app.json / pubspec.yaml / Gradle files / android/ / ios/ / *.xcodeproj / Podfile). ' +
104
+ 'Pass projectRoot="/absolute/path/to/app", or set SWIPIUM_PROJECT_ROOT in the MCP server "env" (or a "cwd" where the client supports it).';
105
+ /** Per-tool-call record of the first project root resolveProjectRoot() found (AsyncLocalStorage,
106
+ * like the response mode). Lets the server wrapper surface `rootSource` on EVERY tool that
107
+ * resolves a root without threading it through each result builder. */
108
+ const rootResolutionStore = new AsyncLocalStorage();
109
+ /** Run `fn` (one tool call) while recording the project root it resolves. */
110
+ export async function withRootResolutionRecording(fn) {
111
+ const slot = {};
112
+ const value = await rootResolutionStore.run(slot, fn);
113
+ return { value, resolved: slot.resolved };
114
+ }
115
+ /** The note shown when the root was guessed from the server's working directory. */
116
+ export function cwdRootNote(root) {
117
+ return `project root taken from server cwd: ${root}; pass projectRoot to override`;
118
+ }
119
+ /** Additively stamp `rootSource` (+ `projectRoot` when absent) onto a successful tool result, and
120
+ * the cwd note onto its text when the root was only guessed from the server cwd. Results that
121
+ * already carry `rootSource`, errors, and results without structuredContent are left as-is. */
122
+ export function annotateRootSource(result, resolved) {
123
+ if (!resolved)
124
+ return result;
125
+ const r = result;
126
+ const sc = r?.structuredContent;
127
+ if (!r || r.isError || !sc || typeof sc !== 'object' || Array.isArray(sc) || 'rootSource' in sc)
128
+ return result;
129
+ const structuredContent = { ...sc, rootSource: resolved.source, ...('projectRoot' in sc ? {} : { projectRoot: resolved.root }) };
130
+ let content = r.content;
131
+ if (resolved.source === 'cwd' && Array.isArray(content)) {
132
+ const i = content.findIndex((c) => c.type === 'text');
133
+ if (i >= 0) {
134
+ const block = content[i];
135
+ content = [...content];
136
+ content[i] = { ...block, text: `${block.text}\nℹ ${cwdRootNote(resolved.root)}` };
137
+ }
138
+ }
139
+ return { ...r, content, structuredContent };
140
+ }
141
+ export async function resolveProjectRoot(server, explicit, opts = {}) {
142
+ const resolved = await resolveProjectRootUnrecorded(server, explicit, opts);
143
+ const slot = rootResolutionStore.getStore();
144
+ if (slot && !slot.resolved && resolved.root)
145
+ slot.resolved = { root: resolved.root, source: resolved.source };
146
+ return resolved;
147
+ }
148
+ async function resolveProjectRootUnrecorded(server, explicit, opts = {}) {
7
149
  // 1) explicit arg wins (must be an absolute, existing directory)
8
150
  if (explicit && explicit.trim()) {
9
151
  const p = explicit.trim();
10
152
  if (!isAbsolute(p)) {
11
153
  return { source: 'none', hint: `projectRoot must be an absolute path, got "${p}".` };
12
154
  }
13
- if (existsSync(p) && statSync(p).isDirectory()) {
155
+ if (isDir(p)) {
14
156
  return { root: p, source: 'arg' };
15
157
  }
16
158
  return { source: 'none', hint: `Path not found or not a directory: ${p}` };
@@ -20,22 +162,35 @@ export async function resolveProjectRoot(server, explicit) {
20
162
  const caps = server.server.getClientCapabilities?.();
21
163
  if (caps?.roots) {
22
164
  const res = await server.server.listRoots();
23
- const fileRoot = res.roots?.find((r) => typeof r.uri === 'string' && r.uri.startsWith('file://'));
24
- if (fileRoot) {
25
- const p = fileURLToPath(fileRoot.uri);
26
- if (existsSync(p) && statSync(p).isDirectory()) {
27
- return { root: p, source: 'mcp-roots' };
28
- }
29
- }
165
+ const picked = pickMcpRoot((res.roots ?? []).map((r) => r.uri), opts.home ?? homedir());
166
+ if (picked)
167
+ return { root: picked, source: 'mcp-roots' };
30
168
  }
31
169
  }
32
170
  catch {
33
- // client doesn't support roots, or the call failed — fall through to needs-input
171
+ // client doesn't support roots, or the call failed; fall through
34
172
  }
35
- // 3) ask
36
- return {
37
- source: 'none',
38
- hint: 'No workspace root exposed by the client. Call qa_start_session with projectRoot="/absolute/path/to/app".',
39
- };
173
+ // 3-5) env vars, then a meaningful cwd
174
+ const fallback = resolveFallbackRoot(opts);
175
+ if (fallback)
176
+ return fallback;
177
+ return { source: 'none', hint: UNRESOLVED_HINT };
178
+ }
179
+ /**
180
+ * The typed error every tool should return when resolveProjectRoot() finds nothing. Keeps the
181
+ * failureCode (PROJECT_ROOT_UNRESOLVED) and wording consistent across call sites.
182
+ */
183
+ export function unresolvedProjectRootError(resolved, opts = {}) {
184
+ return qaError({
185
+ what: opts.what ?? 'Could not resolve a project root',
186
+ changedState: false,
187
+ retrySafe: true,
188
+ failureCode: PROJECT_ROOT_UNRESOLVED,
189
+ nextSteps: opts.nextSteps ?? [
190
+ 'Pass projectRoot="/absolute/path/to/app" (or call qa_start_session with it first).',
191
+ 'Or set SWIPIUM_PROJECT_ROOT in the MCP server config "env".',
192
+ ],
193
+ clientHint: resolved.hint,
194
+ });
40
195
  }
41
196
  //# sourceMappingURL=projectRoot.js.map