@skyramp/mcp 0.2.6 → 0.2.8-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 (248) hide show
  1. package/build/commands/commandLibrary.d.ts +12 -0
  2. package/build/commands/recommendTestsAndExecuteCommand.d.ts +2 -0
  3. package/build/commands/testThisEndpointCommand.d.ts +2 -0
  4. package/build/index.d.ts +2 -0
  5. package/build/index.js +6 -4
  6. package/build/playwright/PlaywrightTraceService.d.ts +32 -0
  7. package/build/playwright/index.d.ts +3 -0
  8. package/build/playwright/registerPlaywrightTools.d.ts +8 -0
  9. package/build/playwright/registerPlaywrightTools.js +12 -11
  10. package/build/playwright/traceRecordingPrompt.d.ts +13 -0
  11. package/build/playwright/traceRecordingPrompt.js +3 -11
  12. package/build/prompts/code-reuse.d.ts +1 -0
  13. package/build/prompts/enhance-assertions/contractProviderAssertionsPrompt.d.ts +2 -0
  14. package/build/prompts/enhance-assertions/integrationAssertionsPrompt.d.ts +2 -0
  15. package/build/prompts/enhance-assertions/sharedAssertionRules.d.ts +15 -0
  16. package/build/prompts/enhance-assertions/uiAssertionsPrompt.d.ts +2 -0
  17. package/build/prompts/enhance-assertions/uiAssertionsPrompt.js +24 -5
  18. package/build/prompts/fix-error-prompt.d.ts +1 -0
  19. package/build/prompts/initialize-workspace/initializeWorkspacePrompt.d.ts +1 -0
  20. package/build/prompts/modularization/integration-test-modularization.d.ts +1 -0
  21. package/build/prompts/modularization/ui-test-modularization.d.ts +1 -0
  22. package/build/prompts/personas.d.ts +21 -0
  23. package/build/prompts/pom-aware-code-reuse.d.ts +1 -0
  24. package/build/prompts/startTraceCollectionPrompts.d.ts +2 -0
  25. package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.d.ts +2 -0
  26. package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.js +114 -0
  27. package/build/prompts/sut-setup/modes/dockerComposePrompt.d.ts +2 -0
  28. package/build/prompts/sut-setup/modes/dockerComposePrompt.js +292 -0
  29. package/build/prompts/sut-setup/shared.d.ts +39 -0
  30. package/build/prompts/sut-setup/shared.js +132 -0
  31. package/build/prompts/test-maintenance/actionsInstructions.d.ts +35 -0
  32. package/build/prompts/test-maintenance/drift-analysis-prompt.d.ts +4 -0
  33. package/build/prompts/test-maintenance/driftAnalysisSections.d.ts +13 -0
  34. package/build/prompts/test-maintenance/driftAnalysisSections.js +9 -3
  35. package/build/prompts/test-recommendation/analysisOutputPrompt.d.ts +84 -0
  36. package/build/prompts/test-recommendation/analysisOutputPrompt.js +1 -1
  37. package/build/prompts/test-recommendation/analysisOutputPrompt.test.d.ts +1 -0
  38. package/build/prompts/test-recommendation/analysisOutputPrompt.test.js +1 -0
  39. package/build/prompts/test-recommendation/diffExecutionPlan.d.ts +17 -0
  40. package/build/prompts/test-recommendation/diffExecutionPlan.js +83 -18
  41. package/build/prompts/test-recommendation/fullRepoCatalog.d.ts +7 -0
  42. package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.d.ts +1 -0
  43. package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.js +1 -0
  44. package/build/prompts/test-recommendation/promptPlan.d.ts +203 -0
  45. package/build/prompts/test-recommendation/promptPlan.test.d.ts +1 -0
  46. package/build/prompts/test-recommendation/recommendationSections.d.ts +35 -0
  47. package/build/prompts/test-recommendation/recommendationShared.d.ts +31 -0
  48. package/build/prompts/test-recommendation/registerRecommendTestsPrompt.d.ts +7 -0
  49. package/build/prompts/test-recommendation/scopeAssessment.d.ts +55 -0
  50. package/build/prompts/test-recommendation/scopeAssessment.js +2 -2
  51. package/build/prompts/test-recommendation/scopeAssessment.test.d.ts +1 -0
  52. package/build/prompts/test-recommendation/scopeAssessment.test.js +1 -0
  53. package/build/prompts/test-recommendation/test-recommendation-prompt.d.ts +6 -0
  54. package/build/prompts/test-recommendation/test-recommendation-prompt.js +4 -4
  55. package/build/prompts/test-recommendation/test-recommendation-prompt.test.d.ts +1 -0
  56. package/build/prompts/test-recommendation/test-recommendation-prompt.test.js +97 -99
  57. package/build/prompts/testbot/testbot-prompts.d.ts +26 -0
  58. package/build/prompts/testbot/testbot-prompts.js +301 -46
  59. package/build/prompts/testbot/testbot-prompts.test.d.ts +1 -0
  60. package/build/prompts/testbot/testbot-prompts.test.js +109 -117
  61. package/build/resources/analysisResources.d.ts +17 -0
  62. package/build/resources/progressResource.d.ts +2 -0
  63. package/build/resources/sutSetupResource.d.ts +2 -0
  64. package/build/resources/sutSetupResource.js +45 -0
  65. package/build/resources/testbotResource.d.ts +2 -0
  66. package/build/resources/testbotResource.js +2 -2
  67. package/build/services/AnalyticsService.d.ts +13 -0
  68. package/build/services/AnalyticsService.test.d.ts +1 -0
  69. package/build/services/AnalyticsService.test.js +86 -0
  70. package/build/services/ModularizationService.d.ts +11 -0
  71. package/build/services/ScenarioGenerationService.d.ts +37 -0
  72. package/build/services/ScenarioGenerationService.integration.test.d.ts +1 -0
  73. package/build/services/ScenarioGenerationService.integration.test.js +4 -0
  74. package/build/services/ScenarioGenerationService.test.d.ts +1 -0
  75. package/build/services/TestDiscoveryService.d.ts +128 -0
  76. package/build/services/TestDiscoveryService.js +22 -12
  77. package/build/services/TestDiscoveryService.test.d.ts +1 -0
  78. package/build/services/TestDiscoveryService.test.js +4 -3
  79. package/build/services/TestExecutionService.d.ts +55 -0
  80. package/build/services/TestExecutionService.js +158 -26
  81. package/build/services/TestExecutionService.test.d.ts +1 -0
  82. package/build/services/TestExecutionService.test.js +339 -25
  83. package/build/services/TestGenerationService.d.ts +56 -0
  84. package/build/services/TestGenerationService.test.d.ts +1 -0
  85. package/build/services/TestGenerationService.test.js +10 -8
  86. package/build/services/containerEnv.d.ts +14 -0
  87. package/build/tool-phase-coverage.test.d.ts +1 -0
  88. package/build/tool-phase-coverage.test.js +2 -0
  89. package/build/tool-phases.d.ts +38 -0
  90. package/build/tools/auth/loginTool.d.ts +2 -0
  91. package/build/tools/auth/logoutTool.d.ts +2 -0
  92. package/build/tools/code-refactor/codeReuseTool.d.ts +2 -0
  93. package/build/tools/code-refactor/enhanceAssertionsTool.d.ts +2 -0
  94. package/build/tools/code-refactor/modularizationTool.d.ts +2 -0
  95. package/build/tools/executeSkyrampTestTool.d.ts +2 -0
  96. package/build/tools/executeSkyrampTestTool.js +26 -7
  97. package/build/tools/fixErrorTool.d.ts +2 -0
  98. package/build/tools/generate-tests/generateBatchScenarioRestTool.d.ts +45 -0
  99. package/build/tools/generate-tests/generateBatchScenarioRestTool.js +1 -1
  100. package/build/tools/generate-tests/generateBatchScenarioRestTool.test.d.ts +1 -0
  101. package/build/tools/generate-tests/generateBatchScenarioRestTool.test.js +11 -9
  102. package/build/tools/generate-tests/generateContractRestTool.d.ts +31 -0
  103. package/build/tools/generate-tests/generateE2ERestTool.d.ts +13 -0
  104. package/build/tools/generate-tests/generateFuzzRestTool.d.ts +10 -0
  105. package/build/tools/generate-tests/generateIntegrationRestTool.d.ts +16 -0
  106. package/build/tools/generate-tests/generateLoadRestTool.d.ts +18 -0
  107. package/build/tools/generate-tests/generateLoadRestTool.test.d.ts +1 -0
  108. package/build/tools/generate-tests/generateMockRestTool.d.ts +64 -0
  109. package/build/tools/generate-tests/generateSmokeRestTool.d.ts +8 -0
  110. package/build/tools/generate-tests/generateUIRestTool.d.ts +14 -0
  111. package/build/tools/generate-tests/generateUIRestTool.js +1 -1
  112. package/build/tools/generate-tests/loadTestSchema.d.ts +39 -0
  113. package/build/tools/one-click/oneClickTool.d.ts +11 -0
  114. package/build/tools/submitReportTool.d.ts +394 -0
  115. package/build/tools/submitReportTool.js +250 -41
  116. package/build/tools/submitReportTool.test.d.ts +1 -0
  117. package/build/tools/submitReportTool.test.js +511 -55
  118. package/build/tools/test-management/actionsTool.d.ts +10 -0
  119. package/build/tools/test-management/actionsTool.js +21 -7
  120. package/build/tools/test-management/analyzeChangesTool.d.ts +27 -0
  121. package/build/tools/test-management/analyzeChangesTool.js +150 -48
  122. package/build/tools/test-management/analyzeChangesTool.test.d.ts +1 -0
  123. package/build/tools/test-management/analyzeChangesTool.test.js +95 -78
  124. package/build/tools/test-management/analyzeTestHealthTool.d.ts +2 -0
  125. package/build/tools/test-management/analyzeTestHealthTool.js +16 -9
  126. package/build/tools/test-management/index.d.ts +3 -0
  127. package/build/tools/test-management/index.js +0 -1
  128. package/build/tools/trace/resolveSaveStoragePath.d.ts +7 -0
  129. package/build/tools/trace/resolveSaveStoragePath.test.d.ts +1 -0
  130. package/build/tools/trace/resolveSessionPaths.d.ts +40 -0
  131. package/build/tools/trace/resolveSessionPaths.test.d.ts +1 -0
  132. package/build/tools/trace/sessionState.d.ts +2 -0
  133. package/build/tools/trace/sessionState.test.d.ts +1 -0
  134. package/build/tools/trace/startTraceCollectionTool.d.ts +2 -0
  135. package/build/tools/trace/stopTraceCollectionTool.d.ts +2 -0
  136. package/build/tools/workspace/initScanWorkspaceTool.d.ts +4 -0
  137. package/build/tools/workspace/initializeWorkspaceTool.d.ts +2 -0
  138. package/build/tools/workspace/initializeWorkspaceTool.js +39 -22
  139. package/build/tools/workspace/initializeWorkspaceTool.test.d.ts +1 -0
  140. package/build/tools/workspace/initializeWorkspaceTool.test.js +134 -0
  141. package/build/tools/workspace/serviceUpsert.d.ts +12 -0
  142. package/build/tools/workspace/serviceUpsert.js +23 -0
  143. package/build/tools/workspace/serviceUpsert.test.d.ts +1 -0
  144. package/build/tools/workspace/serviceUpsert.test.js +50 -0
  145. package/build/types/OneClickCommands.d.ts +68 -0
  146. package/build/types/RepositoryAnalysis.d.ts +3004 -0
  147. package/build/types/TestAnalysis.d.ts +97 -0
  148. package/build/types/TestExecution.d.ts +63 -0
  149. package/build/types/TestExecution.js +11 -1
  150. package/build/types/TestRecommendation.d.ts +12 -0
  151. package/build/types/TestTypes.d.ts +234 -0
  152. package/build/types/TestbotReport.d.ts +68 -0
  153. package/build/types/TestbotReport.js +1 -0
  154. package/build/types/index.d.ts +4 -0
  155. package/build/types/index.js +3 -0
  156. package/build/utils/AnalysisStateManager.d.ts +242 -0
  157. package/build/utils/AnalysisStateManager.js +144 -3
  158. package/build/utils/AnalysisStateManager.test.d.ts +1 -0
  159. package/build/utils/AnalysisStateManager.test.js +98 -0
  160. package/build/utils/analyze-openapi.d.ts +1 -0
  161. package/build/utils/branchDiff.d.ts +18 -0
  162. package/build/utils/dartRouteExtractor.d.ts +45 -0
  163. package/build/utils/dartRouteExtractor.test.d.ts +1 -0
  164. package/build/utils/docker.d.ts +19 -0
  165. package/build/utils/docker.test.d.ts +1 -0
  166. package/build/utils/docker.test.js +10 -9
  167. package/build/utils/featureFlags.d.ts +37 -0
  168. package/build/utils/featureFlags.test.d.ts +1 -0
  169. package/build/utils/gitStaging.d.ts +24 -0
  170. package/build/utils/gitStaging.test.d.ts +1 -0
  171. package/build/utils/gitStaging.test.js +13 -7
  172. package/build/utils/httpDefaults.d.ts +10 -0
  173. package/build/utils/httpDefaults.test.d.ts +1 -0
  174. package/build/utils/initAgent.d.ts +36 -0
  175. package/build/utils/language-helper.d.ts +6 -0
  176. package/build/utils/logger.d.ts +11 -0
  177. package/build/utils/normalizeParams.d.ts +14 -0
  178. package/build/utils/normalizeSkyrampImports.d.ts +13 -0
  179. package/build/utils/pr-comment-parser.d.ts +31 -0
  180. package/build/utils/pr-comment-parser.test.d.ts +1 -0
  181. package/build/utils/pr-comment-parser.test.js +6 -5
  182. package/build/utils/projectMetadata.d.ts +15 -0
  183. package/build/utils/projectMetadata.test.d.ts +1 -0
  184. package/build/utils/proxy-terminal.d.ts +2 -0
  185. package/build/utils/repoScanner.d.ts +27 -0
  186. package/build/utils/repoScanner.test.d.ts +1 -0
  187. package/build/utils/routeParsers.d.ts +53 -0
  188. package/build/utils/routeParsers.js +31 -38
  189. package/build/utils/routeParsers.test.d.ts +1 -0
  190. package/build/utils/scenarioDrafting.d.ts +71 -0
  191. package/build/utils/scenarioDrafting.js +23 -1
  192. package/build/utils/scenarioDrafting.test.d.ts +1 -0
  193. package/build/utils/skyrampMdContent.d.ts +5 -0
  194. package/build/utils/sourceRouteExtractor.d.ts +48 -0
  195. package/build/utils/sourceRouteExtractor.test.d.ts +1 -0
  196. package/build/utils/telemetry.d.ts +32 -0
  197. package/build/utils/telemetry.test.d.ts +1 -0
  198. package/build/utils/trace-parser.d.ts +32 -0
  199. package/build/utils/trace-parser.test.d.ts +6 -0
  200. package/build/utils/uiPageEnumerator.d.ts +146 -0
  201. package/build/utils/uiPageEnumerator.js +58 -14
  202. package/build/utils/uiPageEnumerator.test.d.ts +1 -0
  203. package/build/utils/uiPageEnumerator.test.js +223 -43
  204. package/build/utils/utils.d.ts +45 -0
  205. package/build/utils/utils.js +10 -0
  206. package/build/utils/utils.test.d.ts +1 -0
  207. package/build/utils/versions.d.ts +3 -0
  208. package/build/utils/versions.js +1 -1
  209. package/build/utils/workspaceAuth.d.ts +127 -0
  210. package/build/utils/workspaceAuth.test.d.ts +1 -0
  211. package/build/utils/workspaceAuth.test.js +25 -25
  212. package/build/workspace/index.d.ts +1 -0
  213. package/build/workspace/workspace.d.ts +390 -0
  214. package/build/workspace/workspace.js +7 -7
  215. package/build/workspace/workspace.test.d.ts +1 -0
  216. package/build/workspace/workspace.test.js +6 -6
  217. package/node_modules/playwright/lib/mcp/skyramp/loadTraceTool.js +31 -13
  218. package/node_modules/playwright/lib/mcp/skyramp/traceRecordingBackend.js +88 -15
  219. package/node_modules/playwright/lib/mcp/test/skyRampExport.js +4 -3
  220. package/node_modules/playwright/node_modules/playwright-core/ThirdPartyNotices.txt +23 -126
  221. package/node_modules/playwright/node_modules/playwright-core/lib/generated/injectedScriptSource.js +1 -1
  222. package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/recorderApp.js +79 -19
  223. package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/skyramp/aliasRemapper.js +84 -0
  224. package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/skyramp/replayEngine.js +15 -4
  225. package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/{codeMirrorModule-CPZKmjFR.js → codeMirrorModule-D0BjbCb7.js} +1 -1
  226. package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/index-lvTRGFx-.js +193 -0
  227. package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/index.html +1 -1
  228. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/{codeMirrorModule-B0JOjboO.js → codeMirrorModule-Cqp3cwEJ.js} +1 -1
  229. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/{defaultSettingsView-1anWeyDf.js → defaultSettingsView-CYf9adZh.js} +79 -79
  230. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/{index.Cc5029a3.js → index.B_7ywgmr.js} +1 -1
  231. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.html +2 -2
  232. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/uiMode.html +2 -2
  233. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/{uiMode.Wo5yvvVh.js → uiMode.u4_8VnCV.js} +1 -1
  234. package/node_modules/playwright/node_modules/playwright-core/package.json +1 -1
  235. package/node_modules/playwright/node_modules/playwright-core/src/generated/injectedScriptSource.ts +1 -1
  236. package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/recorderApp.ts +129 -43
  237. package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/skyramp/aliasRemapper.ts +119 -0
  238. package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/skyramp/replayEngine.ts +33 -10
  239. package/node_modules/playwright/package.json +1 -1
  240. package/package.json +16 -4
  241. package/build/tools/test-management/uiAnalyzeChangesTool.js +0 -155
  242. package/build/tools/test-management/uiAnalyzeChangesTool.test.js +0 -147
  243. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/.bin/node-which +0 -52
  244. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/.bin/is-docker +0 -5
  245. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/.bin/mime +0 -46
  246. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/.bin/yaml +0 -11
  247. package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/index-CsgPR2wy.js +0 -193
  248. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.CP3Y8Zsb.js +0 -2
@@ -93,10 +93,10 @@ ${isUIOnlyPR ? `\n**UI-only PR** — no backend changes. UI and E2E tests are mo
93
93
  Output should be concise and immediately actionable.`
94
94
  : `You are in **Repo mode**. Comprehensive test strategy across all endpoints.`;
95
95
  // ── UI rec authoring rules ──
96
- // Anchors every UI recommendation regardless of whether the agent ran
97
- // skyramp_ui_analyze_changes / browser_blueprint before this call. When the
98
- // agent has prior captures in its own tool-result history, those serve as
99
- // grounding; when it doesn't, recommendations fall back to source-grounded
96
+ // Anchors every UI recommendation regardless of whether the agent captured
97
+ // browser_blueprints (from the UI Blueprint Capture section this tool returns).
98
+ // When the agent has prior captures in its own tool-result history, those serve
99
+ // as grounding; when it doesn't, recommendations fall back to source-grounded
100
100
  // prose. Either way, inventing elements / leaking jargon / duplicating UI
101
101
  // tests are wrong, so the rules fire unconditionally.
102
102
  const uiRecRulesSection = `
@@ -1,10 +1,11 @@
1
- jest.mock("@skyramp/skyramp", () => ({
1
+ import { jest } from "@jest/globals";
2
+ import { TestType } from "../../types/TestTypes.js";
3
+ jest.unstable_mockModule("@skyramp/skyramp", () => ({
2
4
  WorkspaceConfigManager: { create: jest.fn() },
3
5
  }));
4
- import { TestType } from "../../types/TestTypes.js";
5
- import { buildRecommendationPrompt, buildExternalCoverageSet, externalDedupKey } from "./test-recommendation-prompt.js";
6
- import { buildExecutionPlan } from "./diffExecutionPlan.js";
7
- import { PATH_PARAM_UUID_GUIDANCE, MAX_TESTS_TO_GENERATE, buildTestQualityCriteria, buildArchitectPreamble, buildContextFetchingGuidance, buildReasoningProtocol, buildFewShotExamples, buildVerificationChecklist, } from "./recommendationSections.js";
6
+ const { buildRecommendationPrompt, buildExternalCoverageSet, externalDedupKey } = await import("./test-recommendation-prompt.js");
7
+ const { buildExecutionPlan } = await import("./diffExecutionPlan.js");
8
+ const { PATH_PARAM_UUID_GUIDANCE, MAX_TESTS_TO_GENERATE, buildTestQualityCriteria, buildArchitectPreamble, buildContextFetchingGuidance, buildReasoningProtocol, buildFewShotExamples, buildVerificationChecklist, } = await import("./recommendationSections.js");
8
9
  import { AnalysisScope } from "../../types/RepositoryAnalysis.js";
9
10
  // ---------------------------------------------------------------------------
10
11
  // Minimal fixtures
@@ -909,6 +910,97 @@ describe("buildRecommendationPrompt — GENERATE slot allocation", () => {
909
910
  expect(additionalBlock).toContain("DELETE /api/gadgets/{id} → 401");
910
911
  });
911
912
  });
913
+ describe("buildExecutionPlan — even-with-spillover test-type distribution", () => {
914
+ // Backend-only PR (hasFrontendChanges=false) so every GENERATE slot is a backend
915
+ // scenario drawn from `scored` — this is where contract-vs-integration distribution
916
+ // applies. baseUrl/auth args mirror the existing buildExecutionPlan tests above.
917
+ const contract = (name, path, priority = "HIGH") => ({
918
+ scenario: minimalScenario({
919
+ scenarioName: name,
920
+ category: "crud",
921
+ testType: TestType.CONTRACT,
922
+ steps: [{ order: 1, method: "POST", path, description: `POST ${path}`, interactionType: "success", expectedStatusCode: 201 }],
923
+ }),
924
+ priority: priority,
925
+ novelty: "new",
926
+ });
927
+ const integration = (name, p1, p2, priority = "HIGH") => ({
928
+ scenario: minimalScenario({
929
+ scenarioName: name,
930
+ category: "data_integrity",
931
+ testType: TestType.INTEGRATION,
932
+ steps: [
933
+ { order: 1, method: "POST", path: p1, description: `POST ${p1}`, interactionType: "success", expectedStatusCode: 201 },
934
+ { order: 2, method: "PATCH", path: p2, description: `PATCH ${p2}`, interactionType: "success", expectedStatusCode: 200 },
935
+ ],
936
+ }),
937
+ priority: priority,
938
+ novelty: "new",
939
+ });
940
+ const plan = (items, maxGen, topN) => buildExecutionPlan(items, maxGen, topN, "http://localhost:3000", "Authorization", ", authScheme: \"Bearer\"", "", "seed", items.length, false);
941
+ it("distributes GENERATE slots across contract AND integration when budget < candidates", () => {
942
+ // 4 contract out-rank 4 integration; pure top-3 rank slice would be all contract.
943
+ const items = [
944
+ contract("c1", "/api/a"), contract("c2", "/api/b"), contract("c3", "/api/c"), contract("c4", "/api/d"),
945
+ integration("i1", "/api/x", "/api/x/{id}"), integration("i2", "/api/y", "/api/y/{id}"),
946
+ ];
947
+ const prompt = plan(items, 3, 6);
948
+ const generated = prompt.slice(0, prompt.indexOf("[ADDITIONAL]") >= 0 ? prompt.indexOf("[ADDITIONAL]") : prompt.length);
949
+ expect(generated).toMatch(/GENERATE\*\* \| contract/);
950
+ expect(generated).toMatch(/GENERATE\*\* \| integration/);
951
+ });
952
+ it("single backend type → unchanged top-N rank slice (no regression)", () => {
953
+ const items = [contract("c1", "/api/a"), contract("c2", "/api/b"), contract("c3", "/api/c"), contract("c4", "/api/d")];
954
+ const prompt = plan(items, 3, 6);
955
+ const generated = prompt.slice(0, prompt.indexOf("[ADDITIONAL]") >= 0 ? prompt.indexOf("[ADDITIONAL]") : prompt.length);
956
+ // Top 3 contract by rank are generated; the 4th is not.
957
+ expect(generated).toContain("POST /api/a → 201");
958
+ expect(generated).toContain("POST /api/b → 201");
959
+ expect(generated).toContain("POST /api/c → 201");
960
+ expect(generated).not.toContain("POST /api/d → 201");
961
+ expect(generated).not.toMatch(/GENERATE\*\* \| integration/);
962
+ });
963
+ it("keeps a CRITICAL item in GENERATE even when lower-ranked than other-type candidates", () => {
964
+ // A CRITICAL integration sits after several HIGH contracts in rank order.
965
+ const items = [
966
+ contract("c1", "/api/a"), contract("c2", "/api/b"), contract("c3", "/api/c"),
967
+ integration("crit", "/api/orders", "/api/orders/{id}", "CRITICAL"),
968
+ ];
969
+ const prompt = plan(items, 3, 6);
970
+ const generated = prompt.slice(0, prompt.indexOf("[ADDITIONAL]") >= 0 ? prompt.indexOf("[ADDITIONAL]") : prompt.length);
971
+ // The CRITICAL integration must occupy a GENERATE slot (protected-first).
972
+ expect(generated).toContain("PATCH /api/orders/{id}");
973
+ });
974
+ it("spills freed slots to the remaining type when one type runs dry", () => {
975
+ // 1 integration + 4 contract, budget 3: round 1 = 1 integration + 1 contract,
976
+ // integration bucket now empty → remaining 1 slot spills to contract → 2 contract total.
977
+ const items = [
978
+ integration("i1", "/api/x", "/api/x/{id}"),
979
+ contract("c1", "/api/a"), contract("c2", "/api/b"), contract("c3", "/api/c"), contract("c4", "/api/d"),
980
+ ];
981
+ const prompt = plan(items, 3, 6);
982
+ const generated = prompt.slice(0, prompt.indexOf("[ADDITIONAL]") >= 0 ? prompt.indexOf("[ADDITIONAL]") : prompt.length);
983
+ const contractSlots = (generated.match(/GENERATE\*\* \| contract/g) || []).length;
984
+ const integrationSlots = (generated.match(/GENERATE\*\* \| integration/g) || []).length;
985
+ expect(integrationSlots).toBe(1);
986
+ expect(contractSlots).toBe(2);
987
+ });
988
+ it("never lists a GENERATE item again under ADDITIONAL (set-difference recompute)", () => {
989
+ const items = [
990
+ contract("c1", "/api/a"), contract("c2", "/api/b"), contract("c3", "/api/c"), contract("c4", "/api/d"),
991
+ integration("i1", "/api/x", "/api/x/{id}"), integration("i2", "/api/y", "/api/y/{id}"),
992
+ ];
993
+ const prompt = plan(items, 3, 6);
994
+ const splitIdx = prompt.indexOf("[ADDITIONAL]");
995
+ expect(splitIdx).toBeGreaterThan(0);
996
+ const generated = prompt.slice(0, splitIdx);
997
+ const additional = prompt.slice(splitIdx);
998
+ // Each generated endpoint must not reappear in the ADDITIONAL section.
999
+ for (const m of generated.matchAll(/(POST|PATCH) (\/api\/[^\s]+)/g)) {
1000
+ expect(additional).not.toContain(`${m[1]} ${m[2]}`);
1001
+ }
1002
+ });
1003
+ });
912
1004
  // ---------------------------------------------------------------------------
913
1005
  // Tests — buildTestQualityCriteria contract-test guidance (regression guard)
914
1006
  // ---------------------------------------------------------------------------
@@ -1669,100 +1761,6 @@ describe("externalDedupKey", () => {
1669
1761
  expect(externalDedupKey(scenario)).toBe("POST::orders::contract");
1670
1762
  });
1671
1763
  });
1672
- describe("UI grounding guidance (Phase C D-1.a)", () => {
1673
- const editOrderScenario = minimalScenario({
1674
- scenarioName: 'edit-order',
1675
- description: 'edit order',
1676
- category: 'new_endpoint',
1677
- priority: 'medium',
1678
- steps: [
1679
- { order: 1, method: 'PATCH', path: '/api/v1/orders/{id}', description: 'edit', interactionType: 'success', expectedStatusCode: 200 },
1680
- ],
1681
- chainingKeys: [],
1682
- });
1683
- const uiGroundingBusinessContext = {
1684
- mainPurpose: "Test API", userFlows: [], dataFlows: [], integrationPatterns: [],
1685
- draftedScenarios: [editOrderScenario],
1686
- };
1687
- const uiOnlyAnalysis = () => minimalAnalysis({
1688
- branchDiffContext: {
1689
- currentBranch: "feature", baseBranch: "main",
1690
- changedFiles: ['frontend/src/components/EditOrder.tsx'],
1691
- newEndpoints: [],
1692
- modifiedEndpoints: [],
1693
- affectedServices: [],
1694
- },
1695
- businessContext: uiGroundingBusinessContext,
1696
- });
1697
- const mixedAnalysis = () => minimalAnalysis({
1698
- branchDiffContext: {
1699
- currentBranch: "feature", baseBranch: "main",
1700
- changedFiles: ['frontend/src/components/EditOrder.tsx', 'backend/orders.py'],
1701
- newEndpoints: [{
1702
- path: '/api/v1/orders/{id}',
1703
- methods: [{ method: 'PATCH', sourceFile: 'backend/orders.py', interactionCount: 1 }],
1704
- }],
1705
- modifiedEndpoints: [],
1706
- affectedServices: [],
1707
- },
1708
- businessContext: uiGroundingBusinessContext,
1709
- });
1710
- const backendOnlyAnalysis = () => minimalAnalysis({
1711
- branchDiffContext: {
1712
- currentBranch: "feature", baseBranch: "main",
1713
- changedFiles: ['backend/orders.py'],
1714
- newEndpoints: [{
1715
- path: '/api/v1/orders',
1716
- methods: [{ method: 'POST', sourceFile: 'backend/orders.py', interactionCount: 1 }],
1717
- }],
1718
- modifiedEndpoints: [],
1719
- affectedServices: [],
1720
- },
1721
- businessContext: uiGroundingBusinessContext,
1722
- });
1723
- it("emits UI grounding block on UI-only PRs", () => {
1724
- const out = buildRecommendationPrompt(uiOnlyAnalysis(), AnalysisScope.CurrentBranchDiff, 10);
1725
- expect(out).toContain("UI recommendation grounding");
1726
- expect(out).toContain("role=<role>");
1727
- expect(out).toContain("accessibleName=");
1728
- });
1729
- it("emits UI grounding block on mixed PRs", () => {
1730
- const out = buildRecommendationPrompt(mixedAnalysis(), AnalysisScope.CurrentBranchDiff, 10);
1731
- expect(out).toContain("UI recommendation grounding");
1732
- expect(out).toContain("contextText=");
1733
- });
1734
- it("does not emit UI grounding block on backend-only PRs", () => {
1735
- const out = buildRecommendationPrompt(backendOnlyAnalysis(), AnalysisScope.CurrentBranchDiff, 10);
1736
- expect(out).not.toContain("UI recommendation grounding");
1737
- });
1738
- it("carves out non-UI entries from the grounding format", () => {
1739
- const out = buildRecommendationPrompt(mixedAnalysis(), AnalysisScope.CurrentBranchDiff, 10);
1740
- expect(out).toMatch(/Contract, integration, e2e.*existing conventions/);
1741
- });
1742
- it("includes contextText example for repeating elements", () => {
1743
- const out = buildRecommendationPrompt(uiOnlyAnalysis(), AnalysisScope.CurrentBranchDiff, 10);
1744
- expect(out).toContain('contextText=["customer@example.com"');
1745
- });
1746
- // Phase C D-1.a/7b: directive instruction strengthening + Validates coverage
1747
- // + marked fallback. Asserts the post-7b language is present.
1748
- it("uses MUST directive for tuple presence in reasoning field", () => {
1749
- const out = buildRecommendationPrompt(uiOnlyAnalysis(), AnalysisScope.CurrentBranchDiff, 10);
1750
- expect(out).toContain("MUST contain at least three of");
1751
- expect(out).toContain("not valid output for UI test types");
1752
- });
1753
- it("instructs the agent to ground the Validates line for UI entries", () => {
1754
- const out = buildRecommendationPrompt(uiOnlyAnalysis(), AnalysisScope.CurrentBranchDiff, 10);
1755
- expect(out).toContain("Validates line — applies to");
1756
- expect(out).toContain("observable behavior the test verifies");
1757
- expect(out).toContain("structural facts");
1758
- });
1759
- it("requires a [no-blueprint-data] marker on source-grounded fallback entries", () => {
1760
- const out = buildRecommendationPrompt(uiOnlyAnalysis(), AnalysisScope.CurrentBranchDiff, 10);
1761
- expect(out).toContain("[no-blueprint-data]");
1762
- expect(out).toContain("issuesFound");
1763
- expect(out).toContain("Do NOT silently produce ungrounded reasoning");
1764
- });
1765
- });
1766
1764
  // ---------------------------------------------------------------------------
1767
1765
  // Tests — UI recommendation authoring rules
1768
1766
  // ---------------------------------------------------------------------------
@@ -0,0 +1,26 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { type Service } from "../../workspace/workspace.js";
3
+ /** One related repository to analyze as shared context in multi-repo mode. */
4
+ export interface RelatedRepository {
5
+ repositoryPath: string;
6
+ baseBranch?: string;
7
+ /** `owner/repo` slug, resolved by the action from the checkout's git remote.
8
+ * Used verbatim as the `repository` argument/attribution for this repo so the
9
+ * agent never has to infer it. */
10
+ repo: string;
11
+ }
12
+ /**
13
+ * Parse the JSON-encoded `relatedRepositories` argument passed via the testbot
14
+ * prompt/resource. Returns undefined for missing/blank input or malformed JSON so the
15
+ * caller cleanly falls back to single-repo behavior.
16
+ */
17
+ export declare function parseRelatedRepositories(raw: string | undefined): RelatedRepository[] | undefined;
18
+ export declare function getTestbotPrompt(prTitle: string, prDescription: string, summaryOutputFile: string, repositoryPath: string, baseBranch?: string, maxRecommendations?: number, maxGenerate?: number, _maxCritical?: number, // Reserved — accepted for API compat but not yet wired into prompt
19
+ prNumber?: number, userPrompt?: string, services?: Service[], uiCredentials?: string, testsRepoDir?: string, relatedRepositories?: RelatedRepository[], primaryRepo?: string): string;
20
+ /**
21
+ * Read services from .skyramp/workspace.yml. Returns empty array if
22
+ * the workspace file doesn't exist or can't be parsed.
23
+ */
24
+ export declare function readWorkspaceServices(repositoryPath: string): Promise<Service[]>;
25
+ export declare function buildWorkspaceRecoveryPrefix(repositoryPath: string): string;
26
+ export declare function registerTestbotPrompt(server: McpServer): void;