@skyramp/mcp 0.3.2-rc.pom-4 → 0.3.3

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 (256) hide show
  1. package/build/adapters/jestAdapter.d.ts +14 -0
  2. package/build/adapters/jestAdapter.js +113 -0
  3. package/build/adapters/mochaAdapter.d.ts +13 -0
  4. package/build/adapters/mochaAdapter.js +87 -0
  5. package/build/adapters/playwrightAdapter.d.ts +17 -0
  6. package/build/adapters/playwrightAdapter.js +182 -0
  7. package/build/adapters/pytestAdapter.d.ts +15 -0
  8. package/build/adapters/pytestAdapter.js +108 -0
  9. package/build/commands/commandLibrary.d.ts +1 -0
  10. package/build/commands/commandLibrary.js +19 -13
  11. package/build/commands/localDevTestChangesCommand.d.ts +15 -0
  12. package/build/commands/localDevTestChangesCommand.js +201 -0
  13. package/build/index.js +129 -8
  14. package/build/playwright/PlaywrightTraceService.d.ts +8 -0
  15. package/build/playwright/PlaywrightTraceService.js +1 -0
  16. package/build/prompts/code-reuse.js +3 -0
  17. package/build/prompts/enhance-assertions/sharedAssertionRules.d.ts +1 -0
  18. package/build/prompts/enhance-assertions/sharedAssertionRules.js +17 -0
  19. package/build/prompts/initialize-workspace/initializeWorkspacePrompt.js +11 -9
  20. package/build/prompts/local-dev/local-dev-plan.d.ts +35 -0
  21. package/build/prompts/local-dev/local-dev-plan.js +429 -0
  22. package/build/prompts/local-dev/local-dev-prompts.d.ts +4 -0
  23. package/build/prompts/local-dev/local-dev-prompts.js +190 -0
  24. package/build/prompts/pom-aware-code-reuse.js +17 -8
  25. package/build/prompts/prompt-utils.d.ts +8 -0
  26. package/build/prompts/prompt-utils.js +33 -0
  27. package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.js +70 -7
  28. package/build/prompts/sut-setup/modes/dockerComposePrompt.js +1 -1
  29. package/build/prompts/sut-setup/shared.js +19 -17
  30. package/build/prompts/test-maintenance/drift-analysis-prompt.d.ts +10 -1
  31. package/build/prompts/test-maintenance/drift-analysis-prompt.js +54 -1
  32. package/build/prompts/test-recommendation/analysisOutputPrompt.js +21 -29
  33. package/build/prompts/test-recommendation/scopeAssessment.d.ts +5 -2
  34. package/build/prompts/test-recommendation/scopeAssessment.js +78 -6
  35. package/build/prompts/test-recommendation/test-recommendation-prompt.js +41 -4
  36. package/build/prompts/testbot/testbot-prompts.d.ts +2 -17
  37. package/build/prompts/testbot/testbot-prompts.js +63 -60
  38. package/build/recommendation/planRanker.d.ts +15 -2
  39. package/build/recommendation/planRanker.js +76 -5
  40. package/build/resources/testbotResource.js +23 -5
  41. package/build/services/AnalyticsService.d.ts +1 -1
  42. package/build/services/TestExecutionService.d.ts +15 -9
  43. package/build/services/TestExecutionService.js +56 -28
  44. package/build/services/TestGenerationService.d.ts +2 -2
  45. package/build/services/TestGenerationService.js +39 -21
  46. package/build/services/containerEnv.js +27 -1
  47. package/build/tool-phases.js +7 -0
  48. package/build/tools/code-refactor/codeReuseTool.js +43 -4
  49. package/build/tools/code-refactor/enhanceAssertionsTool.js +68 -18
  50. package/build/tools/code-refactor/reuse-outcome.d.ts +109 -0
  51. package/build/tools/code-refactor/reuse-outcome.js +158 -0
  52. package/build/tools/code-refactor/reuse-state.d.ts +45 -0
  53. package/build/tools/code-refactor/reuse-state.js +140 -0
  54. package/build/tools/enrichTestWithMocksTool.d.ts +28 -0
  55. package/build/tools/enrichTestWithMocksTool.js +726 -0
  56. package/build/tools/executeSkyrampTestTool.d.ts +11 -0
  57. package/build/tools/executeSkyrampTestTool.js +62 -21
  58. package/build/tools/generate-tests/batchMockGenerationTool.d.ts +106 -0
  59. package/build/tools/generate-tests/batchMockGenerationTool.js +545 -0
  60. package/build/tools/generate-tests/generateBatchScenarioRestTool.js +25 -23
  61. package/build/tools/generate-tests/generateContractRestTool.js +2 -2
  62. package/build/tools/generate-tests/generateE2ERestTool.d.ts +1 -1
  63. package/build/tools/generate-tests/generateE2ERestTool.js +1 -1
  64. package/build/tools/generate-tests/generateLoadRestTool.d.ts +1 -1
  65. package/build/tools/generate-tests/generateLoadRestTool.js +1 -1
  66. package/build/tools/generate-tests/generateMockRestTool.d.ts +179 -6
  67. package/build/tools/generate-tests/generateMockRestTool.js +391 -22
  68. package/build/tools/generate-tests/loadTestSchema.d.ts +1 -1
  69. package/build/tools/generate-tests/planGuard.js +2 -22
  70. package/build/tools/generateEnrichedIntegrationTestTool.d.ts +25 -0
  71. package/build/tools/generateEnrichedIntegrationTestTool.js +235 -0
  72. package/build/tools/localDevWorkerComposeTool.d.ts +24 -0
  73. package/build/tools/localDevWorkerComposeTool.js +264 -0
  74. package/build/tools/one-click/oneClickTool.d.ts +13 -0
  75. package/build/tools/one-click/oneClickTool.js +195 -24
  76. package/build/tools/preflightMockCheckTool.d.ts +2 -0
  77. package/build/tools/preflightMockCheckTool.js +96 -0
  78. package/build/tools/queryProxyMocksTool.d.ts +70 -0
  79. package/build/tools/queryProxyMocksTool.js +521 -0
  80. package/build/tools/runExistingTestsTool.d.ts +138 -0
  81. package/build/tools/runExistingTestsTool.js +644 -0
  82. package/build/tools/submitReportTool.js +40 -2
  83. package/build/tools/test-management/actionsTool.js +12 -2
  84. package/build/tools/test-management/analyzeChangesTool.d.ts +2 -1
  85. package/build/tools/test-management/analyzeChangesTool.js +63 -40
  86. package/build/tools/test-management/analyzeTestHealthTool.d.ts +11 -0
  87. package/build/tools/test-management/analyzeTestHealthTool.js +63 -1
  88. package/build/tools/test-management/registerTestPlanTool.js +55 -7
  89. package/build/tools/trace/startTraceCollectionTool.js +3 -3
  90. package/build/types/ExternalTestExecution.d.ts +67 -0
  91. package/build/types/ExternalTestExecution.js +8 -0
  92. package/build/types/OneClickCommands.d.ts +1 -1
  93. package/build/types/Recommendation.d.ts +20 -0
  94. package/build/types/Recommendation.js +32 -6
  95. package/build/types/RepositoryAnalysis.d.ts +131 -14
  96. package/build/types/RepositoryAnalysis.js +16 -2
  97. package/build/types/ReuseOutcome.d.ts +63 -0
  98. package/build/types/ReuseOutcome.js +33 -0
  99. package/build/types/TestAnalysis.d.ts +7 -3
  100. package/build/types/TestExecution.d.ts +1 -0
  101. package/build/types/TestTypes.d.ts +25 -7
  102. package/build/types/TestTypes.js +25 -7
  103. package/build/types/TestbotPromptOptions.d.ts +35 -0
  104. package/build/types/TestbotPromptOptions.js +1 -0
  105. package/build/types/TestbotReport.d.ts +7 -0
  106. package/build/types/index.d.ts +3 -0
  107. package/build/types/index.js +1 -0
  108. package/build/utils/AnalysisStateManager.d.ts +33 -0
  109. package/build/utils/AnalysisStateManager.js +36 -2
  110. package/build/utils/analyze-openapi.js +18 -1
  111. package/build/utils/branchDiff.d.ts +17 -1
  112. package/build/utils/branchDiff.js +99 -14
  113. package/build/utils/featureFlags.d.ts +31 -0
  114. package/build/utils/featureFlags.js +37 -0
  115. package/build/utils/frontendSelectors.js +0 -1
  116. package/build/utils/gitStaging.d.ts +5 -0
  117. package/build/utils/gitStaging.js +1 -1
  118. package/build/utils/grpcMockValidation.d.ts +1 -0
  119. package/build/utils/grpcMockValidation.js +49 -0
  120. package/build/utils/httpMethodValidation.d.ts +4 -0
  121. package/build/utils/httpMethodValidation.js +15 -0
  122. package/build/utils/logger.js +1 -1
  123. package/build/utils/mockCompatibility.d.ts +49 -0
  124. package/build/utils/mockCompatibility.js +82 -0
  125. package/build/utils/pom-catalog.d.ts +23 -0
  126. package/build/utils/pom-catalog.js +30 -0
  127. package/build/utils/pom-scope/pom-files.d.ts +14 -0
  128. package/build/utils/pom-scope/pom-files.js +32 -6
  129. package/build/utils/pom-scope/testIdDiscovery.d.ts +40 -0
  130. package/build/utils/pom-scope/testIdDiscovery.js +104 -0
  131. package/build/utils/pom-verify/verify.d.ts +5 -0
  132. package/build/utils/pom-verify/verify.js +1 -0
  133. package/build/utils/progress.js +10 -5
  134. package/build/utils/proxy-terminal.js +3 -3
  135. package/build/utils/reportVerification.d.ts +7 -2
  136. package/build/utils/reportVerification.js +9 -3
  137. package/build/utils/routeParsers.d.ts +3 -9
  138. package/build/utils/routeParsers.js +79 -4
  139. package/build/utils/utils.js +2 -2
  140. package/build/utils/versions.d.ts +4 -3
  141. package/build/utils/versions.js +3 -1
  142. package/build/utils/workspaceAuth.d.ts +46 -0
  143. package/build/utils/workspaceAuth.js +156 -1
  144. package/build/workspace/frameworks.d.ts +11 -0
  145. package/build/workspace/frameworks.js +22 -0
  146. package/build/workspace/testSuites.d.ts +20 -0
  147. package/build/workspace/testSuites.js +17 -0
  148. package/build/workspace/workspace.d.ts +206 -24
  149. package/build/workspace/workspace.js +52 -2
  150. package/node_modules/playwright/ThirdPartyNotices.txt +319 -266
  151. package/node_modules/playwright/lib/dom-analyzer/blueprint.js +154 -27
  152. package/node_modules/playwright/lib/dom-analyzer/crawler.js +2 -2
  153. package/node_modules/playwright/lib/mcp/browser/tools/pageBlueprint.js +1 -1
  154. package/node_modules/playwright/lib/mcp/browser/tools/sitemap.js +6 -2
  155. package/node_modules/playwright/lib/mcp/skyramp/loadTraceTool.js +3 -2
  156. package/node_modules/playwright/lib/mcp/skyramp/resultCode.js +4 -3
  157. package/node_modules/playwright/lib/mcp/skyramp/skyRampImport.js +15 -3
  158. package/node_modules/playwright/lib/mcp/skyramp/specImport.js +781 -0
  159. package/node_modules/playwright/lib/mcp/skyramp/traceRecordingBackend.js +14 -3
  160. package/node_modules/playwright/lib/mcp/test/resultCode.test.js +2 -1
  161. package/node_modules/playwright/lib/mcp/test/skyRampExport.js +1 -1
  162. package/node_modules/playwright/lib/mcp/test/skyRampExport.test.js +30 -0
  163. package/node_modules/playwright/lib/transform/babelBundleImpl.js +200 -199
  164. package/node_modules/playwright/node_modules/playwright-core/ThirdPartyNotices.txt +3 -3
  165. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/.package-lock.json +3 -3
  166. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/adapter/aws-lambda/handler.js +16 -25
  167. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/adapter/bun/websocket.js +3 -1
  168. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/adapter/lambda-edge/handler.js +20 -4
  169. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/adapter/aws-lambda/handler.js +16 -25
  170. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/adapter/bun/websocket.js +3 -1
  171. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/adapter/lambda-edge/handler.js +20 -4
  172. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/client/client.js +10 -1
  173. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/client/utils.js +1 -1
  174. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/css/common.js +3 -1
  175. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/css/index.js +9 -1
  176. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/base.js +8 -14
  177. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/components.js +41 -21
  178. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/context.js +131 -5
  179. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/streaming.js +9 -7
  180. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/bearer-auth/index.js +1 -1
  181. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/cache/index.js +1 -1
  182. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/compress/index.js +2 -1
  183. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/cors/index.js +2 -5
  184. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/etag/index.js +2 -1
  185. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/language/language.js +10 -32
  186. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/method-override/index.js +5 -3
  187. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/serve-static/index.js +2 -2
  188. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/timing/timing.js +3 -1
  189. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/trie-router/node.js +9 -0
  190. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/body.js +12 -4
  191. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/buffer.js +2 -1
  192. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/ipaddr.js +6 -1
  193. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/validator/validator.js +3 -3
  194. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/client/client.js +10 -1
  195. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/client/utils.js +1 -1
  196. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/css/common.js +3 -1
  197. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/css/index.js +9 -1
  198. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/base.js +15 -15
  199. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/components.js +42 -22
  200. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/context.js +129 -5
  201. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/streaming.js +10 -8
  202. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/bearer-auth/index.js +1 -1
  203. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/cache/index.js +1 -1
  204. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/compress/index.js +2 -1
  205. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/cors/index.js +2 -5
  206. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/etag/index.js +2 -1
  207. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/language/language.js +10 -32
  208. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/method-override/index.js +5 -3
  209. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/serve-static/index.js +2 -2
  210. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/timing/timing.js +3 -1
  211. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/trie-router/node.js +9 -0
  212. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/adapter/aws-lambda/handler.d.ts +1 -1
  213. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/adapter/lambda-edge/handler.d.ts +1 -1
  214. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/helper/websocket/index.d.ts +1 -1
  215. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/base.d.ts +1 -3
  216. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/context.d.ts +39 -0
  217. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/context-storage/index.d.ts +2 -2
  218. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/language/language.d.ts +18 -0
  219. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/utils/body.d.ts +1 -1
  220. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/utils/types.d.ts +1 -1
  221. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/body.js +12 -4
  222. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/buffer.js +2 -1
  223. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/ipaddr.js +6 -1
  224. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/validator/validator.js +3 -3
  225. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/package.json +29 -22
  226. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/package-lock.json +3 -3
  227. package/node_modules/playwright/node_modules/playwright-core/lib/generated/pollingRecorderSource.js +1 -1
  228. package/node_modules/playwright/node_modules/playwright-core/lib/server/codegen/skyramp/jsonlReader.js +5 -1
  229. package/node_modules/playwright/node_modules/playwright-core/lib/server/codegen/skyramp/specReader.js +781 -0
  230. package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/recorderApp.js +25 -6
  231. package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/skyramp/replayEngine.js +3 -1
  232. package/node_modules/playwright/node_modules/playwright-core/lib/utils.js +2 -0
  233. package/node_modules/playwright/node_modules/playwright-core/lib/vite/htmlReport/index.html +253 -27
  234. package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/{codeMirrorModule-D0BjbCb7.js → codeMirrorModule-DtudTj_v.js} +1 -1
  235. package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/index-BpDwp16L.js +422 -0
  236. package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/index.html +1 -1
  237. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/{codeMirrorModule-Bzd72-bG.js → codeMirrorModule-FNMuBzX1.js} +1 -1
  238. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-Co9upU5h.js +1035 -0
  239. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.DXNIQ_dx.js +2 -0
  240. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.html +2 -2
  241. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/uiMode.CIKB3XSv.js +5 -0
  242. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/uiMode.html +2 -2
  243. package/node_modules/playwright/node_modules/playwright-core/package.json +1 -1
  244. package/node_modules/playwright/node_modules/playwright-core/src/generated/pollingRecorderSource.ts +1 -1
  245. package/node_modules/playwright/node_modules/playwright-core/src/server/codegen/skyramp/jsonlReader.ts +4 -0
  246. package/node_modules/playwright/node_modules/playwright-core/src/server/codegen/skyramp/specReader.ts +1028 -0
  247. package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/recorderApp.ts +31 -8
  248. package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/skyramp/replayEngine.ts +1 -0
  249. package/node_modules/playwright/node_modules/playwright-core/src/utils.ts +1 -0
  250. package/node_modules/playwright/package.json +1 -1
  251. package/package.json +12 -6
  252. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/tsconfig.build.tsbuildinfo +0 -1
  253. package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/index-lvTRGFx-.js +0 -193
  254. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-DzxTioTK.js +0 -809
  255. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.BGc30U3S.js +0 -2
  256. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/uiMode.IaDrb29A.js +0 -5
@@ -9,11 +9,11 @@ import { logger } from "../utils/logger.js";
9
9
  import { TestExecutionStatus, } from "../types/TestExecution.js";
10
10
  import { TestType } from "../types/TestTypes.js";
11
11
  import { buildContainerEnv } from "./containerEnv.js";
12
- import { SKYRAMP_IMAGE_VERSION } from "../utils/versions.js";
12
+ import { EXECUTOR_DOCKER_IMAGE } from "../utils/versions.js";
13
13
  import { walkDir } from "../utils/fileWalk.js";
14
+ export { EXECUTOR_DOCKER_IMAGE };
14
15
  const DEFAULT_TIMEOUT = 300000; // 5 minutes
15
16
  const MAX_CONCURRENT_EXECUTIONS = 5;
16
- export const EXECUTOR_DOCKER_IMAGE = `skyramp/executor:${SKYRAMP_IMAGE_VERSION}`;
17
17
  const DOCKER_PLATFORM = "linux/amd64";
18
18
  const EXECUTION_PROGRESS_INTERVAL = 10000; // 10 seconds between progress updates during execution
19
19
  // Temp file with valid empty JSON — used instead of /dev/null for .json config files
@@ -54,8 +54,11 @@ export const PLAYWRIGHT_CONFIG_FILES = [
54
54
  "playwright.config.js",
55
55
  "playwright.config.mjs",
56
56
  ];
57
- // Directories to skip mounting entirely (cannot bind-mount /dev/null to a directory)
58
- export const EXCLUDED_MOUNT_ITEMS = [
57
+ // Directories the recursive shadow scans must never descend into. node_modules
58
+ // IS mounted (see mountRepoTree) — but walking it would shadow every package's
59
+ // own package.json with empty JSON via MOUNT_NULL_ITEMS, breaking resolution
60
+ // for the whole tree.
61
+ export const MOUNT_SCAN_SKIP_DIRS = [
59
62
  "node_modules",
60
63
  ];
61
64
  // Reserved container subdir under /home/user where a cross-repo test repository
@@ -354,7 +357,7 @@ export function detectSessionFiles(testFilePath) {
354
357
  */
355
358
  export function findExcludedPaths(dir, excludedItems) {
356
359
  const results = [];
357
- const shouldSkipDir = (entry) => excludedItems.includes(entry.name) || EXCLUDED_MOUNT_ITEMS.includes(entry.name);
360
+ const shouldSkipDir = (entry) => excludedItems.includes(entry.name) || MOUNT_SCAN_SKIP_DIRS.includes(entry.name);
358
361
  for (const [entry, fullPath] of walkDir(dir, { shouldSkipDir })) {
359
362
  // Only shadow files — mounting /dev/null to a directory target causes Docker errors
360
363
  if (excludedItems.includes(entry.name)) {
@@ -364,18 +367,23 @@ export function findExcludedPaths(dir, excludedItems) {
364
367
  return results;
365
368
  }
366
369
  /**
367
- * Find every nested `node_modules` directory under `dir` — i.e. all except the
368
- * top-level `<dir>/node_modules` (which the workspace mount already excludes).
369
- * Never descends into a `node_modules`. Used to shadow repo-local node_modules
370
- * that ride into the executor inside a parent directory's wholesale bind-mount;
371
- * a leaked `@playwright/test` becomes a second physical copy and trips
372
- * Playwright's "Requiring @playwright/test second time" guard.
370
+ * Find every `node_modules` directory under `dir`, including the top-level
371
+ * `<dir>/node_modules`. Never descends into a `node_modules`. Used to shadow
372
+ * SHADOWED_NESTED_PACKAGES inside each one: a repo-local `@playwright/test`
373
+ * becomes a second physical copy and trips Playwright's "Requiring
374
+ * @playwright/test second time" guard.
375
+ *
376
+ * The top-level one is deliberately NOT special-cased (SKYR-4140). When
377
+ * `workspacePath` is itself an npm package root — the standard `tests/<suite>/`
378
+ * layout — its node_modules IS the only one, so skipping it left the shadow
379
+ * machinery with nothing to act on and no customer dependency resolvable.
380
+ *
373
381
  * Skips `.git` (nothing importable lives there) and does not follow symlinks —
374
382
  * by design (a symlinked nested node_modules either dangles in-container,
375
383
  * falling through to NODE_PATH's global copy, or its real-path target is
376
384
  * walked directly).
377
385
  */
378
- export function findNestedNodeModules(dir) {
386
+ export function findNodeModulesDirs(dir) {
379
387
  const results = [];
380
388
  const walk = (current) => {
381
389
  let entries;
@@ -392,8 +400,7 @@ export function findNestedNodeModules(dir) {
392
400
  continue;
393
401
  const full = path.join(current, entry.name);
394
402
  if (entry.name === "node_modules") {
395
- if (current !== dir)
396
- results.push(full); // skip the top-level node_modules
403
+ results.push(full);
397
404
  continue; // never descend into a node_modules
398
405
  }
399
406
  walk(full);
@@ -565,10 +572,15 @@ export class TestExecutionService {
565
572
  testFilePath,
566
573
  options.testType,
567
574
  ];
575
+ const networkMode = options.dockerNetwork?.trim()
576
+ ? options.dockerNetwork.trim()
577
+ : options.useHostNetwork && process.platform === "linux"
578
+ ? "host"
579
+ : undefined;
568
580
  // Prepare host config with mounts
569
581
  const hostConfig = {
570
582
  ExtraHosts: ["host.docker.internal:host-gateway"],
571
- ...(options.useHostNetwork && process.platform === "linux" ? { NetworkMode: "host" } : {}),
583
+ ...(networkMode ? { NetworkMode: networkMode } : {}),
572
584
  Mounts: [
573
585
  {
574
586
  Type: "bind",
@@ -588,17 +600,16 @@ export class TestExecutionService {
588
600
  hostConfig.Mounts.push(mount);
589
601
  };
590
602
  // Mount one repo tree (the workspace, or a cross-repo test repository) into
591
- // the container, skipping EXCLUDED_MOUNT_ITEMS completely.
603
+ // the container.
592
604
  //
593
605
  // Each top-level entry is bind-mounted at the canonical container path and —
594
606
  // when mirrorToHost is set — at its host-absolute path too. The dual mount
595
607
  // lets the test resolve any absolute reference the codegen happens to embed
596
608
  // (storageState, fixture paths, snapshots) — including the host workspace
597
609
  // path that Playwright's TypeScript loader sometimes produces from
598
- // `__dirname` — without needing source-code detection. EXCLUDED_MOUNT_ITEMS
599
- // (node_modules) stays excluded at both targets; MOUNT_NULL_ITEMS shadows
600
- // (package.json → empty JSON, etc.), nested-package shadows, and
601
- // PLAYWRIGHT_CONFIG_FILES shadows (minimal config) are applied at both
610
+ // `__dirname` — without needing source-code detection. MOUNT_NULL_ITEMS
611
+ // shadows (package.json → empty JSON, etc.), node_modules package shadows,
612
+ // and PLAYWRIGHT_CONFIG_FILES shadows (minimal config) are applied at both
602
613
  // targets too so the protections survive regardless of which path the test
603
614
  // resolves to.
604
615
  //
@@ -606,7 +617,7 @@ export class TestExecutionService {
606
617
  // later mounts over earlier ones, so the top-level entry mounts must be
607
618
  // pushed BEFORE the shadow mounts that override paths inside them.
608
619
  //
609
- // The three recursive scans (findExcludedPaths × 2 + findNestedNodeModules)
620
+ // The three recursive scans (findExcludedPaths × 2 + findNodeModulesDirs)
610
621
  // are deliberately kept as separate walks rather than fused into one pass:
611
622
  // each skips node_modules/.git so the cost is small, and separate walks keep
612
623
  // each shadow category's semantics independently testable.
@@ -618,11 +629,13 @@ export class TestExecutionService {
618
629
  // otherwise the entry mount would win the dedup race and the repo's own
619
630
  // config (which may import dotenv, or simply isn't the minimal/generated
620
631
  // one) would leak into the container.
632
+ //
633
+ // node_modules is NOT filtered out (SKYR-4140): it carries the customer's
634
+ // test-support deps, and the per-package shadows below neutralise the only
635
+ // copies that must not load from the repo.
621
636
  const entriesToMount = fs
622
637
  .readdirSync(hostRoot)
623
- .filter((file) => !EXCLUDED_MOUNT_ITEMS.includes(file) &&
624
- !MOUNT_NULL_ITEMS.includes(file) &&
625
- !PLAYWRIGHT_CONFIG_FILES.includes(file));
638
+ .filter((file) => !MOUNT_NULL_ITEMS.includes(file) && !PLAYWRIGHT_CONFIG_FILES.includes(file));
626
639
  for (const file of entriesToMount) {
627
640
  const source = path.join(hostRoot, file);
628
641
  pushMount({ Type: "bind", Target: path.join(containerRoot, file), Source: source });
@@ -639,10 +652,9 @@ export class TestExecutionService {
639
652
  pushMount({ Type: "bind", Source: source, Target: absolutePath });
640
653
  }
641
654
  }
642
- // Shadow SHADOWED_NESTED_PACKAGES inside every nested node_modules leaked in
643
- // via a parent-directory bind-mount (see findNestedNodeModules) — the
644
- // top-level node_modules is already excluded above via EXCLUDED_MOUNT_ITEMS.
645
- for (const nested of findNestedNodeModules(hostRoot)) {
655
+ // Shadow SHADOWED_NESTED_PACKAGES inside every mounted node_modules — the
656
+ // repo's own top-level one included (see findNodeModulesDirs).
657
+ for (const nested of findNodeModulesDirs(hostRoot)) {
646
658
  for (const pkg of SHADOWED_NESTED_PACKAGES) {
647
659
  const pkgPath = path.join(nested, pkg);
648
660
  if (!fs.existsSync(pkgPath))
@@ -706,6 +718,22 @@ export class TestExecutionService {
706
718
  if (crossRepoTestRoot) {
707
719
  mountRepoTree(crossRepoTestRoot, path.join(containerMountPath, TEST_REPO_CONTAINER_SUBDIR), true);
708
720
  }
721
+ // runner.sh invokes `npx playwright test`, and npx resolves binaries from
722
+ // <cwd>/node_modules/.bin before PATH — cwd is always containerMountPath. Now
723
+ // that node_modules is mounted (SKYR-4140), a repo-local .bin/playwright would
724
+ // run instead of the image's global CLI. The per-package shadows above do not
725
+ // cover it under a pnpm layout, where .bin/playwright symlinks into .pnpm/
726
+ // rather than into node_modules/playwright. Shadow this one .bin — the only
727
+ // one npx can reach — so binary resolution falls through to PATH as before.
728
+ // Pushed after mountRepoTree so it layers over the node_modules entry mount.
729
+ if (fs.existsSync(path.join(workspacePath, "node_modules", ".bin"))) {
730
+ pushMount({
731
+ Type: "bind",
732
+ Source: EMPTY_DIR_PATH,
733
+ Target: path.join(containerMountPath, "node_modules", ".bin"),
734
+ ReadOnly: true,
735
+ });
736
+ }
709
737
  // Mount video output directory for browser tests (writable)
710
738
  if (browserTest && videoHostDir) {
711
739
  pushMount({
@@ -1,6 +1,6 @@
1
1
  import { SkyrampClient } from "@skyramp/skyramp";
2
2
  import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
3
- import { TestType } from "../types/TestTypes.js";
3
+ import { TestType, MOCK_TYPE } from "../types/TestTypes.js";
4
4
  export interface BaseTestParams {
5
5
  endpointURL?: string;
6
6
  method?: string;
@@ -50,7 +50,7 @@ export declare abstract class TestGenerationService {
50
50
  generateTest(params: BaseTestParams & Record<string, any>): Promise<CallToolResult>;
51
51
  protected validateInputs(params: BaseTestParams): CallToolResult;
52
52
  protected abstract buildGenerationOptions(params: BaseTestParams & Record<string, any>): any;
53
- protected abstract getTestType(): TestType;
53
+ protected abstract getTestType(): TestType | typeof MOCK_TYPE;
54
54
  protected handleApiAnalysis(params: BaseTestParams): Promise<CallToolResult | null>;
55
55
  private static readonly STANDARD_HEADERS;
56
56
  private static simpleWildcardMatch;
@@ -2,10 +2,11 @@ import path from "path";
2
2
  import fs from "fs";
3
3
  import { SkyrampClient } from "@skyramp/skyramp";
4
4
  import { analyzeOpenAPIWithGivenEndpoint } from "../utils/analyze-openapi.js";
5
- import { isAuthorizationHeaderName, KNOWN_AUTH_HEADERS, getWorkspaceAuthConfig, getDefaultAuthHeader, getAuthScheme, WorkspaceAuthType, getWorkspaceSkipTLSVerify, } from "../utils/workspaceAuth.js";
5
+ import { isAuthorizationHeaderName, KNOWN_AUTH_HEADERS, resolveAuthFromWorkspace, getWorkspaceSkipTLSVerify, getWorkspaceDefaultQueryParams, mergeQueryParamsString, } from "../utils/workspaceAuth.js";
6
6
  import { getPathParameterValidationError, OUTPUT_DIR_FIELD_NAME, PATH_PARAMS_FIELD_NAME, QUERY_PARAMS_FIELD_NAME, FORM_PARAMS_FIELD_NAME, validateParams, validatePath, validateRequestData, } from "../utils/utils.js";
7
7
  import { getEntryPoint } from "../utils/telemetry.js";
8
8
  import { getLanguageSteps } from "../utils/language-helper.js";
9
+ import { TestType } from "../types/TestTypes.js";
9
10
  import { logger } from "../utils/logger.js";
10
11
  import { normalizeLanguageParams } from "../utils/normalizeParams.js";
11
12
  import { stageGeneratedPaths, resolveOutputDir } from "../utils/gitStaging.js";
@@ -24,6 +25,19 @@ export function deriveEffectiveFramework(language, framework) {
24
25
  const lang = (language ?? "").trim().toLowerCase();
25
26
  return lang === "typescript" || lang === "javascript" ? "playwright" : "";
26
27
  }
28
+ /**
29
+ * Test types whose generation is driven by a recorded Playwright trace, not a
30
+ * live query-string request the same way contract/fuzz/smoke/load/integration
31
+ * are. Their schemas (uiTestSchema, e2eTestSchema) don't expose a queryParams
32
+ * field at all, so there's no way for a caller to override or even know this
33
+ * field exists — injecting an unrequested, uneditable workspace
34
+ * defaultQueryParams value into that path is not what the design intends
35
+ * (SKYR-4050).
36
+ */
37
+ const SKIP_DEFAULT_QUERY_PARAMS_TEST_TYPES = new Set([
38
+ TestType.UI,
39
+ TestType.E2E,
40
+ ]);
27
41
  export class TestGenerationService {
28
42
  client;
29
43
  constructor() {
@@ -316,29 +330,15 @@ The generated test file remains unchanged and ready to use as-is.
316
330
  async executeGeneration(generateOptions) {
317
331
  try {
318
332
  // Auto-resolve auth from workspace config when authHeader was not explicitly provided.
319
- // undefined = omit (auto-resolve); "" = explicit skip-auth for unauthenticated endpoints.
333
+ // undefined = auto-resolve; "" = caller explicitly said skip-auth.
320
334
  if (generateOptions.authHeader === undefined) {
321
335
  try {
322
336
  const repoPath = generateOptions.outputDir || process.cwd();
323
- const wsAuth = await getWorkspaceAuthConfig(repoPath);
324
- let resolvedHeader = wsAuth.authHeader ?? getDefaultAuthHeader(wsAuth.authType);
325
- if (!resolvedHeader && wsAuth.authScheme !== undefined) {
326
- resolvedHeader = "Authorization";
327
- }
328
- if (wsAuth.authType === WorkspaceAuthType.ApiKey && !resolvedHeader) {
329
- logger.warning("workspace.yml has authType: apiKey but no authHeader is set — " +
330
- "requests will be sent without an auth header and will likely receive 401/403. " +
331
- "Add authHeader: <X-Your-Key-Header> to .skyramp/workspace.yml.");
332
- }
333
- if (resolvedHeader && wsAuth.authType !== WorkspaceAuthType.None) {
334
- logger.info("authHeader not provided — resolved from workspace config", {
335
- authHeader: resolvedHeader,
336
- authType: wsAuth.authType,
337
- });
338
- generateOptions.authHeader = resolvedHeader;
339
- if (isAuthorizationHeaderName(resolvedHeader)) {
340
- generateOptions.authScheme =
341
- generateOptions.authScheme ?? wsAuth.authScheme ?? getAuthScheme(wsAuth.authType);
337
+ const resolved = await resolveAuthFromWorkspace(repoPath, generateOptions.authHeader, generateOptions.authScheme);
338
+ if (resolved) {
339
+ generateOptions.authHeader = resolved.authHeader;
340
+ if (resolved.authScheme !== undefined) {
341
+ generateOptions.authScheme = resolved.authScheme;
342
342
  }
343
343
  }
344
344
  }
@@ -364,6 +364,24 @@ The generated test file remains unchanged and ready to use as-is.
364
364
  logger.warning("Could not resolve skipTLSVerify from workspace config");
365
365
  }
366
366
  }
367
+ // Workspace-declared default query params (SKYR-4050): api.defaultQueryParams
368
+ // are attached to every generated request for the service. Existing
369
+ // queryParams entries (explicit caller values) always win on a key collision.
370
+ if (!SKIP_DEFAULT_QUERY_PARAMS_TEST_TYPES.has(this.getTestType())) {
371
+ try {
372
+ const repoPath = generateOptions.outputDir || process.cwd();
373
+ const defaults = await getWorkspaceDefaultQueryParams(repoPath);
374
+ if (defaults) {
375
+ generateOptions.queryParams = mergeQueryParamsString(generateOptions.queryParams, defaults);
376
+ logger.info("Merged workspace defaultQueryParams into queryParams", {
377
+ keys: Object.keys(defaults),
378
+ });
379
+ }
380
+ }
381
+ catch {
382
+ logger.warning("Could not resolve default query params from workspace config");
383
+ }
384
+ }
367
385
  if (generateOptions.traceFilePath) {
368
386
  const traceAuth = this.extractAuthFromTrace(generateOptions.traceFilePath, generateOptions.generateInclude, generateOptions.generateExclude);
369
387
  if (traceAuth) {
@@ -14,7 +14,9 @@ export function rewriteLocalhostForDocker(url) {
14
14
  */
15
15
  export function buildContainerEnv(options, saveStoragePath, hostEnv = process.env) {
16
16
  const env = [
17
- `SKYRAMP_TEST_TOKEN=${options.token || ""}`,
17
+ // Omit entirely when empty so os.getenv() returns None in the test —
18
+ // unauthenticated endpoints won't send an empty auth header (E7).
19
+ ...(options.token ? [`SKYRAMP_TEST_TOKEN=${options.token}`] : []),
18
20
  "SKYRAMP_IN_DOCKER=true",
19
21
  ];
20
22
  // Skyramp-generated tests are standalone HTTP tests that never need host repo
@@ -42,6 +44,30 @@ export function buildContainerEnv(options, saveStoragePath, hostEnv = process.en
42
44
  env.push(`${key}=${shouldRewrite ? rewriteLocalhostForDocker(val) : val}`);
43
45
  }
44
46
  }
47
+ // Credentials that generated UI tests read from the environment instead of
48
+ // carrying as literals (SKYR-3862). Without this the container never sees
49
+ // them and every generated login fails its guard.
50
+ //
51
+ // Forwarded on presence, not truthiness: the generated guard deliberately
52
+ // distinguishes an unset variable (a misconfiguration, fails fast) from one
53
+ // set to "" (valid on forms that accept a blank password). A truthy check —
54
+ // as used for the URL vars above — would drop the empty case and collapse it
55
+ // into the failure case.
56
+ //
57
+ // TODO(SKYR-4110): only ONE credential pair is forwarded, because testbot
58
+ // exports only the first credential from its `uiCredentials` input. That input
59
+ // was designed to carry several, so the agent can pick per test case by
60
+ // authorization role — so a multi-role suite can get a credential its test did
61
+ // not expect, surfacing as a false 403. The fix is a keyed form
62
+ // (SKYRAMP_UI_PASSWORD_<KEY>), which needs no new forwarding logic here: the
63
+ // loop above already forwards SKYRAMP_TEST_SERVICE_URL_* by prefix, so the
64
+ // same approach applies. Keep the presence-not-truthiness rule when it lands.
65
+ for (const key of ["SKYRAMP_UI_USERNAME", "SKYRAMP_UI_PASSWORD"]) {
66
+ const val = hostEnv[key];
67
+ if (val !== undefined) {
68
+ env.push(`${key}=${val}`);
69
+ }
70
+ }
45
71
  if (hostEnv.SKYRAMP_DEBUG) {
46
72
  env.push(`SKYRAMP_DEBUG=${hostEnv.SKYRAMP_DEBUG}`);
47
73
  }
@@ -11,7 +11,11 @@ export const TOOL_PHASE_MAP = {
11
11
  skyramp_ui_test_generation: "generating",
12
12
  skyramp_batch_scenario_test_generation: "generating",
13
13
  skyramp_mock_generation: "generating",
14
+ skyramp_batch_mock_generation: "generating",
15
+ skyramp_generate_enriched_integration_test: "generating",
16
+ skyramp_enrich_test_with_mocks: "generating",
14
17
  skyramp_execute_test: { before: "maintaining", after: "executing" },
18
+ skyramp_run_existing_tests: { before: "maintaining", after: "executing" },
15
19
  skyramp_analyze_test_health: "maintaining",
16
20
  skyramp_submit_report: "reporting",
17
21
  };
@@ -30,6 +34,7 @@ export const TOOLS_WITHOUT_PHASE = new Set([
30
34
  "skyramp_init_scan",
31
35
  "skyramp_init_workspace",
32
36
  "skyramp_one_click_tool",
37
+ "skyramp_setup_local_dev_worker",
33
38
  "skyramp_actions",
34
39
  "skyramp_start_trace_collection",
35
40
  "skyramp_stop_trace_collection",
@@ -37,4 +42,6 @@ export const TOOLS_WITHOUT_PHASE = new Set([
37
42
  "skyramp_modularization",
38
43
  "skyramp_reuse_code",
39
44
  "skyramp_enhance_assertions",
45
+ "skyramp_preflight_mock_check",
46
+ "skyramp_query_proxy_mocks",
40
47
  ]);
@@ -4,9 +4,11 @@ import { getCodeReusePrompt, isPomAwareTarget } from "../../prompts/code-reuse.j
4
4
  import { selectScopedPoms } from "../../utils/pom-scope/index.js";
5
5
  import { verifyReuse } from "../../utils/pom-verify/index.js";
6
6
  import { infraGateFailure, zeroReuseGateFailure, composeVerifyText } from "./verify-gates.js";
7
+ import { recordCandidates, recordNoPomLayer, recordVerifyOutcome } from "./reuse-state.js";
7
8
  import { codeRefactoringSchema, languageSchema, } from "../../types/TestTypes.js";
8
9
  import { SKYRAMP_UTILS_HEADER } from "../../utils/utils.js";
9
10
  import { AnalyticsService } from "../../services/AnalyticsService.js";
11
+ import { isPomReuseEnabled } from "../../utils/featureFlags.js";
10
12
  import { stageGeneratedPaths } from "../../utils/gitStaging.js";
11
13
  const codeReuseSchema = z.object({
12
14
  testFile: z
@@ -25,6 +27,12 @@ const codeReuseSchema = z.object({
25
27
  .describe("Verify a previously written refactored test's POM calls against source instead of returning the reuse prompt"),
26
28
  });
27
29
  const TOOL_NAME = "skyramp_reuse_code";
30
+ // Only advertised when SKYRAMP_FEATURE_POM_REUSE=1 — with the flag off this tool
31
+ // never takes the POM path, so describing it would promise behavior it won't do.
32
+ const POM_AWARE_MODE_DESCRIPTION = `
33
+
34
+ **POM-AWARE MODE (TypeScript/JavaScript + Playwright):**
35
+ For projects with \`language: "typescript" or "javascript"\` and \`framework: "playwright"\`, this tool first checks whether the project has an existing Page Object Model (POM) library (\`pageobjects/\` directories or \`*.page.ts\` / \`*.page.js\` files). If POMs are found, the test is refactored to use those POM classes and methods — replacing raw inline locators with the existing abstractions. SkyrampUtils consolidation is skipped on this path. If no POMs are found, the tool falls back to the standard SkyrampUtils path. New POM creation is out of scope — existing POMs are reused only. After POM-aware code reuse, do NOT call skyramp_modularization — on this path that supersedes WORKFLOW SUMMARY step 6.`;
28
36
  export function registerCodeReuseTool(server) {
29
37
  server.registerTool(TOOL_NAME, {
30
38
  description: `Analyzes code for reuse opportunities and enforces code reuse principles.
@@ -57,10 +65,7 @@ export function registerCodeReuseTool(server) {
57
65
 
58
66
  **MANDATORY**: ONLY ALLOW CODE REUSE IF THE IS TRACE BASED FLAG IS SET TO TRUE ELSE DO NOT ALLOW CODE REUSE AND LEAVE THE TEST FILE AS IS.
59
67
  **CRITICAL**: NON TRACE BASED TESTS ARE ALREADY MODULARIZED AND DO NOT NEED CODE REUSE.
60
- The tool will provide step-by-step instructions that MUST be followed exactly.
61
-
62
- **POM-AWARE MODE (TypeScript/JavaScript + Playwright):**
63
- For projects with \`language: "typescript" or "javascript"\` and \`framework: "playwright"\`, this tool first checks whether the project has an existing Page Object Model (POM) library (\`pageobjects/\` directories or \`*.page.ts\` / \`*.page.js\` files). If POMs are found, the test is refactored to use those POM classes and methods — replacing raw inline locators with the existing abstractions. SkyrampUtils consolidation is skipped on this path. If no POMs are found, the tool falls back to the standard SkyrampUtils path. New POM creation is out of scope — existing POMs are reused only. After POM-aware code reuse, do NOT call skyramp_modularization.`,
68
+ The tool will provide step-by-step instructions that MUST be followed exactly.${isPomReuseEnabled() ? POM_AWARE_MODE_DESCRIPTION : ""}`,
64
69
  inputSchema: codeReuseSchema.shape,
65
70
  _meta: {
66
71
  keywords: [
@@ -75,9 +80,26 @@ export function registerCodeReuseTool(server) {
75
80
  let errorResult;
76
81
  try {
77
82
  if (params.verify) {
83
+ // The verify pass is POM-only, and it is the sole writer of the report's
84
+ // reuse summary — so with the flag off a stale instruction to verify must
85
+ // not run it, or a POM-less run would still emit POM reuse numbers.
86
+ if (!isPomReuseEnabled()) {
87
+ return {
88
+ content: [
89
+ {
90
+ type: "text",
91
+ text: "VERIFICATION SKIPPED — POM-aware code reuse is disabled. Nothing to verify; continue.",
92
+ },
93
+ ],
94
+ };
95
+ }
78
96
  try {
79
97
  const r = await verifyReuse(params.testFile, params.language);
80
98
  const gate = (await infraGateFailure(params, r)) ?? (await zeroReuseGateFailure(params, r));
99
+ // Record what this pass established before returning the text report:
100
+ // every number in it is already in hand here, so the agent is never
101
+ // asked to read one back out and retype it later.
102
+ await recordVerifyOutcome(params.testFile, r, gate !== undefined, params.language);
81
103
  return { content: [{ type: "text", text: composeVerifyText(gate, r) }] };
82
104
  }
83
105
  catch (err) {
@@ -110,11 +132,28 @@ export function registerCodeReuseTool(server) {
110
132
  });
111
133
  if (tier1.length + tier2.length > 0) {
112
134
  scopedPoms = { tier1, tier2 };
135
+ // Only report candidates found through the conventional POM globs.
136
+ //
137
+ // The selector-grep fallback also matches ordinary in-repo frontend
138
+ // source — app components legitimately contain the spec's test-ids by
139
+ // construction — so in a repo with no page-object layer at all it still
140
+ // yields "candidates". Reporting those would render, on a POM-less repo,
141
+ // "4 candidate POM files detected" next to zero reuse: each number true
142
+ // in isolation, but together they assert reusable page objects existed
143
+ // and were ignored. `zeroReuseGateFailure` already draws this exact line
144
+ // for the same reason; the report has to draw it too.
145
+ //
146
+ // The agent is still handed the grep-discovered files to consider —
147
+ // only the customer-facing count is withheld.
148
+ if (diagnostics.discovery === "globs") {
149
+ await recordCandidates(params.testFile, tier1.length);
150
+ }
113
151
  }
114
152
  else if (diagnostics.selectors > 0 && diagnostics.discovery !== "skipped-too-large") {
115
153
  // A clean scan ran (glob or selector-grep) and found zero overlap — distinct from
116
154
  // "scoping wasn't attempted" (no selectors) or "scan was skipped" (repo too large).
117
155
  scopedPoms = { tier1: [], tier2: [], scannedNoOverlap: true };
156
+ await recordNoPomLayer(params.testFile);
118
157
  }
119
158
  logger.info("POM pre-scoping", {
120
159
  ...diagnostics,
@@ -5,6 +5,7 @@ import { getContractProviderAssertionsPrompt } from "../../prompts/enhance-asser
5
5
  import { getIntegrationAssertionsPrompt } from "../../prompts/enhance-assertions/integrationAssertionsPrompt.js";
6
6
  import { getUIAssertionsPrompt } from "../../prompts/enhance-assertions/uiAssertionsPrompt.js";
7
7
  import { isTestbotEnabled } from "../../utils/featureFlags.js";
8
+ import { renderSharedAssertionRules } from "../../prompts/enhance-assertions/sharedAssertionRules.js";
8
9
  import { stageGeneratedPaths } from "../../utils/gitStaging.js";
9
10
  const TOOL_NAME = "skyramp_enhance_assertions";
10
11
  const TESTBOT_UI_CHECKS = `
@@ -12,6 +13,37 @@ const TESTBOT_UI_CHECKS = `
12
13
  - If no suitable selector exists in the generated file for an assertion you need to add, go back and call \`browser_assert\` on the live page to record it with a valid selector, then re-export and regenerate.
13
14
  - **After executing a UI test that documents a bug from \`issuesFound\`**: if it passed when you expected it to fail, the assertions are too weak — add a stronger \`expect()\` that directly targets the buggy behavior. This counts as the single allowed retry under the 2-attempt cap — do NOT re-run more than once.
14
15
  `;
16
+ function buildAssertionInstructions(testFile, testType, enhanceType) {
17
+ if (testType === TestType.UI) {
18
+ let instructions = getUIAssertionsPrompt(testFile, enhanceType);
19
+ if (isTestbotEnabled()) {
20
+ instructions += TESTBOT_UI_CHECKS;
21
+ }
22
+ return instructions;
23
+ }
24
+ if (testType === TestType.CONTRACT) {
25
+ return getContractProviderAssertionsPrompt(testFile, enhanceType);
26
+ }
27
+ if (testType === TestType.INTEGRATION) {
28
+ return getIntegrationAssertionsPrompt(testFile, enhanceType);
29
+ }
30
+ throw new Error(`Unsupported testType for ${TOOL_NAME}: ${testType}`);
31
+ }
32
+ function buildAutoApplyInstructions(testFile, testType, enhanceType) {
33
+ const typeSpecificInstructions = buildAssertionInstructions(testFile, testType, enhanceType);
34
+ return [
35
+ `Enhance response body assertions in: \`${testFile}\``,
36
+ `Test type: ${testType} | Context: ${enhanceType}`,
37
+ ``,
38
+ `Read the file, apply the type-specific assertion guidance below, and write the file back directly.`,
39
+ `Add assertions after each send_request/sendRequest status-code assertion.`,
40
+ `Use SDK helper: Python \`skyramp.get_response_value(response, "json.path")\`, JS \`getValue(response, "json.path")\`.`,
41
+ `Do NOT restructure, reformat, add comments, or change imports. Only add assertion lines.`,
42
+ ``,
43
+ `Type-specific assertion guidance:`,
44
+ typeSpecificInstructions,
45
+ ].join("\n");
46
+ }
15
47
  const enhanceAssertionsSchema = {
16
48
  testFile: z
17
49
  .string()
@@ -24,6 +56,12 @@ const enhanceAssertionsSchema = {
24
56
  .describe("The context of the enhancement. " +
25
57
  "Use 'generation' after generating a new test file (applies to every test function). " +
26
58
  "Use 'maintenance' during drift UPDATE (applies only to new or diff-affected functions)."),
59
+ autoApply: z
60
+ .boolean()
61
+ .default(false)
62
+ .describe("When true, returns a compact instruction set (10 lines) that tells the agent to " +
63
+ "read the test file, enhance assertions per standard rules, and write it back directly. " +
64
+ "When false (default), returns the full verbose instruction set."),
27
65
  };
28
66
  export function registerEnhanceAssertionsTool(server) {
29
67
  server.registerTool(TOOL_NAME, {
@@ -34,26 +72,33 @@ export function registerEnhanceAssertionsTool(server) {
34
72
  - After updating an existing supported test file during maintenance`,
35
73
  inputSchema: enhanceAssertionsSchema,
36
74
  }, async (params) => {
37
- const { testFile, testType, enhanceType } = params;
75
+ const { testFile, testType, enhanceType, autoApply } = params;
38
76
  // Stage so testbot includes the generated files in its output commit.
39
77
  await stageGeneratedPaths(testFile);
40
- const enhanceCtx = enhanceType;
41
- let instructions;
42
- if (testType === TestType.UI) {
43
- instructions = getUIAssertionsPrompt(testFile, enhanceCtx);
44
- if (isTestbotEnabled()) {
45
- instructions += TESTBOT_UI_CHECKS;
46
- }
47
- }
48
- else if (testType === TestType.CONTRACT) {
49
- instructions = getContractProviderAssertionsPrompt(testFile, enhanceCtx);
50
- }
51
- else if (testType === TestType.INTEGRATION) {
52
- instructions = getIntegrationAssertionsPrompt(testFile, enhanceCtx);
53
- }
54
- else {
55
- throw new Error(`Unsupported testType for ${TOOL_NAME}: ${testType}`);
78
+ if (autoApply) {
79
+ const compactInstructions = [
80
+ `Enhance response body assertions in: \`${testFile}\``,
81
+ `Test type: ${testType} | Context: ${enhanceType}`,
82
+ ``,
83
+ `Read the file, add assertions after each send_request/sendRequest status-code assertion, write it back.`,
84
+ `Use SDK helper: Python \`skyramp.get_response_value(response, "json.path")\`, JS \`getValue(response, "json.path")\`.`,
85
+ ``,
86
+ `Shared assertion rules (apply all that fit):`,
87
+ renderSharedAssertionRules(),
88
+ ``,
89
+ `Do NOT restructure, reformat, add comments, or change imports. Only add assertion lines.`,
90
+ ].join("\n");
91
+ const result = {
92
+ content: [{ type: "text", text: compactInstructions }],
93
+ isError: false,
94
+ };
95
+ AnalyticsService.pushMCPToolEvent(TOOL_NAME, undefined, { testFile: params.testFile, testType: params.testType, enhanceType: params.enhanceType, autoApply: Boolean(params.autoApply) }).catch(() => { });
96
+ return result;
56
97
  }
98
+ const enhanceCtx = enhanceType;
99
+ const instructions = autoApply
100
+ ? buildAutoApplyInstructions(testFile, testType, enhanceCtx)
101
+ : buildAssertionInstructions(testFile, testType, enhanceCtx);
57
102
  const result = {
58
103
  content: [
59
104
  {
@@ -63,7 +108,12 @@ export function registerEnhanceAssertionsTool(server) {
63
108
  ],
64
109
  isError: false,
65
110
  };
66
- AnalyticsService.pushMCPToolEvent(TOOL_NAME, undefined, params).catch(() => { });
111
+ AnalyticsService.pushMCPToolEvent(TOOL_NAME, undefined, {
112
+ testFile: params.testFile,
113
+ testType: params.testType,
114
+ enhanceType: params.enhanceType,
115
+ autoApply: Boolean(params.autoApply),
116
+ }).catch(() => { });
67
117
  return result;
68
118
  });
69
119
  }