swipium 1.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 (387) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +295 -0
  3. package/dist/appMap/automationLink.js +74 -0
  4. package/dist/appMap/automationLink.js.map +1 -0
  5. package/dist/appMap/build.js +193 -0
  6. package/dist/appMap/build.js.map +1 -0
  7. package/dist/appMap/codeIndex.js +73 -0
  8. package/dist/appMap/codeIndex.js.map +1 -0
  9. package/dist/appMap/featureModel.js +83 -0
  10. package/dist/appMap/featureModel.js.map +1 -0
  11. package/dist/appMap/firstRunApply.js +131 -0
  12. package/dist/appMap/firstRunApply.js.map +1 -0
  13. package/dist/appMap/fsWalk.js +75 -0
  14. package/dist/appMap/fsWalk.js.map +1 -0
  15. package/dist/appMap/issues.js +227 -0
  16. package/dist/appMap/issues.js.map +1 -0
  17. package/dist/appMap/migrations.js +87 -0
  18. package/dist/appMap/migrations.js.map +1 -0
  19. package/dist/appMap/prelaunch.js +66 -0
  20. package/dist/appMap/prelaunch.js.map +1 -0
  21. package/dist/appMap/projectRegistry.js +70 -0
  22. package/dist/appMap/projectRegistry.js.map +1 -0
  23. package/dist/appMap/provenance.js +52 -0
  24. package/dist/appMap/provenance.js.map +1 -0
  25. package/dist/appMap/query.js +118 -0
  26. package/dist/appMap/query.js.map +1 -0
  27. package/dist/appMap/runtimeMerge.js +207 -0
  28. package/dist/appMap/runtimeMerge.js.map +1 -0
  29. package/dist/appMap/schema.js +65 -0
  30. package/dist/appMap/schema.js.map +1 -0
  31. package/dist/appMap/screenMatch.js +75 -0
  32. package/dist/appMap/screenMatch.js.map +1 -0
  33. package/dist/appMap/staticScan.js +614 -0
  34. package/dist/appMap/staticScan.js.map +1 -0
  35. package/dist/appMap/store.js +173 -0
  36. package/dist/appMap/store.js.map +1 -0
  37. package/dist/appMap/tsAstScan.js +184 -0
  38. package/dist/appMap/tsAstScan.js.map +1 -0
  39. package/dist/artifacts/bundletool.js +199 -0
  40. package/dist/artifacts/bundletool.js.map +1 -0
  41. package/dist/artifacts/resolve.js +388 -0
  42. package/dist/artifacts/resolve.js.map +1 -0
  43. package/dist/automationGen/appiumModel.js +129 -0
  44. package/dist/automationGen/appiumModel.js.map +1 -0
  45. package/dist/automationGen/ciEmitter.js +80 -0
  46. package/dist/automationGen/ciEmitter.js.map +1 -0
  47. package/dist/automationGen/jsEmitter.js +440 -0
  48. package/dist/automationGen/jsEmitter.js.map +1 -0
  49. package/dist/automationGen/packagePatch.js +56 -0
  50. package/dist/automationGen/packagePatch.js.map +1 -0
  51. package/dist/automationGen/projectProfile.js +317 -0
  52. package/dist/automationGen/projectProfile.js.map +1 -0
  53. package/dist/automationGen/pythonEmitter.js +386 -0
  54. package/dist/automationGen/pythonEmitter.js.map +1 -0
  55. package/dist/automationGen/readmeEmitter.js +66 -0
  56. package/dist/automationGen/readmeEmitter.js.map +1 -0
  57. package/dist/automationGen/suitePlan.js +94 -0
  58. package/dist/automationGen/suitePlan.js.map +1 -0
  59. package/dist/automationGen/validation.js +150 -0
  60. package/dist/automationGen/validation.js.map +1 -0
  61. package/dist/build/parseBuildLog.js +119 -0
  62. package/dist/build/parseBuildLog.js.map +1 -0
  63. package/dist/build/plan.js +150 -0
  64. package/dist/build/plan.js.map +1 -0
  65. package/dist/ci/preflight.js +85 -0
  66. package/dist/ci/preflight.js.map +1 -0
  67. package/dist/cli/init.js +105 -0
  68. package/dist/cli/init.js.map +1 -0
  69. package/dist/cli/scan.js +85 -0
  70. package/dist/cli/scan.js.map +1 -0
  71. package/dist/cli/suite.js +85 -0
  72. package/dist/cli/suite.js.map +1 -0
  73. package/dist/cli/verify.js +62 -0
  74. package/dist/cli/verify.js.map +1 -0
  75. package/dist/consent/consent.js +43 -0
  76. package/dist/consent/consent.js.map +1 -0
  77. package/dist/context/detect.js +156 -0
  78. package/dist/context/detect.js.map +1 -0
  79. package/dist/context/findApps.js +198 -0
  80. package/dist/context/findApps.js.map +1 -0
  81. package/dist/context/projectRoot.js +41 -0
  82. package/dist/context/projectRoot.js.map +1 -0
  83. package/dist/context/scan.js +167 -0
  84. package/dist/context/scan.js.map +1 -0
  85. package/dist/core/target.js +115 -0
  86. package/dist/core/target.js.map +1 -0
  87. package/dist/core/targetPlan.js +140 -0
  88. package/dist/core/targetPlan.js.map +1 -0
  89. package/dist/drivers/DirectDriver.js +228 -0
  90. package/dist/drivers/DirectDriver.js.map +1 -0
  91. package/dist/drivers/Driver.js +4 -0
  92. package/dist/drivers/Driver.js.map +1 -0
  93. package/dist/drivers/SimctlDriver.js +127 -0
  94. package/dist/drivers/SimctlDriver.js.map +1 -0
  95. package/dist/drivers/WdaDriver.js +250 -0
  96. package/dist/drivers/WdaDriver.js.map +1 -0
  97. package/dist/explore/candidates.js +93 -0
  98. package/dist/explore/candidates.js.map +1 -0
  99. package/dist/explore/graph.js +116 -0
  100. package/dist/explore/graph.js.map +1 -0
  101. package/dist/explore/memory.js +35 -0
  102. package/dist/explore/memory.js.map +1 -0
  103. package/dist/explore/planner.js +105 -0
  104. package/dist/explore/planner.js.map +1 -0
  105. package/dist/explore/policy.js +85 -0
  106. package/dist/explore/policy.js.map +1 -0
  107. package/dist/explore/runner.js +475 -0
  108. package/dist/explore/runner.js.map +1 -0
  109. package/dist/explore/signatures.js +35 -0
  110. package/dist/explore/signatures.js.map +1 -0
  111. package/dist/explore/suite.js +55 -0
  112. package/dist/explore/suite.js.map +1 -0
  113. package/dist/featureTesting/executionBootstrap.js +140 -0
  114. package/dist/featureTesting/executionBootstrap.js.map +1 -0
  115. package/dist/firstRun/authStateMachine.js +83 -0
  116. package/dist/firstRun/authStateMachine.js.map +1 -0
  117. package/dist/firstRun/classifyScreen.js +201 -0
  118. package/dist/firstRun/classifyScreen.js.map +1 -0
  119. package/dist/firstRun/firstRunPlanner.js +207 -0
  120. package/dist/firstRun/firstRunPlanner.js.map +1 -0
  121. package/dist/firstRun/firstRunRunner.js +331 -0
  122. package/dist/firstRun/firstRunRunner.js.map +1 -0
  123. package/dist/firstRun/generatedDataPolicy.js +215 -0
  124. package/dist/firstRun/generatedDataPolicy.js.map +1 -0
  125. package/dist/firstRun/inputPlanner.js +67 -0
  126. package/dist/firstRun/inputPlanner.js.map +1 -0
  127. package/dist/firstRun/onboardingStateMachine.js +46 -0
  128. package/dist/firstRun/onboardingStateMachine.js.map +1 -0
  129. package/dist/firstRun/paywallPolicy.js +54 -0
  130. package/dist/firstRun/paywallPolicy.js.map +1 -0
  131. package/dist/firstRun/types.js +7 -0
  132. package/dist/firstRun/types.js.map +1 -0
  133. package/dist/fixtures/catalog.js +131 -0
  134. package/dist/fixtures/catalog.js.map +1 -0
  135. package/dist/flows/discover.js +18 -0
  136. package/dist/flows/discover.js.map +1 -0
  137. package/dist/flows/generate.js +211 -0
  138. package/dist/flows/generate.js.map +1 -0
  139. package/dist/flows/lint.js +97 -0
  140. package/dist/flows/lint.js.map +1 -0
  141. package/dist/flows/pack.js +68 -0
  142. package/dist/flows/pack.js.map +1 -0
  143. package/dist/flows/run.js +738 -0
  144. package/dist/flows/run.js.map +1 -0
  145. package/dist/flows/schema.js +240 -0
  146. package/dist/flows/schema.js.map +1 -0
  147. package/dist/flows/seedExec.js +108 -0
  148. package/dist/flows/seedExec.js.map +1 -0
  149. package/dist/flows/templates.js +155 -0
  150. package/dist/flows/templates.js.map +1 -0
  151. package/dist/flows/waitGuards.js +12 -0
  152. package/dist/flows/waitGuards.js.map +1 -0
  153. package/dist/index.js +33 -0
  154. package/dist/index.js.map +1 -0
  155. package/dist/ios/signing.js +182 -0
  156. package/dist/ios/signing.js.map +1 -0
  157. package/dist/issues/classify.js +186 -0
  158. package/dist/issues/classify.js.map +1 -0
  159. package/dist/issues/fingerprint.js +130 -0
  160. package/dist/issues/fingerprint.js.map +1 -0
  161. package/dist/issues/index.js +240 -0
  162. package/dist/issues/index.js.map +1 -0
  163. package/dist/issues/metrics.js +155 -0
  164. package/dist/issues/metrics.js.map +1 -0
  165. package/dist/issues/recurrence.js +193 -0
  166. package/dist/issues/recurrence.js.map +1 -0
  167. package/dist/issues/report.js +110 -0
  168. package/dist/issues/report.js.map +1 -0
  169. package/dist/issues/reportBridge.js +119 -0
  170. package/dist/issues/reportBridge.js.map +1 -0
  171. package/dist/issues/schema.js +90 -0
  172. package/dist/issues/schema.js.map +1 -0
  173. package/dist/issues/sourceRevision.js +108 -0
  174. package/dist/issues/sourceRevision.js.map +1 -0
  175. package/dist/issues/store.js +155 -0
  176. package/dist/issues/store.js.map +1 -0
  177. package/dist/lib/android.js +278 -0
  178. package/dist/lib/android.js.map +1 -0
  179. package/dist/lib/commandTemplate.js +55 -0
  180. package/dist/lib/commandTemplate.js.map +1 -0
  181. package/dist/lib/coordSpace.js +23 -0
  182. package/dist/lib/coordSpace.js.map +1 -0
  183. package/dist/lib/device.js +87 -0
  184. package/dist/lib/device.js.map +1 -0
  185. package/dist/lib/gitignore.js +22 -0
  186. package/dist/lib/gitignore.js.map +1 -0
  187. package/dist/lib/image.js +97 -0
  188. package/dist/lib/image.js.map +1 -0
  189. package/dist/lib/logger.js +8 -0
  190. package/dist/lib/logger.js.map +1 -0
  191. package/dist/lib/metroState.js +45 -0
  192. package/dist/lib/metroState.js.map +1 -0
  193. package/dist/lib/needsInput.js +201 -0
  194. package/dist/lib/needsInput.js.map +1 -0
  195. package/dist/lib/png.js +103 -0
  196. package/dist/lib/png.js.map +1 -0
  197. package/dist/lib/redact.js +21 -0
  198. package/dist/lib/redact.js.map +1 -0
  199. package/dist/lib/result.js +87 -0
  200. package/dist/lib/result.js.map +1 -0
  201. package/dist/lib/schemaHash.js +65 -0
  202. package/dist/lib/schemaHash.js.map +1 -0
  203. package/dist/lib/sensitive.js +13 -0
  204. package/dist/lib/sensitive.js.map +1 -0
  205. package/dist/lib/simctl.js +149 -0
  206. package/dist/lib/simctl.js.map +1 -0
  207. package/dist/lib/spawn.js +144 -0
  208. package/dist/lib/spawn.js.map +1 -0
  209. package/dist/lib/wda.js +347 -0
  210. package/dist/lib/wda.js.map +1 -0
  211. package/dist/lib/wdaConfig.js +69 -0
  212. package/dist/lib/wdaConfig.js.map +1 -0
  213. package/dist/lib/wdaTune.js +58 -0
  214. package/dist/lib/wdaTune.js.map +1 -0
  215. package/dist/oracle/auth.js +22 -0
  216. package/dist/oracle/auth.js.map +1 -0
  217. package/dist/oracle/failures.js +193 -0
  218. package/dist/oracle/failures.js.map +1 -0
  219. package/dist/oracle/health.js +123 -0
  220. package/dist/oracle/health.js.map +1 -0
  221. package/dist/oracle/record.js +36 -0
  222. package/dist/oracle/record.js.map +1 -0
  223. package/dist/orchestration/envelope.js +52 -0
  224. package/dist/orchestration/envelope.js.map +1 -0
  225. package/dist/orchestration/goal.js +98 -0
  226. package/dist/orchestration/goal.js.map +1 -0
  227. package/dist/plan/plan.js +124 -0
  228. package/dist/plan/plan.js.map +1 -0
  229. package/dist/prompts/index.js +63 -0
  230. package/dist/prompts/index.js.map +1 -0
  231. package/dist/report/artifactManifest.js +44 -0
  232. package/dist/report/artifactManifest.js.map +1 -0
  233. package/dist/report/coverage.js +60 -0
  234. package/dist/report/coverage.js.map +1 -0
  235. package/dist/report/evidence.js +84 -0
  236. package/dist/report/evidence.js.map +1 -0
  237. package/dist/report/export.js +447 -0
  238. package/dist/report/export.js.map +1 -0
  239. package/dist/report/flake.js +61 -0
  240. package/dist/report/flake.js.map +1 -0
  241. package/dist/report/history.js +564 -0
  242. package/dist/report/history.js.map +1 -0
  243. package/dist/report/policy.js +98 -0
  244. package/dist/report/policy.js.map +1 -0
  245. package/dist/report/qaLevel.js +96 -0
  246. package/dist/report/qaLevel.js.map +1 -0
  247. package/dist/report/readiness.js +213 -0
  248. package/dist/report/readiness.js.map +1 -0
  249. package/dist/report/summary.js +42 -0
  250. package/dist/report/summary.js.map +1 -0
  251. package/dist/report/testCatalog.js +93 -0
  252. package/dist/report/testCatalog.js.map +1 -0
  253. package/dist/report/timing.js +37 -0
  254. package/dist/report/timing.js.map +1 -0
  255. package/dist/server.js +180 -0
  256. package/dist/server.js.map +1 -0
  257. package/dist/services/automationGenerate.js +60 -0
  258. package/dist/services/automationGenerate.js.map +1 -0
  259. package/dist/services/build.js +66 -0
  260. package/dist/services/build.js.map +1 -0
  261. package/dist/services/preflight.js +51 -0
  262. package/dist/services/preflight.js.map +1 -0
  263. package/dist/services/prepareAndroid.js +183 -0
  264. package/dist/services/prepareAndroid.js.map +1 -0
  265. package/dist/services/prepareIos.js +162 -0
  266. package/dist/services/prepareIos.js.map +1 -0
  267. package/dist/services/report.js +537 -0
  268. package/dist/services/report.js.map +1 -0
  269. package/dist/services/smoke.js +120 -0
  270. package/dist/services/smoke.js.map +1 -0
  271. package/dist/services/suiteGenerate.js +123 -0
  272. package/dist/services/suiteGenerate.js.map +1 -0
  273. package/dist/services/testSuiteKnowledge.js +150 -0
  274. package/dist/services/testSuiteKnowledge.js.map +1 -0
  275. package/dist/session/attach.js +47 -0
  276. package/dist/session/attach.js.map +1 -0
  277. package/dist/session/progress.js +56 -0
  278. package/dist/session/progress.js.map +1 -0
  279. package/dist/session/store.js +329 -0
  280. package/dist/session/store.js.map +1 -0
  281. package/dist/snapshot/overlays.js +132 -0
  282. package/dist/snapshot/overlays.js.map +1 -0
  283. package/dist/snapshot/parse.js +204 -0
  284. package/dist/snapshot/parse.js.map +1 -0
  285. package/dist/snapshot/present.js +12 -0
  286. package/dist/snapshot/present.js.map +1 -0
  287. package/dist/snapshot/settle.js +36 -0
  288. package/dist/snapshot/settle.js.map +1 -0
  289. package/dist/state/profile.js +318 -0
  290. package/dist/state/profile.js.map +1 -0
  291. package/dist/suite/compile.js +176 -0
  292. package/dist/suite/compile.js.map +1 -0
  293. package/dist/suite/lint.js +45 -0
  294. package/dist/suite/lint.js.map +1 -0
  295. package/dist/suite/pom.js +285 -0
  296. package/dist/suite/pom.js.map +1 -0
  297. package/dist/suite/testcase.js +87 -0
  298. package/dist/suite/testcase.js.map +1 -0
  299. package/dist/testSuite/generator.js +222 -0
  300. package/dist/testSuite/generator.js.map +1 -0
  301. package/dist/testSuite/history.js +44 -0
  302. package/dist/testSuite/history.js.map +1 -0
  303. package/dist/testSuite/issueLinks.js +96 -0
  304. package/dist/testSuite/issueLinks.js.map +1 -0
  305. package/dist/testSuite/merge.js +190 -0
  306. package/dist/testSuite/merge.js.map +1 -0
  307. package/dist/testSuite/schema.js +86 -0
  308. package/dist/testSuite/schema.js.map +1 -0
  309. package/dist/testSuite/store.js +116 -0
  310. package/dist/testSuite/store.js.map +1 -0
  311. package/dist/testSuite/traceability.js +55 -0
  312. package/dist/testSuite/traceability.js.map +1 -0
  313. package/dist/tools/act.js +457 -0
  314. package/dist/tools/act.js.map +1 -0
  315. package/dist/tools/agent.js +225 -0
  316. package/dist/tools/agent.js.map +1 -0
  317. package/dist/tools/appMap.js +317 -0
  318. package/dist/tools/appMap.js.map +1 -0
  319. package/dist/tools/assertVisual.js +74 -0
  320. package/dist/tools/assertVisual.js.map +1 -0
  321. package/dist/tools/automationGenerate.js +394 -0
  322. package/dist/tools/automationGenerate.js.map +1 -0
  323. package/dist/tools/capabilities.js +114 -0
  324. package/dist/tools/capabilities.js.map +1 -0
  325. package/dist/tools/clearOverlay.js +150 -0
  326. package/dist/tools/clearOverlay.js.map +1 -0
  327. package/dist/tools/detectContext.js +41 -0
  328. package/dist/tools/detectContext.js.map +1 -0
  329. package/dist/tools/doctor.js +116 -0
  330. package/dist/tools/doctor.js.map +1 -0
  331. package/dist/tools/explore.js +289 -0
  332. package/dist/tools/explore.js.map +1 -0
  333. package/dist/tools/firstRun.js +136 -0
  334. package/dist/tools/firstRun.js.map +1 -0
  335. package/dist/tools/flow.js +331 -0
  336. package/dist/tools/flow.js.map +1 -0
  337. package/dist/tools/flowGenerate.js +55 -0
  338. package/dist/tools/flowGenerate.js.map +1 -0
  339. package/dist/tools/getArtifact.js +39 -0
  340. package/dist/tools/getArtifact.js.map +1 -0
  341. package/dist/tools/health.js +41 -0
  342. package/dist/tools/health.js.map +1 -0
  343. package/dist/tools/ios.js +492 -0
  344. package/dist/tools/ios.js.map +1 -0
  345. package/dist/tools/jobs.js +20 -0
  346. package/dist/tools/jobs.js.map +1 -0
  347. package/dist/tools/network.js +50 -0
  348. package/dist/tools/network.js.map +1 -0
  349. package/dist/tools/note.js +69 -0
  350. package/dist/tools/note.js.map +1 -0
  351. package/dist/tools/plan.js +49 -0
  352. package/dist/tools/plan.js.map +1 -0
  353. package/dist/tools/prepareIosTarget.js +99 -0
  354. package/dist/tools/prepareIosTarget.js.map +1 -0
  355. package/dist/tools/prepareTarget.js +257 -0
  356. package/dist/tools/prepareTarget.js.map +1 -0
  357. package/dist/tools/report.js +42 -0
  358. package/dist/tools/report.js.map +1 -0
  359. package/dist/tools/screenRecord.js +24 -0
  360. package/dist/tools/screenRecord.js.map +1 -0
  361. package/dist/tools/screenshot.js +63 -0
  362. package/dist/tools/screenshot.js.map +1 -0
  363. package/dist/tools/smoke.js +39 -0
  364. package/dist/tools/smoke.js.map +1 -0
  365. package/dist/tools/snapshot.js +129 -0
  366. package/dist/tools/snapshot.js.map +1 -0
  367. package/dist/tools/startSession.js +169 -0
  368. package/dist/tools/startSession.js.map +1 -0
  369. package/dist/tools/state.js +87 -0
  370. package/dist/tools/state.js.map +1 -0
  371. package/dist/tools/suite.js +412 -0
  372. package/dist/tools/suite.js.map +1 -0
  373. package/dist/tools/testThis.js +774 -0
  374. package/dist/tools/testThis.js.map +1 -0
  375. package/dist/tools/wda.js +477 -0
  376. package/dist/tools/wda.js.map +1 -0
  377. package/dist/version.js +62 -0
  378. package/dist/version.js.map +1 -0
  379. package/dist/visual/ocr.js +72 -0
  380. package/dist/visual/ocr.js.map +1 -0
  381. package/dist/visual/provider.js +75 -0
  382. package/dist/visual/provider.js.map +1 -0
  383. package/docs/README.md +19 -0
  384. package/docs/assets/swipium-lockup-ink-on-light.png +0 -0
  385. package/docs/mcp-server.md +135 -0
  386. package/docs/tools.md +130 -0
  387. package/package.json +70 -0
@@ -0,0 +1,211 @@
1
+ // qa_flow_generate core (PHASE3-PLAN §4.1 / DESIGN §8). Two pure pieces:
2
+ // - recordableTap: at qa_act time, turn a resolved tap target into a replayable descriptor +
3
+ // exportability tag (translating an @ref into its visible text/label where possible — the
4
+ // key durability insight: a ref is run-time-only, but its label survives).
5
+ // - generateFlow: serialize the recorded action IR into a durable flow YAML + a durability
6
+ // grade and the brittle steps that need a testID/accessibilityLabel.
7
+ import { createHash } from 'node:crypto';
8
+ import { stringify } from 'yaml';
9
+ import { waitForVisibleGuard } from './waitGuards.js';
10
+ function currentScreenSignature(session) {
11
+ const sigs = session.lastSnapshot?.signatures;
12
+ if (!sigs?.size)
13
+ return undefined;
14
+ return createHash('sha1').update([...sigs].sort().join('\n')).digest('hex').slice(0, 16);
15
+ }
16
+ function bucketBounds(bounds, point) {
17
+ const b = bounds ?? (point ? [point.x, point.y, point.x, point.y] : undefined);
18
+ if (!b)
19
+ return undefined;
20
+ const bucket = (n) => Math.floor(n / 50) * 50;
21
+ return `${bucket(b[0])},${bucket(b[1])},${bucket(b[2])},${bucket(b[3])}`;
22
+ }
23
+ function provenance(session, opts) {
24
+ const node = opts.point?.ref ? session.lastSnapshot?.fullByRef.get(opts.point.ref) : undefined;
25
+ const out = {
26
+ originalScreenSignature: currentScreenSignature(session),
27
+ elementRole: node?.cls?.split('.').pop(),
28
+ className: node?.cls,
29
+ text: node?.text || undefined,
30
+ accessibilityLabel: node?.desc || undefined,
31
+ resourceId: node?.id || undefined,
32
+ boundsBucket: bucketBounds(node?.bounds, opts.point),
33
+ screenshotUri: session.artifacts?.filter((a) => a.kind === 'screenshot').at(-1)?.uri,
34
+ selectorKind: opts.selectorKind,
35
+ selectorValue: opts.selectorValue,
36
+ };
37
+ return Object.values(out).some((v) => v != null) ? out : undefined;
38
+ }
39
+ /** Map a resolved tap to a replayable descriptor. Prefers a visible text/label (durable);
40
+ * falls back to coordinates (brittle) when the element exposes no human-readable handle. */
41
+ export function recordableTap(session, target, point) {
42
+ if (target?.x != null)
43
+ return { x: point.x, y: point.y, selectorKind: 'coords', exportability: 'coordinate', provenance: provenance(session, { selectorKind: 'coords', point }) };
44
+ if (target?.id) {
45
+ const selectorKind = session.driver?.kind === 'wda' ? 'accessibility_id' : 'resource_id';
46
+ return { selector: target.id, selectorKind, exportability: 'semantic', provenance: provenance(session, { selectorKind, selectorValue: target.id, point }) };
47
+ }
48
+ const node = point.ref ? session.lastSnapshot?.fullByRef.get(point.ref) : target?.ref ? session.lastSnapshot?.fullByRef.get(target.ref) : undefined;
49
+ if (session.driver?.kind === 'wda' && node?.id)
50
+ return { selector: node.id, selectorKind: 'accessibility_id', exportability: 'semantic', provenance: provenance(session, { selectorKind: 'accessibility_id', selectorValue: node.id, point }) };
51
+ let label;
52
+ if (target?.text)
53
+ label = target.text;
54
+ else
55
+ label = node?.text || node?.desc || undefined;
56
+ if (label) {
57
+ const warning = session.driver?.kind === 'wda'
58
+ ? `iOS label/name selector "${label}" is usable, but add an accessibilityIdentifier for CI-stable replay`
59
+ : undefined;
60
+ return { selector: label, selectorKind: 'text', exportability: 'semantic', warning, provenance: provenance(session, { selectorKind: 'text', selectorValue: label, point }) };
61
+ }
62
+ return { x: point.x, y: point.y, selectorKind: 'coords', exportability: 'coordinate', provenance: provenance(session, { selectorKind: 'coords', point }) };
63
+ }
64
+ export function recordableNativeSelector(session, selectorKind, selectorValue) {
65
+ return { provenance: provenance(session, { selectorKind, selectorValue }) };
66
+ }
67
+ function actionSelector(a) {
68
+ if (!a.selector || !['text', 'accessibility_id', 'resource_id', 'name', 'predicate', 'class_chain'].includes(a.selectorKind ?? ''))
69
+ return null;
70
+ return a.selectorKind === 'accessibility_id'
71
+ ? `accessibility id=${a.selector}`
72
+ : a.selectorKind === 'resource_id'
73
+ ? `id=${a.selector}` // Flow V2 runner resolves `id=<resource-id>` via resolveTarget({ id })
74
+ : a.selectorKind === 'name'
75
+ ? `name=${a.selector}`
76
+ : a.selectorKind === 'predicate'
77
+ ? `predicate string=${a.selector}`
78
+ : a.selectorKind === 'class_chain'
79
+ ? `class chain=${a.selector}`
80
+ : a.selector;
81
+ }
82
+ function addProvenance(entries, a, actionIndex, generatedStepIndex, generatedKind, selector) {
83
+ if (!a.provenance)
84
+ return;
85
+ entries.push({ actionIndex, generatedStepIndex, generatedKind, action: a.action, selector: selector ?? a.selector, ...a.provenance });
86
+ }
87
+ function pushSelectorAction(steps, provenanceEntries, a, actionIndex, selector, action, generatedKind) {
88
+ const waitIndex = steps.length + 1;
89
+ const actionStepIndex = steps.length + 2;
90
+ steps.push(waitForVisibleGuard(selector), action);
91
+ addProvenance(provenanceEntries, a, actionIndex, waitIndex, 'waitForVisible', selector);
92
+ addProvenance(provenanceEntries, a, actionIndex, actionStepIndex, generatedKind, selector);
93
+ }
94
+ export function generateFlow(actions, opts) {
95
+ const steps = ['prepareTarget'];
96
+ const brittleSteps = [];
97
+ const variables = [];
98
+ const provenanceEntries = [];
99
+ let semantic = 0;
100
+ let coordinate = 0;
101
+ let needsHumanData = 0;
102
+ let secretCount = 0;
103
+ actions.forEach((a, i) => {
104
+ const actionIndex = i + 1;
105
+ switch (a.action) {
106
+ case 'tap':
107
+ {
108
+ const selector = actionSelector(a);
109
+ if (selector) {
110
+ pushSelectorAction(steps, provenanceEntries, a, actionIndex, selector, { tap: selector }, 'tap');
111
+ semantic++;
112
+ if (a.warning)
113
+ brittleSteps.push({ index: i, reason: a.warning });
114
+ }
115
+ else {
116
+ addProvenance(provenanceEntries, a, actionIndex, steps.length + 1, 'tapAt');
117
+ steps.push({ tapAt: [a.x ?? 0, a.y ?? 0] });
118
+ coordinate++;
119
+ brittleSteps.push({ index: i, reason: `tapped by coordinates (${a.x},${a.y})${a.screen ? ` on ${a.screen}` : ''} — add a testID/accessibilityLabel for a durable selector` });
120
+ }
121
+ }
122
+ break;
123
+ case 'clear': {
124
+ const selector = actionSelector(a);
125
+ if (selector) {
126
+ pushSelectorAction(steps, provenanceEntries, a, actionIndex, selector, { inputText: { into: selector, text: '' } }, 'inputText');
127
+ semantic++;
128
+ }
129
+ else {
130
+ addProvenance(provenanceEntries, a, actionIndex, steps.length + 1, 'tapAt');
131
+ steps.push({ tapAt: [a.x ?? 0, a.y ?? 0] }, { inputText: '' });
132
+ coordinate++;
133
+ brittleSteps.push({ index: i, reason: `cleared by coordinates (${a.x},${a.y})${a.screen ? ` on ${a.screen}` : ''} — add a testID/accessibilityLabel for a durable selector` });
134
+ }
135
+ break;
136
+ }
137
+ case 'type':
138
+ {
139
+ const selector = actionSelector(a);
140
+ const text = a.secret ? `\${SECRET_${++secretCount}}` : a.text ?? '';
141
+ if (a.secret) {
142
+ variables.push(`SECRET_${secretCount}`);
143
+ needsHumanData++;
144
+ }
145
+ else {
146
+ semantic++;
147
+ }
148
+ if (selector)
149
+ pushSelectorAction(steps, provenanceEntries, a, actionIndex, selector, { inputText: { into: selector, text } }, 'inputText');
150
+ else {
151
+ addProvenance(provenanceEntries, a, actionIndex, steps.length + 1, 'inputText');
152
+ steps.push({ inputText: text });
153
+ }
154
+ }
155
+ break;
156
+ case 'swipe':
157
+ steps.push({ swipe: a.direction ?? 'up' });
158
+ coordinate++;
159
+ break;
160
+ case 'scroll':
161
+ if (a.selector) {
162
+ addProvenance(provenanceEntries, a, actionIndex, steps.length + 1, 'scrollTo', a.selector);
163
+ steps.push({ scrollTo: a.selector });
164
+ semantic++;
165
+ }
166
+ else {
167
+ steps.push({ swipe: a.direction ?? 'up' });
168
+ coordinate++;
169
+ }
170
+ break;
171
+ case 'press':
172
+ steps.push({ press: a.key ?? 'back' });
173
+ semantic++;
174
+ break;
175
+ case 'open_url':
176
+ steps.push({ openUrl: a.url ?? '' });
177
+ semantic++;
178
+ break;
179
+ case 'assert_visual':
180
+ addProvenance(provenanceEntries, a, actionIndex, steps.length + 1, 'assertVisual', a.assertion ?? a.selector ?? 'visual checkpoint');
181
+ steps.push({ assertVisual: a.assertion ?? a.selector ?? 'visual checkpoint' });
182
+ semantic++;
183
+ break;
184
+ }
185
+ });
186
+ const total = semantic + coordinate + needsHumanData;
187
+ const semanticPct = total ? Math.round((semantic / total) * 100) : 100;
188
+ const grade = semanticPct >= 90 ? 'A' : semanticPct >= 70 ? 'B' : 'C';
189
+ const flowObj = { name: opts.name };
190
+ if (opts.appId)
191
+ flowObj.appId = opts.appId;
192
+ if (opts.budgetProfile)
193
+ flowObj.budgetProfile = opts.budgetProfile;
194
+ if (provenanceEntries.length)
195
+ flowObj.provenance = provenanceEntries;
196
+ flowObj.steps = steps;
197
+ const header = [
198
+ `# Generated by Swipium qa_flow_generate — review before committing.`,
199
+ `# durability: ${grade} (${semanticPct}% semantic; ${coordinate} coordinate, ${needsHumanData} needs-human-data)`,
200
+ ...(variables.length ? [`# variables — provide via qa_flow_run { variables }: ${variables.join(', ')}`] : []),
201
+ ...brittleSteps.map((b) => `# WARNING step ${b.index}: ${b.reason}`),
202
+ ].join('\n');
203
+ return {
204
+ yaml: `${header}\n${stringify(flowObj)}`,
205
+ stepCount: steps.length,
206
+ durability: { grade, semanticPct, semantic, coordinate, needsHumanData },
207
+ brittleSteps,
208
+ variables,
209
+ };
210
+ }
211
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/flows/generate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,97 @@
1
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { parseFlow } from './schema.js';
4
+ import { ciMutationAllowed, loadPolicy } from '../report/policy.js';
5
+ const MUTATING = new Set(['networkOffline', 'networkOnline', 'seed', 'restartApp']);
6
+ const SECRET_LITERAL = /password|passwd|secret|token|otp|api[_-]?key/i;
7
+ function stepText(step) {
8
+ switch (step.kind) {
9
+ case 'tap': return step.selector;
10
+ case 'inputText': return step.value;
11
+ case 'assertVisible':
12
+ case 'assertNotVisible':
13
+ case 'waitForVisible':
14
+ case 'wait':
15
+ case 'scrollTo':
16
+ return 'query' in step && typeof step.query === 'string' ? step.query : '';
17
+ default:
18
+ return '';
19
+ }
20
+ }
21
+ function mutatingPolicyMessage(step, policy) {
22
+ if (!MUTATING.has(step.kind))
23
+ return null;
24
+ if (policy === undefined)
25
+ return null;
26
+ if (ciMutationAllowed(policy, step.kind))
27
+ return null;
28
+ return policy
29
+ ? `${step.kind} changes device/app/test state but is not allowed by .swipium/policy.json ciAllowMutations.`
30
+ : `${step.kind} changes device/app/test state but no .swipium/policy.json ciAllowMutations policy was found.`;
31
+ }
32
+ export function lintFlowObject(file, flow, policy) {
33
+ return lintFlowObjectWithOptions(file, flow, { policy });
34
+ }
35
+ export function lintFlowObjectWithOptions(file, flow, opts = {}) {
36
+ const findings = [];
37
+ const all = [...flow.setup, ...flow.steps, ...flow.teardown];
38
+ const setupHasMutation = flow.setup.some((step) => MUTATING.has(step.kind));
39
+ if (setupHasMutation && !flow.teardown.length) {
40
+ findings.push({ file, flow: flow.name, severity: 'warn', code: 'MUTATING_SETUP_WITHOUT_TEARDOWN', message: 'Setup mutates device/app/test state but the flow has no teardown; add cleanup/restore steps or document why state reuse is safe.' });
41
+ }
42
+ for (let i = 0; i < all.length; i++) {
43
+ const step = all[i];
44
+ const stepNo = i + 1;
45
+ const text = stepText(step);
46
+ if (step.kind === 'tapAt') {
47
+ findings.push({ file, flow: flow.name, step: stepNo, severity: 'warn', code: 'COORDINATE_ONLY', message: 'Coordinate-only tap is brittle; prefer an accessibility id or stable text locator.' });
48
+ }
49
+ if (/xpath=|^\/\//i.test(text)) {
50
+ findings.push({ file, flow: flow.name, step: stepNo, severity: 'warn', code: 'XPATH_LOCATOR', message: 'XPath locators are brittle and slow; prefer accessibility id/name, predicate/class-chain on iOS, or resource id on Android.' });
51
+ }
52
+ if ((opts.platform === 'cross-platform' || (!opts.platform && flow.mode === 'auto')) && /(resource-id=|uiautomator|android\.|accessibility id=|name=|class chain|predicate string|XCUIElementType)/i.test(text)) {
53
+ findings.push({ file, flow: flow.name, step: stepNo, severity: 'warn', code: 'PLATFORM_SPECIFIC_LOCATOR', message: 'Platform-specific locator in an auto/cross-platform flow; prefer shared text/testID/accessibility labels or split into platform-specific flows.' });
54
+ }
55
+ if (opts.platform === 'ios' && /resource-id=|uiautomator|android\./i.test(text)) {
56
+ findings.push({ file, flow: flow.name, step: stepNo, severity: 'warn', code: 'ANDROID_LOCATOR_IN_IOS_FLOW', message: 'Android-specific locator in an iOS flow; prefer accessibilityIdentifier/name/label, predicate string, or class chain.' });
57
+ }
58
+ if (opts.platform === 'android' && /class chain|predicate string|XCUIElementType|accessibility id=|name=/i.test(text)) {
59
+ findings.push({ file, flow: flow.name, step: stepNo, severity: 'warn', code: 'IOS_LOCATOR_IN_ANDROID_FLOW', message: 'iOS-specific locator in an Android flow; prefer resource-id, content-desc, or stable text.' });
60
+ }
61
+ if (step.kind === 'inputText' && !/\$\{[^}]+}/.test(step.value) && (step.secret || SECRET_LITERAL.test(step.value))) {
62
+ findings.push({ file, flow: flow.name, step: stepNo, severity: 'error', code: 'INLINE_SECRET', message: 'Secret-looking input is inline; use ${ENV_VAR} from CI secrets instead.' });
63
+ }
64
+ if ((step.kind === 'assertVisible' || step.kind === 'assertNotVisible') && i > 0) {
65
+ const prev = all[i - 1];
66
+ if (!['wait', 'waitForVisible', 'waitForIdle', 'assertVisible', 'assertNotVisible'].includes(prev.kind)) {
67
+ findings.push({ file, flow: flow.name, step: stepNo, severity: 'warn', code: 'ASSERT_WITHOUT_WAIT', message: 'Assertion follows an action without an explicit wait; add waitForVisible/waitForIdle for CI stability.' });
68
+ }
69
+ }
70
+ if (MUTATING.has(step.kind)) {
71
+ findings.push({ file, flow: flow.name, step: stepNo, severity: 'warn', code: 'MUTATING_STEP', message: 'Mutating step requires explicit CI policy allowance and should have teardown where applicable.' });
72
+ const policyMessage = mutatingPolicyMessage(step, opts.policy);
73
+ if (policyMessage) {
74
+ findings.push({ file, flow: flow.name, step: stepNo, severity: 'error', code: 'MUTATING_STEP_WITHOUT_POLICY', message: policyMessage });
75
+ }
76
+ }
77
+ }
78
+ return findings;
79
+ }
80
+ export function lintFlowFiles(root, opts = {}) {
81
+ const dir = join(root, '.swipium', 'flows');
82
+ if (!existsSync(dir))
83
+ return { files: 0, findings: [{ file: dir, severity: 'error', code: 'NO_FLOWS_DIR', message: 'No .swipium/flows directory found.' }] };
84
+ const policy = loadPolicy(root);
85
+ const files = readdirSync(dir).filter((f) => /\.ya?ml$/i.test(f)).map((f) => join(dir, f));
86
+ const findings = [];
87
+ for (const file of files) {
88
+ const { flow, errors } = parseFlow(readFileSync(file, 'utf8'));
89
+ if (errors.length || !flow) {
90
+ findings.push({ file, severity: 'error', code: 'INVALID_FLOW', message: errors.join('; ') || 'Invalid flow.' });
91
+ continue;
92
+ }
93
+ findings.push(...lintFlowObjectWithOptions(file, flow, { ...opts, policy }));
94
+ }
95
+ return { files: files.length, findings };
96
+ }
97
+ //# sourceMappingURL=lint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint.js","sourceRoot":"","sources":["../../src/flows/lint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ // Flow packs (NEXT-PLAN: Flow System V2). A pack (.swipium/packs/*.yaml) names an ordered set of
2
+ // flows to run as one release suite. v1 runs them sequentially on the one attached device
3
+ // (parallel:true is accepted but ignored with a warning — parallel on a single device is unsafe).
4
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
5
+ import { join, basename } from 'node:path';
6
+ import { parse as parseYaml } from 'yaml';
7
+ import { parseFlow } from './schema.js';
8
+ import { runFlow } from './run.js';
9
+ export function parsePack(yamlText) {
10
+ let doc;
11
+ try {
12
+ doc = parseYaml(yamlText);
13
+ }
14
+ catch (e) {
15
+ return { errors: [`YAML parse error: ${String(e.message ?? e)}`] };
16
+ }
17
+ if (!doc || typeof doc !== 'object')
18
+ return { errors: ['pack must be a YAML map with name + flows.'] };
19
+ const d = doc;
20
+ const errors = [];
21
+ if (typeof d.name !== 'string' || !d.name.trim())
22
+ errors.push('pack needs a non-empty `name`.');
23
+ if (!Array.isArray(d.flows) || d.flows.length === 0 || !d.flows.every((f) => typeof f === 'string'))
24
+ errors.push('pack needs a non-empty `flows` list of flow names.');
25
+ if (errors.length)
26
+ return { errors };
27
+ return { pack: { name: d.name, flows: d.flows, parallel: d.parallel === true }, errors: [] };
28
+ }
29
+ export function listPackFiles(root) {
30
+ const dir = join(root, '.swipium', 'packs');
31
+ if (!existsSync(dir))
32
+ return [];
33
+ try {
34
+ return readdirSync(dir)
35
+ .filter((f) => /\.ya?ml$/i.test(f))
36
+ .map((f) => ({ name: basename(f).replace(/\.ya?ml$/i, ''), path: join(dir, f) }));
37
+ }
38
+ catch {
39
+ return [];
40
+ }
41
+ }
42
+ function flowPath(root, name) {
43
+ for (const p of [join(root, '.swipium', 'flows', `${name}.yaml`), join(root, '.swipium', 'flows', `${name}.yml`)])
44
+ if (existsSync(p))
45
+ return p;
46
+ return null;
47
+ }
48
+ export async function runPack(sessions, session, driver, root, pack, opts = {}) {
49
+ const warnings = [];
50
+ if (pack.parallel)
51
+ warnings.push('parallel:true ignored — flows run sequentially on a single device (parallel needs a device matrix).');
52
+ const results = [];
53
+ for (const name of pack.flows) {
54
+ const p = flowPath(root, name);
55
+ if (!p) {
56
+ results.push({ name, passed: false, reason: `flow not found: ${name}`, failureCode: 'NO_ARTIFACT', steps: [], durationSec: 0, counters: session.counters });
57
+ continue;
58
+ }
59
+ const { flow, errors } = parseFlow(readFileSync(p, 'utf8'));
60
+ if (errors.length || !flow) {
61
+ results.push({ name, passed: false, reason: `invalid flow: ${errors[0] ?? 'parse error'}`, failureCode: 'UNKNOWN', steps: [], durationSec: 0, counters: session.counters });
62
+ continue;
63
+ }
64
+ results.push(await runFlow(sessions, session, driver, flow, opts));
65
+ }
66
+ return { pack: pack.name, parallelRequested: pack.parallel, results, passed: results.every((r) => r.passed), warnings };
67
+ }
68
+ //# sourceMappingURL=pack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pack.js","sourceRoot":"","sources":["../../src/flows/pack.ts"],"names":[],"mappings":"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"}