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,329 @@
1
+ // Session + job + artifact store with DISK PERSISTENCE (DESIGN §3, M6).
2
+ // Live, non-serializable bits (driver, lastSnapshot, abort controllers) stay in memory;
3
+ // a serializable subset is written to <sessionDir>/state.json on every mutation, and a
4
+ // small registry under ~/.swipium/registry.json lets a fresh server instance reload
5
+ // prior sessions so artifacts/reports/job-status survive a server restart. (A restart does
6
+ // NOT resurrect a running child process — such jobs are marked failed on reload.)
7
+ import { createHash, randomUUID } from 'node:crypto';
8
+ import { mkdirSync, writeFileSync, readFileSync, existsSync } from 'node:fs';
9
+ import { join, resolve } from 'node:path';
10
+ import { homedir } from 'node:os';
11
+ import { DEFAULT_RESPONSE_MODE } from '../lib/result.js';
12
+ import { makeRedactor } from '../lib/redact.js';
13
+ // Phase 2.2 P1.6: budget classes (minutes) keyed by workflow ambition.
14
+ export const BUDGET_PROFILES = {
15
+ guardrail: 8, // guardrail/setup validation
16
+ login_smoke: 10, // login + one workflow
17
+ full_smoke: 15, // full authenticated smoke
18
+ install_smoke: 20, // install/boot/rebuild involved
19
+ };
20
+ // Security model (REQ-02): raw secret values (generated passwords/OTPs/tokens) must never touch
21
+ // disk. In memory we keep the raw value (for same-session reuse via inputValues), but the
22
+ // serialized form sent to state.json redacts secret values while preserving all reproducibility
23
+ // metadata (varName/field/generator/secret/artifactUri/timestamps). Non-secret generated values
24
+ // (e.g. a yopmail email) stay intact for evidence.
25
+ export function serializeGeneratedValues(records) {
26
+ return records.map((r) => (r.secret ? { ...r, value: '<redacted>' } : r));
27
+ }
28
+ export const DEFAULT_BUDGET = {
29
+ maxMinutes: 8,
30
+ maxActions: 20,
31
+ maxScreenshots: 8,
32
+ maxSnapshotFailures: 3,
33
+ maxNoChangeActions: 3,
34
+ };
35
+ const REGISTRY_DIR = join(homedir(), '.swipium');
36
+ const REGISTRY = join(REGISTRY_DIR, 'registry.json');
37
+ const TEXT_MIME_RE = /^(text\/[^;]+|application\/(json|xml|yaml|x-yaml|javascript|x-ndjson)|[^;]+\+(json|xml|yaml))(?:$|;)/i;
38
+ export function isTextArtifactMime(mime) {
39
+ return TEXT_MIME_RE.test(mime);
40
+ }
41
+ export function artifactDirectoryName(kind) {
42
+ switch (kind) {
43
+ case 'screenshot': return 'screenshots';
44
+ case 'recording': return 'videos';
45
+ case 'logs':
46
+ case 'logcat':
47
+ case 'metro':
48
+ case 'wda':
49
+ return 'logs';
50
+ default:
51
+ return kind;
52
+ }
53
+ }
54
+ function defaultSessionDir(root, id) {
55
+ const projectHash = createHash('sha256').update(resolve(root)).digest('hex').slice(0, 16);
56
+ return join(REGISTRY_DIR, 'runs', projectHash, id);
57
+ }
58
+ export class SessionStore {
59
+ sessions = new Map();
60
+ constructor() {
61
+ this.loadRegistry();
62
+ }
63
+ create(root, budget, opts) {
64
+ const id = randomUUID().slice(0, 8);
65
+ const dir = opts?.sessionDir ?? defaultSessionDir(root, id);
66
+ mkdirSync(dir, { recursive: true });
67
+ const now = Date.now();
68
+ const s = {
69
+ id, root, dir, createdAt: now, screenshotCount: 0,
70
+ mode: 'structured',
71
+ responseMode: opts?.responseMode ?? DEFAULT_RESPONSE_MODE,
72
+ sensitive: opts?.sensitive ?? false,
73
+ budget: { ...DEFAULT_BUDGET, ...(budget ?? {}) },
74
+ counters: { actions: 0, screenshots: 0, snapshotFailures: 0, noChangeActions: 0 },
75
+ envChanges: [], workarounds: [],
76
+ jobs: new Map(), artifacts: [], findings: [], notes: [], mutations: [], recordedActions: [],
77
+ fixtures: opts?.fixtures ?? [], auth: {}, milestones: { session_start: now }, budgetProfile: opts?.budgetProfile,
78
+ secrets: new Set(), inputs: [], generatedValues: [], inputValues: new Map(), aborts: new Map(),
79
+ };
80
+ this.sessions.set(id, s);
81
+ this.appendRegistry(id, dir);
82
+ this.persist(s);
83
+ return s;
84
+ }
85
+ get(id) {
86
+ return this.sessions.get(id);
87
+ }
88
+ list() {
89
+ return [...this.sessions.values()];
90
+ }
91
+ persist(s) {
92
+ try {
93
+ const state = {
94
+ id: s.id, root: s.root, dir: s.dir, createdAt: s.createdAt,
95
+ device: s.device, appId: s.appId, headless: s.headless, metroPid: s.metroPid, screenshotCount: s.screenshotCount,
96
+ network: s.network, envChanges: s.envChanges, workarounds: s.workarounds,
97
+ mode: s.mode, responseMode: s.responseMode, sensitive: s.sensitive, budget: s.budget, counters: s.counters,
98
+ jobs: [...s.jobs.values()], artifacts: s.artifacts, findings: s.findings, notes: s.notes, mutations: s.mutations, recordedActions: s.recordedActions,
99
+ fixtures: s.fixtures, auth: s.auth, milestones: s.milestones, budgetProfile: s.budgetProfile,
100
+ inputs: s.inputs, // METADATA only — never the values
101
+ generatedValues: serializeGeneratedValues(s.generatedValues), // secret raw values redacted before disk
102
+ exploration: s.exploration,
103
+ };
104
+ writeFileSync(join(s.dir, 'state.json'), JSON.stringify(state, null, 2));
105
+ }
106
+ catch {
107
+ /* best-effort */
108
+ }
109
+ }
110
+ // ---- jobs ----
111
+ createJob(s, kind) {
112
+ const job = { jobId: randomUUID().slice(0, 8), kind, status: 'running', startedAt: Date.now(), artifactUris: [] };
113
+ s.jobs.set(job.jobId, job);
114
+ s.aborts.set(job.jobId, new AbortController());
115
+ this.persist(s);
116
+ return job;
117
+ }
118
+ abortSignal(s, jobId) {
119
+ return s.aborts.get(jobId)?.signal;
120
+ }
121
+ // ---- mode + budget + counters (Phase 1) ----
122
+ setMode(s, mode) {
123
+ s.mode = mode;
124
+ this.persist(s);
125
+ }
126
+ bump(s, key, by = 1) {
127
+ s.counters[key] += by;
128
+ this.persist(s);
129
+ }
130
+ /** Returns a stop reason if any budget is exhausted, else null. */
131
+ budgetStop(s) {
132
+ const c = s.counters;
133
+ const b = s.budget;
134
+ const mins = (Date.now() - s.createdAt) / 60000;
135
+ if (mins >= b.maxMinutes)
136
+ return `time budget reached (${mins.toFixed(1)}/${b.maxMinutes} min)`;
137
+ if (c.actions >= b.maxActions)
138
+ return `action budget reached (${c.actions}/${b.maxActions})`;
139
+ if (c.screenshots >= b.maxScreenshots)
140
+ return `screenshot budget reached (${c.screenshots}/${b.maxScreenshots})`;
141
+ if (c.noChangeActions >= b.maxNoChangeActions)
142
+ return `repeated no-change actions (${c.noChangeActions}/${b.maxNoChangeActions}) — likely wrong coords / disabled element / auth wall`;
143
+ return null;
144
+ }
145
+ updateJob(s, job, patch) {
146
+ Object.assign(job, patch);
147
+ this.persist(s);
148
+ }
149
+ /** Apply a patch ONLY while the job is still running — so a cancelled (or otherwise
150
+ * terminal) job is never overwritten back to done/failed by a racing worker. */
151
+ updateJobIfRunning(s, job, patch) {
152
+ const cur = s.jobs.get(job.jobId);
153
+ if (!cur || cur.status !== 'running')
154
+ return false;
155
+ Object.assign(cur, patch);
156
+ this.persist(s);
157
+ return true;
158
+ }
159
+ cancelJob(s, jobId) {
160
+ const j = s.jobs.get(jobId);
161
+ if (!j || j.status !== 'running')
162
+ return false;
163
+ s.aborts.get(jobId)?.abort();
164
+ j.status = 'cancelled';
165
+ j.endedAt = Date.now();
166
+ this.persist(s);
167
+ return true;
168
+ }
169
+ // ---- findings + artifacts ----
170
+ addFinding(s, f) {
171
+ s.findings.push(f);
172
+ this.persist(s);
173
+ }
174
+ addEnvChange(s, note) {
175
+ s.envChanges.push(`${new Date().toISOString()} ${note}`);
176
+ this.persist(s);
177
+ }
178
+ /** Record a safe fallback Swipium chose (roadmap §11 "workarounds attempted"). De-duped. */
179
+ addWorkaround(s, note) {
180
+ if (!s.workarounds.includes(note)) {
181
+ s.workarounds.push(note);
182
+ this.persist(s);
183
+ }
184
+ }
185
+ addNote(s, note) {
186
+ s.notes.push(note);
187
+ this.persist(s);
188
+ }
189
+ recordMutation(s, mutation) {
190
+ const rec = { id: randomUUID().slice(0, 8), at: Date.now(), ...mutation };
191
+ s.mutations.push(rec);
192
+ if (s.mutations.length > 500)
193
+ s.mutations.splice(0, s.mutations.length - 500);
194
+ this.persist(s);
195
+ return rec;
196
+ }
197
+ /** Append an action-IR step (bounded) for qa_flow_generate. */
198
+ addRecordedAction(s, ra) {
199
+ s.recordedActions.push(ra);
200
+ if (s.recordedActions.length > 300)
201
+ s.recordedActions.splice(0, s.recordedActions.length - 300);
202
+ this.persist(s);
203
+ }
204
+ /** Record a phase-timing marker the first time it happens (Phase 2.2 P1.6). */
205
+ milestone(s, key) {
206
+ if (s.milestones[key] == null) {
207
+ s.milestones[key] = Date.now();
208
+ this.persist(s);
209
+ }
210
+ }
211
+ /** Add an accumulated duration marker in milliseconds for report timing diagnostics. */
212
+ addMilestoneDuration(s, key, ms) {
213
+ if (!Number.isFinite(ms) || ms < 0)
214
+ return;
215
+ s.milestones[key] = (s.milestones[key] ?? 0) + ms;
216
+ this.persist(s);
217
+ }
218
+ /** Merge an auth-state observation (Phase 2.2 P1.5). */
219
+ markAuth(s, patch) {
220
+ s.auth = { ...s.auth, ...patch };
221
+ this.persist(s);
222
+ }
223
+ /** Store a user-provided input (hardening P0.5). The VALUE stays in-memory only; secrets are
224
+ * added to the redaction set. Persists metadata so reports can say it was provided. */
225
+ setInput(s, varName, value, secret, source) {
226
+ s.inputValues.set(varName, value);
227
+ if (secret)
228
+ s.secrets.add(value);
229
+ const existing = s.inputs.find((i) => i.varName === varName);
230
+ if (existing) {
231
+ existing.secret = secret;
232
+ existing.source = source;
233
+ existing.at = Date.now();
234
+ }
235
+ else {
236
+ s.inputs.push({ varName, secret, source, at: Date.now() });
237
+ }
238
+ this.persist(s);
239
+ }
240
+ /** Variable map (varName → value) for the flow runner. In-memory values only. */
241
+ inputVariables(s) {
242
+ return Object.fromEntries(s.inputValues);
243
+ }
244
+ /** Clear all stored input values (e.g. session close). Metadata is left for the report. */
245
+ clearInputValues(s) {
246
+ s.inputValues.clear();
247
+ }
248
+ /** Record the latest guided-exploration result (Phase 3.3) for qa_report. */
249
+ setExploration(s, rec) {
250
+ s.exploration = rec;
251
+ this.persist(s);
252
+ }
253
+ saveArtifact(s, kind, name, data, mime, label) {
254
+ const sub = join(s.dir, artifactDirectoryName(kind));
255
+ mkdirSync(sub, { recursive: true });
256
+ const path = join(sub, name);
257
+ const redact = makeRedactor(s.secrets);
258
+ const storedData = typeof data === 'string' && isTextArtifactMime(mime) ? (redact(data) ?? '') : data;
259
+ const storedLabel = label ? redact(label) : label;
260
+ writeFileSync(path, storedData);
261
+ const uri = `swipium://session/${s.id}/${kind}/${name}`;
262
+ s.artifacts.push({ uri, path, mime, kind, createdAt: Date.now(), label: storedLabel });
263
+ this.persist(s);
264
+ return uri;
265
+ }
266
+ findArtifact(uri) {
267
+ for (const s of this.sessions.values()) {
268
+ const rec = s.artifacts.find((a) => a.uri === uri);
269
+ if (rec)
270
+ return { session: s, rec };
271
+ }
272
+ return undefined;
273
+ }
274
+ // ---- persistence reload ----
275
+ loadRegistry() {
276
+ try {
277
+ if (!existsSync(REGISTRY))
278
+ return;
279
+ const reg = JSON.parse(readFileSync(REGISTRY, 'utf8'));
280
+ for (const { dir } of reg) {
281
+ const sp = join(dir, 'state.json');
282
+ if (!existsSync(sp))
283
+ continue;
284
+ try {
285
+ const st = JSON.parse(readFileSync(sp, 'utf8'));
286
+ const jobs = new Map((st.jobs ?? []).map((j) => [j.jobId, j]));
287
+ for (const j of jobs.values()) {
288
+ if (j.status === 'running') {
289
+ j.status = 'failed';
290
+ j.error = 'server restarted while job was running (child process gone)';
291
+ }
292
+ }
293
+ const s = {
294
+ id: st.id, root: st.root, dir: st.dir, createdAt: st.createdAt,
295
+ device: st.device, appId: st.appId, headless: st.headless, metroPid: st.metroPid, screenshotCount: st.screenshotCount ?? 0,
296
+ network: st.network, envChanges: st.envChanges ?? [], workarounds: st.workarounds ?? [],
297
+ mode: st.mode ?? 'structured',
298
+ responseMode: st.responseMode ?? DEFAULT_RESPONSE_MODE,
299
+ sensitive: st.sensitive ?? false,
300
+ budget: { ...DEFAULT_BUDGET, ...(st.budget ?? {}) },
301
+ counters: { actions: 0, screenshots: 0, snapshotFailures: 0, noChangeActions: 0, ...(st.counters ?? {}) },
302
+ jobs, artifacts: st.artifacts ?? [], findings: st.findings ?? [], notes: st.notes ?? [], mutations: st.mutations ?? [], recordedActions: st.recordedActions ?? [],
303
+ fixtures: st.fixtures ?? [], auth: st.auth ?? {}, milestones: st.milestones ?? { session_start: st.createdAt }, budgetProfile: st.budgetProfile,
304
+ secrets: new Set(), inputs: st.inputs ?? [], generatedValues: st.generatedValues ?? [], inputValues: new Map(), exploration: st.exploration, aborts: new Map(),
305
+ };
306
+ this.sessions.set(s.id, s);
307
+ }
308
+ catch {
309
+ /* skip a corrupt session */
310
+ }
311
+ }
312
+ }
313
+ catch {
314
+ /* no registry */
315
+ }
316
+ }
317
+ appendRegistry(id, dir) {
318
+ try {
319
+ mkdirSync(REGISTRY_DIR, { recursive: true });
320
+ const reg = existsSync(REGISTRY) ? JSON.parse(readFileSync(REGISTRY, 'utf8')) : [];
321
+ reg.push({ id, dir });
322
+ writeFileSync(REGISTRY, JSON.stringify(reg.slice(-200), null, 2));
323
+ }
324
+ catch {
325
+ /* best-effort */
326
+ }
327
+ }
328
+ }
329
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/session/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,132 @@
1
+ // Overlay detection + tap-obstruction analysis (Phase 2 CR4). Works from a single-window
2
+ // uiautomator dump (allNodes, DFS-ordered). Toasts are NOT in the dump (separate windows);
3
+ // keyboard + foreground-owner are detected by the caller via the driver and merged in.
4
+ import { boundsContain } from './parse.js';
5
+ const LOGBOX_RE = /open debugger|view warnings|LogBox|\b\d+ (warning|error)s?\b/i;
6
+ const REDBOX_RE = /unhandled (js|javascript) exception|render error|reload\b.*\bdismiss/i;
7
+ /** Overlays visible in the current window's UI tree (not toasts/IME/foreign — see callers). */
8
+ const DISMISS_RE = /close|dismiss|got it|ok\b|minimize|×|✕|✖/i;
9
+ /**
10
+ * Heuristic detector for persistent in-app debug banners / snackbars / toast-like RN views
11
+ * (RevenueCat debug banner, custom error toasts, etc.) that the id/class detectors miss.
12
+ * A banner is a wide, short, edge-pinned content block that is NOT the full screen.
13
+ */
14
+ function detectBanners(allNodes, screen) {
15
+ if (!screen)
16
+ return [];
17
+ const [sw, sh] = screen;
18
+ if (!sw || !sh)
19
+ return [];
20
+ const out = [];
21
+ for (const n of allNodes) {
22
+ const [x1, y1, x2, y2] = n.bounds;
23
+ const w = x2 - x1;
24
+ const h = y2 - y1;
25
+ if (!(n.text || n.desc) || w <= 0 || h <= 0)
26
+ continue;
27
+ const wideEnough = w >= sw * 0.6;
28
+ const shortEnough = h <= sh * 0.22 && h >= sh * 0.02;
29
+ const atTop = y1 <= sh * 0.16;
30
+ const atBottom = y2 >= sh * 0.82;
31
+ const fullScreen = h >= sh * 0.85;
32
+ if (!wideEnough || !shortEnough || fullScreen || (!atTop && !atBottom))
33
+ continue;
34
+ const sub = allNodes.filter((m) => m.dfs >= n.dfs && m.dfs <= n.subtreeEnd);
35
+ const dismissible = sub.some((m) => (m.clickable || m.cls.includes('Button')) && DISMISS_RE.test(`${m.text} ${m.desc}`));
36
+ const label = (n.text || n.desc).trim().slice(0, 60);
37
+ out.push({ type: atBottom ? 'snackbar' : 'banner', detail: `${atBottom ? 'bottom snackbar/banner' : 'top banner'}: "${label}"`, bounds: n.bounds, dismissible });
38
+ }
39
+ const dedupe = (band) => {
40
+ const inBand = out.filter((o) => o.type === band);
41
+ return inBand.length ? [inBand[inBand.length - 1]] : [];
42
+ };
43
+ return [...dedupe('banner'), ...dedupe('snackbar')];
44
+ }
45
+ export function detectTreeOverlays(allNodes, screen) {
46
+ const out = [];
47
+ const text = (n) => `${n.text} ${n.desc}`;
48
+ const joined = allNodes.map(text).join('  ');
49
+ if (REDBOX_RE.test(joined)) {
50
+ out.push({ type: 'rn_redbox', detail: 'React Native redbox (fatal JS error) overlay' });
51
+ }
52
+ else if (LOGBOX_RE.test(joined)) {
53
+ const node = allNodes.find((n) => LOGBOX_RE.test(text(n)));
54
+ out.push({ type: 'rn_logbox', detail: 'React Native LogBox warning/error overlay', bounds: node?.bounds });
55
+ }
56
+ // Native AlertDialog (incl. the standard button ids).
57
+ const dlg = allNodes.find((n) => /AlertDialog|android:id\/(button1|alertTitle)/.test(`${n.cls} ${n.id}`));
58
+ if (dlg)
59
+ out.push({ type: 'native_dialog', detail: `native dialog (${dlg.cls.split('.').pop()})`, bounds: dlg.bounds });
60
+ // Material Snackbar (in-tree, by id).
61
+ const snack = allNodes.find((n) => /snackbar_text|snackbar_action/.test(n.id));
62
+ if (snack)
63
+ out.push({ type: 'snackbar', detail: 'Material snackbar', bounds: snack.bounds });
64
+ // Heuristic banners/snackbars the id/class checks miss (RN debug banners etc.), de-duped
65
+ // against the explicit detections above.
66
+ const haveSnack = out.some((o) => o.type === 'snackbar');
67
+ const haveRn = out.some((o) => o.type === 'rn_logbox' || o.type === 'rn_redbox');
68
+ for (const b of detectBanners(allNodes, screen)) {
69
+ if (b.type === 'snackbar' && haveSnack)
70
+ continue;
71
+ if (b.type === 'banner' && haveRn)
72
+ continue; // likely the LogBox banner already reported
73
+ out.push(b);
74
+ }
75
+ return out;
76
+ }
77
+ const UNABLE_TO_LOAD_RE = /unable to load script|loadJSBundleFromAssets|index\.android\.bundle|could not connect to development server/i;
78
+ /** Detect the RN red-box and whether it's the fatal "unable to load JS bundle" variant. */
79
+ export function detectRedBox(allNodes) {
80
+ const joined = allNodes.map((n) => `${n.text} ${n.desc}`).join(' ');
81
+ const present = REDBOX_RE.test(joined) || UNABLE_TO_LOAD_RE.test(joined);
82
+ return { present, unableToLoadScript: UNABLE_TO_LOAD_RE.test(joined) };
83
+ }
84
+ /** Classify the foreground owner string into an overlay class (system/foreign surfaces). */
85
+ export function classifyForeground(appId, foreground) {
86
+ if (appId && foreground.startsWith(appId))
87
+ return null;
88
+ if (/permissioncontroller/i.test(foreground))
89
+ return { type: 'permission_dialog', detail: foreground };
90
+ if (/accountpicker|account\.|gms/i.test(foreground))
91
+ return { type: 'account_picker', detail: foreground };
92
+ if (/launcher/i.test(foreground))
93
+ return null; // not an overlay — handled by health
94
+ if (/inputmethod/i.test(foreground))
95
+ return { type: 'keyboard', detail: foreground };
96
+ if (foreground && foreground !== 'unknown')
97
+ return { type: 'foreign_app', detail: foreground };
98
+ return null;
99
+ }
100
+ /**
101
+ * Is the point (x,y) — typically the center of the intended target — covered by content
102
+ * drawn ON TOP of the target's subtree? Topmost = greatest DFS index among nodes containing
103
+ * the point; an obstruction is a topmost node OUTSIDE the target's subtree that carries
104
+ * visible content (text/desc/clickable or a known overlay class).
105
+ */
106
+ export function obstructionAt(allNodes, target, x, y) {
107
+ const containing = allNodes.filter((n) => boundsContain(n.bounds, x, y));
108
+ if (containing.length === 0)
109
+ return { obstructed: false };
110
+ // Topmost = greatest DFS (pre-order) index among containing nodes. `drawing-order` is only
111
+ // meaningful among SIBLINGS (per-parent); comparing it globally across unrelated branches
112
+ // misclassifies, so we use DFS order as the safe global signal (later DFS = drawn later).
113
+ const topmost = containing.reduce((a, b) => (b.dfs > a.dfs ? b : a));
114
+ if (!target) {
115
+ // no known target → only flag if the topmost is clearly an overlay-ish content node
116
+ const looksOverlay = !!(topmost.text || topmost.desc) && topmost.isLeaf;
117
+ return looksOverlay ? { obstructed: false } : { obstructed: false };
118
+ }
119
+ const withinTarget = topmost.dfs >= target.dfs && topmost.dfs <= target.subtreeEnd;
120
+ const isAncestor = topmost.dfs <= target.dfs && topmost.subtreeEnd >= target.subtreeEnd;
121
+ if (withinTarget || isAncestor)
122
+ return { obstructed: false };
123
+ // topmost is outside the target subtree and on top → only an obstruction if it's real content
124
+ const realContent = !!(topmost.text || topmost.desc) || topmost.clickable;
125
+ if (!realContent)
126
+ return { obstructed: false };
127
+ return {
128
+ obstructed: true,
129
+ by: { cls: topmost.cls, id: topmost.id || undefined, text: (topmost.text || topmost.desc) || undefined, bounds: topmost.bounds },
130
+ };
131
+ }
132
+ //# sourceMappingURL=overlays.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlays.js","sourceRoot":"","sources":["../../src/snapshot/overlays.ts"],"names":[],"mappings":"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"}