@skyramp/mcp 0.4.1 → 0.4.2-rc.2

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 (583) hide show
  1. package/build/commands/localDevTestChangesCommand.js +2 -1
  2. package/build/commands/recommendTestsAndExecuteCommand.js +15 -7
  3. package/build/commands/testThisEndpointCommand.js +35 -6
  4. package/build/execution/wrapperConfig.d.ts +56 -0
  5. package/build/execution/wrapperConfig.js +155 -0
  6. package/build/index.js +40 -10
  7. package/build/playwright/blueprintDigest.js +28 -7
  8. package/build/playwright/registerPlaywrightTools.js +47 -28
  9. package/build/playwright/traceExportStore.d.ts +22 -0
  10. package/build/playwright/traceExportStore.js +81 -0
  11. package/build/playwright/traceRecordingPrompt.js +11 -3
  12. package/build/prompts/code-reuse.js +118 -49
  13. package/build/prompts/fix-error-prompt.d.ts +9 -1
  14. package/build/prompts/fix-error-prompt.js +31 -28
  15. package/build/prompts/local-dev/local-dev-plan.d.ts +3 -0
  16. package/build/prompts/local-dev/local-dev-plan.js +8 -23
  17. package/build/prompts/local-dev/local-dev-prompts.d.ts +1 -1
  18. package/build/prompts/local-dev/local-dev-prompts.js +31 -4
  19. package/build/prompts/modularization/integration-test-modularization.js +13 -6
  20. package/build/prompts/modularization/ui-test-modularization.js +1 -1
  21. package/build/prompts/personas.js +1 -1
  22. package/build/prompts/pom-aware-code-reuse.js +7 -9
  23. package/build/prompts/reuse-hand-off.d.ts +64 -0
  24. package/build/prompts/reuse-hand-off.js +130 -0
  25. package/build/prompts/shared-helper-policy.d.ts +124 -2
  26. package/build/prompts/shared-helper-policy.js +178 -12
  27. package/build/prompts/startTraceCollectionPrompts.js +1 -1
  28. package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.js +7 -8
  29. package/build/prompts/sut-setup/modes/dockerComposePrompt.js +1 -1
  30. package/build/prompts/sut-setup/shared.d.ts +4 -1
  31. package/build/prompts/sut-setup/shared.js +6 -4
  32. package/build/prompts/test-maintenance/actionsInstructions.d.ts +19 -11
  33. package/build/prompts/test-maintenance/actionsInstructions.js +47 -26
  34. package/build/prompts/test-maintenance/drift-analysis-prompt.d.ts +16 -8
  35. package/build/prompts/test-maintenance/drift-analysis-prompt.js +93 -38
  36. package/build/prompts/test-maintenance/driftAnalysisSections.js +5 -3
  37. package/build/prompts/test-maintenance/driftAnalysisShared.js +4 -2
  38. package/build/prompts/test-maintenance/uiDriftAnalysisSections.js +8 -5
  39. package/build/prompts/test-recommendation/recommendationSections.js +19 -8
  40. package/build/prompts/test-recommendation/recommendationShared.d.ts +1 -1
  41. package/build/prompts/test-recommendation/recommendationShared.js +0 -1
  42. package/build/prompts/test-recommendation/registerRecommendTestsPrompt.js +5 -2
  43. package/build/prompts/test-recommendation/test-recommendation-prompt.js +10 -7
  44. package/build/prompts/testbot/testbot-prompts.js +133 -63
  45. package/build/recommendation/answers.js +18 -9
  46. package/build/recommendation/pullRequestText.js +1 -1
  47. package/build/recommendation/registerPlan.js +31 -17
  48. package/build/recommendation/subjectStep.d.ts +8 -10
  49. package/build/recommendation/subjectStep.js +17 -16
  50. package/build/recommendation/types.d.ts +71 -17
  51. package/build/recommendation/types.js +9 -15
  52. package/build/recommendation/verifierContracts.d.ts +7 -3
  53. package/build/recommendation/verifierContracts.js +8 -4
  54. package/build/recommendation/verifiers/changedFile.js +11 -13
  55. package/build/recommendation/verifiers/citedPath.d.ts +8 -0
  56. package/build/recommendation/verifiers/citedPath.js +16 -2
  57. package/build/recommendation/verifiers/coverage.d.ts +2 -2
  58. package/build/recommendation/verifiers/coverage.js +190 -134
  59. package/build/recommendation/verifiers/defects.js +56 -16
  60. package/build/recommendation/verifiers/deliveredMatchesPlan.d.ts +7 -1
  61. package/build/recommendation/verifiers/deliveredMatchesPlan.js +28 -14
  62. package/build/recommendation/verifiers/endpointGrounded.js +14 -8
  63. package/build/recommendation/verifiers/existingCoverage.d.ts +6 -0
  64. package/build/recommendation/verifiers/existingCoverage.js +30 -21
  65. package/build/recommendation/verifiers/expectedOutcome.js +17 -8
  66. package/build/recommendation/verifiers/expectedValueSourced.js +54 -43
  67. package/build/recommendation/verifiers/issueTraceability.d.ts +5 -0
  68. package/build/recommendation/verifiers/issueTraceability.js +64 -7
  69. package/build/recommendation/verifiers/removedElementGuarded.js +19 -11
  70. package/build/recommendation/verifiers/reportedCategory.js +9 -4
  71. package/build/recommendation/verifiers/requirementSourced.js +34 -21
  72. package/build/recommendation/verifiers/screenRoute.js +15 -10
  73. package/build/recommendation/verifiers/statedDifference.js +15 -8
  74. package/build/recommendation/verifiers/uiElementGrounded.js +50 -16
  75. package/build/resources/analysisResources.js +7 -3
  76. package/build/resources/progressResource.js +4 -2
  77. package/build/resources/sutSetupResource.js +20 -2
  78. package/build/resources/testbotResource.js +19 -1
  79. package/build/services/AnalyticsService.js +3 -1
  80. package/build/services/ScenarioGenerationService.js +5 -5
  81. package/build/services/TestDiscoveryService.js +53 -9
  82. package/build/services/TestExecutionService.js +63 -21
  83. package/build/services/TestGenerationService.d.ts +1 -1
  84. package/build/services/TestGenerationService.js +43 -24
  85. package/build/skills/enhanceAssertionsSkill.d.ts +45 -0
  86. package/build/skills/enhanceAssertionsSkill.js +103 -0
  87. package/build/skills/fixTestImportErrorsSkill.d.ts +2 -2
  88. package/build/skills/fixTestImportErrorsSkill.js +2 -2
  89. package/build/skills/runTestSkill.d.ts +6 -0
  90. package/build/skills/runTestSkill.js +17 -0
  91. package/build/skills/skillFiles.d.ts +38 -0
  92. package/build/skills/skillFiles.js +94 -0
  93. package/build/skills/validateAssertionAlignmentSkill.d.ts +34 -0
  94. package/build/skills/validateAssertionAlignmentSkill.js +59 -0
  95. package/build/tool-phases.js +4 -1
  96. package/build/tools/auth/loginTool.js +3 -1
  97. package/build/tools/auth/logoutTool.js +3 -1
  98. package/build/tools/budgetExcuse.d.ts +15 -0
  99. package/build/tools/budgetExcuse.js +113 -0
  100. package/build/tools/code-refactor/alignAssertionsTool.d.ts +2 -0
  101. package/build/tools/code-refactor/alignAssertionsTool.js +51 -0
  102. package/build/tools/code-refactor/assertion-state.d.ts +1 -1
  103. package/build/tools/code-refactor/assertion-state.js +1 -1
  104. package/build/tools/code-refactor/assertionOperations.d.ts +44 -0
  105. package/build/tools/code-refactor/assertionOperations.js +82 -0
  106. package/build/tools/code-refactor/assertionSkillTools.d.ts +3 -0
  107. package/build/tools/code-refactor/assertionSkillTools.js +86 -0
  108. package/build/tools/code-refactor/codeReuseTool.js +27 -3
  109. package/build/tools/code-refactor/enhanceAssertionsTool.js +19 -83
  110. package/build/tools/code-refactor/gate-markers.d.ts +51 -0
  111. package/build/tools/code-refactor/gate-markers.js +95 -0
  112. package/build/tools/code-refactor/retrofit-state.d.ts +3 -1
  113. package/build/tools/code-refactor/retrofit-state.js +44 -2
  114. package/build/tools/code-refactor/reuse-outcome.d.ts +23 -1
  115. package/build/tools/code-refactor/reuse-outcome.js +36 -13
  116. package/build/tools/code-refactor/reuse-state.d.ts +90 -16
  117. package/build/tools/code-refactor/reuse-state.js +191 -61
  118. package/build/tools/code-refactor/utils-verify-gates.d.ts +4 -0
  119. package/build/tools/code-refactor/utils-verify-gates.js +269 -30
  120. package/build/tools/code-refactor/verify-gates.d.ts +15 -1
  121. package/build/tools/code-refactor/verify-gates.js +36 -4
  122. package/build/tools/enrichTestWithMocksTool.d.ts +1 -1
  123. package/build/tools/enrichTestWithMocksTool.js +9 -5
  124. package/build/tools/executeSkyrampTestTool.d.ts +118 -48
  125. package/build/tools/executeSkyrampTestTool.js +998 -372
  126. package/build/tools/execution-video-state.js +1 -1
  127. package/build/tools/fixErrorTool.js +5 -6
  128. package/build/tools/generate-tests/batchMockGenerationTool.js +1 -1
  129. package/build/tools/generate-tests/generateBatchScenarioRestTool.js +114 -73
  130. package/build/tools/generate-tests/generateContractRestTool.js +34 -16
  131. package/build/tools/generate-tests/generateE2ERestTool.d.ts +1 -0
  132. package/build/tools/generate-tests/generateE2ERestTool.js +9 -1
  133. package/build/tools/generate-tests/generateIntegrationRestTool.js +22 -7
  134. package/build/tools/generate-tests/generateMockRestTool.js +3 -1
  135. package/build/tools/generate-tests/generateUIRestTool.d.ts +2 -0
  136. package/build/tools/generate-tests/generateUIRestTool.js +11 -2
  137. package/build/tools/generate-tests/loadTestSchema.js +1 -3
  138. package/build/tools/generate-tests/planGuard.js +6 -3
  139. package/build/tools/generate-tests/scenarioFileIdentity.js +4 -1
  140. package/build/tools/generate-tests/scenarioLint.js +17 -5
  141. package/build/tools/generate-tests/trace-reuse-guard.js +5 -2
  142. package/build/tools/generateEnrichedIntegrationTestTool.js +9 -3
  143. package/build/tools/one-click/oneClickTool.js +3 -1
  144. package/build/tools/preflightMockCheckTool.js +23 -7
  145. package/build/tools/submitReportTool.d.ts +51 -12
  146. package/build/tools/submitReportTool.js +988 -161
  147. package/build/tools/test-management/actionsTool.js +241 -51
  148. package/build/tools/test-management/analyzeChangesTool.d.ts +8 -9
  149. package/build/tools/test-management/analyzeChangesTool.js +127 -68
  150. package/build/tools/test-management/analyzeTestHealthTool.d.ts +0 -11
  151. package/build/tools/test-management/analyzeTestHealthTool.js +42 -76
  152. package/build/tools/test-management/registerTestPlanTool.d.ts +44 -34
  153. package/build/tools/test-management/registerTestPlanTool.js +255 -111
  154. package/build/tools/test-management/resolveScreenTool.js +33 -9
  155. package/build/tools/test-management/testsOwedBeforeRun.d.ts +28 -0
  156. package/build/tools/test-management/testsOwedBeforeRun.js +53 -0
  157. package/build/tools/trace/startTraceCollectionTool.js +3 -1
  158. package/build/tools/trace/stopTraceCollectionTool.js +42 -6
  159. package/build/tools/verifyTestDependenciesTool.d.ts +3 -0
  160. package/build/tools/verifyTestDependenciesTool.js +54 -0
  161. package/build/tools/workspace/initScanWorkspaceTool.js +9 -3
  162. package/build/tools/workspace/initializeWorkspaceTool.js +3 -1
  163. package/build/types/AssertionOutcome.d.ts +1 -1
  164. package/build/types/EnhanceType.d.ts +6 -0
  165. package/build/types/EnhanceType.js +1 -0
  166. package/build/types/RepositoryAnalysis.d.ts +32 -72
  167. package/build/types/ReuseOutcome.d.ts +100 -7
  168. package/build/types/ReuseOutcome.js +16 -0
  169. package/build/types/StepMethod.js +20 -6
  170. package/build/types/TestAnalysis.d.ts +10 -2
  171. package/build/types/TestExecution.d.ts +45 -0
  172. package/build/types/TestRecommendation.d.ts +1 -1
  173. package/build/types/TestRecommendation.js +4 -1
  174. package/build/types/TestTypes.d.ts +16 -0
  175. package/build/types/TestTypes.js +40 -3
  176. package/build/types/TestbotPromptOptions.d.ts +9 -1
  177. package/build/types/TestbotReport.d.ts +45 -9
  178. package/build/utils/AnalysisStateManager.d.ts +137 -34
  179. package/build/utils/AnalysisStateManager.js +228 -44
  180. package/build/utils/assertion-verify/api-shared-lints.js +34 -16
  181. package/build/utils/assertion-verify/metrics.js +39 -6
  182. package/build/utils/assertion-verify/ui-lints.js +4 -2
  183. package/build/utils/branchDiff.js +47 -12
  184. package/build/utils/canonicalJson.js +3 -1
  185. package/build/utils/connectionErrors.d.ts +10 -0
  186. package/build/utils/connectionErrors.js +10 -0
  187. package/build/utils/dartRouteExtractor.js +36 -7
  188. package/build/utils/fixAttempts.d.ts +26 -0
  189. package/build/utils/fixAttempts.js +109 -0
  190. package/build/utils/frontendSelectors.js +23 -4
  191. package/build/utils/generatedTestRecord.d.ts +19 -0
  192. package/build/utils/generatedTestRecord.js +61 -0
  193. package/build/utils/gitStaging.js +7 -2
  194. package/build/utils/initAgent.js +26 -6
  195. package/build/utils/language-helper.js +60 -45
  196. package/build/utils/pathMatching.js +2 -1
  197. package/build/utils/pathSignatures.js +6 -2
  198. package/build/utils/planMatchKeys.d.ts +2 -2
  199. package/build/utils/planMatchKeys.js +20 -14
  200. package/build/utils/pom-catalog-parse.js +7 -2
  201. package/build/utils/pom-scope/import-expansion.js +6 -1
  202. package/build/utils/pom-scope/index.js +50 -12
  203. package/build/utils/pom-scope/scoring.js +13 -3
  204. package/build/utils/pom-scope/selector-extractor.js +16 -3
  205. package/build/utils/pom-scope/strip.d.ts +8 -0
  206. package/build/utils/pom-scope/strip.js +238 -0
  207. package/build/utils/pom-scope/testIdDiscovery.js +14 -2
  208. package/build/utils/pom-verify/__fixtures__/af-style/asset-list.page.d.ts +1 -1
  209. package/build/utils/pom-verify/__fixtures__/af-style/asset-list.page.js +4 -2
  210. package/build/utils/pom-verify/__fixtures__/af-style/report.iframe.page.js +3 -1
  211. package/build/utils/pom-verify/__fixtures__/af-style/workflow-footer.page.js +3 -1
  212. package/build/utils/pom-verify/bindings.js +5 -1
  213. package/build/utils/pom-verify/calls.js +9 -2
  214. package/build/utils/pom-verify/verify.js +27 -5
  215. package/build/utils/pr-comment-parser.js +20 -7
  216. package/build/utils/progress.d.ts +1 -1
  217. package/build/utils/progress.js +1 -1
  218. package/build/utils/proxy-terminal.d.ts +19 -1
  219. package/build/utils/proxy-terminal.js +346 -21
  220. package/build/utils/rebaselineSnapshots.d.ts +1 -1
  221. package/build/utils/rebaselineSnapshots.js +6 -16
  222. package/build/utils/removedUiElements.js +1 -1
  223. package/build/utils/reportLanguage.js +35 -7
  224. package/build/utils/reportVerification.d.ts +14 -8
  225. package/build/utils/reportVerification.js +19 -19
  226. package/build/utils/repositorySlug.d.ts +32 -0
  227. package/build/utils/repositorySlug.js +77 -0
  228. package/build/utils/reuseRouting.d.ts +10 -0
  229. package/build/utils/reuseRouting.js +21 -2
  230. package/build/utils/runContextGauge.d.ts +27 -0
  231. package/build/utils/runContextGauge.js +181 -0
  232. package/build/utils/runSerialized.d.ts +3 -0
  233. package/build/utils/runSerialized.js +39 -0
  234. package/build/utils/screenRoutes.js +74 -18
  235. package/build/utils/skyrampMdContent.d.ts +1 -1
  236. package/build/utils/skyrampMdContent.js +1 -1
  237. package/build/utils/skyrampSdkVersion.d.ts +9 -0
  238. package/build/utils/skyrampSdkVersion.js +16 -0
  239. package/build/utils/sourceRouteExtractor.js +13 -6
  240. package/build/utils/telemetry.d.ts +1 -0
  241. package/build/utils/telemetry.js +8 -5
  242. package/build/utils/testDependencyPolicy.d.ts +9 -0
  243. package/build/utils/testDependencyPolicy.js +809 -0
  244. package/build/utils/testExecutionRecord.d.ts +94 -0
  245. package/build/utils/testExecutionRecord.js +269 -0
  246. package/build/utils/testFileClassification.d.ts +8 -0
  247. package/build/utils/testFileClassification.js +39 -4
  248. package/build/utils/trace-parser.js +62 -14
  249. package/build/utils/urlPath.js +3 -1
  250. package/build/utils/utils-verify/action-key.d.ts +46 -0
  251. package/build/utils/utils-verify/action-key.js +120 -38
  252. package/build/utils/utils-verify/action-sites.d.ts +32 -0
  253. package/build/utils/utils-verify/action-sites.js +202 -0
  254. package/build/utils/utils-verify/allow.d.ts +122 -3
  255. package/build/utils/utils-verify/allow.js +146 -21
  256. package/build/utils/utils-verify/body-reach.d.ts +120 -0
  257. package/build/utils/utils-verify/body-reach.js +333 -0
  258. package/build/utils/utils-verify/call-sites.d.ts +31 -7
  259. package/build/utils/utils-verify/call-sites.js +80 -13
  260. package/build/utils/utils-verify/delivered-imports.d.ts +43 -0
  261. package/build/utils/utils-verify/delivered-imports.js +84 -0
  262. package/build/utils/utils-verify/fixed-sleep.d.ts +96 -0
  263. package/build/utils/utils-verify/fixed-sleep.js +461 -0
  264. package/build/utils/utils-verify/in-house.d.ts +93 -0
  265. package/build/utils/utils-verify/in-house.js +719 -0
  266. package/build/utils/utils-verify/incumbent.d.ts +3 -0
  267. package/build/utils/utils-verify/incumbent.js +75 -0
  268. package/build/utils/utils-verify/index.d.ts +2 -0
  269. package/build/utils/utils-verify/index.js +2 -0
  270. package/build/utils/utils-verify/language-spec.d.ts +51 -10
  271. package/build/utils/utils-verify/language-spec.js +232 -21
  272. package/build/utils/utils-verify/locate.d.ts +26 -0
  273. package/build/utils/utils-verify/locate.js +125 -23
  274. package/build/utils/utils-verify/module-name.d.ts +40 -0
  275. package/build/utils/utils-verify/module-name.js +98 -0
  276. package/build/utils/utils-verify/parse.d.ts +56 -7
  277. package/build/utils/utils-verify/parse.js +195 -40
  278. package/build/utils/utils-verify/retrofit-equivalence.d.ts +5 -0
  279. package/build/utils/utils-verify/retrofit-equivalence.js +4 -2
  280. package/build/utils/utils-verify/stage.d.ts +5 -0
  281. package/build/utils/utils-verify/stage.js +47 -2
  282. package/build/utils/utils-verify/status-once.d.ts +62 -0
  283. package/build/utils/utils-verify/status-once.js +207 -0
  284. package/build/utils/utils-verify/typecheck.d.ts +61 -0
  285. package/build/utils/utils-verify/typecheck.js +338 -0
  286. package/build/utils/utils-verify/verify.d.ts +79 -3
  287. package/build/utils/utils-verify/verify.js +531 -61
  288. package/build/utils/versions.d.ts +3 -3
  289. package/build/utils/versions.js +1 -1
  290. package/build/utils/workspaceAuth.js +107 -37
  291. package/build/workspace/queryParamResolution.js +11 -4
  292. package/build/workspace/workspace.d.ts +72 -52
  293. package/build/workspace/workspace.js +19 -15
  294. package/node_modules/playwright/ThirdPartyNotices.txt +19 -19
  295. package/node_modules/playwright/lib/mcp/skyramp/assertTool.js +8 -2
  296. package/node_modules/playwright/lib/mcp/skyramp/common/cssValue.js +87 -0
  297. package/node_modules/playwright/lib/mcp/skyramp/loadTraceTool.js +31 -0
  298. package/node_modules/playwright/lib/mcp/skyramp/skyRampImport.js +3 -0
  299. package/node_modules/playwright/lib/mcp/skyramp/traceRecordingBackend.js +181 -15
  300. package/node_modules/playwright/lib/mcp/test/skyRampExport.js +24 -0
  301. package/node_modules/playwright/lib/transform/babelBundleImpl.js +2353 -190
  302. package/node_modules/playwright/node_modules/playwright-core/ThirdPartyNotices.txt +62 -34
  303. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/.package-lock.json +72 -41
  304. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/@hono/node-server/dist/serve-static.js +1 -1
  305. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/@hono/node-server/dist/serve-static.mjs +1 -1
  306. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/@hono/node-server/package.json +2 -2
  307. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/README.md +16 -1
  308. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/index.js +4 -20
  309. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/lib/read.js +17 -17
  310. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/lib/types/json.js +60 -32
  311. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/lib/types/raw.js +3 -3
  312. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/lib/types/text.js +3 -3
  313. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/lib/types/urlencoded.js +16 -20
  314. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/lib/utils.js +18 -16
  315. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/node_modules/content-type/LICENSE +22 -0
  316. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/node_modules/content-type/README.md +71 -0
  317. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/node_modules/content-type/dist/index.d.ts +46 -0
  318. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/node_modules/content-type/dist/index.js +176 -0
  319. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/node_modules/content-type/dist/index.js.map +1 -0
  320. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/node_modules/content-type/package.json +52 -0
  321. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/package.json +23 -10
  322. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/es-object-atoms/CHANGELOG.md +21 -14
  323. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/es-object-atoms/isObject.d.ts +1 -1
  324. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/es-object-atoms/package.json +6 -7
  325. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/es-object-atoms/tsconfig.json +1 -0
  326. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/index.js +266 -45
  327. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/lib/schemes.js +9 -4
  328. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/lib/utils.js +396 -92
  329. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/package.json +1 -1
  330. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/component-safe-serialization.test.js +163 -0
  331. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/equal.test.js +31 -3
  332. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/fixtures/uri-js-parse.json +2 -0
  333. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/ipv6-canonical.test.js +34 -0
  334. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/ipv6-validation.test.js +124 -0
  335. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/malformed-percent.test.js +77 -0
  336. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/malformed-urn.test.js +61 -0
  337. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/parse.test.js +7 -3
  338. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/query-fragment-normalization.test.js +33 -0
  339. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/reserved-path-normalization.test.js +109 -0
  340. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/scheme-validation.test.js +124 -0
  341. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/security-normalization.test.js +101 -0
  342. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/security.test.js +301 -3
  343. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/urn-full-input.test.js +29 -0
  344. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/websocket-query-preservation.test.js +24 -0
  345. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hasown/CHANGELOG.md +7 -0
  346. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hasown/index.d.ts +0 -1
  347. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hasown/package.json +4 -5
  348. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/client/client.js +30 -16
  349. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/client/utils.js +4 -1
  350. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/context.js +32 -13
  351. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/accepts/accepts.js +36 -2
  352. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/proxy/index.js +4 -0
  353. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/ssg/ssg.js +1 -1
  354. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/ssg/utils.js +30 -10
  355. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/streaming/sse.js +5 -4
  356. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/hono-base.js +10 -8
  357. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/base.js +44 -23
  358. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/components.js +25 -26
  359. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/context.js +5 -5
  360. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/dom/render.js +2 -0
  361. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/dom/server.js +5 -1
  362. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/hooks/index.js +16 -13
  363. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/intrinsic-element/components.js +3 -3
  364. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/streaming.js +4 -5
  365. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/cache/index.js +103 -8
  366. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/compress/index.js +5 -0
  367. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/cors/index.js +17 -14
  368. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/csrf/index.js +1 -1
  369. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/etag/digest.js +47 -1
  370. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/etag/index.js +7 -4
  371. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/jwk/jwk.js +9 -4
  372. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/jwt/jwt.js +9 -4
  373. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/language/language.js +10 -6
  374. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/method-not-allowed/index.js +90 -0
  375. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/pretty-json/index.js +3 -1
  376. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/secure-headers/secure-headers.js +16 -7
  377. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/request.js +20 -13
  378. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/linear-router/router.js +7 -2
  379. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/pattern-router/router.js +3 -9
  380. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/reg-exp-router/node.js +65 -59
  381. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/reg-exp-router/router.js +71 -128
  382. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/reg-exp-router/trie.js +14 -5
  383. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/trie-router/node.js +47 -70
  384. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/trie-router/router.js +3 -11
  385. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/utils.js +27 -0
  386. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router.js +1 -1
  387. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/accept.js +1 -1
  388. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/body.js +21 -3
  389. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/cookie.js +4 -3
  390. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/ipaddr.js +5 -3
  391. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/stream.js +12 -3
  392. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/url.js +19 -11
  393. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/client/client.js +30 -16
  394. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/client/utils.js +4 -1
  395. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/context.js +32 -13
  396. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/accepts/accepts.js +36 -2
  397. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/proxy/index.js +4 -0
  398. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/ssg/ssg.js +1 -1
  399. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/ssg/utils.js +30 -10
  400. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/streaming/sse.js +5 -4
  401. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/hono-base.js +10 -8
  402. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/base.js +41 -23
  403. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/components.js +26 -27
  404. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/context.js +6 -6
  405. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/dom/render.js +2 -0
  406. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/dom/server.js +5 -1
  407. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/hooks/index.js +16 -13
  408. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/intrinsic-element/components.js +4 -4
  409. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/streaming.js +5 -6
  410. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/cache/index.js +103 -8
  411. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/compress/index.js +5 -0
  412. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/cors/index.js +17 -14
  413. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/csrf/index.js +1 -1
  414. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/etag/digest.js +47 -1
  415. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/etag/index.js +7 -4
  416. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/jwk/jwk.js +9 -4
  417. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/jwt/jwt.js +9 -4
  418. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/language/language.js +10 -6
  419. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/method-not-allowed/index.js +68 -0
  420. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/pretty-json/index.js +3 -1
  421. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/secure-headers/secure-headers.js +16 -7
  422. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/request.js +21 -14
  423. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/linear-router/router.js +7 -2
  424. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/pattern-router/router.js +3 -9
  425. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/reg-exp-router/node.js +61 -58
  426. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/reg-exp-router/router.js +77 -129
  427. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/reg-exp-router/trie.js +14 -5
  428. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/trie-router/node.js +47 -70
  429. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/trie-router/router.js +3 -11
  430. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/utils.js +5 -0
  431. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router.js +1 -1
  432. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/adapter/aws-lambda/types.d.ts +9 -0
  433. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/client/types.d.ts +1 -1
  434. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/context.d.ts +6 -2
  435. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/hono-base.d.ts +4 -3
  436. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/base.d.ts +7 -2
  437. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/dom/index.d.ts +5 -5
  438. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/dom/intrinsic-element/components.d.ts +2 -2
  439. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/dom/server.d.ts +5 -5
  440. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/hooks/index.d.ts +8 -6
  441. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/index.d.ts +5 -5
  442. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/cache/index.d.ts +6 -4
  443. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/combine/index.d.ts +1 -1
  444. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/cors/index.d.ts +1 -1
  445. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/jsx-renderer/index.d.ts +2 -2
  446. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/jwk/jwk.d.ts +2 -0
  447. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/jwt/jwt.d.ts +2 -0
  448. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/method-not-allowed/index.d.ts +49 -0
  449. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/secure-headers/permissions-policy.d.ts +3 -3
  450. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/router/reg-exp-router/node.d.ts +4 -1
  451. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/router/reg-exp-router/trie.d.ts +2 -1
  452. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/router/trie-router/node.d.ts +1 -2
  453. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/router/trie-router/router.d.ts +0 -1
  454. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/router/utils.d.ts +1 -0
  455. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/router.d.ts +1 -1
  456. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/utils/headers.d.ts +2 -2
  457. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/utils/url.d.ts +5 -0
  458. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/accept.js +1 -1
  459. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/body.js +21 -3
  460. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/cookie.js +5 -4
  461. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/ipaddr.js +5 -3
  462. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/stream.js +12 -3
  463. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/url.js +17 -10
  464. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/package.json +11 -4
  465. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/README.md +173 -143
  466. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/address-error.d.ts +11 -0
  467. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/address-error.js.map +1 -1
  468. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/common.d.ts +49 -0
  469. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/common.js +79 -4
  470. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/common.js.map +1 -1
  471. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/ipv4.d.ts +78 -5
  472. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/ipv4.js +119 -24
  473. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/ipv4.js.map +1 -1
  474. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/ipv6.d.ts +151 -10
  475. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/ipv6.js +316 -90
  476. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/ipv6.js.map +1 -1
  477. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/v4/constants.d.ts +12 -0
  478. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/v4/constants.js +45 -2
  479. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/v4/constants.js.map +1 -1
  480. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/v6/constants.d.ts +14 -0
  481. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/v6/constants.js +50 -3
  482. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/v6/constants.js.map +1 -1
  483. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/package.json +6 -4
  484. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/.github/THREAT_MODEL.md +3 -3
  485. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/CHANGELOG.md +26 -0
  486. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/README.md +19 -1
  487. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/dist/qs.js +25 -25
  488. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/eslint.config.mjs +1 -1
  489. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/lib/parse.js +16 -6
  490. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/lib/stringify.js +23 -8
  491. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/lib/utils.js +57 -11
  492. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/package.json +8 -7
  493. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/test/parse.js +419 -0
  494. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/test/stringify.js +317 -0
  495. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/test/utils.js +206 -0
  496. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/side-channel/CHANGELOG.md +10 -0
  497. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/side-channel/README.md +1 -1
  498. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/side-channel/index.js +5 -2
  499. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/side-channel/package.json +10 -10
  500. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/side-channel/test/index.js +16 -0
  501. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/index.js +8 -18
  502. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/node_modules/content-type/LICENSE +22 -0
  503. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/node_modules/content-type/README.md +71 -0
  504. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/node_modules/content-type/dist/index.d.ts +46 -0
  505. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/node_modules/content-type/dist/index.js +176 -0
  506. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/node_modules/content-type/dist/index.js.map +1 -0
  507. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/node_modules/content-type/package.json +52 -0
  508. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/package.json +9 -5
  509. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/package-lock.json +72 -41
  510. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/.package-lock.json +6 -6
  511. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/brace-expansion/README.md +23 -1
  512. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/brace-expansion/index.js +265 -86
  513. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/brace-expansion/package.json +1 -1
  514. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/README.md +173 -143
  515. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/address-error.d.ts +11 -0
  516. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/address-error.js.map +1 -1
  517. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/common.d.ts +49 -0
  518. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/common.js +79 -4
  519. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/common.js.map +1 -1
  520. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/ipv4.d.ts +78 -5
  521. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/ipv4.js +119 -24
  522. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/ipv4.js.map +1 -1
  523. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/ipv6.d.ts +151 -10
  524. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/ipv6.js +316 -90
  525. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/ipv6.js.map +1 -1
  526. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/v4/constants.d.ts +12 -0
  527. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/v4/constants.js +45 -2
  528. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/v4/constants.js.map +1 -1
  529. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/v6/constants.d.ts +14 -0
  530. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/v6/constants.js +50 -3
  531. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/v6/constants.js.map +1 -1
  532. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/package.json +6 -4
  533. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/package-lock.json +6 -6
  534. package/node_modules/playwright/node_modules/playwright-core/lib/cli/program.js +18 -9
  535. package/node_modules/playwright/node_modules/playwright-core/lib/mcpBundleImpl/index.js +47 -47
  536. package/node_modules/playwright/node_modules/playwright-core/lib/server/codegen/skyramp/jsonlReader.js +3 -0
  537. package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/recorderRunner.js +42 -0
  538. package/node_modules/playwright/node_modules/playwright-core/lib/utilsBundleImpl/index.js +121 -121
  539. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/{index.B7KbSQcC.js → index.BAkLd5DX.js} +1 -1
  540. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.html +1 -1
  541. package/node_modules/playwright/node_modules/playwright-core/package.json +1 -1
  542. package/node_modules/playwright/node_modules/playwright-core/src/cli/program.ts +31 -9
  543. package/node_modules/playwright/node_modules/playwright-core/src/server/codegen/skyramp/jsonlReader.ts +1 -0
  544. package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/recorderRunner.ts +57 -1
  545. package/node_modules/playwright/package.json +2 -2
  546. package/package.json +7 -6
  547. package/plugin/prompts/code-reuse/hand-off.md +30 -0
  548. package/plugin/prompts/generate-tests/generation.md +1 -1
  549. package/plugin/prompts/plan-tests.md +14 -14
  550. package/plugin/prompts/testbot-task1.md +2 -2
  551. package/plugin/skills/enhance-assertions/SKILL.md +25 -0
  552. package/plugin/skills/enhance-assertions/reference/contract.md +51 -0
  553. package/plugin/skills/enhance-assertions/reference/integration.md +58 -0
  554. package/plugin/skills/enhance-assertions/reference/shared-rules.md +220 -0
  555. package/plugin/skills/enhance-assertions/reference/ui.md +373 -0
  556. package/plugin/skills/fix-test-import-errors/SKILL.md +45 -50
  557. package/plugin/skills/run-test/SKILL.md +16 -0
  558. package/plugin/skills/validate-assertion-alignment-post-execution/SKILL.md +32 -0
  559. package/plugin/skills/validate-assertion-alignment-post-execution/reference/checks.md +44 -0
  560. package/plugin/skills/validate-assertion-alignment-post-execution/reference/evidence.md +47 -0
  561. package/build/adapters/jestAdapter.d.ts +0 -14
  562. package/build/adapters/jestAdapter.js +0 -113
  563. package/build/adapters/mochaAdapter.d.ts +0 -13
  564. package/build/adapters/mochaAdapter.js +0 -87
  565. package/build/adapters/playwrightAdapter.d.ts +0 -17
  566. package/build/adapters/playwrightAdapter.js +0 -182
  567. package/build/adapters/pytestAdapter.d.ts +0 -15
  568. package/build/adapters/pytestAdapter.js +0 -108
  569. package/build/prompts/enhance-assertions/contractProviderAssertionsPrompt.d.ts +0 -2
  570. package/build/prompts/enhance-assertions/contractProviderAssertionsPrompt.js +0 -29
  571. package/build/prompts/enhance-assertions/integrationAssertionsPrompt.d.ts +0 -2
  572. package/build/prompts/enhance-assertions/integrationAssertionsPrompt.js +0 -36
  573. package/build/prompts/enhance-assertions/sharedAssertionRules.d.ts +0 -16
  574. package/build/prompts/enhance-assertions/sharedAssertionRules.js +0 -284
  575. package/build/prompts/enhance-assertions/uiAssertionsPrompt.d.ts +0 -2
  576. package/build/prompts/enhance-assertions/uiAssertionsPrompt.js +0 -388
  577. package/build/tools/runExistingTestsTool.d.ts +0 -138
  578. package/build/tools/runExistingTestsTool.js +0 -644
  579. package/build/types/ExternalTestExecution.d.ts +0 -67
  580. package/build/types/ExternalTestExecution.js +0 -8
  581. package/build/workspace/testSuites.d.ts +0 -20
  582. package/build/workspace/testSuites.js +0 -17
  583. package/node_modules/playwright/node_modules/playwright-core/.DS_Store +0 -0
@@ -14,9 +14,104 @@
14
14
  * values / literal arguments, the helper holds actions + structural waits.
15
15
  */
16
16
  import { isBrowserTestType } from "../utils/reuseRouting.js";
17
+ /**
18
+ * Where a test states the status it expects: ONCE, as the argument of the helper
19
+ * call. The helper asserts it (that is the shared invariant), so the policy has to
20
+ * say what the spec contains after that — left unsaid, the agent left the status
21
+ * behind a defaulted parameter the call omitted, or asserted it a second time on the
22
+ * response the helper returned. Quoted by the prompt and by the two verify findings
23
+ * (`status-default`, `status-restated`) that enforce it, so the sentence the agent
24
+ * reads is the sentence the gate returns.
25
+ */
26
+ export const STATUS_ONCE_RULE = {
27
+ /** Written as the ACTION to take and the helpers it applies to. A first version
28
+ * said the parameter "carries NO default" in the present tense; quoted beside a
29
+ * finding that showed `expected_status=201`, it read as a description that was
30
+ * false about the very line it quoted, and the advisory was acted on 0 of 9 times. */
31
+ noDefault: "Give every helper THIS RUN WRITES its expected status as a required parameter: no default value, not optional. A call site that can omit the status hides the expectation, so every call site passes the status it expects. A helper that already exists at HEAD keeps the signature it has, default included — never remove an incumbent's default, since callers this run cannot see rely on it; a call site this run writes still passes the status explicitly, whether or not the helper would default it. A helper whose status NEVER varies may assert the literal instead of taking a parameter at all: what this rule forbids is a DEFAULT, which lets a call site silently inherit an expectation it never stated, and a pinned literal no caller can vary hides nothing. Give it a parameter the moment a second call site needs a different status. Declare the expected-status parameter BEFORE any parameter that carries a default: Python refuses `def create_product(client, headers, body=DEFAULT_BODY, expected_status)` with `SyntaxError: non-default argument follows default argument`, and a module that does not import takes every test in the file with it at collection.",
32
+ notRestated: "the test body does not assert the status again on the response the helper returns — the helper asserted it, and the call's status argument is the one statement of it",
33
+ };
17
34
  /** Why the assertion rule exists — quoted wherever the rule is stated. */
18
35
  export const SHARED_HELPER_WHY = "A scenario-specific assertion inside a helper carries one scenario's data into a shared function and fails the next scenario that calls it — the helper is shared, the claims are not.";
19
- export const BROWSER_STRUCTURAL_WAITS = '`waitForResponse`, `waitForLoadState`, `waitFor({ state: "visible" })`, and `toBeVisible` on a STRUCTURAL locator (a test id, or a role + name of a control) a check that an element rendered, not what it says';
36
+ /** Playwright matchers that answer "did this element render" — the browser analogue
37
+ * of a structural wait. `.not` forms included: `not.toBeVisible` is the same claim. */
38
+ const BROWSER_PRESENCE_MATCHERS = [
39
+ "toBeVisible",
40
+ "toBeHidden",
41
+ "toBeAttached",
42
+ ];
43
+ /** Matchers that answer what STATE an element is in. Not a structural wait: a button
44
+ * is enabled in one scenario and disabled in the next, so the claim belongs to the
45
+ * scenario and not to the shared step. Playwright's own actionability checks already
46
+ * wait for Enabled before `click()` and for Editable before `fill()`, so a helper
47
+ * loses no readiness by leaving these out. */
48
+ const BROWSER_STATE_MATCHERS = [
49
+ "toBeEnabled",
50
+ "toBeDisabled",
51
+ "toBeEditable",
52
+ "toBeFocused",
53
+ "toBeInViewport",
54
+ ];
55
+ /**
56
+ * ARIA roles whose accessible name is the page's own CONTENT rather than a control's
57
+ * label. A locator built from one of these plus a name selects by what the page SAYS,
58
+ * which is the scenario's data: `getByRole("heading", { name: "Your cart is empty!" })`
59
+ * is the scenario's outcome wearing a structural locator.
60
+ *
61
+ * A DENY-list, not an allow-list. The rule blocks a customer's run, so a role nobody
62
+ * has listed has to pass — an allow-list refused `getByRole("dialog", { name })`, which
63
+ * is an ordinary wait for a named modal and is permitted everywhere else.
64
+ */
65
+ export const CONTENT_ROLES = [
66
+ "heading",
67
+ "paragraph",
68
+ "cell",
69
+ "gridcell",
70
+ "columnheader",
71
+ "rowheader",
72
+ "row",
73
+ "listitem",
74
+ "definition",
75
+ "term",
76
+ "img",
77
+ "figure",
78
+ "article",
79
+ "note",
80
+ "tooltip",
81
+ "alert",
82
+ "log",
83
+ "marquee",
84
+ "timer",
85
+ "blockquote",
86
+ "caption",
87
+ // A row of data, a list entry or a menu entry is named by what it shows.
88
+ "option",
89
+ "menuitem",
90
+ "menuitemcheckbox",
91
+ "menuitemradio",
92
+ "treeitem",
93
+ ];
94
+ const list = (names) => names.map((n) => `\`${n}\``).join(", ");
95
+ /** Spoken once, quoted everywhere. */
96
+ export const BROWSER_ASSERTION_BOUNDARY = `a shared browser helper holds actions and structural waits only — a check that an element RENDERED (${list(BROWSER_PRESENCE_MATCHERS)}, negated or not — \`.not.toBeVisible()\` in TypeScript, \`not_to_be_visible()\` in Python, which has no \`.not\` to chain through) on a STRUCTURAL locator: a test id, a CSS selector, a label, or a role + name — any role EXCEPT one that names the page's own content (${list(CONTENT_ROLES)}), whose name is the scenario's data rather than a label. A check of element STATE (${list(BROWSER_STATE_MATCHERS)}) is a value assertion, not a wait — it says what the element IS, which the next scenario calling the helper may need to be the opposite of, and \`click()\` and \`fill()\` already wait for the element to be enabled and editable. A matcher on a locator that selects by RENDERED TEXT (\`getByText(...)\`, \`filter({ hasText: ... })\`, or a role + name where the role names CONTENT rather than a control, such as \`getByRole("heading", { name: "Your cart is empty!" })\` or \`getByRole("option", { name: "Order deleted" })\`) is a value assertion too, whether or not the text holds a digit. A digit inside a STRUCTURAL selector — \`locator("h1")\`, \`getByTestId("step-2-panel")\`, \`getByLabel("Address line 1")\` — is not scenario data and is permitted. Two exceptions, because a digit THERE is the scenario's own value: a role name that carries one (\`getByRole("button", { name: "Add 2 items" })\`), and a test id built out of a row rather than written as a name (\`getByTestId("order-def@mail.com - 2 items")\`). The verify pass reports only the locator forms it can recognise as text-selecting, so a locator it does not know passes — write to the rule, not to what the check happens to catch`;
97
+ export const HELPER_ASSERTION_POLICIES = {
98
+ api: {
99
+ permittedMatchers: [],
100
+ refusedMatchers: [],
101
+ boundary: "a shared API helper asserts only the status code; move this assertion to the test body, applied to the response the helper returns",
102
+ },
103
+ browser: {
104
+ permittedMatchers: BROWSER_PRESENCE_MATCHERS,
105
+ refusedMatchers: BROWSER_STATE_MATCHERS,
106
+ boundary: BROWSER_ASSERTION_BOUNDARY,
107
+ },
108
+ };
109
+ /** The WAIT FORMS a shared browser helper may use. It deliberately stops short of
110
+ * what a structural locator is: the boundary states that, once, and this clause is
111
+ * rendered beside it. A second summary of the locator rule was a second rule to keep
112
+ * equal, and it fell behind the boundary the first time the boundary gained an
113
+ * exception. */
114
+ export const BROWSER_STRUCTURAL_WAITS = `\`waitForResponse\`, \`waitForLoadState\`, \`waitFor({ state: "visible" })\`, and ${list(BROWSER_PRESENCE_MATCHERS)} on a STRUCTURAL locator as the boundary below defines one — a check that an element rendered, not what it says or what state it is in`;
20
115
  /**
21
116
  * Relocation never reorders execution. Two variants, because the two ends of the
22
117
  * chain may do different things with a helper whose value assertion sits BETWEEN
@@ -25,15 +120,44 @@ export const BROWSER_STRUCTURAL_WAITS = '`waitForResponse`, `waitForLoadState`,
25
120
  */
26
121
  export const ASSERTION_BOUNDARY_RULE_EXTRACT = "Relocation must preserve the original order: an assertion that sits BETWEEN two actions is a HELPER BOUNDARY — end the helper before it and start the next helper after it (each named per the naming rule), so the assertion sits between the two calls in the test body exactly where it was. Never move an assertion across an action.";
27
122
  export const ASSERTION_BOUNDARY_RULE_MOVE = "Relocation must preserve the original order: only a TRAILING assertion (after the helper's last action) may move to the test body right after the call. A helper whose excluded assertion sits BETWEEN two actions is NOT moved and NOT split — leave it local in the test file; splitting is modularization's job, not this step's.";
28
- export const BROWSER_VALUE_ASSERTIONS = 'any `expect` whose matcher OR locator carries scenario data: `toHaveText`, `toContainText`, `toHaveValue`, `toHaveCount`, `toHaveURL` with a literal, or ANY matcher — `toBeVisible` included — on a locator that embeds scenario text such as `getByText("Total: $899.98")`';
123
+ export const BROWSER_VALUE_ASSERTIONS = `any \`expect\` whose matcher OR locator carries scenario data: \`toHaveText\`, \`toContainText\`, \`toHaveValue\`, \`toHaveCount\`, \`toHaveURL\` with a literal, every element-STATE matcher (${list(BROWSER_STATE_MATCHERS)}), or ANY matcher — \`toBeVisible\` included — on a locator that selects by rendered text, such as \`getByText("Total: $899.98")\`, \`getByText("Order deleted")\` or \`getByRole("heading", { name: "Your cart is empty!" })\``;
29
124
  const BROWSER_LIFTABLE = "fill values, option labels, or literal arguments";
30
- const API_LIFTABLE = "body literals, `data_override` values, or expected status";
125
+ const BROWSER_SAME_STEP = "the SAME action sequence (same Playwright primitives in the same order, selectors identical)";
126
+ const BROWSER_BODY_SHAPE_RULE = `**A BROWSER HELPER HAS NO REQUEST BODY, SO IT HAS NOTHING ELSE TO LIFT.** What it sends is the sequence of fills and clicks it performs, and every value in that sequence is already a liftable difference under the rule above (${BROWSER_LIFTABLE}). There is no second thing the helper holds that a caller might need to replace, so the body rule the API helpers carry has no counterpart here.`;
127
+ const API_LIFTABLE = "the request body (literals inside it, or the body as a whole), the query parameters it sends, `data_override` values, or expected status";
128
+ const API_BODY_SHAPE_RULE = `**WHAT A CALLER NEEDS TO CHANGE ABOUT THE REQUEST BODY MUST BE REACHABLE FROM THE HELPER'S SIGNATURE.** A helper is shared, and the next caller of the same method+path rarely sends the same body. Whatever a caller needs to change is a PARAMETER, defaulted to what the helper sends today so existing call sites stay valid unchanged. Two forms are acceptable; take the FIRST one that reaches everything the callers need:
129
+ 1. **One parameter per differing value, applied through \`data_override\`** — each defaulted to the literal the helper sends today, applied through the request's \`data_override\` map rather than edited into the body string. Use it whenever every caller's body differs only in the VALUE at a path the generated body already carries. It is the additive form: a caller passes only what it changes, and the body string stays as generated.
130
+ 2. **One parameter carrying the whole body** — defaulted to the body the helper sends today and passed straight to the request. Python: \`def update_order(client, headers, order_id, body=DEFAULT_ORDER_BODY)\` calling \`send_request(..., body=body)\`; TypeScript/JavaScript: \`updateOrder(client, orderId, body = DEFAULT_ORDER_BODY)\` calling \`sendRequest({ ..., body })\`. Use it when a caller needs a body \`data_override\` cannot express: a field the generated body does not carry, a field left out, or a different array shape.
131
+
132
+ A module-level constant is the right home for that default, because the parameter falls back to it and any caller can pass another body instead.
133
+
134
+ **TAKE ONE FORM, NEVER BOTH.** A helper that carries a whole-body parameter AND a general override parameter passed straight to the request reaches the same body twice: the body parameter already reaches every property the override could, so the second one changes nothing the first cannot, and nothing decides whether to write it. That is how one run wrote \`create_order(client, headers, expected_status, body=DEFAULT_ORDER_BODY, data_override=None)\` and the next wrote the same helper for the same route without the override. One mechanism per helper. (An override that BUILDS a map out of named parameters — \`data_override={"name": unique_suffix(name)}\` — is form 1 working, and is not this.)
135
+
136
+ **CHANGE FORM WHEN THE CALLERS OUTGROW IT.** Form 1 reaches the values the generated body already carries and nothing else. The moment a caller needs a body form 1 cannot reach, move to form 2. The shapes named above are the ones seen so far, not the whole set — judge by whether the caller can be carried, not by whether it matches one of them. Leaving it on form 1 is what sends that caller off to write its own helper for the same method+path, which is the duplication this file exists to remove, re-created one directory away.
137
+
138
+ **A BODY NO PARAMETER REACHES AT ALL IS NEVER ACCEPTABLE.** That includes a module-level constant the helper reads DIRECTLY, with no parameter standing in front of it: it is one body, and no caller can send another. Put the current body in the parameter's default, never in a value the parameter cannot stand in for.`;
139
+ /**
140
+ * TypeScript only in effect (Python passes keyword arguments; there is no options
141
+ * object to build). The SDK types `sendRequest`'s argument, and a value built as a
142
+ * record has lost that type by the time it is passed: `TS2345 … missing url, path,
143
+ * method from SendRequestV2Options`. The executor transpiles without typechecking, so
144
+ * the run reports success and the customer's own `tsc` is the first to see it. The
145
+ * verify pass now compiles the delivered files; this is the same rule where the
146
+ * helper is authored, so it is written right the first time.
147
+ */
148
+ const API_OPTIONS_SHAPE_RULE = `**THE REQUEST OPTIONS ARE ONE OBJECT LITERAL, WRITTEN AT THE CALL.** TypeScript/JavaScript: pass \`sendRequest\` a single object literal — \`client.sendRequest({ url, path, method, headers, queryParams: query })\` — with every optional field written INLINE. A query that some callers send and others do not is a parameter defaulted to an empty map — \`query = {}\` in JavaScript; in TypeScript typed by what \`sendRequest\`'s \`queryParams\` accepts (a map of \`string | number | boolean | object | null\`, so \`query: Record<string, string | string[]> = {}\` where a key may repeat); an empty map is the same request as sending none — and passed as \`queryParams: query\`; a field that must be genuinely absent is a conditional spread inside the literal (\`...(filter ? { queryParams: { filter } } : {})\`). NEVER declare the options as \`Record<string, unknown>\` (or an untyped \`{}\`) and add fields to it afterwards: the record has no \`url\`, \`path\` or \`method\` the compiler can see, so \`sendRequest(options)\` fails the customer's typecheck even though the executor runs it. TypeScript only, the same discipline applies to every parameter's type: annotate each with the type the SDK call accepts (\`client: SkyrampClient\`, \`headers: Record<string, string>\`, a path or query value as \`string | number\`) — never \`unknown\`, which is assignable to nothing but itself and fails at its first use, and never \`any\`.`;
31
149
  const API_ASSERTION_MERGE_LINE = `a merged helper asserts ONLY the status code. If either version carries response-body assertions, relocate them to that version's test body (applied to the returned response) before merging. ${SHARED_HELPER_WHY}`;
32
150
  // (API helpers are one request + trailing assertions, so the move variant's
33
151
  // between-actions case does not arise; API_HELPERS.moveRule is empty.)
34
152
  function oneHelperLine(fileName, unit) {
35
153
  return `One ${unit} = one helper in \`${fileName}\`.`;
36
154
  }
155
+ /**
156
+ * What qualifies as a browser reuse target — stated once, read by the page-object
157
+ * prompt and by the in-house search on the shared-module path, so the two cannot
158
+ * disagree about which of the customer's modules the run may call.
159
+ */
160
+ export const SELECTOR_OWNING_MODULE_RULE = `**A reuse target does not have to be a class.** Selector-owning helper libraries qualify — modules exporting free functions like \`bookFirstEvent(page)\` whose bodies contain the selector literals. A helper module qualifies only if its functions OWN selectors; a module whose functions take selectors as parameters (generic interaction utilities) owns nothing and is not a reuse target. Playwright fixture factories wired into the repo's own \`test\` object (\`test.extend\`-style) are NOT substitutable either — using them requires replacing the Skyramp runtime imports, which is forbidden.`;
37
161
  /**
38
162
  * A helper kept local must never share a name with a utils export — the import
39
163
  * and the local definition would then describe two different behaviours under
@@ -46,7 +170,7 @@ export const API_HELPERS = {
46
170
  liftableLiterals: API_LIFTABLE,
47
171
  structuralNoise: "",
48
172
  namingRule: "**NAME** each helper by method + resource ONLY, written in the naming convention of the language it is emitted in — Python `create_product`, `update_order`, `get_order`, `get_orders_list`; TypeScript/JavaScript `createProduct`, `updateOrder`, `getOrder`, `getOrdersList`. Match the surrounding test file: snake_case helpers in a camelCase TS suite read as foreign code the repo did not write. Scenario adjectives in names are FORBIDDEN (`create_discount_test_product`, `updateOrder50Discount`) — other tests define the same step, and a shared utils file can hold only one canonical name per step. Scenario data belongs in ARGUMENTS, never in the name.",
49
- assertionRule: `**THE ONLY ASSERTION INSIDE A SHARED HELPER IS THE STATUS CODE**, written in the test's own assertion syntax (Python \`assert response.status_code == expected_status\`; TypeScript/JavaScript \`expect(response.status).toBe(expectedStatus)\`), with the expected status a parameter defaulted to this scenario's expected code. EVERY response-body assertion (echo-backs, computed totals, field checks) stays in the test body, applied to the response the helper returns. ${SHARED_HELPER_WHY}`,
173
+ assertionRule: `**THE ONLY ASSERTION INSIDE A SHARED HELPER IS THE STATUS CODE**, written in the test's own assertion syntax (Python \`assert response.status_code == expected_status\`; TypeScript/JavaScript \`expect(response.status).toBe(expectedStatus)\`). ${STATUS_ONCE_RULE.noDefault} (\`create_order(client, headers, body, 201)\`, never \`expected_status=201\` in a signature this run writes — a helper named for the happy path that defaults to a rejection reads as a bug on sight, and \`None\` is a default too.) In turn, ${STATUS_ONCE_RULE.notRestated}. EVERY response-body assertion (echo-backs, computed totals, field checks) stays in the test body, applied to the response the helper returns. ${SHARED_HELPER_WHY}`,
50
174
  relocationTarget: "the test body, applied to the response the helper returns",
51
175
  moveRule: "",
52
176
  namingExample: "E.g. `update_order` (Python) / `updateOrder` (TypeScript), not `update_order_discount` or `updateOrder50Discount`.",
@@ -54,6 +178,21 @@ export const API_HELPERS = {
54
178
  // The API section below carries its own worked example; the generic
55
179
  // Playwright one would teach intent-naming and locator merges to a Python prompt.
56
180
  nearDupExample: () => "",
181
+ bodyShapeRule: API_BODY_SHAPE_RULE,
182
+ optionsShapeRule: API_OPTIONS_SHAPE_RULE,
183
+ inlineSite: {
184
+ noun: "inline request block",
185
+ nouns: "Inline request blocks",
186
+ unit: "block",
187
+ stepNoun: "request step",
188
+ extendClause: " — or, for API request helpers, by EXTENDING them with defaulted parameters as the rules below allow",
189
+ match: (fileName) => `whose method+path matches a helper now defined in \`${fileName}\``,
190
+ target: (fileName) => `CALLS TO \`${fileName}\``,
191
+ lift: (fileName) => `lift a literal the helper lacks to a defaulted parameter in \`${fileName}\``,
192
+ keeps: "its other steps, assertions and order stay verbatim",
193
+ afterSteps: "",
194
+ },
195
+ inlineCallSiteRule: `**INLINE REQUEST BLOCKS ARE CALL SITES, NOT HELPERS.** A request step written inline — one \`client.send_request(...)\` / \`client.sendRequest(...)\` call plus its status-code assertion, not wrapped in a function — is never something to move or author a helper from. But when a helper for the SAME method+path already exists, the block is that helper's near-duplicate (judge it by the API near-duplicate criteria in STEP 4b: same method+path and call structure; differences limited to ${API_LIFTABLE}): REPLACE the block with a call to the helper, passing the block's own literals as arguments — the status its assertion expected becomes the call's status argument, and that assertion is DELETED, not kept beside the call (the helper asserts it) — and lift anything the helper does not yet take — the block's BODY and the query parameters it sends included, not only the scalars inside them — to a parameter DEFAULTED to the helper's current value, so every existing call site sends what it sent before. The expected status is the one exception to that default: a helper that pins a literal status lifts it to a parameter with NO default, and every existing call site of that helper is updated to pass the literal it pinned. KEEP the block's response variable — \`<same variable> = <helper>(...)\` — so the assertions that read it afterwards are unchanged. A value the block wraps in \`uniqueSuffix(...)\` or routes through \`data_override\` where the helper uses a plain literal (or vice versa) is a LITERAL difference, not a structural one — pass the expression as the argument. A block whose request differs structurally (extra step, different method or path) stays as it is.`,
57
196
  // API request helpers are one SDK call + assertions, so near-duplicate
58
197
  // equivalence is judged by method+path, not Playwright primitives — and the
59
198
  // SDK's data_override makes literal-lifting mechanical, which is why this
@@ -65,25 +204,30 @@ For helpers that wrap one SDK request call (e.g. \`client.send_request(...)\`),
65
204
 
66
205
  1. **Same method and same path** (path parameters count as the same path).
67
206
  2. **Same call structure** — same request-call shape; no extra steps in one but not the other.
68
- 3. **Differences are limited to**: literals inside the request-body string, values in \`data_override\`, the expected status code, or which values are lifted to parameters.
207
+ 3. **Differences are limited to**: the request body — literals inside it, or the body as a whole — the query parameters it sends, values in \`data_override\`, the expected status code, or which values are lifted to parameters.
69
208
 
70
- Merge procedure for an API near-duplicate pair — these rules OVERRIDE the generic procedure below on two points: body literals ARE liftable differences (via \`data_override\`), and defaults are REQUIRED (the generic "no defaults" rule applies to Playwright helpers only):
209
+ Merge procedure for an API near-duplicate pair — these rules OVERRIDE the generic procedure below on two points: what the request SENDS — its body and its query IS a liftable difference, and defaults are REQUIRED for every lifted value except the expected status (the generic "no defaults" rule applies to Playwright helpers only; the expected status is the one API parameter that never has one):
71
210
  - **Name**: method + resource only (\`create_product\`, \`update_order\`) — never a scenario adjective.
72
211
  - **Lift each differing body literal into a parameter applied via \`data_override\`, with the parameter's DEFAULT set to the literal the incumbent version used.** Defaults make the merge additive: every existing call site keeps its behavior without edits; only the other test passes its values explicitly.
73
- - **Union the parameter lists**; a parameter one version lacked gets the default from that version's literal. A differing expected status lifts the same way: \`expected_status\` parameter, default from the incumbent.
212
+ - **Union the parameter lists**; a parameter one version lacked gets the default from that version's literal. The expected status is the exception. ${STATUS_ONCE_RULE.noDefault} Merging two versions this run wrote that expected different statuses means each call site passes its own — and a call site's own status assertion, if it wrote one beside the call, is deleted (${STATUS_ONCE_RULE.notRestated}).
213
+ - **A differing query lifts the same way**: the query map is a parameter, defaulted to the map the incumbent sends — an EMPTY map where it sends none, which is the same request, so a helper that omits the query keeps omitting it for every existing caller. Where both versions send the same keys and only the values differ, one parameter per differing value is enough.
74
214
  - **Assertions**: ${API_ASSERTION_MERGE_LINE}
75
- - Structural differences (different items-array shape, extra request) → NOT near-duplicates; leave them alone.
215
+ - Structural differences (an extra request, a different method or path, an extra step) → NOT near-duplicates; leave them alone. What the request SENDS is not structure, whatever form the difference takes: a body that differs is a body difference, and a query that differs is a query difference. A parameter carries each of them; a second helper carries neither.
216
+
217
+ ${API_BODY_SHAPE_RULE}
76
218
 
77
- Worked example: \`update_order_discount(client, headers, order_id, product_id)\` with \`"discount_percent": 25\` in the body, and \`update_order_50_discount(client, headers, order_id, product_id, quantity)\` with \`"discount_percent": 50\` → ONE helper \`update_order(client, headers, order_id, product_id, discount_percent=25, quantity=2)\` that applies \`discount_percent\` and \`quantity\` via \`data_override\`. ${oneHelperLine(fileName, "method+path")}
219
+ ${API_OPTIONS_SHAPE_RULE}
220
+
221
+ Worked example: \`update_order_discount(client, headers, order_id, product_id)\` with \`"discount_percent": 25\` in the body, and \`update_order_50_discount(client, headers, order_id, product_id, quantity)\` with \`"discount_percent": 50\` → ONE helper \`update_order(client, headers, order_id, product_id, expected_status, discount_percent=25, quantity=2)\` that applies \`discount_percent\` and \`quantity\` via \`data_override\` — the expected status required and declared before the defaulted parameters, per the assertion rule above. ${oneHelperLine(fileName, "method+path")}
78
222
  `,
79
223
  };
80
224
  export const BROWSER_HELPERS = {
81
225
  kind: "browser",
82
- sameStep: "the SAME action sequence (same Playwright primitives in the same order, selectors identical)",
226
+ sameStep: BROWSER_SAME_STEP,
83
227
  liftableLiterals: BROWSER_LIFTABLE,
84
- structuralNoise: "`waitForTimeout(...)` lines and the `getValue(playwrightRequestN, ...)` value wrapper around a fill are RECORDER NOISE, not structure — two bodies that differ only by them perform the same step, so merge them; keep the body WITHOUT the `waitForTimeout` lines. A fixed sleep is not a structural wait: it is the one line of the pair that carries no meaning, and in a shared helper every importer pays it on every run. Where a step genuinely needs to wait, wait on the element the next line touches (`toBeVisible`, `toBeEnabled`)",
228
+ structuralNoise: '`waitForTimeout(...)` lines and the `getValue(playwrightRequestN, ...)` value wrapper around a fill are RECORDER NOISE, not structure — two bodies that differ only by them perform the same step, so merge them; keep the body WITHOUT the `waitForTimeout` lines. A fixed sleep is not a structural wait: it is the one line of the pair that carries no meaning, and in a shared helper every importer pays it on every run. Where a step genuinely needs to wait, wait on the element the next line touches (`toBeVisible`, or `waitFor({ state: "visible" })`) — never on its state (`toBeEnabled`), which is a scenario\'s claim and which `click()` and `fill()` already wait for',
85
229
  namingRule: "**NAME** each helper by the user INTENT it performs, shared across tests: `openEditOrderForm`, `applyDiscount`, `submitProductForm`, `removeOrderItem`. Scenario values or adjectives in names are FORBIDDEN (`applyFiftyPercentDiscount`, `editOrder1Discount`, `createExpensiveProduct`) — another test performs the same action with different data, and a shared utils file holds ONE canonical name per action. Scenario data belongs in ARGUMENTS, never in the name.",
86
- assertionRule: `**A SHARED HELPER CONTAINS ACTIONS AND STRUCTURAL WAITS ONLY**: clicks, fills, selects, ${BROWSER_STRUCTURAL_WAITS}. EVERY VALUE ASSERTION (${BROWSER_VALUE_ASSERTIONS}) stays in the test body, placed immediately after the helper call it verifies, with its selector verbatim and its expected value unchanged. ${SHARED_HELPER_WHY}`,
230
+ assertionRule: `**A SHARED HELPER CONTAINS ACTIONS AND STRUCTURAL WAITS ONLY**: clicks, fills, selects, ${BROWSER_STRUCTURAL_WAITS}. Stated once, exactly as the verify pass states it: ${BROWSER_ASSERTION_BOUNDARY}. EVERY VALUE ASSERTION (${BROWSER_VALUE_ASSERTIONS}) stays in the test body, placed immediately after the helper call it verifies, with its selector verbatim and its expected value unchanged. ${SHARED_HELPER_WHY}`,
87
231
  relocationTarget: "the test body, immediately after the helper call, selector verbatim",
88
232
  moveRule: ASSERTION_BOUNDARY_RULE_MOVE,
89
233
  namingExample: "E.g. `applyDiscount`, not `applyTwentyPercentDiscount`.",
@@ -116,6 +260,26 @@ export async function applyDiscount(page: Page, discountPercent: string) {
116
260
  \`\`\`
117
261
 
118
262
  Both test files import and call \`applyDiscount(page, "10")\` / \`applyDiscount(page, "20")\`. A pair whose selectors differ (\`getByTestId("edit-order-submit-btn")\` vs \`getByRole("button", { name: "Save" })\`, or one side carrying \`.first()\`) is NOT a near-duplicate — leave both in place.`,
263
+ bodyShapeRule: BROWSER_BODY_SHAPE_RULE,
264
+ optionsShapeRule: "",
265
+ inlineSite: {
266
+ noun: "inline action sequence",
267
+ nouns: "Inline action sequences",
268
+ unit: "sequence",
269
+ stepNoun: "action sequence",
270
+ extendClause: "",
271
+ // The in-house clause is unconditional here: this rule renders on the seeded UI
272
+ // flow only, and that is the flow STEP 2b/3b render on.
273
+ match: (fileName) => `whose action key equals a helper now defined in \`${fileName}\` — or, when STEP 2b found a qualifying in-house module, one of THEIR helpers whose key is defined (their module is not edited in this step; STEP 3b's rules govern the call, and a helper whose key is undefined is left alone). A sibling's OWN module-level copy of the sequence counts: delete it and import the shared helper in its place`,
274
+ // A site matched against the customer's helper passes what their signature
275
+ // takes and lifts nothing: their module is STEP 3b's to change, and on that
276
+ // path the Skyramp module was never created.
277
+ target: (fileName) => `CALLS TO THE SHARED HELPER (IN \`${fileName}\`, OR THE REPOSITORY'S OWN MODULE)`,
278
+ lift: (fileName) => `for a helper in \`${fileName}\`, lift a literal it lacks to a defaulted parameter there; for one of the repository's own helpers, pass only the literals its signature takes and lift nothing — their module is not edited in this step`,
279
+ keeps: "its other steps, assertions, page-error guard and order stay verbatim",
280
+ afterSteps: "5. Run every sibling you edited with skyramp_execute_test after the verify call — an edited pre-existing test without a recorded execution cannot be reported.\n",
281
+ },
282
+ inlineCallSiteRule: `**An inline action sequence is a call site, not a helper.** A step written inline — a run of browser actions (clicks, fills, selects, presses) and the structural waits between them, not wrapped in a function — is never something to author a helper from in this pass. But when a helper that performs ${BROWSER_SAME_STEP} already exists — judge it by the action key: the verb plus the locator chain of each action, in order, argument values aside — the run is that helper's call site: REPLACE the run with a call to the helper, passing the run's own literals (${BROWSER_LIFTABLE}) as arguments; lift a literal the helper does not yet take to a parameter DEFAULTED to the helper's current literal, so every existing call site keeps its behaviour. The call replaces the actions and the structural waits between them and NOTHING else: every value assertion stays in the test body — one that follows the run stays right after the call, selector verbatim and expected value unchanged — and the page-error guard (\`page.on('pageerror'...)\`, error collectors and their final \`expect\`) stays where it is. A run with a value assertion, a guard or any other statement BETWEEN two of its actions is NOT a call site — a call cannot carry it, and an assertion never moves across an action — leave the run as it is. A \`waitForTimeout(...)\` line between two actions of the run is recorder noise, not a difference: the run still matches, and the call replaces the sleep with it. A run whose selectors differ from the helper's, or that has an action the helper lacks or lacks one the helper has, stays as it is.`,
119
283
  // Browser helpers already have the Playwright near-duplicate criteria in the
120
284
  // generic STEP 4b text; what they lack for a shared file is the
121
285
  // defaulted-parameter merge (so an incumbent utils helper can absorb a new
@@ -127,6 +291,8 @@ For this flow the rules below OVERRIDE two points of the generic text above and
127
291
  - **Name**: the INTENT the action sequence performs (\`openEditOrderForm\`, \`applyDiscount\`, \`submitProductForm\`) — never a scenario adjective or value (\`applyFiftyPercentDiscount\`, \`editOrder1Discount\`). ${oneHelperLine(fileName, "intent")}
128
292
  - **Lift each differing literal into a parameter with its DEFAULT set to the literal the incumbent version used** (${BROWSER_LIFTABLE}). Defaults make the merge additive: every existing call site keeps its behavior without edits; only the new test passes its values explicitly. Selectors stay verbatim in the body.
129
293
  - **Assertions**: before merging, apply the assertion rule to both versions — relocate a trailing value assertion to that version's test body immediately after the helper call. ${ASSERTION_BOUNDARY_RULE_MOVE} ${SHARED_HELPER_WHY}
294
+
295
+ ${BROWSER_BODY_SHAPE_RULE}
130
296
  `,
131
297
  };
132
298
  /** Which helper policy a test type's helpers follow. */
@@ -76,7 +76,7 @@ When playwright is enabled for trace collection, you can optionally configure:
76
76
  1. Start the trace collection.
77
77
  2. Have the user log in once.
78
78
  3. STOP IMMEDIATELY after login completes — any further interactions will pollute the trace.
79
- - Re-use the saved file by passing it as \`playwrightStoragePath\` (option 3) on later \`skyramp_start_trace_collection\` runs (skips login). Generated tests that reference \`storageState\` will also auto-mount it when run via \`skyramp_execute_test\`.
79
+ - Re-use the saved file by passing it as \`playwrightStoragePath\` (option 3) on later \`skyramp_start_trace_collection\` runs (skips login). Generated tests that reference \`storageState\` read it from that path when run via \`skyramp_execute_test\`.
80
80
  - Example user prompts: "save my session", "store login session for future tests", "record auth state", "with session storage".
81
81
 
82
82
  **Example usage prompt for trace collection:**
@@ -92,7 +92,7 @@ function buildSubstrateBody() {
92
92
 
93
93
  For each suite that DOES need the SUT, bring up its substrate INSIDE \`.skyramp/sut/setup.sh\` — the same script that brings up the preflight SUT app — so one \`targetSetupCommand\` stands up every consumer. Bring-up and teardown always live in \`setup.sh\` / \`teardown.sh\`, never in \`workspace.yml\`. Install the suite's dev/test dependencies from the repo's OWN lockfile (\`package-lock.json\`, \`uv.lock\`, \`go.sum\` — never "latest"), and pin any UI browser image to the repo's version, inside that script. Choose the most reuse the suite can reach, in order of preference:
94
94
 
95
- **Reuse the running SUT (prefer this).** When the suite targets the app over HTTP from a base-URL env var and does not boot its own app (no \`webServer\`, or one that defaults to \`reuseExistingServer\`, or a global-setup that only logs in / seeds against a running server), point it at the already-running SUT — stand up no second app and no separate env-start, and bake the suite's OWN base-URL env var into \`testRunCommand\` as an inline prefix referencing the SUT's exported URL. The left-hand name is whatever that repo's config reads — e.g. \`PW_BASE_URL=$SKYRAMP_TEST_BASE_URL npx playwright test\` for a Playwright config that reads \`PW_BASE_URL\`, or \`APP_BASE_URL=$SKYRAMP_TEST_BASE_URL <run cmd>\` for one that reads \`APP_BASE_URL\`. Read the config to find the real name; never assume it. Use \`$SKYRAMP_TEST_BASE_URL\` for a single-URL SUT, or \`$SKYRAMP_TEST_SERVICE_URL_<SERVICENAME>\` (service name upper-cased, \`- . : /\` replaced with \`_\`) when the SUT exposes multiple distinct service URLs, matching the service the suite targets. Inline ONLY this base-URL prefix (it must be shell-expanded); record any STATIC env the suite needs (e.g. \`NODE_ENV\`, a test-DB driver) in the suite's \`testEnv\` map when you record the contract, not as an inline prefix.
95
+ **Reuse the running SUT (prefer this).** When the suite targets the app over HTTP from a base-URL env var and does not boot its own app (no \`webServer\`, or one that defaults to \`reuseExistingServer\`, or a global-setup that only logs in / seeds against a running server), point it at the already-running SUT — stand up no second app and no separate env-start, and bake the suite's OWN base-URL env var into \`testRunCommand\` as an inline prefix referencing the SUT's exported URL. The left-hand name is whatever that repo's config reads — e.g. \`PW_BASE_URL=$SKYRAMP_TEST_BASE_URL npx playwright test\` for a Playwright config that reads \`PW_BASE_URL\`, or \`APP_BASE_URL=$SKYRAMP_TEST_BASE_URL <run cmd>\` for one that reads \`APP_BASE_URL\`. Read the config to find the real name; never assume it. Use \`$SKYRAMP_TEST_BASE_URL\` for a single-URL SUT, or \`$SKYRAMP_TEST_SERVICE_URL_<SERVICENAME>\` (service name upper-cased, \`- . : /\` replaced with \`_\`) when the SUT exposes multiple distinct service URLs, matching the service the suite targets. Put any STATIC env the suite needs (e.g. \`NODE_ENV\`, a test-DB driver) in the same inline prefix.
96
96
 
97
97
  **Reuse the SUT's built image + infra — when the suite boots its own app.** When the suite MUST boot its own app instances (e.g. per-worker containers via its own orchestration), reuse what the SUT phase already produced — the built image and the running infra — instead of rebuilding from source or standing up a duplicate data tier (rebuilding wastes the SUT's work and duplicate infra desyncs from it). The suite owns spawning the app instances; you own the substrate and the handoff, in \`setup.sh\`. So read its orchestration code for how it FINDS each thing it needs, and satisfy that mechanism — an equivalent service under a different identity provides nothing, because the suite looks for the one its code names, does not find it, and dies in its own setup having never reached a test. The mechanism is one of:
98
98
  - A config value it reads — typically a mode flag telling it to use a prebuilt image, plus a variable naming the tag; also base URLs and DSNs. The names are repo-specific (\`E2E_APP_IMAGE\`, \`<APP>_E2E_IMAGE\`, …). Build the app image ONCE and export the tag under the name that suite reads. And a suite that spawns containers needs EVERY image it launches present in the local daemon, not just the app's — \`docker pull\` any gateway, proxy, database or browser image it names, explicitly, in \`setup.sh\`. Do not leave one to chance because it happened to be cached while you were working: that is ambient runner state, the next runner will not have it, and the suite fails in its own global setup naming an image you never provided.
@@ -110,12 +110,11 @@ function buildRecordTestContractBody() {
110
110
 
111
111
  Recording a suite documents that it EXISTS and how it is invoked; provisioning it is the substrate step's business and proving it is the local canary's. Maintenance runs choose what to execute from this list and cannot discover a suite missing from it, so record a suite even when its environment is one you could not build or its command needs infra you did not stand up — write a working \`testRunCommand\` and record the unmet requirement in that suite's \`canaryDetail\` (below) so CI can supply it. Some suites are hard to reduce to a single command — they want a Docker socket, their own orchestration, or a long list of env vars. Record those too: follow the \`testRunCommand\` rules below, and say in your summary what the suite needs. Each entry sets:
112
112
  - \`framework\` — the suite's runner.
113
- - \`testRunCommand\` — the base run command. An in-process suite is just the repo's own standalone command (e.g. \`yarn test:unit\`). At run time the adapter appends a machine-readable reporter flag and the specific test-file paths to the END of this string, and points the reporter at an output path — so the command has to be one that can actually receive them. **The reporter itself must exist in the suite's environment, and \`setup.sh\` is what installs it**: Playwright and Mocha ship theirs, but **pytest needs the \`pytest-json-report\` plugin** — without it pytest exits on an unrecognised option and the suite reports nothing however healthy it is. The runner process also has to be able to WRITE the reporter's output path, which is the same constraint the container rule below describes. The rules below follow from all that, and breaking any of them means the suite can never report a result:
114
- - It must accept appended arguments. Record the invocation that receives them (\`npx playwright test\`, \`pnpm --filter <package> test:unit\`). **Prefer invoking the runner directly** — the repo's own config via a flag or package filter, the suite's static env in \`testEnv\` — which satisfies this rule by construction. Most of what a repo's launcher script does IS just that env, so reach for the script only when it does setup you cannot express that way: values it derives at run time, files it sources, a sidecar it starts. Then a repo's own wrapper is fine but only if it FORWARDS its arguments to the runner. Open the script and check: one ending in \`exec "$@"\` (or otherwise passing \`"$@"\` on) is safe, and you record it with the runner's own command appended, e.g. \`bash <wrapper-script> playwright test\`. A script that hardcodes the test invocation inside itself is NOT safe: your appended arguments are ignored, so it silently runs the WHOLE suite and writes no report where the adapter looks. **When a repo ships several entrypoints for one suite, read them all and pick the forwarding one** — a \`…-host\` and a \`…-container\` variant commonly sit side by side, and only one of them can be driven. Only when the setup is genuinely irreducible AND no shipped entrypoint both forwards arguments and runs from the repository root, write your own thin wrapper in \`.skyramp/sut/\` — translate the appended paths if the script it calls changes directory, and \`exec\` with \`"$@"\`.
115
- - The appended paths are relative to the repository root, and the command runs from the repository root. So do not \`cd\` into a subdirectory — the paths will not resolve from there. Point the runner at the subdirectory instead, with the config the repo ALREADY has (e.g. \`npx playwright test --config <path/to/playwright.config.*>\` — the repo's own file, which you have read and confirmed exists) or a package filter (e.g. \`pnpm --filter @scope/e2e test\`); for pytest, name its config and target from the root (e.g. \`pytest -c pytest.ini tests/api\`, or \`--rootdir\` when the suite needs one) rather than changing directory, since pytest resolves \`conftest.py\` and \`sys.path\` from where it runs. **Never name a path you did not write**: a command pointing at a config you invented but never created fails everywhere, and a config you write outside \`.skyramp/sut/\` is not captured with the SUT files, so it is missing on the next run even though it worked on yours.
116
- - A value that must be SHELL-EXPANDED at run time goes directly in front of the runner, e.g. \`PW_BASE_URL=$SKYRAMP_TEST_BASE_URL npx playwright test\` — the executor writes \`testEnv\` values verbatim and cannot expand \`$…\`. Never put such an assignment in front of a \`cd\` (\`VAR=$X cd e2e && npx playwright test\`): the assignment applies only to the \`cd\`, so the runner never sees VAR. Static values belong in \`testEnv\` (next), not inlined here.
117
- - If the repo runs this suite inside a container (a script doing \`docker run … <runner>\`), that boundary swallows the appended arguments, drops any environment the reporter is configured through, and leaves the reporter writing to an output path that does not exist inside the container — so the wrapper cannot be the \`testRunCommand\`. Record the runner invocation itself, and KEEP the wiring that script provided by moving the env it set into \`testEnv\` — a bare runner that has lost the mode flags and image tags is just as unrunnable as the wrapper. State the container requirement (docker socket, runner size) in your summary so CI can supply it. Record the suite either way, never drop it.
118
- - \`testEnv\` — a map of STATIC environment variables the suite needs, as literal values with no shell expansion (e.g. \`NODE_ENV: testing\`, \`DB: better-sqlite3\`). The executor injects these into the test process's environment at run time, so record them here instead of inlining them into \`testRunCommand\`: structured env is adapter-safe (selectors are appended to the command without disturbing env) and lets maintenance inspect or override it. Omit when the suite needs no static env. (Values that need runtime shell expansion, like the SUT base-URL, stay inline in \`testRunCommand\` — see above.)
113
+ - \`testRunCommand\` — the base run command. An in-process suite is just the repo's own standalone command (e.g. \`yarn test:unit\`). To run one test file, the agent adds that file's path to the END of this string, so the command has to be one that can actually receive it. Put every environment variable the suite needs in front of the runner (e.g. \`NODE_ENV=testing PW_BASE_URL=$SKYRAMP_TEST_BASE_URL npx playwright test\`). Breaking any rule below means the suite can never run a single file:
114
+ - It must accept an appended path. Record the invocation that receives it (\`npx playwright test\`, \`pnpm --filter <package> test:unit\`). **Prefer invoking the runner directly** — the repo's own config via a flag or package filter, the suite's env as an inline prefix — which satisfies this rule by construction. Most of what a repo's launcher script does IS just that env, so reach for the script only when it does setup you cannot express that way: values it derives at run time, files it sources, a sidecar it starts. Then a repo's own wrapper is fine but only if it FORWARDS its arguments to the runner. Open the script and check: one ending in \`exec "$@"\` (or otherwise passing \`"$@"\` on) is safe, and you record it with the runner's own command appended, e.g. \`bash <wrapper-script> playwright test\`. A script that hardcodes the test invocation inside itself is NOT safe: the appended path is ignored, so it silently runs the WHOLE suite. **When a repo ships several entrypoints for one suite, read them all and pick the forwarding one** — a \`…-host\` and a \`…-container\` variant commonly sit side by side, and only one of them can be driven. Only when the setup is genuinely irreducible AND no shipped entrypoint both forwards arguments and runs from the repository root, write your own thin wrapper in \`.skyramp/sut/\` — translate the appended path if the script it calls changes directory, and \`exec\` with \`"$@"\`.
115
+ - The appended path is relative to the repository root, and the command runs from the repository root. So do not \`cd\` into a subdirectory — the path will not resolve from there. Point the runner at the subdirectory instead, with the config the repo ALREADY has (e.g. \`npx playwright test --config <path/to/playwright.config.*>\` — the repo's own file, which you have read and confirmed exists) or a package filter (e.g. \`pnpm --filter @scope/e2e test\`); for pytest, name its config from the root (e.g. \`pytest -c pytest.ini\`, or \`--rootdir\` when the suite needs one) and no test directory rather than changing directory, since pytest resolves \`conftest.py\` and \`sys.path\` from where it runs. **Never name a path you did not write**: a command pointing at a config you invented but never created fails everywhere, and a config you write outside \`.skyramp/sut/\` is not captured with the SUT files, so it is missing on the next run even though it worked on yours.
116
+ - Never put an environment assignment in front of a \`cd\` (\`VAR=$X cd e2e && npx playwright test\`): the assignment applies only to the \`cd\`, so the runner never sees VAR.
117
+ - If the repo runs this suite inside a container (a script doing \`docker run … <runner>\`), that boundary swallows the appended path and drops the environment set in front of it — so the wrapper cannot be the \`testRunCommand\`. Record the runner invocation itself, and KEEP the wiring that script provided by moving the env it set into the inline prefix — a bare runner that has lost the mode flags and image tags is just as unrunnable as the wrapper. State the container requirement (docker socket, runner size) in your summary so CI can supply it. Record the suite either way, never drop it.
119
118
  - \`pathGlobs\` — the repo-relative paths that suite owns, written as globs (e.g. a package's \`test/unit/**\` for a backend unit suite, \`e2e/tests/**\` for a browser suite). **Record it on every suite, always** — including when the repo has only one. It is what sends a test file to the suite that can actually run it, and a suite with no globs accepts EVERY file, so an omitted entry means a suite gets handed specs it cannot load and its runner dies parsing them. Keep the globs disjoint, so no file matches two suites. Scope by DIRECTORY, not by filename — \`e2e/tests/**\`, not \`e2e/tests/**/*.spec.ts\`. A directory owns whatever the suite runs; narrowing by filename quietly drops every file named differently, and one suite routinely mixes conventions — \`.test.ts\` beside \`.spec.ts\`, or \`test_*.py\` beside \`*_test.py\`. Only narrow by filename when one directory genuinely holds two runners' files, and then list every pattern the suite owns after checking the real filenames on disk.
120
119
  - \`canaryStatus\` + \`canaryDetail\` — filled in AFTER the local canary, not now. \`proven\` means you watched a test from that suite execute; \`unproven\` means you did not, and \`canaryDetail\` then states what it still needs. An unproven suite stays recorded and stays maintained, so never delete an entry to avoid marking it.
121
120
  The workspace records only how to run and where to find each suite; the environment a suite needs — a built image, shared infra, a browser — is brought up by \`setup.sh\`.`;
@@ -152,7 +151,7 @@ const _adaptPlan = new PromptPlan()
152
151
  .subStep("RECORD_CONTRACT", "Record the run contract in workspace.yml", buildRecordTestContractBody)
153
152
  .step("VERIFY", "Verify", () => "")
154
153
  .subStep("COMMON_ERRORS", "Common SUT errors", () => buildCommonSutErrorsSection())
155
- .subStep("LOCAL_VALIDATION", "Local validation", () => buildLocalValidationSection())
154
+ .subStep("LOCAL_VALIDATION", "Local validation", (args) => buildLocalValidationSection(args))
156
155
  .done();
157
156
  // ── Goal section (static prose above the plan) ────────────────────────────────
158
157
  function buildGoalSection(args) {
@@ -287,7 +287,7 @@ const _composePlan = new PromptPlan()
287
287
  .subStep("APPLY", "Apply the chosen strategy", buildApplyStrategyBody)
288
288
  .step("VERIFY", "Verify", () => "")
289
289
  .subStep("COMMON_ERRORS", "Common SUT errors", () => buildCommonSutErrorsSection())
290
- .subStep("LOCAL_VALIDATION", "Local validation", () => buildLocalValidationSection())
290
+ .subStep("LOCAL_VALIDATION", "Local validation", (args) => buildLocalValidationSection(args))
291
291
  .done();
292
292
  export function getDockerComposePrompt(args) {
293
293
  const composeFile = args.sutSourceDockerComposeFile?.trim();
@@ -10,6 +10,9 @@ export declare enum SutSetupMode {
10
10
  }
11
11
  export interface SutPromptArgs {
12
12
  repositoryPath: string;
13
+ /** `owner/repo` of the checkout at repositoryPath. The canary calls
14
+ * skyramp_execute_test, which names its repository on every call. */
15
+ repository: string;
13
16
  sutSetupMode: string;
14
17
  sutSourceWorkflowFile: string;
15
18
  sutSourceDockerComposeFile: string;
@@ -41,7 +44,7 @@ export declare function buildSeedDataDiscoverySection(): string;
41
44
  * generated `.skyramp/sut/*` files.
42
45
  */
43
46
  export declare function buildWorkspaceInitSection(): string;
44
- export declare function buildLocalValidationSection(): string;
47
+ export declare function buildLocalValidationSection(args: SutPromptArgs): string;
45
48
  /**
46
49
  * Returns the canonical "add to the Testbot workflow" block: every input that
47
50
  * controls the SUT lifecycle, auth, and workflow-level setup, followed by the
@@ -1,3 +1,5 @@
1
+ import { RUN_TEST_COMMAND_RULES } from "../../skills/runTestSkill.js";
2
+ import { runnableLanguagesText } from "../../types/TestTypes.js";
1
3
  /**
2
4
  * Path of the Testbot workflow file relative to the repo root. Created by the
3
5
  * Testbot installer and edited in-place by every SUT setup mode.
@@ -82,7 +84,7 @@ export function buildWorkspaceInitSection() {
82
84
 
83
85
  Later steps in this SUT bootstrap run write \`.skyramp/sut/*\` files alongside the workspace file. If you need to update per-service \`runtimeDetails.serverStartCommand\` to match the new SUT files, call \`skyramp_init_workspace\` again (see its tool description for the edit-mode / \`force\` contract) rather than editing \`.skyramp/workspace.yml\` directly.`;
84
86
  }
85
- export function buildLocalValidationSection() {
87
+ export function buildLocalValidationSection(args) {
86
88
  return `Before reporting success, exercise the adapted workflow locally. Testbot's external fix loop only retries when SUT lifecycle commands are set on the Testbot action. When the SUT is brought up by surrounding GHA steps (skipTargetSetup: 'true'), the fix loop is skipped — so the local check below is the only safety net before the workflow is committed.
87
89
  Run commands one at a time in your shell — individual execution pinpoints failures far faster than running the whole workflow at once. For any setup, build, or lifecycle command, a non-zero exit is a fix-needed signal: adjust the workflow, re-run the failing command, and do not proceed until it passes. (The suite canary in step 4 is the one exception — judge it on whether the test executes, not on its pass/fail result.)
88
90
  1. Validate build scripts and helper programs first — run these before anything else so build and auth failures surface cheaply:
@@ -95,10 +97,10 @@ Run commands one at a time in your shell — individual execution pinpoints fail
95
97
  3. Validate the SUT lifecycle comes up — choose the branch that matches the chosen pattern:
96
98
  a. If lifecycle commands are set on the Testbot action (skipTargetSetup is unset): run \`targetSetupCommand\` (confirm exit 0), then poll \`targetReadyCheckCommand\` until it exits 0 within \`targetReadyCheckTimeout\` seconds.
97
99
  b. If GHA steps wrap the Testbot action (skipTargetSetup: 'true'): the SETUP steps you ran in step 2 already brought the SUT up, so just poll \`targetReadyCheckCommand\` until it exits 0.
98
- 4. Canary the repository's own suite(s) — do this only when a suite was recorded (a \`testSuites\` entry under a service's \`runtimeDetails\` in \`workspace.yml\`); skip it when none was recorded. With the SUT still running from step 3 and before teardown, call **\`skyramp_run_existing_tests\`** with \`workspacePath\` and \`testSelectors\` — one real test FILE per recorded suite. Do NOT canary by running the suite's command in your shell. **Maintenance runs every suite through this tool, so it is the only thing that proves what maintenance will actually be able to do**: a shell command you drove by hand can succeed while the same suite is unrunnable through the tool, and then the failure surfaces on a customer's first PR instead of here. It also resolves each selector to its owning suite via \`pathGlobs\`, so one call checks your routing too, and it appends the reporter flag and selector itself you do not hand-build those.
100
+ 4. Canary the repository's own suite(s) — do this only when a suite was recorded (a \`testSuites\` entry under a service's \`runtimeDetails\` in \`workspace.yml\`); skip it when none was recorded. With the SUT still running from step 3 and before teardown, pick one real test FILE per recorded suite. For each file, call **\`skyramp_execute_test\`** with \`commandOverride\`: the suite's recorded \`testRunCommand\` limited to that file, plus \`cwd\`, \`testFile\`, \`language\`, \`testType\`, and \`repository\`: "${args.repository}". Shape the command this way: ${RUN_TEST_COMMAND_RULES}. Pass no \`stateFile\`. Do NOT canary by running the suite's command in your shell. \`skyramp_execute_test\` takes ${runnableLanguagesText()} only: a suite in any other language (Go, RSpec, Jasmine) cannot be canaried this way record \`canaryStatus: unproven\` with \`canaryDetail\` naming the language.
99
101
  - Cover **every** suite in \`runtimeDetails.testSuites\`, not a subset you choose: do not rank them or trim by cost. A suite that spawns its OWN app instances (per-worker containers via its own orchestration) belongs in the set like any other — it depends entirely on your provisioning, so its weight is a reason to run it, never a reason to defer it. HTTP readiness only shows the app answers; one real test per suite is what proves each suite's environment is present — its browser, the built e2e image, dev/test dependencies, and base-URL wiring.
100
- - Read the result per suite: \`summary.ran > 0\` is the suite executing. \`environmentHealthy: false\` or \`skipped: true\` means it did not — \`healthDetail\`/\`skipReason\` says why, and that text is what belongs in the suite's \`canaryDetail\`.
101
- - A suite that executed and then FAILED its assertions is fine — the environment is runnable, so proceed. A suite that did not execute is the fix-needed signal — the exit criteria below say what you must fix and when you are allowed to stop trying. Never edit, skip, or delete the repo's tests to force a pass; that is out of scope for setup.
102
+ - Read the verdict per file, and the output with it. Some runners exit 0 when they find no test (mocha; junit with \`-DfailIfNoTests=false\`), so \`Pass\` on its own does not prove a test ran: the output must show at least one test from that file executing. If it does not, the suite is not proven — treat it as you would an \`Error\`. \`Fail\` does prove the command works, because only a test that ran can fail. \`Error\` means that it does not — the output says why, and that text belongs in the suite's \`canaryDetail\`.
103
+ - A \`Fail\` verdict is fine — the environment is runnable, so proceed. An \`Error\` verdict is the fix-needed signal — the exit criteria below say what you must fix and when you are allowed to stop trying. Never edit, skip, or delete the repo's tests to force a pass; that is out of scope for setup.
102
104
  5. Tear down — run \`targetTeardownCommand\` (branch a), or each TEARDOWN step's body in order (branch b), so the next iteration starts clean; confirm exit 0.
103
105
  Only proceed to the success report once pre-steps → setup → health check → canary (every suite in the mandatory set) → teardown all pass, and every recorded suite carries a \`canaryStatus\`. \`proven\` requires that you watched a test execute. \`unproven\` is NOT a way to close out a suite you could have fixed — it is permitted only when the blocker is something only CI can grant (a secret, a registry credential, a hosted dependency), and then \`canaryDetail\` must name that grant. Every other cause is yours to fix before you finish, and those are the common ones: a runner binary the suite needs that is installed in the repo but absent from \`PATH\`, an image nobody built, infra the bring-up never started, a wrong path in \`testRunCommand\`. Fix the artifact — \`setup.sh\`, the workflow pre-steps, \`workspace.yml\` — and canary that suite again. Only after two genuine fix attempts have failed on the same cause may you record \`unproven\`, with \`canaryDetail\` naming both the cause and what you tried. **Keep every suite recorded either way** — an unproven suite is still maintained from source, so removing the entry is the only move that loses that coverage outright.`;
104
106
  }
@@ -1,10 +1,4 @@
1
- /**
2
- * Prompt language for skyramp_actions output — the LLM_INSTRUCTIONS block
3
- * emitted to the agent that applies UPDATE, REGENERATE, and DELETE actions.
4
- *
5
- * Kept separate from actionsTool.ts so prompt text is co-located with other
6
- * maintenance prompts and can be reviewed/edited without touching tool logic.
7
- */
1
+ import { TestType } from "../../types/TestTypes.js";
8
2
  export interface RenameEntry {
9
3
  oldPath: string;
10
4
  newPath: string;
@@ -14,12 +8,17 @@ export interface RenameEntry {
14
8
  export declare function buildRenameStrategy(): string;
15
9
  /** Strategy string for file renames after path substitution. */
16
10
  export declare function buildFileRenameStrategy(): string;
17
- /** Strategy string for in-place UPDATE edits. */
18
- export declare function buildUpdateStrategy(): string;
11
+ /** Strategy string for in-place UPDATE edits. `withPostEditSteps` is set when at
12
+ * least one update_context entry carries post_edit_steps — the modularize → reuse
13
+ * pair an updated test owes, which skyramp_execute_test refuses the file without. */
14
+ export declare function buildUpdateStrategy(withPostEditSteps?: boolean): string;
19
15
  /** Strategy string for UPDATE entries that refresh visual-snapshot baselines (SKYR-4298). */
20
16
  export declare function buildRebaselineStrategy(): string;
21
- /** Strategy string for REGENERATE — call generation tool to overwrite the file. */
22
- export declare function buildRegenerateStrategy(): string;
17
+ /** Strategy string for REGENERATE — call generation tool to overwrite the file.
18
+ * `withGenerationArgs` is set when at least one regenerate_context entry carries
19
+ * generation_args — the codeReuse options that arm the modularize → reuse chain the
20
+ * regenerated file owes. */
21
+ export declare function buildRegenerateStrategy(withGenerationArgs?: boolean): string;
23
22
  /** Strategy string for DELETE — remove obsolete test files whose covered endpoints/UI no longer exist. */
24
23
  export declare function buildDeleteStrategy(): string;
25
24
  /** Per-file instruction block for a single UPDATE recommendation. */
@@ -31,6 +30,9 @@ export declare function buildUpdateFileInstruction(params: {
31
30
  rationale?: string;
32
31
  /** Visual baselines to refresh at final execution instead of editing (SKYR-4298). */
33
32
  rebaselineSnapshots?: string[];
33
+ /** The modularize → reuse next-steps block for a test that owes the pair; closes
34
+ * the file's instruction so the edit comes first. */
35
+ postEditSteps?: string;
34
36
  }): string;
35
37
  /** Per-file instruction block for a single REGENERATE recommendation. */
36
38
  export declare function buildRegenerateFileInstruction(params: {
@@ -38,4 +40,10 @@ export declare function buildRegenerateFileInstruction(params: {
38
40
  updateInstructions?: string;
39
41
  outputDir: string;
40
42
  outputFile: string;
43
+ /** The recommendation's test type, normalized to the catalog's where the catalog
44
+ * has one, so the clause and regenerate_context[].generation_args agree. */
45
+ testType: TestType;
46
+ /** The cataloged language. Optional because the catalog does not always carry
47
+ * one: an uncataloged but real test file is accepted deliberately. */
48
+ language?: string;
41
49
  }): string;