@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
@@ -1,17 +1,24 @@
1
1
  import { z } from "zod";
2
2
  import { logger } from "../../utils/logger.js";
3
3
  import { AnalyticsService } from "../../services/AnalyticsService.js";
4
- import { buildPathParamGuidance, } from "../test-recommendation/recommendationSections.js";
4
+ import { buildPathParamGuidance } from "../test-recommendation/recommendationSections.js";
5
5
  import { setReportLanguage } from "../../utils/reportLanguage.js";
6
6
  import { setPlanOnlyMode } from "../../utils/planOnlyMode.js";
7
+ import { parseMaxFixAttemptsArg, resolveMaxFixAttempts, setMaxFixAttempts, } from "../../utils/fixAttempts.js";
8
+ import { setPrimaryRepository } from "../../utils/AnalysisStateManager.js";
7
9
  import { recordPullRequestText } from "../../recommendation/pullRequestText.js";
8
10
  import { AUTH_MIDDLEWARE_PATTERNS_STR } from "../../utils/workspaceAuth.js";
9
11
  import { TASK_ANALYZE_MAINTAIN, TASK_GENERATE, TASK_SUBMIT, TESTBOT_TASK1_MAINTAIN_LABELS, TESTBOT_TASK1_MULTIREPO_LABELS, TESTBOT_TASK1_STEP_LABELS, orderedLabels, stepSubRef, taskRef, } from "../test-recommendation/recommendationShared.js";
10
12
  import { getTraceRecordingPromptText } from "../../playwright/traceRecordingPrompt.js";
11
13
  import { isContractConsumerModeEnabled, isPomReuseEnabled, isUtilsReuseEnabled, isSkillsLoaded, } from "../../utils/featureFlags.js";
12
14
  import { fixErrorsInstruction } from "../../skills/fixTestImportErrorsSkill.js";
15
+ import { runTestCall } from "../../skills/runTestSkill.js";
16
+ import { alignAssertionsStep } from "../../skills/validateAssertionAlignmentSkill.js";
17
+ import { ASSERTION_ENHANCEABLE_TEST_TYPES } from "../../types/TestTypes.js";
18
+ import { enhanceAssertionsCall } from "../../skills/enhanceAssertionsSkill.js";
13
19
  import { resolveServiceDetailsRef } from "../../utils/utils.js";
14
20
  import { section, sectionBody } from "../promptAssets.js";
21
+ import { CODE_REUSE_GENERATION_CLAUSE } from "../reuse-hand-off.js";
15
22
  import { readPromptAsset } from "../promptAssets.js";
16
23
  import { fillPlaceholders } from "../../recommendation/verifierContracts.js";
17
24
  import { buildServiceContext, readWorkspaceServices } from "../prompt-utils.js";
@@ -118,28 +125,31 @@ export const EXEC_FAIL = orderedLabels([
118
125
  "INFRA_RETRY",
119
126
  "REPORT_FAIL",
120
127
  ]);
128
+ function capitalize(text) {
129
+ return text.charAt(0).toUpperCase() + text.slice(1);
130
+ }
121
131
  // The UI enhance entry of the post-generation list. On the modularize-first UI
122
132
  // flow the enhance call is the first sub-step of the generation result's chain — but
123
133
  // that chain exists only for a TS/JS UI generation with enhanceAssertions on,
124
134
  // which this prompt cannot see per call. So the step keeps the call and lets
125
135
  // the agent skip it only when it already made it for that file.
126
136
  const UI_ENHANCE_STEP = UI_UTILS_REUSE
127
- ? `Call \`skyramp_enhance_assertions\` with \`testFile\` set to the absolute path of the generated UI test file, \`testType: "ui"\`, and \`enhanceType: "generation"\`, and apply every instruction returned to that file — UNLESS you already called it for this file as the first sub-step of step ${POSTGEN.UI_CODE_REUSE}'s chain, in which case skip it (never enhance the same file twice; never leave a generated UI test un-enhanced). The guidance below on which assertions to add applies to whichever call enhances the file.`
128
- : `Call \`skyramp_enhance_assertions\` with \`testFile\` set to the absolute path of the generated UI test file, \`testType: "ui"\`, and \`enhanceType: "generation"\`. Apply every instruction returned to that file.`;
137
+ ? `${capitalize(enhanceAssertionsCall("ui", "generated UI test file"))} — UNLESS you already did it for this file as the first sub-step of step ${POSTGEN.UI_CODE_REUSE}'s chain, in which case skip it (never enhance the same file twice; never leave a generated UI test un-enhanced). The guidance below on which assertions to add applies to whichever call enhances the file.`
138
+ : `${capitalize(enhanceAssertionsCall("ui", "generated UI test file"))}.`;
129
139
  // Post-generation code-reuse step for UI tests. The POM catalog, the `verify: true`
130
140
  // loop and the `.raw.bak` restore only exist on the POM-aware path — when that path
131
141
  // is flagged off, `skyramp_reuse_code` returns the SkyrampUtils workflow instead, so
132
142
  // the agent must not be sent looking for artifacts nothing produces.
133
143
  const UI_CODE_REUSE_STEP = POM_REUSE_ENABLED
134
- ? `${POSTGEN.UI_CODE_REUSE}. **[MANDATORY] After \`skyramp_ui_test_generation\` with \`codeReuse: true\`**: the generation result directs you to call \`skyramp_reuse_code\` — do this BEFORE \`skyramp_enhance_assertions\`. Two outcomes: (1) a response starting "No reusable POM layer detected" — this is a normal outcome, continue immediately (do NOT retry); (2) a refactoring workflow — follow it to completion INCLUDING its verification loop (\`skyramp_reuse_code\` with \`verify: true\`), finish only when it reports PASSED. If a reused test later fails execution and the failure points at a substituted POM call, restore the saved \`<testFile>.raw.bak\` over the test file and re-run — do NOT hand-edit the customer's POM methods (this re-run counts toward the 2-attempt execution cap — prefer this restore over the generic timeout fix-up when the failing locator came from a POM substitution). **Cleanup before reporting:** \`.raw.bak\` files are internal scratch — after ALL test executions are complete (pass or fail) and before calling \`skyramp_submit_report\`, delete every \`*.raw.bak\` you created so they are not committed to the customer-facing branch. The \`skyramp-pom-catalog.md\` is NOT scratch — leave it in place (later runs reuse it).`
144
+ ? `${POSTGEN.UI_CODE_REUSE}. **[MANDATORY] After \`skyramp_ui_test_generation\` with \`codeReuse: true\`**: the generation result directs you to call \`skyramp_reuse_code\` — do this BEFORE enhancing assertions. Two outcomes: (1) a response starting "No reusable POM layer detected" — this is a normal outcome, continue immediately (do NOT retry); (2) a refactoring workflow — follow it to completion INCLUDING its verification loop (\`skyramp_reuse_code\` with \`verify: true\`), finish only when it reports PASSED. If a reused test later fails execution and the failure points at a substituted POM call, restore the saved \`<testFile>.raw.bak\` over the test file and re-run — do NOT hand-edit the customer's POM methods (this re-run counts toward the per-file execution attempt cap; when the budget allows no re-run, restore the file for delivery and report the failure instead of executing again — prefer this restore over the generic timeout fix-up when the failing locator came from a POM substitution). **Cleanup before reporting:** \`.raw.bak\` files are internal scratch — after ALL test executions are complete (pass or fail) and before calling \`skyramp_submit_report\`, delete every \`*.raw.bak\` you created so they are not committed to the customer-facing branch. The \`skyramp-pom-catalog.md\` is NOT scratch — leave it in place (later runs reuse it).`
135
145
  : UI_UTILS_REUSE
136
- ? `${POSTGEN.UI_CODE_REUSE}. **[MANDATORY] After \`skyramp_ui_test_generation\` with \`codeReuse: true\`**: the generation result carries three CRITICAL NEXT STEPS — \`skyramp_enhance_assertions\` (on the freshly generated file, while its selectors are still inline), then \`skyramp_modularization\`, then \`skyramp_reuse_code\` — with the exact arguments for each. Do all three, in that order and to completion, for EVERY generated UI test file — the enhance sub-step is that file's step ${POSTGEN.UI_ENHANCE} below (do not call \`skyramp_enhance_assertions\` a second time for the same file, and do not skip it for later files). Sibling tests offering nothing to reuse is a normal outcome, but the reuse steps still move this test's own helpers into the shared utils file and import them back, so the test file IS expected to change. Then continue (do NOT retry).`
137
- : `${POSTGEN.UI_CODE_REUSE}. **[MANDATORY] After \`skyramp_ui_test_generation\` with \`codeReuse: true\`**: the generation result directs you to call \`skyramp_reuse_code\` — do this BEFORE \`skyramp_enhance_assertions\`. Follow the returned steps exactly. If it finds no existing helper functions to reuse, that is a normal outcome — leave the test file unchanged and continue immediately (do NOT retry).`;
146
+ ? `${POSTGEN.UI_CODE_REUSE}. **[MANDATORY] After \`skyramp_ui_test_generation\` with \`codeReuse: true\`**: the generation result carries three CRITICAL NEXT STEPS — \`skyramp_enhance_assertions\` (on the freshly generated file, while its selectors are still inline), then \`skyramp_modularization\`, then \`skyramp_reuse_code\` — with the exact arguments for each. Do all three, in that order and to completion, for EVERY generated UI test file — the enhance sub-step is that file's step ${POSTGEN.UI_ENHANCE} below (do not call \`skyramp_enhance_assertions\` a second time for the same file, and do not skip it for later files). Sibling tests offering nothing to reuse is a normal outcome, but the reuse steps still move this test's own helpers into the shared utils file — or, where the repository already has a browser helper module of its own, call its helpers and add to that module what it lacks — and import them back, so the test file IS expected to change. Then continue (do NOT retry).`
147
+ : `${POSTGEN.UI_CODE_REUSE}. **[MANDATORY] After \`skyramp_ui_test_generation\` with \`codeReuse: true\`**: the generation result directs you to call \`skyramp_reuse_code\` — do this BEFORE enhancing assertions. Follow the returned steps exactly. If it finds no existing helper functions to reuse, that is a normal outcome — leave the test file unchanged and continue immediately (do NOT retry).`;
138
148
  // Generation-call clause for the integration pipeline: only ask for codeReuse when
139
149
  // utils reuse is enabled — with the flag off, integration generation behaves exactly
140
150
  // as it did before the feature existed (no file-rewriting post-steps).
141
151
  const INTEGRATION_CODE_REUSE_GEN_CLAUSE = UTILS_REUSE_ENABLED
142
- ? `, setting \`modularizeCode: false\` and \`codeReuse: true\` (TypeScript/JavaScript/Python — leave \`codeReuse\` unset for Java: cross-file helpers do not compile in the test executor)`
152
+ ? CODE_REUSE_GENERATION_CLAUSE
143
153
  : ``;
144
154
  // The post-generation modularize → reuse steps are NOT listed here: the
145
155
  // generation tool's own result emits them (see TestGenerationService) when called
@@ -176,8 +186,40 @@ export function parseRelatedRepositories(raw) {
176
186
  return undefined;
177
187
  }
178
188
  }
189
+ // The UI-timeout diagnosis is the same whatever the budget: read the output,
190
+ // rule on the route, rule on a positional locator before the failing step. Only
191
+ // the "then retry" part depends on the cap, so the cap-of-one variant of the
192
+ // fix-up section shares these and drops the retry.
193
+ const UI_TIMEOUT_READ_OUTPUT = `If a generated UI test fails with a timeout waiting for an element after navigation (e.g. \`TimeoutError\` on \`getByTestId\` or \`locator\`), first read the test output \`skyramp_execute_test\` returned — its console lines and the URL the page ended on.`;
194
+ const UI_TIMEOUT_ROUTE_BULLET = `- **The route is broken** when that output reports a failed load of the page the test navigated to, or when the page ended on a route that is neither the login page nor another spelling of the URL it navigated to. Report \`status: "Fail"\` and name in the details both the route the test asked for and the URL the page reached. Do not change the waits.
195
+ `;
196
+ // The two waits a late-element timeout gets. Rendered at every cap: at one the
197
+ // agent edits the delivered file and reports; above one it re-runs.
198
+ const UI_TIMEOUT_WAIT_STEPS = `1. After the login submit, add \`await page.waitForURL((u) => !u.pathname.startsWith('/login'));\`. After every other \`page.goto()\`, wait for the first element the next step uses with \`await expect(locator).toBeVisible();\`. Do not add \`waitForLoadState('networkidle')\`.
199
+ 2. Add \`await page.locator('[data-testid="some-element"]').waitFor({ state: 'visible', timeout: 10000 });\` for the specific element the test needs.
200
+ Do NOT use \`page.waitForTimeout()\` with fixed delays.`;
201
+ const UI_TIMEOUT_POSITIONAL_BULLET = `- **The step before the failing one used a positional locator** — \`.nth(n)\`, \`.first()\`, \`.last()\`, or a bare tag chain such as \`locator("div").nth(80).locator("span")\` — and the element that timed out is an option, panel or message that step should have opened. A positional click that lands on the wrong element does not fail; the error surfaces one line late. But do not convict the locator on that pattern alone — the following step can be at fault by itself (the PR renamed or removed the option it waits for, the panel renders late, the route is broken). Establish which before editing, with the app still running: open the page with \`browser_snapshot\`/\`browser_blueprint\` and see what the positional path resolves to now, and check whether the diff added or removed siblings ahead of the recorded control.
202
+ - If it now resolves to a different control than the one recorded: the locator is the cause. Re-scope it to the control's labelled container or its role and name — \`getByRole('group', { name: 'Protocols' }).getByRole('combobox')\`, or a container test id narrowed to the control — never bump the index or add \`.first()\`. If the page offers no stable anchor for it, report the test as \`status: "Fail"\` naming the positional locator as the cause.
203
+ - If it still resolves to the recorded control: the failing step is at fault. Handle it under the other branches here (a broken route, a late element) or as maintenance of what the PR changed (a renamed label, a removed option) — do not spend an attempt on the locator. Making the positional locator stable in the same edit is good hygiene, not the fix.
204
+ `;
179
205
  export function getTestbotPrompt(opts) {
180
206
  const { prTitle, prDescription, repositoryPath, baseBranch, prNumber, userPrompt, services, uiCredentials, testsRepoDir, relatedRepositories, primaryRepo, planOnly = false, language, } = opts;
207
+ // The per-file execution attempt cap for the fix-and-rerun loop (SKYR-4460):
208
+ // the URI/prompt argument, else SKYRAMP_MAX_FIX_ATTEMPTS, else the default.
209
+ // Recorded for the run so skyramp_execute_test enforces the number this
210
+ // prompt states, not a second reading of the environment.
211
+ const maxFixAttempts = resolveMaxFixAttempts(opts.maxFixAttempts);
212
+ setMaxFixAttempts(maxFixAttempts);
213
+ const fixReruns = maxFixAttempts - 1;
214
+ const fixBudgetClause = fixReruns === 0
215
+ ? `the first run only — this run allows NO fix-and-rerun iteration`
216
+ : `the first run plus at most ${fixReruns} fix-and-rerun iteration${fixReruns === 1 ? "" : "s"}`;
217
+ // Rendering the prompt is where the run declares its primary checkout — the
218
+ // action passes its workingDirectory and its slug here. Write order must not
219
+ // decide it (SKYR-4333). Set, not set-if-unset: one server can render a second
220
+ // run for a different checkout, and keeping the first would route the second
221
+ // one as a related repository.
222
+ setPrimaryRepository({ repositoryPath, repo: primaryRepo });
181
223
  // Kept in the process for the plan tool, which is registered on this server.
182
224
  recordPullRequestText(prTitle, prDescription);
183
225
  // The legacy count arguments are DECLARED NOWHERE, so zod strips them and their
@@ -206,32 +248,40 @@ export function getTestbotPrompt(opts) {
206
248
  const analyzeBlock = fillPlaceholders(sectionBody(TESTBOT_TASK1_MD, "## Analyze the change"), {
207
249
  analyzeStep: TASK1.ANALYZE,
208
250
  repositoryPath,
251
+ primaryRepo,
209
252
  analyzeCountArgs,
210
253
  baseBranchArg: baseBranch ? `, \`baseBranch\`: "${baseBranch}"` : "",
211
254
  prNumberArg: prNumber ? `, \`prNumber\`: ${prNumber}` : "",
212
- testsRepoDirArg: testsRepoDir ? `, \`testsRepoDir\`: "${testsRepoDir}"` : "",
213
- uiCredentialsNote: uiCredentials ? ` ${sectionBody(TESTBOT_TASK1_MD, "## Log in before capturing")}` : "",
255
+ testsRepoDirArg: testsRepoDir
256
+ ? `, \`testsRepoDir\`: "${testsRepoDir}"`
257
+ : "",
258
+ uiCredentialsNote: uiCredentials
259
+ ? ` ${sectionBody(TESTBOT_TASK1_MD, "## Log in before capturing")}`
260
+ : "",
214
261
  submitTask: taskRef(TASK_SUBMIT),
215
262
  generateTask: taskRef(TASK_GENERATE),
216
- }) + (hasRelatedRepos
217
- ? `\n\n ${fillPlaceholders(sectionBody(TESTBOT_TASK1_MD, "## Multi-repo context"), {
218
- analyzeStep: TASK1.ANALYZE,
219
- registerServicesStep: MULTIREPO.REGISTER_SERVICES,
220
- analyzeRepoStep: MULTIREPO.ANALYZE_REPO,
221
- onFailureStep: MULTIREPO.ON_FAILURE,
222
- registerServicesRef: stepSubRef(TASK1.ANALYZE, MULTIREPO.REGISTER_SERVICES),
223
- relatedRepoCount: relatedRepositories.length,
224
- repoWord: relatedRepositories.length === 1 ? "repository" : "repositories",
225
- callWord: relatedRepositories.length === 1 ? "call" : "calls",
226
- repositoryPath,
227
- primaryRepo: primaryRepo || "<the primary repo's owner/repo>",
228
- generateTask: taskRef(TASK_GENERATE),
229
- testRepoExclusionNote: testsRepoDir
230
- ? " — NOT in the configured test repo, even though generated test files are delivered there"
231
- : "",
232
- testRepoExclusionShort: testsRepoDir ? " and NOT the test repo" : "",
233
- })}`
234
- : "\n");
263
+ }) +
264
+ (hasRelatedRepos
265
+ ? `\n\n ${fillPlaceholders(sectionBody(TESTBOT_TASK1_MD, "## Multi-repo context"), {
266
+ analyzeStep: TASK1.ANALYZE,
267
+ registerServicesStep: MULTIREPO.REGISTER_SERVICES,
268
+ analyzeRepoStep: MULTIREPO.ANALYZE_REPO,
269
+ onFailureStep: MULTIREPO.ON_FAILURE,
270
+ registerServicesRef: stepSubRef(TASK1.ANALYZE, MULTIREPO.REGISTER_SERVICES),
271
+ relatedRepoCount: relatedRepositories.length,
272
+ repoWord: relatedRepositories.length === 1 ? "repository" : "repositories",
273
+ callWord: relatedRepositories.length === 1 ? "call" : "calls",
274
+ repositoryPath,
275
+ primaryRepo,
276
+ generateTask: taskRef(TASK_GENERATE),
277
+ testRepoExclusionNote: testsRepoDir
278
+ ? " — NOT in the configured test repo, even though generated test files are delivered there"
279
+ : "",
280
+ testRepoExclusionShort: testsRepoDir
281
+ ? " and NOT the test repo"
282
+ : "",
283
+ })}`
284
+ : "\n");
235
285
  // SKYR-4023: user-facing report language. English display names improve
236
286
  // instruction-following vs bare codes; Intl.DisplayNames (Node >=18) names any
237
287
  // code correctly, falling back to the raw code only if it can't be resolved.
@@ -258,16 +308,19 @@ export function getTestbotPrompt(opts) {
258
308
 
259
309
  `;
260
310
  }
261
- // The Task 1 maintenance baseline sub-step branches in plan-only eval runs (SKYR-3879
262
- // plan-only lane): the SUT is not running, so the pre-edit baseline
263
- // execution is replaced by static-analysis-only verdicts. Defined before
264
- // task1Section, which interpolates it.
311
+ // The Task 1 maintenance sub-steps that run tests branch in plan-only eval runs
312
+ // (SKYR-3879 plan-only lane): the SUT is not running, so those runs are replaced
313
+ // by static-analysis-only verdicts. Defined before task1Section, which
314
+ // interpolates them.
265
315
  let maintenanceBeforeExecStep;
316
+ let verifyExternalStep;
266
317
  if (planOnly) {
318
+ verifyExternalStep = ` ${MAINTAIN.VERIFY_EXTERNAL}. Plan-only run: do not run the external tests you edited.`;
267
319
  maintenanceBeforeExecStep = ` ${MAINTAIN.BASELINE}. Plan-only run: skip the pre-edit baseline execution — the application is not running. Record every maintenance verdict from static drift analysis alone; execution statuses simply remain unrecorded.`;
268
320
  }
269
321
  else {
270
- maintenanceBeforeExecStep = ` ${MAINTAIN.BASELINE}. Call \`skyramp_execute_test\` with \`phase: "before"\` and \`stateFile\` for every UPDATE/REGENERATE/DELETE test. Exclude tests marked \`[external]\` those are baselined in ${stepSubRef(TASK1.MAINTAIN, MAINTAIN.CONFIRM_EXTERNAL)} via \`skyramp_run_existing_tests\`. Run them sequentially, not in parallel. This captures the pre-edit baseline do not skip even if you expect the test to fail. Never pass \`rebaselineSnapshots\` here: a \`Screenshot comparison failed\` on this run is the evidence that a visual baseline is stale, and the refresh belongs to the final execution.`;
322
+ verifyExternalStep = ` ${MAINTAIN.VERIFY_EXTERNAL}. Run the external tests you edited again. Do this step right after ${stepSubRef(TASK1.MAINTAIN, MAINTAIN.APPLY_ACTIONS)}. It applies to each \`[external]\` test file that you edited in ${stepSubRef(TASK1.MAINTAIN, MAINTAIN.APPLY_ACTIONS)} and that ${stepSubRef(TASK1.MAINTAIN, MAINTAIN.BASELINE)} ran. Run each such file with \`skyramp_execute_test\`, \`phase: "after"\` and \`stateFile\`, and use the same command as in ${stepSubRef(TASK1.MAINTAIN, MAINTAIN.BASELINE)}. Record each result as the file's \`afterStatus\`. The final execution excludes \`[external]\` files, so this step is where they get their after-run. If no file applies, say so in your report. If a file still fails, report it do not run it again.`;
323
+ maintenanceBeforeExecStep = ` ${MAINTAIN.BASELINE}. Call \`skyramp_execute_test\` with \`phase: "before"\` and \`stateFile\` for every Skyramp test you will change, and for every test the repository owns that you will mark UPDATE: ${runTestCall()}. Run them one at a time, not in parallel. Run the command even when you expect the runner or a package to be missing: the failure output is what names what is missing, and a check you make before the run reaches no repair. On this run repair the environment only — install what is missing and run the file again — and never edit the test file, because the result of the file as the repository wrote it IS the baseline. This captures the pre-edit baseline — do not skip it even when you expect the test to fail. \`skyramp_actions\` refuses an UPDATE of the repository's own test until that test has this run. Nothing else owes one: a VERIFY changes no file, and a REGENERATE or a DELETE of the repository's own test is a recommendation you report rather than apply. Never pass \`rebaselineSnapshots\` on this run: a \`Screenshot comparison failed\` here is the evidence that a visual baseline is stale, and the refresh belongs to the final execution.`;
271
324
  }
272
325
  // For follow-up requests: emit the @skyramp-testbot header + guardrails, both stop-early.
273
326
  // For first-run prompts: emit the full Task 1 analysis + maintenance section.
@@ -297,8 +350,6 @@ ${analyzeBlock}
297
350
 
298
351
  ${TASK1.MAINTAIN}. **Maintain existing tests:**
299
352
 
300
- ${MAINTAIN.CONFIRM_EXTERNAL}. Confirm external-test breakage before assessment. If any service in \`${repositoryPath}/.skyramp/workspace.yml\` declares test-env config (\`runtimeDetails.test*\`), call \`skyramp_run_existing_tests\` (\`mode: "confirm"\`, \`stateFile\`) on the tests \`skyramp_analyze_changes\` marked \`[external]\` — the repo's OWN suite, not the Skyramp-generated tests — before \`skyramp_analyze_test_health\`, so the run-confirmed failures fold into its assessment. Do NOT read the \`[external]\` test files to *guess* the change's impact — RUN them with \`skyramp_run_existing_tests\` to get real pass/fail; reading them is not a substitute for running them. These \`[external]\` suites also do not run through \`skyramp_execute_test\`, so skipping this leaves their status \`Unknown\`. Selector, health-gate, and self-skip behavior are in the tool description. (Skyramp-generated tests are handled in ${stepSubRef(TASK1.MAINTAIN, MAINTAIN.BASELINE)}, not here.)
301
-
302
353
  ${MAINTAIN.TEST_HEALTH}. Call \`skyramp_analyze_test_health\` with \`stateFile\` (from \`skyramp_analyze_changes\` output). Pass \`blueprintCaptured: true\` when \`browser_blueprint\` was called successfully earlier in this session — see the parameter description for when this applies. **Do NOT read application source files** (routes, models, controllers) — all change information you need is in the \`skyramp_analyze_changes\` output and the diff. Exception: the UI drift pre-scan (\`UI_SYMBOL_PRESCAN\`) may instruct you to read changed frontend files to extract exported symbols — follow those instructions when present.
303
354
 
304
355
  ${MAINTAIN.UPDATE_INSTRUCTIONS}. Write \`updateInstructions\` for each UPDATE or REGENERATE test before calling \`skyramp_actions\` — articulating the change first prevents file content from overriding diff-based reasoning.
@@ -307,7 +358,7 @@ ${maintenanceBeforeExecStep}
307
358
 
308
359
  ${MAINTAIN.APPLY_ACTIONS}. Call \`skyramp_actions\` with \`stateFile\` (from \`skyramp_analyze_changes\` output) and apply the edits it returns.
309
360
 
310
- ${MAINTAIN.VERIFY_EXTERNAL}. Verify external-test fixes. **This step is not optional and it is the easiest one to forget — you have just edited files in ${stepSubRef(TASK1.MAINTAIN, MAINTAIN.APPLY_ACTIONS)}, so come back here before you move on to anything else.** It applies whenever ${stepSubRef(TASK1.MAINTAIN, MAINTAIN.CONFIRM_EXTERNAL)} reported a real pass/fail result for a file you then edited. It does NOT apply when ${stepSubRef(TASK1.MAINTAIN, MAINTAIN.CONFIRM_EXTERNAL)} returned \`skipped: true\` or \`ran: 0\` for every suite — there is no baseline to compare against, so say so in your report instead of re-running. When it applies: re-run those \`[external]\` files with \`skyramp_run_existing_tests\` (\`mode: "verify"\`, \`stateFile\`) and record each file's result as its \`afterStatus\`. Editing an \`[external]\` file that ${stepSubRef(TASK1.MAINTAIN, MAINTAIN.CONFIRM_EXTERNAL)} confirmed failing and NOT re-running it leaves your own fix unverified — you would be reporting a repair you never saw work. A still-failing verify is surfaced in the report — do not loop.
361
+ ${verifyExternalStep}
311
362
 
312
363
  ${codeReviewBlock}
313
364
 
@@ -467,7 +518,8 @@ ${CONTRACT_MODE_GUIDANCE}
467
518
  - **\`browser_assert\`**: the \`browser_navigate\` result states the rule this tool has to satisfy on every page you reach. Call multiple assertions in the same tool call batch when checking independent elements.
468
519
  - **Removal guard — when \`uiContext.removedElements\` is non-empty**: the server lists which elements this PR removed — each identified by a \`data-*\` attribute and value, with the file it came from (renames, moves and deleted files are excluded). Read that file and the route or page files that render it to decide which page each appeared on. Per PAGE: \`browser_navigate\` to it, wait for the app to render, then call \`browser_assert_hidden\` once per listed element using the target the list shows — \`testId: "<value>"\` when the attribute is \`data-testid\`, otherwise \`attribute: "<name>", value: "<value>"\` (e.g. \`attribute: "data-cy"\`); no \`ref\` — the element no longer exists, so no snapshot has one; the tool checks the live page and refuses to record on a blank or un-rendered page. Then at least one \`browser_assert\` on a RETAINED element of the same page verifying its text, value or state. If a UI trace for that page is already planned, record the guard assertions inside that trace; otherwise this is its own trace and spec, \`verify-removed-ui-<page-slug>\`. The generated test asserts \`toBeHidden()\` on \`getByTestId(...)\` or \`page.locator('[data-cy="..."]')\` accordingly. A removed element the server did not list still gets its test (the removal check requires it) — ground that one in the diff and prefix its \`reasoning\` with \`[removed-element diff-grounded]\`; prefix \`reasoning\` with \`[removed-element server-listed]\` when the element came from \`uiContext.removedElements\`. When the removed element lived inside a control the page has to open — an \`option\` of a \`select\`, an item of a closed menu — open that control before asserting: a closed control's contents are never visible, so a hidden assertion recorded against a shut one passes whether the element was removed or not. \`browser_assert_hidden\` stays the tool either way, because \`browser_assert\` needs a snapshot \`ref\` and a removed element has none; where the control cannot be opened, say so in \`reasoning\` so the assertion step turns that guard into a count. **Deleted routes or pages are deleted features, not removed elements**: test the removal through the link or entry point that survives. A trace may still open the retired URL — to assert the app's fallback there, or that the old page's elements are gone — after it has recorded a positive \`browser_assert\` on a surviving page; a trace whose only visited page is the dead URL has no positive companion and is not a guard spec.
469
520
  - **Renames are not removals — on every PR, whatever \`uiContext.removedElements\` holds**: when a test id, \`aria-label\` or other accessible name changed, assert the element by its new identifier and leave the retired identifier alone (no \`browser_assert_hidden\` on it). A rename PR removes nothing, so this rule applies when the removed list is empty.
470
- - **\`browser_visual_snapshot\` — for visual/appearance checks**: when the instruction asks to take a screenshot, capture a baseline, or verify how a page/element/region *looks* (not its text or value), call \`browser_visual_snapshot\` — it records a \`toHaveScreenshot()\` assertion so the generated test pixel-compares against a baseline on every run. Do NOT use \`browser_take_screenshot\` for this: it captures a throwaway image that is dropped at export and never appears in the generated test (use it only to view the page yourself).
521
+ - **\`browser_visual_snapshot\` — for visual/appearance checks**: when the instruction asks to take a screenshot, capture a baseline, or verify how a page/element/region *looks* (not its text or value), call \`browser_visual_snapshot\` — it records a \`toHaveScreenshot()\` assertion so the generated test pixel-compares against a baseline on every run. **EXCEPTION:** when the look in question IS the change under test (a colour, class, attribute or element-order the diff makes), assert the property directly instead — see the next bullet. Do NOT use \`browser_take_screenshot\` for this: it captures a throwaway image that is dropped at export and never appears in the generated test (use it only to view the page yourself).
522
+ - **A colour, class or attribute change the diff makes**: record it directly — \`browser_assert\` \`type: css/class/attribute\` on the element that OWNS the property (the flex container for \`flex-direction\`, not its children). If that owner has no stable ref, say so in \`reasoning\` as a recording gap — do not assert the wrong element or screenshot it. Element order has no assert kind: use \`flex-direction\` when the diff flipped it, else a \`boundingBox()\` comparison at the enhance step. \`browser_visual_snapshot\` only for a look no property expresses (image, gradient, chart).
471
523
  - **Wait for stable state before the second capture**: After performing an action that affects computed fields (filling a discount, submitting a form, adding an item), check the current page state before calling the second \`browser_blueprint\` (the capture after the action). If a computed field — total, price, count, derived text — still shows its initial empty or zero value (e.g. \`$0.00\`, \`0\`, \`Loading...\`, empty string), that means async data hasn't finished loading yet. Use \`browser_wait_for\` to wait up to 10 seconds for the field to update to a real value (for example, wait for the total to show a non-zero amount like \`$799.99\` instead of \`$0.00\`). Once the field shows a real value, THEN call the second \`browser_blueprint\` to capture stable state. If after 10 seconds the field still hasn't updated, skip the assertion on that field — don't capture and assert a value that hasn't loaded.
472
524
  If \`browser_navigate\` fails (app not running / connection refused), apply skip condition (a) above: leave the planned test in your plan, say in \`businessCaseAnalysis\` why it was not written, AND record the outage in \`issuesFound\`.
473
525
  Each trace costs browser tool calls, so record the ones your plan holds and no more. One trace that asserts a real outcome is worth more than three that assert a heading.
@@ -537,31 +589,36 @@ ${EXEC_FAIL.EXPECTED_FAILURE}. **Expected failure check (no retry):** If the fai
537
589
 
538
590
  This path also covers an assertion failure that application behavior outside this PR's diff explains — for example child records that survive the deletion of their parent, state inherited when an ID is recycled or reused, or a value that ignores a status the test set. Before you keep such a test red, confirm the cause in the source: read the handler, model, or query that should have done the work, and find the specific operation that is missing or wrong. If you find it, report the test as \`status: "Fail"\` and add an \`issuesFound\` entry for it. Do NOT retry.
539
591
 
540
- If you cannot point at the missing or wrong line in application code, the app is not at fault — shared or seeded data, parallel test workers, or setup the test itself never did explain the collision. Treat that as an infrastructure failure: fix it and retry once as in step ${EXEC_FAIL.INFRA_RETRY}.
592
+ If you cannot point at the missing or wrong line in application code, the app is not at fault — shared or seeded data, parallel test workers, or setup the test itself never did explain the collision. Treat that as an infrastructure failure: fix it and re-run inside the budget of step ${EXEC_FAIL.INFRA_RETRY}.
541
593
 
542
594
  **If you did confirm the missing or wrong operation in the source, do NOT make the test pass.** Never add a reset, cleanup, or setup call for isolation. Never weaken the assertion — no \`==\` to \`>=\`, no exact value to a range. A failing test whose diagnosis names a pre-existing bug is the most valuable output of this run; a passing version of it reports nothing.
543
595
 
544
- ${EXEC_FAIL.INFRA_RETRY}. Apply a targeted fix and retry **once** only for **infrastructure failures** — that means exactly **2 total \`skyramp_execute_test\` calls per test file** for these cases. Examples of infrastructure failures worth fixing:
596
+ ${maxFixAttempts === 1
597
+ ? `${EXEC_FAIL.INFRA_RETRY}. **This run's budget is one final-phase execution per file — there is no fix-and-rerun iteration.** Diagnose an infrastructure failure from the output; if the cause is clear, fix the file so the delivered test is right, but do NOT execute it again — the tool refuses a second call. Report it as \`status: "Fail"\` with the cause. The unchanged-re-run allowances do not apply either: a no-output run or a connection error is reported, not re-run (the tool's own retry of a connection error it catches still happens inside the one execution, and its response says so).\n`
598
+ : `${EXEC_FAIL.INFRA_RETRY}. Apply a targeted fix and re-run, only for **infrastructure failures**, inside a per-file budget of **${maxFixAttempts} final-phase execution${maxFixAttempts === 1 ? "" : "s"}** (${fixBudgetClause}; a maintained test's \`phase: "before"\` baseline run and a call the tool refused before running do not count). Each iteration: read the failure output the tool returned, change the test file or its inputs to address that specific cause, then execute again. Never re-run an unchanged file — with ONE exception per file, for either of two failures: a run that produced no output at all, or a connection error (connection refused, EOF). It does not apply when the tool's response carries its retry note ("re-ran this file once unchanged before answering"), and it is spent once the response says the run was itself an unchanged re-run of the previous one: the tool compares the file's contents run to run. Do not re-apply a fix that already failed; if the new output names no new cause, stop and report. Because you pass \`stateFile\` and \`repository\` on every \`skyramp_execute_test\` call in this run, the tool counts each file's final-phase executions there, appends "Execution attempt k of ${maxFixAttempts}" to every failure, and refuses the call once the budget is spent. Examples of infrastructure failures worth fixing:
545
599
  - Assertion mismatch from floating-point precision, or an expected value mis-transcribed from the observed response or computed with an arithmetic slip. If application behavior outside the diff explains the mismatch, it is not an infrastructure failure — use step ${EXEC_FAIL.EXPECTED_FAILURE} instead.
546
600
  - Import error, syntax error, or missing dependency in the generated test file${FIX_ERRORS_RETRY_HINT}
547
- - Connection refused or timeout unrelated to the app under test
548
- ${EXEC_FAIL.REPORT_FAIL}. If it still fails after the retry, report it as \`status: "Fail"\` with the error details and move on — do NOT edit and re-run a third time. A failing test that documents a real bug is a valid outcome.
549
- A report-time check can then object to that row — a test you declared green that failed, or a red that fell over before it reached the behavior it targets. Expect that objection here: the cap stopped you, not the test. Answer it through \`answers\` on a second \`skyramp_submit_report\` call. Say whether the failure is the bug or the test, and that you reached the two-attempt cap. Do NOT run the test a third time to close the objection.
550
-
551
- ### UI Test Execution Fix-up (counts toward the 2-attempt cap above)
552
- If a generated UI test fails with a timeout waiting for an element after navigation (e.g. \`TimeoutError\` on \`getByTestId\` or \`locator\`), first read the test output \`skyramp_execute_test\` returned its console lines and the URL the page ended on.
553
- - **The route is broken** when that output reports a failed load of the page the test navigated to, or when the page ended on a route that is neither the login page nor another spelling of the URL it navigated to. Report \`status: "Fail"\` and name in the details both the route the test asked for and the URL the page reached. Do not change the waits.
554
- - **Otherwise** apply BOTH fixes in a single edit before retrying:
555
- 1. After the login submit, add \`await page.waitForURL((u) => !u.pathname.startsWith('/login'));\`. After every other \`page.goto()\`, wait for the first element the next step uses with \`await expect(locator).toBeVisible();\`. Do not add \`waitForLoadState('networkidle')\`.
556
- 2. Add \`await page.locator('[data-testid="some-element"]').waitFor({ state: 'visible', timeout: 10000 });\` for the specific element the test needs.
557
- Do NOT use \`page.waitForTimeout()\` with fixed delays. Do NOT retry more than once — if the test still fails after this fix, report it as "Fail".
601
+ - Connection refused or timeout unrelated to the app under test\n`}
602
+ ${EXEC_FAIL.REPORT_FAIL}. If it still fails when the budget is spent, report it as \`status: "Fail"\` with the last error details and move on — do NOT edit and re-run past the cap. A failing test that documents a real bug is a valid outcome.
603
+ A report-time check can then object to that row — a test you declared green that failed, or a red that fell over before it reached the behavior it targets. Expect that objection here: the cap stopped you, not the test. Answer it through \`answers\` on a second \`skyramp_submit_report\` call. Say whether the failure is the bug or the test, and that you reached the ${maxFixAttempts}-attempt cap. Do NOT run the test again to close the objection.
604
+
605
+ ${maxFixAttempts === 1
606
+ ? `### UI Test Execution Fix-up (diagnosis onlythis run's budget is one execution per file)
607
+ The tool refuses a second execution, so a UI timeout is diagnosed and reported, never retried; the diagnosis below still decides what you report and what you fix in the delivered file. ${UI_TIMEOUT_READ_OUTPUT}
608
+ ${UI_TIMEOUT_ROUTE_BULLET}${UI_TIMEOUT_POSITIONAL_BULLET}- **Otherwise** the element was late or the wait was missing: make BOTH edits below in the delivered file, but do NOT execute it again; report \`status: "Fail"\` naming the element that timed out and the waits you added.
609
+ ${UI_TIMEOUT_WAIT_STEPS}\n`
610
+ : `### UI Test Execution Fix-up (counts toward the ${maxFixAttempts}-attempt cap above)
611
+ ${UI_TIMEOUT_READ_OUTPUT}
612
+ ${UI_TIMEOUT_ROUTE_BULLET}${UI_TIMEOUT_POSITIONAL_BULLET}- **Otherwise** apply BOTH fixes in a single edit before retrying:
613
+ ${UI_TIMEOUT_WAIT_STEPS}
614
+ If the test still fails after this fix, spend a remaining attempt only on a different, specific cause the new output names — never re-apply the same waits. When the budget is spent, report it as "Fail".\n`}
558
615
 
559
616
  **After generation, complete these steps** (generation results may add their own CRITICAL NEXT STEPS — e.g. modularize-then-reuse for integration or UI tests generated with \`codeReuse: true\` — follow those too, in the order the result states):
560
- ${POSTGEN.INTEGRATION_ENHANCE}. **[MANDATORY] After \`skyramp_integration_test_generation\`**: Call \`skyramp_enhance_assertions\` with \`testFile\` set to the absolute path of the generated integration test file, \`testType: "integration"\`, and \`enhanceType: "generation"\`. Apply every instruction returned to that file.
561
- ${POSTGEN.CONTRACT_ENHANCE}. **[MANDATORY] After \`skyramp_contract_test_generation\` with \`providerMode\`**: Call \`skyramp_enhance_assertions\` with \`testFile\` set to the absolute path of the generated provider contract test file, \`testType: "contract"\`, and \`enhanceType: "generation"\`. Apply every instruction returned to that file.
617
+ ${POSTGEN.INTEGRATION_ENHANCE}. **[MANDATORY] After \`skyramp_integration_test_generation\`**: ${capitalize(enhanceAssertionsCall("integration", "generated integration test file"))}.
618
+ ${POSTGEN.CONTRACT_ENHANCE}. **[MANDATORY] After \`skyramp_contract_test_generation\` with \`providerMode\`**: ${capitalize(enhanceAssertionsCall("contract", "generated provider contract test file"))}.
562
619
  ${UI_CODE_REUSE_STEP}
563
620
  ${POSTGEN.UI_ENHANCE}. **[MANDATORY] After \`skyramp_ui_test_generation\`**: ${UI_ENHANCE_STEP} The HIGH-tier \`possibleAssertions\` from your second \`browser_blueprint\` captures (after each action) during trace recording are in your context — when the enhance instructions ask you to add assertions for state-changing actions, use those grounded candidates first (they contain exact computed values from the DOM delta, e.g. \`toHaveText('Total: $899.98')\`). Only fall back to deriving values from the test file or source code when no HIGH-tier candidate covers the action.
564
- ${POSTGEN.WAIT}. **Wait**: Do NOT proceed to test execution until steps ${POSTGEN.INTEGRATION_ENHANCE}–${POSTGEN.UI_ENHANCE} (plus any generation-result CRITICAL NEXT STEPS) are complete and the verification checklist in the \`skyramp_enhance_assertions\` tool result has been validated for EVERY generated test file.
621
+ ${POSTGEN.WAIT}. **Wait**: Do NOT proceed to test execution until steps ${POSTGEN.INTEGRATION_ENHANCE}–${POSTGEN.UI_ENHANCE} (plus any generation-result CRITICAL NEXT STEPS) are complete and the assertion verification has passed for EVERY generated test file. Count them before you proceed: list the test files you generated, and confirm each one has both a recorded assertion baseline and a passing verification. A file missing either is not done — go back and finish it.
565
622
  Do not make any changes other than the code-reuse refactoring (step ${POSTGEN.UI_CODE_REUSE} and the generation-result reuse steps) and the assertion enhancements described above. For example: do not modify auth headers, cookies, tokens, env vars, or imports that the generation tool already set correctly — those are correct by construction and changing them breaks auth or execution.
566
623
 
567
624
  ${FINISH_CHECKS_BLOCK}
@@ -569,13 +626,15 @@ ${FINISH_CHECKS_BLOCK}
569
626
  **Execution timing:**
570
627
  - **beforeStatus** (maintained tests only): execute each maintained test file **once at the start** (before any edits) to capture \`beforeStatus\`. This is the only execution allowed before edits.
571
628
  - **Probe residue**: before the final execution, delete through the API the records your own probes and recordings created. Find each one by the id its create response returned, or by the exact value you typed for it during a recording. Do not delete anything else, and do not delete by a pattern. Do not use the database or a container. Do not add the deletion to a test. List in the report the records the API could not remove.
572
- - **Final execution**: Do NOT call \`skyramp_execute_test\` again until ALL maintenance edits AND ALL new test generation/enhancement are complete. Then execute every test file once — maintained files (for \`afterStatus\`) and new files together. For a maintained spec whose \`skyramp_actions\` entry carried \`rebaseline_snapshots\`, pass that exact list as \`rebaselineSnapshots\` on this run and only this run. **Execute tests SEQUENTIALLY (one at a time)** — do NOT send multiple \`skyramp_execute_test\` calls in the same tool call batch, as concurrent execution overwhelms the stdio transport and causes MCP disconnection. Exclude tests marked \`[external]\`.
629
+ - **Final execution**: Apart from ${stepSubRef(TASK1.MAINTAIN, MAINTAIN.VERIFY_EXTERNAL)}, do NOT call \`skyramp_execute_test\` again until ALL maintenance edits AND ALL new test generation/enhancement are complete. Then execute every test file once — maintained files (for \`afterStatus\`) and new files together — passing \`stateFile\` and \`repository\` on every call: the attempt cap and the \`afterStatus\` the report reads both live in that file, and \`repository\` names the section the result lands in. Omitting \`stateFile\` does not skip the cap — the tool falls back to this run's own state file — but a wrong or missing \`repository\` fails the call. For a maintained spec whose \`skyramp_actions\` entry carried \`rebaseline_snapshots\`, pass that exact list as \`rebaselineSnapshots\` on this run and only this run. **Execute tests SEQUENTIALLY (one at a time)** — do NOT send multiple \`skyramp_execute_test\` calls in the same tool call batch, as concurrent execution overwhelms the stdio transport and causes MCP disconnection. Exclude tests marked \`[external]\`.
573
630
  - Only report test results for files you actually ran.
631
+
632
+ ### Post-Execution: Assertion Alignment
633
+ Once execution is final, for each ${ASSERTION_ENHANCEABLE_TEST_TYPES.join(", ")} test, new or maintained, verify its assertions validate the scenario it was created for: ${alignAssertionsStep()}
634
+
574
635
  **Auth**: If \`skyramp_analyze_changes\` reports an auth token or \`SKYRAMP_TEST_TOKEN\` is set, pass it in **every** \`skyramp_execute_test\` call from the first attempt — do NOT wait for a 401/403 to discover auth is needed.`;
575
636
  }
576
- const primaryRepoBlock = primaryRepo
577
- ? `<REPOSITORY>${primaryRepo}</REPOSITORY>\n`
578
- : "";
637
+ const primaryRepoBlock = `<REPOSITORY>${primaryRepo}</REPOSITORY>\n`;
579
638
  // Placed AHEAD of Task 1, not next to the register call in Task 2: the agent has
580
639
  // to name the changed file it is about, and cite the file it sits
581
640
  // in, and cite `routes` from the checkout, and all of those happen while
@@ -614,10 +673,9 @@ In these cases:
614
673
 
615
674
  ${task3CountRule ? `${task3CountRule}\n\n` : ""}${reportLanguageBlock}Call \`skyramp_submit_report\`. Field names, types, and formats are defined in the tool's parameter schema — follow them exactly. A report check objects to an \`issuesFound\` entry with \`category: bug\` that no delivered test proves. The \`plannedTestId\` and \`defectId\` descriptions in the schema say what closes it. Answer an objection in one line.
616
675
 
617
- ${hasRelatedRepos
618
- ? `
619
- - **MULTI-REPO attribution**: Set the \`repository\` field (\`owner/repo\`) on EVERY \`newTestsCreated\`, \`testResults\` and \`issuesFound\` item — including items about the PRIMARY repo — so each objection is unambiguously attributed. The primary repo's \`repository\` is \`${primaryRepo || "<the primary repo's owner/repo>"}\`; items derived from a related repo's diff (from the \`<related_repositories>\` analysis) carry that repo's \`repository\` value. In \`businessCaseAnalysis\`, include a short per-repo subsection and call out any cross-repo correlations you found.
620
- `
676
+
677
+ - **Repository attribution**: Set the \`repository\` field (\`owner/repo\`) on EVERY \`newTestsCreated\`, \`testResults\`, \`issuesFound\` and \`additionalRecommendations\` item. The primary repo's \`repository\` is \`${primaryRepo}\`.${hasRelatedRepos
678
+ ? ` Items derived from a related repo's diff (from the \`<related_repositories>\` analysis) carry that repo's \`repository\` value. In \`businessCaseAnalysis\`, include a short per-repo subsection and call out any cross-repo correlations you found.`
621
679
  : ""}
622
680
 
623
681
  ${getTraceRecordingPromptText({ outputDir: `${repositoryPath}/.skyramp`, modularize: false, modularizeViaGenerationResult: UI_UTILS_REUSE })}`;
@@ -670,8 +728,9 @@ export function registerTestbotPrompt(server) {
670
728
  .describe("JSON-encoded array of {repo, repositoryPath, baseBranch?} for related repositories to analyze (multi-repo mode). `repo` is the owner/repo slug (resolved by the action; used verbatim, never inferred). Each is analyzed with its own skyramp_analyze_changes call; the agent correlates cross-repo changes and submits ONE plan covering every repo. Generated test files are delivered into each service's declared testDirectory, relative to the single delivery root (the primary repo, or the configured test repo)."),
671
729
  primaryRepo: z
672
730
  .string()
673
- .optional()
674
- .describe("The primary repository's owner/repo slug (where the testbot workflow runs). Used verbatim as the `repository` attribution for the primary repo's analysis, tests, and report items in multi-repo runs."),
731
+ .trim()
732
+ .min(1)
733
+ .describe("The primary repository's 'owner/repo' (e.g. 'letsramp/api-insight'), read from its checkout's origin remote. Every report item, planned test and tool call attributes to this name or to a related repository's own."),
675
734
  planOnly: z
676
735
  // Prompt/resource URL args arrive as strings — accept "true"/"1"
677
736
  // alongside a real boolean; anything else (incl. undefined) is false.
@@ -682,6 +741,16 @@ export function registerTestbotPrompt(server) {
682
741
  .string()
683
742
  .optional()
684
743
  .describe("Language code (e.g. 'ja') for user-facing report content. When set to a non-English language, the agent writes all free-text report fields in that language; identifiers, endpoints, file names, and enum values stay untranslated. Omitted or 'en' → English."),
744
+ // "perTest…" on the wire (the argument name reaches the agent's context;
745
+ // a bare "maxFixAttempts" reads as a run-wide total); `maxFixAttempts`
746
+ // in code.
747
+ perTestMaxFixAttempts: z
748
+ // Prompt args arrive as strings. The shared parser maps an unusable
749
+ // spelling or an out-of-range value to undefined, so this entry point
750
+ // falls through to SKYRAMP_MAX_FIX_ATTEMPTS and the default exactly
751
+ // like the resource does, instead of rejecting the call.
752
+ .preprocess((v) => parseMaxFixAttemptsArg(v), z.number().int().min(1).max(10).optional())
753
+ .describe("Per-TEST-FILE cap on skyramp_execute_test calls in the final phase: the first run plus the fix-and-rerun iterations the agent may spend on an infrastructure failure for that one file (SKYR-4460). 1..10; falls back to SKYRAMP_MAX_FIX_ATTEMPTS, then 3."),
685
754
  },
686
755
  }, async (args) => {
687
756
  const services = await readWorkspaceServices(args.repositoryPath);
@@ -699,6 +768,7 @@ export function registerTestbotPrompt(server) {
699
768
  primaryRepo: args.primaryRepo,
700
769
  planOnly: args.planOnly,
701
770
  language: args.language,
771
+ maxFixAttempts: args.perTestMaxFixAttempts,
702
772
  });
703
773
  if (args.workspaceValidationFailed) {
704
774
  prompt = buildWorkspaceRecoveryPrefix(args.repositoryPath) + prompt;
@@ -6,13 +6,13 @@ export const UNKNOWN_ANSWER_PREFIX = "answers:unknown:";
6
6
  export function answerFor(objection, acknowledged) {
7
7
  const wantsBlocker = needsBlocker(objection.objectionId);
8
8
  for (const entry of acknowledged) {
9
- if (entry?.objectionId !== objection.objectionId)
9
+ if (entry.objectionId !== objection.objectionId)
10
10
  continue;
11
11
  const rawAnswer = entry.answer;
12
12
  const answer = typeof rawAnswer === "string" ? rawAnswer.trim() : "";
13
13
  if (answer.length === 0)
14
14
  continue;
15
- if (wantsBlocker && String(entry?.blocker ?? "").trim().length === 0)
15
+ if (wantsBlocker && String(entry.blocker ?? "").trim().length === 0)
16
16
  continue;
17
17
  return answer;
18
18
  }
@@ -23,7 +23,9 @@ export function answerFor(objection, acknowledged) {
23
23
  * recognised BY ITS PREFIX and never draws an objection of its own. `scope` and
24
24
  * `suggestion` are passed in: the two callers raise this about different lists. */
25
25
  export function unknownAnswerObjections(objections, acknowledged, { scope, suggestion }) {
26
- const answered = acknowledged.map((entry) => entry?.objectionId).filter((id) => typeof id === "string");
26
+ const answered = acknowledged
27
+ .map((entry) => entry.objectionId)
28
+ .filter((id) => typeof id === "string");
27
29
  const raised = new Set(objections.map((objection) => objection.objectionId));
28
30
  const raisedHere = [];
29
31
  const seen = new Set();
@@ -47,7 +49,8 @@ export function unknownAnswerObjections(objections, acknowledged, { scope, sugge
47
49
  * leave the bug. `verifierContracts.ts` carries the evidence. */
48
50
  export const NON_ANSWERABLE_PREFIX = "coverage:stateTest:";
49
51
  export function isNonAnswerable(objectionId) {
50
- return typeof objectionId === "string" && objectionId.startsWith(NON_ANSWERABLE_PREFIX);
52
+ return (typeof objectionId === "string" &&
53
+ objectionId.startsWith(NON_ANSWERABLE_PREFIX));
51
54
  }
52
55
  /** The objections a sentence alone does not close either. A change with no test
53
56
  * needs the test, and a defect with no test needs the test — a defect the code
@@ -59,9 +62,13 @@ export function isNonAnswerable(objectionId) {
59
62
  * Prose closed every uncovered change, including changes nothing prevented a test
60
63
  * from reaching. Runs 34423214322 and 34423217796 then lost three defects the
61
64
  * baseline reported: each was listed and closed by a sentence. */
62
- export const BLOCKER_ONLY_PREFIXES = ["coverage:change:", "defects:untested:"];
65
+ export const BLOCKER_ONLY_PREFIXES = [
66
+ "coverage:change:",
67
+ "defects:untested:",
68
+ ];
63
69
  export function needsBlocker(objectionId) {
64
- return typeof objectionId === "string" && BLOCKER_ONLY_PREFIXES.some((prefix) => objectionId.startsWith(prefix));
70
+ return (typeof objectionId === "string" &&
71
+ BLOCKER_ONLY_PREFIXES.some((prefix) => objectionId.startsWith(prefix)));
65
72
  }
66
73
  /** The objection raised below carries this prefix and the id it objects to. */
67
74
  export const REFUSED_ANSWER_PREFIX = "answers:refused:";
@@ -69,11 +76,13 @@ export const REFUSED_ANSWER_PREFIX = "answers:refused:";
69
76
  * objection STAYS OPEN — this says so, rather than letting the answer pass in
70
77
  * silence while the plan still owes the test. */
71
78
  export function refusedAnswerObjections(objections, acknowledged) {
72
- const raised = new Set(objections.map((objection) => objection.objectionId).filter((id) => isNonAnswerable(id) || needsBlocker(id)));
79
+ const raised = new Set(objections
80
+ .map((objection) => objection.objectionId)
81
+ .filter((id) => isNonAnswerable(id) || needsBlocker(id)));
73
82
  const refused = [];
74
83
  const seen = new Set();
75
84
  for (const entry of acknowledged) {
76
- const id = entry?.objectionId;
85
+ const id = entry.objectionId;
77
86
  if (typeof id !== "string" || !raised.has(id) || seen.has(id))
78
87
  continue;
79
88
  const answer = entry.answer;
@@ -81,7 +90,7 @@ export function refusedAnswerObjections(objections, acknowledged) {
81
90
  continue;
82
91
  // An answer that names a blocker DOES close an untested change, so it is not
83
92
  // refused. Only the sentence on its own is.
84
- if (needsBlocker(id) && String(entry?.blocker ?? "").trim().length > 0)
93
+ if (needsBlocker(id) && String(entry.blocker ?? "").trim().length > 0)
85
94
  continue;
86
95
  seen.add(id);
87
96
  refused.push({
@@ -7,7 +7,7 @@
7
7
  * ONE SLOT, last write wins. A run renders the prompt once, and a second render is
8
8
  * a second run whose text replaces the first. */
9
9
  let recorded;
10
- const asText = (value) => (typeof value === "string" ? value : "");
10
+ const asText = (value) => typeof value === "string" ? value : "";
11
11
  /** Called by every entry point that renders the testbot prompt, with the values it
12
12
  * renders. */
13
13
  export function recordPullRequestText(title, description) {
@@ -1,4 +1,4 @@
1
- import { answerFor, isNonAnswerable, refusedAnswerObjections, unknownAnswerObjections } from "./answers.js";
1
+ import { answerFor, isNonAnswerable, refusedAnswerObjections, unknownAnswerObjections, } from "./answers.js";
2
2
  import { runPlanTimeVerifiers } from "./runVerifiers.js";
3
3
  import { logger } from "../utils/logger.js";
4
4
  function storedRegistrationNumber(registration) {
@@ -16,19 +16,29 @@ function carriedAnswerFor(objectionId, previous) {
16
16
  // Both buckets: a blocker close is stored apart from an answer, and an objection
17
17
  // that recurs still carries the one it was closed with.
18
18
  const answered = [
19
- ...(Array.isArray(previous?.answeredObjections) ? previous.answeredObjections : []),
20
- ...(Array.isArray(previous?.unverifiedCloses) ? previous.unverifiedCloses : []),
19
+ ...(Array.isArray(previous?.answeredObjections)
20
+ ? previous.answeredObjections
21
+ : []),
22
+ ...(Array.isArray(previous?.unverifiedCloses)
23
+ ? previous.unverifiedCloses
24
+ : []),
21
25
  ];
22
26
  if (answered.length === 0)
23
27
  return undefined;
24
28
  for (const entry of answered) {
29
+ // `previous` is the plan read back from the state file, which is cast, not
30
+ // validated. A null entry there must not stop a new registration being stored.
25
31
  if (entry?.objection?.objectionId !== objectionId)
26
32
  continue;
27
33
  const answer = typeof entry.answer === "string" ? entry.answer.trim() : "";
28
34
  // The blocker travels with the answer it belongs to. Carrying the sentence
29
35
  // alone would reopen every untested change the previous registration closed.
30
36
  if (answer.length > 0)
31
- return { objectionId, answer, ...(entry.blocker ? { blocker: entry.blocker } : {}) };
37
+ return {
38
+ objectionId,
39
+ answer,
40
+ ...(entry.blocker ? { blocker: entry.blocker } : {}),
41
+ };
32
42
  }
33
43
  return undefined;
34
44
  }
@@ -50,16 +60,12 @@ function carriedAnswers(objections, acknowledged, previous) {
50
60
  return carried;
51
61
  }
52
62
  export function registerPlan(registration, ctx, previous) {
53
- const acknowledged = Array.isArray(registration.answers) ? registration.answers : [];
54
- const plannedTests = Array.isArray(registration.plannedTests) ? registration.plannedTests : [];
55
- const changes = Array.isArray(registration.changes) ? registration.changes : [];
56
- const defects = Array.isArray(registration.defects) ? registration.defects : [];
63
+ const acknowledged = registration.answers;
64
+ const plannedTests = registration.plannedTests;
65
+ const changes = registration.changes;
66
+ const defects = registration.defects;
57
67
  const registrationNumber = storedRegistrationNumber(registration);
58
- // The verifiers see the same normalised fields the STORED plan gets, not the raw
59
- // registration: handing them the raw one let a malformed top-level field crash
60
- // every check at once, giving eight `:crashed` objections and no real ones.
61
- // Crash containment is for a malformed field INSIDE a planned test.
62
- const verified = runPlanTimeVerifiers({ ...registration, plannedTests, changes, defects, answers: acknowledged }, ctx);
68
+ const verified = runPlanTimeVerifiers(registration, ctx);
63
69
  const objections = [
64
70
  ...verified,
65
71
  ...unknownAnswerObjections(verified, acknowledged, {
@@ -81,9 +87,12 @@ export function registerPlan(registration, ctx, previous) {
81
87
  // a planned test too, unless the answer names what stopped this run from
82
88
  // writing one. Either way an answer that does not close it leaves it open and
83
89
  // draws the refusal objection raised above.
84
- const answer = isNonAnswerable(objection.objectionId) ? undefined : answerFor(objection, answers);
90
+ const answer = isNonAnswerable(objection.objectionId)
91
+ ? undefined
92
+ : answerFor(objection, answers);
85
93
  if (answer) {
86
- const blocker = answers.find((entry) => entry?.objectionId === objection.objectionId && String(entry?.blocker ?? "").trim().length > 0)?.blocker;
94
+ const blocker = answers.find((entry) => entry.objectionId === objection.objectionId &&
95
+ String(entry.blocker ?? "").trim().length > 0)?.blocker;
87
96
  // A blocker closes the objection and nothing here can check it, so it is
88
97
  // counted apart from an answer the plan itself makes checkable.
89
98
  if (blocker)
@@ -104,7 +113,12 @@ export function registerPlan(registration, ctx, previous) {
104
113
  objections,
105
114
  summary,
106
115
  ...(carried.length > 0 && previous
107
- ? { carried: { registrationNumber: previous.registrationNumber, answers: carried } }
116
+ ? {
117
+ carried: {
118
+ registrationNumber: previous.registrationNumber,
119
+ answers: carried,
120
+ },
121
+ }
108
122
  : {}),
109
123
  plan: {
110
124
  changes,
@@ -112,7 +126,7 @@ export function registerPlan(registration, ctx, previous) {
112
126
  plannedTests,
113
127
  // Only when declared: the field is optional, and writing `[]` on every plan
114
128
  // would change the stored shape of every run that maintains nothing.
115
- ...(Array.isArray(registration.maintains) && registration.maintains.length > 0
129
+ ...(registration.maintains?.length
116
130
  ? { maintains: registration.maintains }
117
131
  : {}),
118
132
  answeredObjections,