@skyramp/mcp 0.4.1 → 0.4.2-rc.1

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 (543) hide show
  1. package/build/adapters/jestAdapter.js +23 -5
  2. package/build/adapters/mochaAdapter.js +7 -1
  3. package/build/adapters/playwrightAdapter.js +3 -1
  4. package/build/adapters/pytestAdapter.js +14 -3
  5. package/build/commands/localDevTestChangesCommand.js +1 -0
  6. package/build/commands/recommendTestsAndExecuteCommand.js +5 -6
  7. package/build/commands/testThisEndpointCommand.js +16 -4
  8. package/build/index.js +34 -4
  9. package/build/playwright/blueprintDigest.js +28 -7
  10. package/build/playwright/registerPlaywrightTools.js +33 -28
  11. package/build/playwright/traceRecordingPrompt.js +9 -2
  12. package/build/prompts/code-reuse.js +95 -29
  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 +3 -1
  17. package/build/prompts/local-dev/local-dev-prompts.d.ts +1 -1
  18. package/build/prompts/local-dev/local-dev-prompts.js +30 -3
  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 +88 -2
  26. package/build/prompts/shared-helper-policy.js +145 -11
  27. package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.js +1 -1
  28. package/build/prompts/sut-setup/modes/dockerComposePrompt.js +1 -1
  29. package/build/prompts/sut-setup/shared.d.ts +4 -1
  30. package/build/prompts/sut-setup/shared.js +2 -2
  31. package/build/prompts/test-maintenance/actionsInstructions.d.ts +19 -11
  32. package/build/prompts/test-maintenance/actionsInstructions.js +47 -26
  33. package/build/prompts/test-maintenance/drift-analysis-prompt.js +3 -2
  34. package/build/prompts/test-maintenance/driftAnalysisSections.js +5 -3
  35. package/build/prompts/test-maintenance/driftAnalysisShared.js +4 -2
  36. package/build/prompts/test-maintenance/uiDriftAnalysisSections.js +7 -4
  37. package/build/prompts/test-recommendation/recommendationSections.js +19 -8
  38. package/build/prompts/test-recommendation/registerRecommendTestsPrompt.js +5 -2
  39. package/build/prompts/test-recommendation/test-recommendation-prompt.js +10 -7
  40. package/build/prompts/testbot/testbot-prompts.js +123 -55
  41. package/build/recommendation/answers.js +18 -9
  42. package/build/recommendation/pullRequestText.js +1 -1
  43. package/build/recommendation/registerPlan.js +31 -17
  44. package/build/recommendation/subjectStep.d.ts +8 -10
  45. package/build/recommendation/subjectStep.js +17 -16
  46. package/build/recommendation/types.d.ts +71 -17
  47. package/build/recommendation/types.js +9 -15
  48. package/build/recommendation/verifierContracts.d.ts +7 -3
  49. package/build/recommendation/verifierContracts.js +8 -4
  50. package/build/recommendation/verifiers/changedFile.js +11 -13
  51. package/build/recommendation/verifiers/citedPath.d.ts +8 -0
  52. package/build/recommendation/verifiers/citedPath.js +16 -2
  53. package/build/recommendation/verifiers/coverage.d.ts +2 -2
  54. package/build/recommendation/verifiers/coverage.js +190 -134
  55. package/build/recommendation/verifiers/defects.js +56 -16
  56. package/build/recommendation/verifiers/deliveredMatchesPlan.d.ts +7 -1
  57. package/build/recommendation/verifiers/deliveredMatchesPlan.js +28 -14
  58. package/build/recommendation/verifiers/endpointGrounded.js +14 -8
  59. package/build/recommendation/verifiers/existingCoverage.d.ts +6 -0
  60. package/build/recommendation/verifiers/existingCoverage.js +30 -21
  61. package/build/recommendation/verifiers/expectedOutcome.js +17 -8
  62. package/build/recommendation/verifiers/expectedValueSourced.js +54 -43
  63. package/build/recommendation/verifiers/issueTraceability.d.ts +5 -0
  64. package/build/recommendation/verifiers/issueTraceability.js +64 -7
  65. package/build/recommendation/verifiers/removedElementGuarded.js +19 -11
  66. package/build/recommendation/verifiers/reportedCategory.js +9 -4
  67. package/build/recommendation/verifiers/requirementSourced.js +34 -21
  68. package/build/recommendation/verifiers/screenRoute.js +15 -10
  69. package/build/recommendation/verifiers/statedDifference.js +15 -8
  70. package/build/recommendation/verifiers/uiElementGrounded.js +50 -16
  71. package/build/resources/analysisResources.js +7 -3
  72. package/build/resources/progressResource.js +4 -2
  73. package/build/resources/sutSetupResource.js +20 -2
  74. package/build/resources/testbotResource.js +19 -1
  75. package/build/services/AnalyticsService.js +3 -1
  76. package/build/services/ScenarioGenerationService.js +5 -5
  77. package/build/services/TestDiscoveryService.js +21 -5
  78. package/build/services/TestExecutionService.js +63 -21
  79. package/build/services/TestGenerationService.d.ts +1 -1
  80. package/build/services/TestGenerationService.js +43 -24
  81. package/build/skills/enhanceAssertionsSkill.d.ts +45 -0
  82. package/build/skills/enhanceAssertionsSkill.js +103 -0
  83. package/build/skills/fixTestImportErrorsSkill.d.ts +2 -2
  84. package/build/skills/fixTestImportErrorsSkill.js +2 -2
  85. package/build/skills/skillFiles.d.ts +38 -0
  86. package/build/skills/skillFiles.js +94 -0
  87. package/build/skills/validateAssertionAlignmentSkill.d.ts +34 -0
  88. package/build/skills/validateAssertionAlignmentSkill.js +59 -0
  89. package/build/tool-phases.js +4 -0
  90. package/build/tools/auth/loginTool.js +3 -1
  91. package/build/tools/auth/logoutTool.js +3 -1
  92. package/build/tools/code-refactor/alignAssertionsTool.d.ts +2 -0
  93. package/build/tools/code-refactor/alignAssertionsTool.js +51 -0
  94. package/build/tools/code-refactor/assertion-state.d.ts +1 -1
  95. package/build/tools/code-refactor/assertion-state.js +1 -1
  96. package/build/tools/code-refactor/assertionOperations.d.ts +44 -0
  97. package/build/tools/code-refactor/assertionOperations.js +82 -0
  98. package/build/tools/code-refactor/assertionSkillTools.d.ts +3 -0
  99. package/build/tools/code-refactor/assertionSkillTools.js +86 -0
  100. package/build/tools/code-refactor/codeReuseTool.js +27 -3
  101. package/build/tools/code-refactor/enhanceAssertionsTool.js +19 -83
  102. package/build/tools/code-refactor/gate-markers.d.ts +51 -0
  103. package/build/tools/code-refactor/gate-markers.js +95 -0
  104. package/build/tools/code-refactor/retrofit-state.d.ts +3 -1
  105. package/build/tools/code-refactor/retrofit-state.js +44 -2
  106. package/build/tools/code-refactor/reuse-outcome.d.ts +23 -1
  107. package/build/tools/code-refactor/reuse-outcome.js +36 -13
  108. package/build/tools/code-refactor/reuse-state.d.ts +90 -16
  109. package/build/tools/code-refactor/reuse-state.js +191 -61
  110. package/build/tools/code-refactor/utils-verify-gates.d.ts +4 -0
  111. package/build/tools/code-refactor/utils-verify-gates.js +252 -27
  112. package/build/tools/code-refactor/verify-gates.d.ts +15 -1
  113. package/build/tools/code-refactor/verify-gates.js +36 -4
  114. package/build/tools/enrichTestWithMocksTool.d.ts +1 -1
  115. package/build/tools/enrichTestWithMocksTool.js +9 -5
  116. package/build/tools/executeSkyrampTestTool.d.ts +22 -1
  117. package/build/tools/executeSkyrampTestTool.js +571 -271
  118. package/build/tools/execution-video-state.js +1 -1
  119. package/build/tools/fixErrorTool.js +5 -6
  120. package/build/tools/generate-tests/batchMockGenerationTool.js +1 -1
  121. package/build/tools/generate-tests/generateBatchScenarioRestTool.js +114 -73
  122. package/build/tools/generate-tests/generateContractRestTool.js +34 -16
  123. package/build/tools/generate-tests/generateE2ERestTool.d.ts +1 -0
  124. package/build/tools/generate-tests/generateE2ERestTool.js +9 -1
  125. package/build/tools/generate-tests/generateIntegrationRestTool.js +22 -7
  126. package/build/tools/generate-tests/generateMockRestTool.js +3 -1
  127. package/build/tools/generate-tests/generateUIRestTool.d.ts +2 -0
  128. package/build/tools/generate-tests/generateUIRestTool.js +11 -2
  129. package/build/tools/generate-tests/loadTestSchema.js +1 -3
  130. package/build/tools/generate-tests/planGuard.js +6 -3
  131. package/build/tools/generate-tests/scenarioFileIdentity.js +4 -1
  132. package/build/tools/generate-tests/scenarioLint.js +17 -5
  133. package/build/tools/generate-tests/trace-reuse-guard.js +5 -2
  134. package/build/tools/generateEnrichedIntegrationTestTool.js +9 -3
  135. package/build/tools/one-click/oneClickTool.js +3 -1
  136. package/build/tools/preflightMockCheckTool.js +23 -7
  137. package/build/tools/runExistingTestsTool.d.ts +1 -1
  138. package/build/tools/runExistingTestsTool.js +43 -21
  139. package/build/tools/submitReportTool.d.ts +51 -12
  140. package/build/tools/submitReportTool.js +860 -161
  141. package/build/tools/test-management/actionsTool.js +210 -51
  142. package/build/tools/test-management/analyzeChangesTool.d.ts +4 -5
  143. package/build/tools/test-management/analyzeChangesTool.js +127 -68
  144. package/build/tools/test-management/analyzeTestHealthTool.js +35 -13
  145. package/build/tools/test-management/registerTestPlanTool.d.ts +44 -34
  146. package/build/tools/test-management/registerTestPlanTool.js +255 -111
  147. package/build/tools/test-management/resolveScreenTool.js +33 -9
  148. package/build/tools/trace/startTraceCollectionTool.js +3 -1
  149. package/build/tools/trace/stopTraceCollectionTool.js +41 -5
  150. package/build/tools/verifyTestDependenciesTool.d.ts +3 -0
  151. package/build/tools/verifyTestDependenciesTool.js +54 -0
  152. package/build/tools/workspace/initScanWorkspaceTool.js +9 -3
  153. package/build/tools/workspace/initializeWorkspaceTool.js +3 -1
  154. package/build/types/AssertionOutcome.d.ts +1 -1
  155. package/build/types/EnhanceType.d.ts +6 -0
  156. package/build/types/EnhanceType.js +1 -0
  157. package/build/types/ExternalTestExecution.d.ts +2 -2
  158. package/build/types/RepositoryAnalysis.d.ts +0 -40
  159. package/build/types/ReuseOutcome.d.ts +96 -4
  160. package/build/types/ReuseOutcome.js +16 -0
  161. package/build/types/StepMethod.js +20 -6
  162. package/build/types/TestAnalysis.d.ts +10 -2
  163. package/build/types/TestExecution.d.ts +45 -0
  164. package/build/types/TestRecommendation.d.ts +1 -1
  165. package/build/types/TestRecommendation.js +4 -1
  166. package/build/types/TestTypes.d.ts +13 -0
  167. package/build/types/TestTypes.js +34 -3
  168. package/build/types/TestbotPromptOptions.d.ts +9 -1
  169. package/build/types/TestbotReport.d.ts +45 -9
  170. package/build/utils/AnalysisStateManager.d.ts +137 -27
  171. package/build/utils/AnalysisStateManager.js +227 -43
  172. package/build/utils/assertion-verify/api-shared-lints.js +34 -16
  173. package/build/utils/assertion-verify/metrics.js +39 -6
  174. package/build/utils/assertion-verify/ui-lints.js +4 -2
  175. package/build/utils/branchDiff.js +47 -12
  176. package/build/utils/canonicalJson.js +3 -1
  177. package/build/utils/dartRouteExtractor.js +36 -7
  178. package/build/utils/fixAttempts.d.ts +26 -0
  179. package/build/utils/fixAttempts.js +109 -0
  180. package/build/utils/frontendSelectors.js +23 -4
  181. package/build/utils/generatedTestRecord.d.ts +19 -0
  182. package/build/utils/generatedTestRecord.js +61 -0
  183. package/build/utils/gitStaging.js +7 -2
  184. package/build/utils/initAgent.js +26 -6
  185. package/build/utils/language-helper.js +39 -45
  186. package/build/utils/pathMatching.js +2 -1
  187. package/build/utils/pathSignatures.js +6 -2
  188. package/build/utils/planMatchKeys.d.ts +2 -2
  189. package/build/utils/planMatchKeys.js +20 -14
  190. package/build/utils/pom-catalog-parse.js +7 -2
  191. package/build/utils/pom-scope/import-expansion.js +6 -1
  192. package/build/utils/pom-scope/index.js +50 -12
  193. package/build/utils/pom-scope/scoring.js +13 -3
  194. package/build/utils/pom-scope/selector-extractor.js +16 -3
  195. package/build/utils/pom-scope/strip.d.ts +8 -0
  196. package/build/utils/pom-scope/strip.js +238 -0
  197. package/build/utils/pom-scope/testIdDiscovery.js +14 -2
  198. package/build/utils/pom-verify/__fixtures__/af-style/asset-list.page.d.ts +1 -1
  199. package/build/utils/pom-verify/__fixtures__/af-style/asset-list.page.js +4 -2
  200. package/build/utils/pom-verify/__fixtures__/af-style/report.iframe.page.js +3 -1
  201. package/build/utils/pom-verify/__fixtures__/af-style/workflow-footer.page.js +3 -1
  202. package/build/utils/pom-verify/bindings.js +5 -1
  203. package/build/utils/pom-verify/calls.js +9 -2
  204. package/build/utils/pom-verify/verify.js +27 -5
  205. package/build/utils/pr-comment-parser.js +20 -7
  206. package/build/utils/proxy-terminal.d.ts +19 -1
  207. package/build/utils/proxy-terminal.js +346 -21
  208. package/build/utils/removedUiElements.js +1 -1
  209. package/build/utils/reportLanguage.js +35 -7
  210. package/build/utils/reportVerification.d.ts +14 -8
  211. package/build/utils/reportVerification.js +19 -19
  212. package/build/utils/repositorySlug.d.ts +32 -0
  213. package/build/utils/repositorySlug.js +77 -0
  214. package/build/utils/reuseRouting.js +6 -2
  215. package/build/utils/runSerialized.d.ts +3 -0
  216. package/build/utils/runSerialized.js +39 -0
  217. package/build/utils/screenRoutes.js +74 -18
  218. package/build/utils/sourceRouteExtractor.js +13 -6
  219. package/build/utils/telemetry.d.ts +1 -0
  220. package/build/utils/telemetry.js +8 -5
  221. package/build/utils/testDependencyPolicy.d.ts +9 -0
  222. package/build/utils/testDependencyPolicy.js +788 -0
  223. package/build/utils/testExecutionRecord.d.ts +90 -0
  224. package/build/utils/testExecutionRecord.js +267 -0
  225. package/build/utils/testFileClassification.js +3 -1
  226. package/build/utils/trace-parser.js +62 -14
  227. package/build/utils/urlPath.js +3 -1
  228. package/build/utils/utils-verify/action-key.d.ts +4 -0
  229. package/build/utils/utils-verify/action-key.js +2 -2
  230. package/build/utils/utils-verify/allow.d.ts +122 -3
  231. package/build/utils/utils-verify/allow.js +146 -21
  232. package/build/utils/utils-verify/body-reach.d.ts +120 -0
  233. package/build/utils/utils-verify/body-reach.js +335 -0
  234. package/build/utils/utils-verify/call-sites.d.ts +6 -1
  235. package/build/utils/utils-verify/call-sites.js +72 -8
  236. package/build/utils/utils-verify/delivered-imports.d.ts +43 -0
  237. package/build/utils/utils-verify/delivered-imports.js +84 -0
  238. package/build/utils/utils-verify/fixed-sleep.d.ts +96 -0
  239. package/build/utils/utils-verify/fixed-sleep.js +461 -0
  240. package/build/utils/utils-verify/in-house.d.ts +93 -0
  241. package/build/utils/utils-verify/in-house.js +719 -0
  242. package/build/utils/utils-verify/incumbent.d.ts +3 -0
  243. package/build/utils/utils-verify/incumbent.js +75 -0
  244. package/build/utils/utils-verify/index.d.ts +1 -0
  245. package/build/utils/utils-verify/index.js +1 -0
  246. package/build/utils/utils-verify/language-spec.d.ts +26 -10
  247. package/build/utils/utils-verify/language-spec.js +217 -20
  248. package/build/utils/utils-verify/locate.d.ts +26 -0
  249. package/build/utils/utils-verify/locate.js +125 -23
  250. package/build/utils/utils-verify/module-name.d.ts +40 -0
  251. package/build/utils/utils-verify/module-name.js +98 -0
  252. package/build/utils/utils-verify/parse.d.ts +46 -6
  253. package/build/utils/utils-verify/parse.js +176 -38
  254. package/build/utils/utils-verify/retrofit-equivalence.d.ts +5 -0
  255. package/build/utils/utils-verify/retrofit-equivalence.js +4 -2
  256. package/build/utils/utils-verify/stage.d.ts +5 -0
  257. package/build/utils/utils-verify/stage.js +47 -2
  258. package/build/utils/utils-verify/status-once.d.ts +62 -0
  259. package/build/utils/utils-verify/status-once.js +207 -0
  260. package/build/utils/utils-verify/typecheck.d.ts +61 -0
  261. package/build/utils/utils-verify/typecheck.js +338 -0
  262. package/build/utils/utils-verify/verify.d.ts +76 -1
  263. package/build/utils/utils-verify/verify.js +516 -44
  264. package/build/utils/versions.d.ts +3 -3
  265. package/build/utils/versions.js +1 -1
  266. package/build/utils/workspaceAuth.js +107 -37
  267. package/build/workspace/queryParamResolution.js +11 -4
  268. package/build/workspace/workspace.js +7 -7
  269. package/node_modules/playwright/ThirdPartyNotices.txt +19 -19
  270. package/node_modules/playwright/lib/mcp/skyramp/assertTool.js +8 -2
  271. package/node_modules/playwright/lib/mcp/skyramp/common/cssValue.js +87 -0
  272. package/node_modules/playwright/lib/mcp/skyramp/loadTraceTool.js +31 -0
  273. package/node_modules/playwright/lib/mcp/skyramp/skyRampImport.js +3 -0
  274. package/node_modules/playwright/lib/mcp/skyramp/traceRecordingBackend.js +181 -15
  275. package/node_modules/playwright/lib/mcp/test/skyRampExport.js +24 -0
  276. package/node_modules/playwright/lib/transform/babelBundleImpl.js +2353 -190
  277. package/node_modules/playwright/node_modules/playwright-core/ThirdPartyNotices.txt +62 -34
  278. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/.package-lock.json +72 -41
  279. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/@hono/node-server/dist/serve-static.js +1 -1
  280. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/@hono/node-server/dist/serve-static.mjs +1 -1
  281. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/@hono/node-server/package.json +2 -2
  282. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/README.md +16 -1
  283. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/index.js +4 -20
  284. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/lib/read.js +17 -17
  285. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/lib/types/json.js +60 -32
  286. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/lib/types/raw.js +3 -3
  287. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/lib/types/text.js +3 -3
  288. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/lib/types/urlencoded.js +16 -20
  289. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/lib/utils.js +18 -16
  290. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/node_modules/content-type/LICENSE +22 -0
  291. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/node_modules/content-type/README.md +71 -0
  292. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/node_modules/content-type/dist/index.d.ts +46 -0
  293. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/node_modules/content-type/dist/index.js +176 -0
  294. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/node_modules/content-type/dist/index.js.map +1 -0
  295. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/node_modules/content-type/package.json +52 -0
  296. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/body-parser/package.json +23 -10
  297. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/es-object-atoms/CHANGELOG.md +21 -14
  298. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/es-object-atoms/isObject.d.ts +1 -1
  299. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/es-object-atoms/package.json +6 -7
  300. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/es-object-atoms/tsconfig.json +1 -0
  301. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/index.js +266 -45
  302. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/lib/schemes.js +9 -4
  303. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/lib/utils.js +396 -92
  304. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/package.json +1 -1
  305. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/component-safe-serialization.test.js +163 -0
  306. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/equal.test.js +31 -3
  307. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/fixtures/uri-js-parse.json +2 -0
  308. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/ipv6-canonical.test.js +34 -0
  309. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/ipv6-validation.test.js +124 -0
  310. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/malformed-percent.test.js +77 -0
  311. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/malformed-urn.test.js +61 -0
  312. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/parse.test.js +7 -3
  313. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/query-fragment-normalization.test.js +33 -0
  314. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/reserved-path-normalization.test.js +109 -0
  315. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/scheme-validation.test.js +124 -0
  316. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/security-normalization.test.js +101 -0
  317. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/security.test.js +301 -3
  318. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/urn-full-input.test.js +29 -0
  319. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/fast-uri/test/websocket-query-preservation.test.js +24 -0
  320. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hasown/CHANGELOG.md +7 -0
  321. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hasown/index.d.ts +0 -1
  322. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hasown/package.json +4 -5
  323. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/client/client.js +30 -16
  324. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/client/utils.js +4 -1
  325. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/context.js +32 -13
  326. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/accepts/accepts.js +36 -2
  327. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/proxy/index.js +4 -0
  328. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/ssg/ssg.js +1 -1
  329. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/ssg/utils.js +30 -10
  330. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/helper/streaming/sse.js +5 -4
  331. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/hono-base.js +10 -8
  332. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/base.js +44 -23
  333. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/components.js +25 -26
  334. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/context.js +5 -5
  335. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/dom/render.js +2 -0
  336. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/dom/server.js +5 -1
  337. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/hooks/index.js +16 -13
  338. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/intrinsic-element/components.js +3 -3
  339. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/jsx/streaming.js +4 -5
  340. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/cache/index.js +103 -8
  341. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/compress/index.js +5 -0
  342. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/cors/index.js +17 -14
  343. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/csrf/index.js +1 -1
  344. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/etag/digest.js +47 -1
  345. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/etag/index.js +7 -4
  346. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/jwk/jwk.js +9 -4
  347. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/jwt/jwt.js +9 -4
  348. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/language/language.js +10 -6
  349. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/method-not-allowed/index.js +90 -0
  350. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/pretty-json/index.js +3 -1
  351. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/middleware/secure-headers/secure-headers.js +16 -7
  352. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/request.js +20 -13
  353. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/linear-router/router.js +7 -2
  354. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/pattern-router/router.js +3 -9
  355. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/reg-exp-router/node.js +65 -59
  356. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/reg-exp-router/router.js +71 -128
  357. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/reg-exp-router/trie.js +14 -5
  358. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/trie-router/node.js +47 -70
  359. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/trie-router/router.js +3 -11
  360. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router/utils.js +27 -0
  361. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/router.js +1 -1
  362. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/accept.js +1 -1
  363. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/body.js +21 -3
  364. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/cookie.js +4 -3
  365. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/ipaddr.js +5 -3
  366. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/stream.js +12 -3
  367. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/cjs/utils/url.js +19 -11
  368. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/client/client.js +30 -16
  369. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/client/utils.js +4 -1
  370. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/context.js +32 -13
  371. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/accepts/accepts.js +36 -2
  372. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/proxy/index.js +4 -0
  373. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/ssg/ssg.js +1 -1
  374. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/ssg/utils.js +30 -10
  375. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/helper/streaming/sse.js +5 -4
  376. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/hono-base.js +10 -8
  377. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/base.js +41 -23
  378. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/components.js +26 -27
  379. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/context.js +6 -6
  380. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/dom/render.js +2 -0
  381. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/dom/server.js +5 -1
  382. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/hooks/index.js +16 -13
  383. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/intrinsic-element/components.js +4 -4
  384. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/jsx/streaming.js +5 -6
  385. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/cache/index.js +103 -8
  386. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/compress/index.js +5 -0
  387. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/cors/index.js +17 -14
  388. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/csrf/index.js +1 -1
  389. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/etag/digest.js +47 -1
  390. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/etag/index.js +7 -4
  391. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/jwk/jwk.js +9 -4
  392. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/jwt/jwt.js +9 -4
  393. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/language/language.js +10 -6
  394. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/method-not-allowed/index.js +68 -0
  395. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/pretty-json/index.js +3 -1
  396. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/middleware/secure-headers/secure-headers.js +16 -7
  397. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/request.js +21 -14
  398. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/linear-router/router.js +7 -2
  399. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/pattern-router/router.js +3 -9
  400. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/reg-exp-router/node.js +61 -58
  401. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/reg-exp-router/router.js +77 -129
  402. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/reg-exp-router/trie.js +14 -5
  403. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/trie-router/node.js +47 -70
  404. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/trie-router/router.js +3 -11
  405. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router/utils.js +5 -0
  406. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/router.js +1 -1
  407. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/adapter/aws-lambda/types.d.ts +9 -0
  408. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/client/types.d.ts +1 -1
  409. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/context.d.ts +6 -2
  410. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/hono-base.d.ts +4 -3
  411. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/base.d.ts +7 -2
  412. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/dom/index.d.ts +5 -5
  413. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/dom/intrinsic-element/components.d.ts +2 -2
  414. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/dom/server.d.ts +5 -5
  415. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/hooks/index.d.ts +8 -6
  416. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/jsx/index.d.ts +5 -5
  417. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/cache/index.d.ts +6 -4
  418. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/combine/index.d.ts +1 -1
  419. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/cors/index.d.ts +1 -1
  420. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/jsx-renderer/index.d.ts +2 -2
  421. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/jwk/jwk.d.ts +2 -0
  422. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/jwt/jwt.d.ts +2 -0
  423. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/method-not-allowed/index.d.ts +49 -0
  424. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/middleware/secure-headers/permissions-policy.d.ts +3 -3
  425. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/router/reg-exp-router/node.d.ts +4 -1
  426. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/router/reg-exp-router/trie.d.ts +2 -1
  427. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/router/trie-router/node.d.ts +1 -2
  428. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/router/trie-router/router.d.ts +0 -1
  429. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/router/utils.d.ts +1 -0
  430. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/router.d.ts +1 -1
  431. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/utils/headers.d.ts +2 -2
  432. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/types/utils/url.d.ts +5 -0
  433. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/accept.js +1 -1
  434. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/body.js +21 -3
  435. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/cookie.js +5 -4
  436. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/ipaddr.js +5 -3
  437. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/stream.js +12 -3
  438. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/dist/utils/url.js +17 -10
  439. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/hono/package.json +11 -4
  440. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/README.md +173 -143
  441. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/address-error.d.ts +11 -0
  442. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/address-error.js.map +1 -1
  443. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/common.d.ts +49 -0
  444. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/common.js +79 -4
  445. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/common.js.map +1 -1
  446. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/ipv4.d.ts +78 -5
  447. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/ipv4.js +119 -24
  448. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/ipv4.js.map +1 -1
  449. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/ipv6.d.ts +151 -10
  450. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/ipv6.js +316 -90
  451. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/ipv6.js.map +1 -1
  452. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/v4/constants.d.ts +12 -0
  453. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/v4/constants.js +45 -2
  454. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/v4/constants.js.map +1 -1
  455. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/v6/constants.d.ts +14 -0
  456. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/v6/constants.js +50 -3
  457. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/dist/v6/constants.js.map +1 -1
  458. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/ip-address/package.json +6 -4
  459. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/.github/THREAT_MODEL.md +3 -3
  460. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/CHANGELOG.md +26 -0
  461. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/README.md +19 -1
  462. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/dist/qs.js +25 -25
  463. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/eslint.config.mjs +1 -1
  464. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/lib/parse.js +16 -6
  465. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/lib/stringify.js +23 -8
  466. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/lib/utils.js +57 -11
  467. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/package.json +8 -7
  468. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/test/parse.js +419 -0
  469. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/test/stringify.js +317 -0
  470. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/qs/test/utils.js +206 -0
  471. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/side-channel/CHANGELOG.md +10 -0
  472. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/side-channel/README.md +1 -1
  473. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/side-channel/index.js +5 -2
  474. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/side-channel/package.json +10 -10
  475. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/side-channel/test/index.js +16 -0
  476. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/index.js +8 -18
  477. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/node_modules/content-type/LICENSE +22 -0
  478. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/node_modules/content-type/README.md +71 -0
  479. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/node_modules/content-type/dist/index.d.ts +46 -0
  480. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/node_modules/content-type/dist/index.js +176 -0
  481. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/node_modules/content-type/dist/index.js.map +1 -0
  482. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/node_modules/content-type/package.json +52 -0
  483. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/type-is/package.json +9 -5
  484. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/package-lock.json +72 -41
  485. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/.package-lock.json +6 -6
  486. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/brace-expansion/README.md +23 -1
  487. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/brace-expansion/index.js +265 -86
  488. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/brace-expansion/package.json +1 -1
  489. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/README.md +173 -143
  490. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/address-error.d.ts +11 -0
  491. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/address-error.js.map +1 -1
  492. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/common.d.ts +49 -0
  493. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/common.js +79 -4
  494. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/common.js.map +1 -1
  495. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/ipv4.d.ts +78 -5
  496. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/ipv4.js +119 -24
  497. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/ipv4.js.map +1 -1
  498. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/ipv6.d.ts +151 -10
  499. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/ipv6.js +316 -90
  500. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/ipv6.js.map +1 -1
  501. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/v4/constants.d.ts +12 -0
  502. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/v4/constants.js +45 -2
  503. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/v4/constants.js.map +1 -1
  504. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/v6/constants.d.ts +14 -0
  505. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/v6/constants.js +50 -3
  506. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/dist/v6/constants.js.map +1 -1
  507. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/ip-address/package.json +6 -4
  508. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/package-lock.json +6 -6
  509. package/node_modules/playwright/node_modules/playwright-core/lib/cli/program.js +18 -9
  510. package/node_modules/playwright/node_modules/playwright-core/lib/mcpBundleImpl/index.js +47 -47
  511. package/node_modules/playwright/node_modules/playwright-core/lib/server/codegen/skyramp/jsonlReader.js +3 -0
  512. package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/recorderRunner.js +42 -0
  513. package/node_modules/playwright/node_modules/playwright-core/lib/utilsBundleImpl/index.js +121 -121
  514. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/{index.B7KbSQcC.js → index.BAkLd5DX.js} +1 -1
  515. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.html +1 -1
  516. package/node_modules/playwright/node_modules/playwright-core/package.json +1 -1
  517. package/node_modules/playwright/node_modules/playwright-core/src/cli/program.ts +31 -9
  518. package/node_modules/playwright/node_modules/playwright-core/src/server/codegen/skyramp/jsonlReader.ts +1 -0
  519. package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/recorderRunner.ts +57 -1
  520. package/node_modules/playwright/package.json +2 -2
  521. package/package.json +7 -6
  522. package/plugin/prompts/code-reuse/hand-off.md +30 -0
  523. package/plugin/prompts/generate-tests/generation.md +1 -1
  524. package/plugin/prompts/plan-tests.md +14 -14
  525. package/plugin/prompts/testbot-task1.md +4 -2
  526. package/plugin/skills/enhance-assertions/SKILL.md +25 -0
  527. package/plugin/skills/enhance-assertions/reference/contract.md +51 -0
  528. package/plugin/skills/enhance-assertions/reference/integration.md +58 -0
  529. package/plugin/skills/enhance-assertions/reference/shared-rules.md +220 -0
  530. package/plugin/skills/enhance-assertions/reference/ui.md +373 -0
  531. package/plugin/skills/fix-test-import-errors/SKILL.md +44 -50
  532. package/plugin/skills/validate-assertion-alignment-post-execution/SKILL.md +32 -0
  533. package/plugin/skills/validate-assertion-alignment-post-execution/reference/checks.md +44 -0
  534. package/plugin/skills/validate-assertion-alignment-post-execution/reference/evidence.md +47 -0
  535. package/build/prompts/enhance-assertions/contractProviderAssertionsPrompt.d.ts +0 -2
  536. package/build/prompts/enhance-assertions/contractProviderAssertionsPrompt.js +0 -29
  537. package/build/prompts/enhance-assertions/integrationAssertionsPrompt.d.ts +0 -2
  538. package/build/prompts/enhance-assertions/integrationAssertionsPrompt.js +0 -36
  539. package/build/prompts/enhance-assertions/sharedAssertionRules.d.ts +0 -16
  540. package/build/prompts/enhance-assertions/sharedAssertionRules.js +0 -284
  541. package/build/prompts/enhance-assertions/uiAssertionsPrompt.d.ts +0 -2
  542. package/build/prompts/enhance-assertions/uiAssertionsPrompt.js +0 -388
  543. package/node_modules/playwright/node_modules/playwright-core/.DS_Store +0 -0
@@ -1,17 +1,23 @@
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 { alignAssertionsStep } from "../../skills/validateAssertionAlignmentSkill.js";
16
+ import { ASSERTION_ENHANCEABLE_TEST_TYPES } from "../../types/TestTypes.js";
17
+ import { enhanceAssertionsCall } from "../../skills/enhanceAssertionsSkill.js";
13
18
  import { resolveServiceDetailsRef } from "../../utils/utils.js";
14
19
  import { section, sectionBody } from "../promptAssets.js";
20
+ import { CODE_REUSE_GENERATION_CLAUSE } from "../reuse-hand-off.js";
15
21
  import { readPromptAsset } from "../promptAssets.js";
16
22
  import { fillPlaceholders } from "../../recommendation/verifierContracts.js";
17
23
  import { buildServiceContext, readWorkspaceServices } from "../prompt-utils.js";
@@ -118,28 +124,31 @@ export const EXEC_FAIL = orderedLabels([
118
124
  "INFRA_RETRY",
119
125
  "REPORT_FAIL",
120
126
  ]);
127
+ function capitalize(text) {
128
+ return text.charAt(0).toUpperCase() + text.slice(1);
129
+ }
121
130
  // The UI enhance entry of the post-generation list. On the modularize-first UI
122
131
  // flow the enhance call is the first sub-step of the generation result's chain — but
123
132
  // that chain exists only for a TS/JS UI generation with enhanceAssertions on,
124
133
  // which this prompt cannot see per call. So the step keeps the call and lets
125
134
  // the agent skip it only when it already made it for that file.
126
135
  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.`;
136
+ ? `${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.`
137
+ : `${capitalize(enhanceAssertionsCall("ui", "generated UI test file"))}.`;
129
138
  // Post-generation code-reuse step for UI tests. The POM catalog, the `verify: true`
130
139
  // loop and the `.raw.bak` restore only exist on the POM-aware path — when that path
131
140
  // is flagged off, `skyramp_reuse_code` returns the SkyrampUtils workflow instead, so
132
141
  // the agent must not be sent looking for artifacts nothing produces.
133
142
  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).`
143
+ ? `${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
144
  : 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).`;
145
+ ? `${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).`
146
+ : `${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
147
  // Generation-call clause for the integration pipeline: only ask for codeReuse when
139
148
  // utils reuse is enabled — with the flag off, integration generation behaves exactly
140
149
  // as it did before the feature existed (no file-rewriting post-steps).
141
150
  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)`
151
+ ? CODE_REUSE_GENERATION_CLAUSE
143
152
  : ``;
144
153
  // The post-generation modularize → reuse steps are NOT listed here: the
145
154
  // generation tool's own result emits them (see TestGenerationService) when called
@@ -176,8 +185,40 @@ export function parseRelatedRepositories(raw) {
176
185
  return undefined;
177
186
  }
178
187
  }
188
+ // The UI-timeout diagnosis is the same whatever the budget: read the output,
189
+ // rule on the route, rule on a positional locator before the failing step. Only
190
+ // the "then retry" part depends on the cap, so the cap-of-one variant of the
191
+ // fix-up section shares these and drops the retry.
192
+ 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.`;
193
+ 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.
194
+ `;
195
+ // The two waits a late-element timeout gets. Rendered at every cap: at one the
196
+ // agent edits the delivered file and reports; above one it re-runs.
197
+ 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')\`.
198
+ 2. Add \`await page.locator('[data-testid="some-element"]').waitFor({ state: 'visible', timeout: 10000 });\` for the specific element the test needs.
199
+ Do NOT use \`page.waitForTimeout()\` with fixed delays.`;
200
+ 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.
201
+ - 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.
202
+ - 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.
203
+ `;
179
204
  export function getTestbotPrompt(opts) {
180
205
  const { prTitle, prDescription, repositoryPath, baseBranch, prNumber, userPrompt, services, uiCredentials, testsRepoDir, relatedRepositories, primaryRepo, planOnly = false, language, } = opts;
206
+ // The per-file execution attempt cap for the fix-and-rerun loop (SKYR-4460):
207
+ // the URI/prompt argument, else SKYRAMP_MAX_FIX_ATTEMPTS, else the default.
208
+ // Recorded for the run so skyramp_execute_test enforces the number this
209
+ // prompt states, not a second reading of the environment.
210
+ const maxFixAttempts = resolveMaxFixAttempts(opts.maxFixAttempts);
211
+ setMaxFixAttempts(maxFixAttempts);
212
+ const fixReruns = maxFixAttempts - 1;
213
+ const fixBudgetClause = fixReruns === 0
214
+ ? `the first run only — this run allows NO fix-and-rerun iteration`
215
+ : `the first run plus at most ${fixReruns} fix-and-rerun iteration${fixReruns === 1 ? "" : "s"}`;
216
+ // Rendering the prompt is where the run declares its primary checkout — the
217
+ // action passes its workingDirectory and its slug here. Write order must not
218
+ // decide it (SKYR-4333). Set, not set-if-unset: one server can render a second
219
+ // run for a different checkout, and keeping the first would route the second
220
+ // one as a related repository.
221
+ setPrimaryRepository({ repositoryPath, repo: primaryRepo });
181
222
  // Kept in the process for the plan tool, which is registered on this server.
182
223
  recordPullRequestText(prTitle, prDescription);
183
224
  // The legacy count arguments are DECLARED NOWHERE, so zod strips them and their
@@ -206,32 +247,40 @@ export function getTestbotPrompt(opts) {
206
247
  const analyzeBlock = fillPlaceholders(sectionBody(TESTBOT_TASK1_MD, "## Analyze the change"), {
207
248
  analyzeStep: TASK1.ANALYZE,
208
249
  repositoryPath,
250
+ primaryRepo,
209
251
  analyzeCountArgs,
210
252
  baseBranchArg: baseBranch ? `, \`baseBranch\`: "${baseBranch}"` : "",
211
253
  prNumberArg: prNumber ? `, \`prNumber\`: ${prNumber}` : "",
212
- testsRepoDirArg: testsRepoDir ? `, \`testsRepoDir\`: "${testsRepoDir}"` : "",
213
- uiCredentialsNote: uiCredentials ? ` ${sectionBody(TESTBOT_TASK1_MD, "## Log in before capturing")}` : "",
254
+ testsRepoDirArg: testsRepoDir
255
+ ? `, \`testsRepoDir\`: "${testsRepoDir}"`
256
+ : "",
257
+ uiCredentialsNote: uiCredentials
258
+ ? ` ${sectionBody(TESTBOT_TASK1_MD, "## Log in before capturing")}`
259
+ : "",
214
260
  submitTask: taskRef(TASK_SUBMIT),
215
261
  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");
262
+ }) +
263
+ (hasRelatedRepos
264
+ ? `\n\n ${fillPlaceholders(sectionBody(TESTBOT_TASK1_MD, "## Multi-repo context"), {
265
+ analyzeStep: TASK1.ANALYZE,
266
+ registerServicesStep: MULTIREPO.REGISTER_SERVICES,
267
+ analyzeRepoStep: MULTIREPO.ANALYZE_REPO,
268
+ onFailureStep: MULTIREPO.ON_FAILURE,
269
+ registerServicesRef: stepSubRef(TASK1.ANALYZE, MULTIREPO.REGISTER_SERVICES),
270
+ relatedRepoCount: relatedRepositories.length,
271
+ repoWord: relatedRepositories.length === 1 ? "repository" : "repositories",
272
+ callWord: relatedRepositories.length === 1 ? "call" : "calls",
273
+ repositoryPath,
274
+ primaryRepo,
275
+ generateTask: taskRef(TASK_GENERATE),
276
+ testRepoExclusionNote: testsRepoDir
277
+ ? " — NOT in the configured test repo, even though generated test files are delivered there"
278
+ : "",
279
+ testRepoExclusionShort: testsRepoDir
280
+ ? " and NOT the test repo"
281
+ : "",
282
+ })}`
283
+ : "\n");
235
284
  // SKYR-4023: user-facing report language. English display names improve
236
285
  // instruction-following vs bare codes; Intl.DisplayNames (Node >=18) names any
237
286
  // code correctly, falling back to the raw code only if it can't be resolved.
@@ -467,7 +516,8 @@ ${CONTRACT_MODE_GUIDANCE}
467
516
  - **\`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
517
  - **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
518
  - **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).
519
+ - **\`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).
520
+ - **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
521
  - **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
522
  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
523
  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 +587,36 @@ ${EXEC_FAIL.EXPECTED_FAILURE}. **Expected failure check (no retry):** If the fai
537
587
 
538
588
  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
589
 
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}.
590
+ 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
591
 
542
592
  **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
593
 
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:
594
+ ${maxFixAttempts === 1
595
+ ? `${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`
596
+ : `${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
597
  - 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
598
  - 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".
599
+ - Connection refused or timeout unrelated to the app under test\n`}
600
+ ${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.
601
+ 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.
602
+
603
+ ${maxFixAttempts === 1
604
+ ? `### UI Test Execution Fix-up (diagnosis only — this run's budget is one execution per file)
605
+ 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}
606
+ ${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.
607
+ ${UI_TIMEOUT_WAIT_STEPS}\n`
608
+ : `### UI Test Execution Fix-up (counts toward the ${maxFixAttempts}-attempt cap above)
609
+ ${UI_TIMEOUT_READ_OUTPUT}
610
+ ${UI_TIMEOUT_ROUTE_BULLET}${UI_TIMEOUT_POSITIONAL_BULLET}- **Otherwise** apply BOTH fixes in a single edit before retrying:
611
+ ${UI_TIMEOUT_WAIT_STEPS}
612
+ 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
613
 
559
614
  **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.
615
+ ${POSTGEN.INTEGRATION_ENHANCE}. **[MANDATORY] After \`skyramp_integration_test_generation\`**: ${capitalize(enhanceAssertionsCall("integration", "generated integration test file"))}.
616
+ ${POSTGEN.CONTRACT_ENHANCE}. **[MANDATORY] After \`skyramp_contract_test_generation\` with \`providerMode\`**: ${capitalize(enhanceAssertionsCall("contract", "generated provider contract test file"))}.
562
617
  ${UI_CODE_REUSE_STEP}
563
618
  ${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.
619
+ ${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
620
  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
621
 
567
622
  ${FINISH_CHECKS_BLOCK}
@@ -569,13 +624,15 @@ ${FINISH_CHECKS_BLOCK}
569
624
  **Execution timing:**
570
625
  - **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
626
  - **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]\`.
627
+ - **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 — 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
628
  - Only report test results for files you actually ran.
629
+
630
+ ### Post-Execution: Assertion Alignment
631
+ 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()}
632
+
574
633
  **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
634
  }
576
- const primaryRepoBlock = primaryRepo
577
- ? `<REPOSITORY>${primaryRepo}</REPOSITORY>\n`
578
- : "";
635
+ const primaryRepoBlock = `<REPOSITORY>${primaryRepo}</REPOSITORY>\n`;
579
636
  // Placed AHEAD of Task 1, not next to the register call in Task 2: the agent has
580
637
  // to name the changed file it is about, and cite the file it sits
581
638
  // in, and cite `routes` from the checkout, and all of those happen while
@@ -614,10 +671,9 @@ In these cases:
614
671
 
615
672
  ${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
673
 
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
- `
674
+
675
+ - **Repository attribution**: Set the \`repository\` field (\`owner/repo\`) on EVERY \`newTestsCreated\`, \`testResults\`, \`issuesFound\` and \`additionalRecommendations\` item. The primary repo's \`repository\` is \`${primaryRepo}\`.${hasRelatedRepos
676
+ ? ` 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
677
  : ""}
622
678
 
623
679
  ${getTraceRecordingPromptText({ outputDir: `${repositoryPath}/.skyramp`, modularize: false, modularizeViaGenerationResult: UI_UTILS_REUSE })}`;
@@ -670,8 +726,9 @@ export function registerTestbotPrompt(server) {
670
726
  .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
727
  primaryRepo: z
672
728
  .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."),
729
+ .trim()
730
+ .min(1)
731
+ .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
732
  planOnly: z
676
733
  // Prompt/resource URL args arrive as strings — accept "true"/"1"
677
734
  // alongside a real boolean; anything else (incl. undefined) is false.
@@ -682,6 +739,16 @@ export function registerTestbotPrompt(server) {
682
739
  .string()
683
740
  .optional()
684
741
  .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."),
742
+ // "perTest…" on the wire (the argument name reaches the agent's context;
743
+ // a bare "maxFixAttempts" reads as a run-wide total); `maxFixAttempts`
744
+ // in code.
745
+ perTestMaxFixAttempts: z
746
+ // Prompt args arrive as strings. The shared parser maps an unusable
747
+ // spelling or an out-of-range value to undefined, so this entry point
748
+ // falls through to SKYRAMP_MAX_FIX_ATTEMPTS and the default exactly
749
+ // like the resource does, instead of rejecting the call.
750
+ .preprocess((v) => parseMaxFixAttemptsArg(v), z.number().int().min(1).max(10).optional())
751
+ .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
752
  },
686
753
  }, async (args) => {
687
754
  const services = await readWorkspaceServices(args.repositoryPath);
@@ -699,6 +766,7 @@ export function registerTestbotPrompt(server) {
699
766
  primaryRepo: args.primaryRepo,
700
767
  planOnly: args.planOnly,
701
768
  language: args.language,
769
+ maxFixAttempts: args.perTestMaxFixAttempts,
702
770
  });
703
771
  if (args.workspaceValidationFailed) {
704
772
  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,
@@ -1,36 +1,34 @@
1
- import { ScenarioStep } from "../types/RepositoryAnalysis.js";
2
- import { PlannedTest } from "./types.js";
1
+ import { PlannedStep, PlannedTest } from "./types.js";
3
2
  export declare const HTTP_METHODS: ReadonlySet<string>;
4
3
  /** Whether the planned test carries a `ui` or `e2e` label. The label alone exempts
5
4
  * nothing (see `isUICandidate`); the schema reads it alone only for a planned test
6
5
  * with no steps to look at. */
7
6
  export declare function hasUITestTypeLabel(rawTestType: unknown): boolean;
8
7
  /** Whether a step is an HTTP call: a real request method AND a path, since a verb
9
- * with no path names no route. `interactionType` is deliberately not consulted —
10
- * it labels what a step exercises, not how it reaches the app. Applied PER STEP. */
11
- export declare function isHTTPStep(step: ScenarioStep | undefined): boolean;
8
+ * with no path names no route. Applied PER STEP. */
9
+ export declare function isHTTPStep(step: PlannedStep | undefined): boolean;
12
10
  /** Whether a step calls the app rather than driving a screen: anything with a
13
11
  * target whose method is not a page interaction, so an HTTP request and an
14
12
  * `OPERATION` both count. The page interactions are the closed set. */
15
- export declare function isCallStep(step: ScenarioStep | undefined): boolean;
13
+ export declare function isCallStep(step: PlannedStep | undefined): boolean;
16
14
  /** Whether a planned test is exempt from the route checks. A UI test's endpoints are
17
15
  * attributions the agent wrote, not what it asserts. THE LABEL DECIDES: inferring
18
16
  * from method names read a fixed list of HTTP verbs, so a GraphQL or Thrift call
19
17
  * looked like a browser click. Every verifier reads this one function. */
20
18
  export declare function isUIPlannedTest(plannedTest: PlannedTest): boolean;
21
19
  /** Every step that calls the app rather than driving a screen. */
22
- export declare function callSteps(plannedTest: PlannedTest): ScenarioStep[];
20
+ export declare function callSteps(plannedTest: PlannedTest): PlannedStep[];
23
21
  /** The step a planned test's test is about: the one `stepUnderTest` names, or the only
24
22
  * call the planned test makes. A planned test that makes several calls and names none
25
23
  * has NO subject — the agent states it and the server asks when it is missing,
26
24
  * rather than ranking write methods and path prefixes to guess. A `stepUnderTest`
27
25
  * matching no call is undefined too: the declaration is wrong, not a hint. */
28
- export declare function subjectStep(plannedTest: PlannedTest): ScenarioStep | undefined;
26
+ export declare function subjectStep(plannedTest: PlannedTest): PlannedStep | undefined;
29
27
  /** One step's route as a single key, `METHOD path`. The method is trimmed and
30
28
  * upper-cased, because a method is case-insensitive by protocol; the PATH is
31
29
  * compared AS WRITTEN, so two spellings of one route stay two routes. A step
32
30
  * with no path names no route and gets no key. */
33
- export declare function stepRouteKey(step: ScenarioStep | undefined): string | undefined;
31
+ export declare function stepRouteKey(step: PlannedStep | undefined): string | undefined;
34
32
  /** One step's route as `METHOD path` with every record id folded to `{id}`.
35
33
  *
36
34
  * The state test asks whether the PLAN covers a route, and the id a step happened
@@ -39,4 +37,4 @@ export declare function stepRouteKey(step: ScenarioStep | undefined): string | u
39
37
  * close one by renumbering (run 33988304641, LB03). `stepRouteKey` keeps the path
40
38
  * as written because `statedDifference` asks the opposite question — whether two
41
39
  * planned tests test the same thing — and there two spellings must stay two. */
42
- export declare function stateRouteKey(step: ScenarioStep | undefined): string | undefined;
40
+ export declare function stateRouteKey(step: PlannedStep | undefined): string | undefined;