@skyramp/mcp 0.3.2-rc.pom-3 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/build/commands/commandLibrary.d.ts +1 -0
  2. package/build/commands/commandLibrary.js +19 -13
  3. package/build/commands/localDevTestChangesCommand.d.ts +15 -0
  4. package/build/commands/localDevTestChangesCommand.js +201 -0
  5. package/build/index.js +80 -6
  6. package/build/prompts/code-reuse.js +3 -0
  7. package/build/prompts/enhance-assertions/sharedAssertionRules.d.ts +1 -0
  8. package/build/prompts/enhance-assertions/sharedAssertionRules.js +17 -0
  9. package/build/prompts/initialize-workspace/initializeWorkspacePrompt.js +11 -9
  10. package/build/prompts/local-dev/local-dev-plan.d.ts +35 -0
  11. package/build/prompts/local-dev/local-dev-plan.js +429 -0
  12. package/build/prompts/local-dev/local-dev-prompts.d.ts +4 -0
  13. package/build/prompts/local-dev/local-dev-prompts.js +190 -0
  14. package/build/prompts/pom-aware-code-reuse.js +12 -0
  15. package/build/prompts/prompt-utils.d.ts +8 -0
  16. package/build/prompts/prompt-utils.js +33 -0
  17. package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.js +37 -14
  18. package/build/prompts/sut-setup/shared.js +16 -12
  19. package/build/prompts/test-recommendation/analysisOutputPrompt.js +21 -29
  20. package/build/prompts/test-recommendation/scopeAssessment.d.ts +24 -7
  21. package/build/prompts/test-recommendation/scopeAssessment.js +111 -12
  22. package/build/prompts/test-recommendation/test-recommendation-prompt.js +41 -4
  23. package/build/prompts/testbot/testbot-prompts.d.ts +0 -5
  24. package/build/prompts/testbot/testbot-prompts.js +32 -52
  25. package/build/recommendation/planRanker.d.ts +15 -2
  26. package/build/recommendation/planRanker.js +76 -5
  27. package/build/resources/testbotResource.js +2 -1
  28. package/build/services/AnalyticsService.d.ts +1 -1
  29. package/build/services/TestExecutionService.d.ts +2 -1
  30. package/build/services/TestExecutionService.js +8 -3
  31. package/build/services/TestGenerationService.d.ts +2 -2
  32. package/build/services/TestGenerationService.js +39 -21
  33. package/build/services/containerEnv.js +3 -1
  34. package/build/tool-phases.js +6 -0
  35. package/build/tools/code-refactor/codeReuseTool.js +43 -4
  36. package/build/tools/code-refactor/enhanceAssertionsTool.js +68 -18
  37. package/build/tools/code-refactor/reuse-outcome.d.ts +109 -0
  38. package/build/tools/code-refactor/reuse-outcome.js +158 -0
  39. package/build/tools/code-refactor/reuse-state.d.ts +45 -0
  40. package/build/tools/code-refactor/reuse-state.js +140 -0
  41. package/build/tools/enrichTestWithMocksTool.d.ts +28 -0
  42. package/build/tools/enrichTestWithMocksTool.js +726 -0
  43. package/build/tools/executeSkyrampTestTool.d.ts +11 -0
  44. package/build/tools/executeSkyrampTestTool.js +62 -21
  45. package/build/tools/generate-tests/batchMockGenerationTool.d.ts +106 -0
  46. package/build/tools/generate-tests/batchMockGenerationTool.js +545 -0
  47. package/build/tools/generate-tests/generateBatchScenarioRestTool.js +25 -23
  48. package/build/tools/generate-tests/generateContractRestTool.js +2 -2
  49. package/build/tools/generate-tests/generateE2ERestTool.d.ts +1 -1
  50. package/build/tools/generate-tests/generateE2ERestTool.js +1 -1
  51. package/build/tools/generate-tests/generateLoadRestTool.d.ts +1 -1
  52. package/build/tools/generate-tests/generateLoadRestTool.js +1 -1
  53. package/build/tools/generate-tests/generateMockRestTool.d.ts +179 -6
  54. package/build/tools/generate-tests/generateMockRestTool.js +391 -22
  55. package/build/tools/generate-tests/loadTestSchema.d.ts +1 -1
  56. package/build/tools/generate-tests/planGuard.js +2 -22
  57. package/build/tools/generateEnrichedIntegrationTestTool.d.ts +25 -0
  58. package/build/tools/generateEnrichedIntegrationTestTool.js +235 -0
  59. package/build/tools/localDevWorkerComposeTool.d.ts +24 -0
  60. package/build/tools/localDevWorkerComposeTool.js +264 -0
  61. package/build/tools/one-click/oneClickTool.d.ts +13 -0
  62. package/build/tools/one-click/oneClickTool.js +195 -24
  63. package/build/tools/preflightMockCheckTool.d.ts +2 -0
  64. package/build/tools/preflightMockCheckTool.js +96 -0
  65. package/build/tools/queryProxyMocksTool.d.ts +70 -0
  66. package/build/tools/queryProxyMocksTool.js +522 -0
  67. package/build/tools/runExistingTestsTool.d.ts +31 -0
  68. package/build/tools/runExistingTestsTool.js +214 -13
  69. package/build/tools/submitReportTool.js +38 -3
  70. package/build/tools/test-management/analyzeChangesTool.d.ts +2 -1
  71. package/build/tools/test-management/analyzeChangesTool.js +63 -40
  72. package/build/tools/test-management/registerTestPlanTool.js +55 -7
  73. package/build/tools/trace/startTraceCollectionTool.js +3 -3
  74. package/build/types/FrontendIntegration.d.ts +3 -0
  75. package/build/types/FrontendIntegration.js +3 -0
  76. package/build/types/OneClickCommands.d.ts +1 -1
  77. package/build/types/Recommendation.d.ts +20 -0
  78. package/build/types/Recommendation.js +32 -6
  79. package/build/types/RepositoryAnalysis.d.ts +131 -14
  80. package/build/types/RepositoryAnalysis.js +16 -2
  81. package/build/types/ReuseOutcome.d.ts +63 -0
  82. package/build/types/ReuseOutcome.js +33 -0
  83. package/build/types/TestExecution.d.ts +1 -0
  84. package/build/types/TestTypes.d.ts +25 -7
  85. package/build/types/TestTypes.js +22 -6
  86. package/build/types/TestbotReport.d.ts +7 -0
  87. package/build/types/index.d.ts +2 -0
  88. package/build/types/index.js +1 -0
  89. package/build/utils/AnalysisStateManager.d.ts +26 -0
  90. package/build/utils/AnalysisStateManager.js +31 -1
  91. package/build/utils/analyze-openapi.js +18 -1
  92. package/build/utils/branchDiff.d.ts +17 -1
  93. package/build/utils/branchDiff.js +99 -14
  94. package/build/utils/featureFlags.d.ts +31 -0
  95. package/build/utils/featureFlags.js +37 -0
  96. package/build/utils/frontendIntegration.js +8 -1
  97. package/build/utils/grpcMockValidation.d.ts +1 -0
  98. package/build/utils/grpcMockValidation.js +49 -0
  99. package/build/utils/httpMethodValidation.d.ts +4 -0
  100. package/build/utils/httpMethodValidation.js +15 -0
  101. package/build/utils/logger.js +1 -1
  102. package/build/utils/mockCompatibility.d.ts +49 -0
  103. package/build/utils/mockCompatibility.js +82 -0
  104. package/build/utils/pom-scope/pom-files.js +7 -0
  105. package/build/utils/pom-verify/bindings.js +11 -1
  106. package/build/utils/pom-verify/re-exports.d.ts +10 -0
  107. package/build/utils/pom-verify/re-exports.js +61 -0
  108. package/build/utils/pom-verify/resolve.d.ts +4 -1
  109. package/build/utils/pom-verify/resolve.js +7 -4
  110. package/build/utils/pom-verify/verify.d.ts +5 -0
  111. package/build/utils/pom-verify/verify.js +25 -3
  112. package/build/utils/progress.js +10 -5
  113. package/build/utils/proxy-terminal.js +3 -3
  114. package/build/utils/routeParsers.d.ts +3 -9
  115. package/build/utils/routeParsers.js +79 -4
  116. package/build/utils/utils.js +2 -2
  117. package/build/utils/versions.d.ts +4 -3
  118. package/build/utils/versions.js +3 -1
  119. package/build/utils/workspaceAuth.d.ts +46 -0
  120. package/build/utils/workspaceAuth.js +156 -1
  121. package/build/workspace/testSuites.d.ts +2 -1
  122. package/build/workspace/testSuites.js +1 -1
  123. package/build/workspace/workspace.d.ts +108 -32
  124. package/build/workspace/workspace.js +32 -4
  125. package/package.json +5 -2
  126. package/build/adapters/jestAdapter.test.d.ts +0 -1
  127. package/build/adapters/jestAdapter.test.js +0 -93
  128. package/build/adapters/mochaAdapter.test.d.ts +0 -1
  129. package/build/adapters/mochaAdapter.test.js +0 -63
  130. package/build/adapters/playwrightAdapter.test.d.ts +0 -1
  131. package/build/adapters/playwrightAdapter.test.js +0 -169
  132. package/build/adapters/pytestAdapter.test.d.ts +0 -1
  133. package/build/adapters/pytestAdapter.test.js +0 -90
  134. package/build/prompts/code-reuse.test.d.ts +0 -1
  135. package/build/prompts/code-reuse.test.js +0 -62
  136. package/build/prompts/pom-aware-code-reuse.test.d.ts +0 -1
  137. package/build/prompts/pom-aware-code-reuse.test.js +0 -11
  138. package/build/prompts/test-maintenance/drift-analysis-prompt.test.d.ts +0 -1
  139. package/build/prompts/test-maintenance/drift-analysis-prompt.test.js +0 -51
  140. package/build/prompts/test-recommendation/analysisOutputPrompt.test.d.ts +0 -1
  141. package/build/prompts/test-recommendation/analysisOutputPrompt.test.js +0 -264
  142. package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.d.ts +0 -1
  143. package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.js +0 -126
  144. package/build/prompts/test-recommendation/promptPlan.test.d.ts +0 -1
  145. package/build/prompts/test-recommendation/promptPlan.test.js +0 -336
  146. package/build/prompts/test-recommendation/scopeAssessment.test.d.ts +0 -1
  147. package/build/prompts/test-recommendation/scopeAssessment.test.js +0 -371
  148. package/build/prompts/test-recommendation/test-recommendation-prompt.test.d.ts +0 -1
  149. package/build/prompts/test-recommendation/test-recommendation-prompt.test.js +0 -1925
  150. package/build/prompts/testbot/testbot-prompts.test.d.ts +0 -1
  151. package/build/prompts/testbot/testbot-prompts.test.js +0 -451
  152. package/build/recommendation/budgeters/diversityBalancedBudgeter.test.d.ts +0 -1
  153. package/build/recommendation/budgeters/diversityBalancedBudgeter.test.js +0 -138
  154. package/build/recommendation/budgeters/fixedNBudgeter.test.d.ts +0 -1
  155. package/build/recommendation/budgeters/fixedNBudgeter.test.js +0 -66
  156. package/build/recommendation/discriminators.test.d.ts +0 -1
  157. package/build/recommendation/discriminators.test.js +0 -324
  158. package/build/recommendation/diversity.test.d.ts +0 -1
  159. package/build/recommendation/diversity.test.js +0 -77
  160. package/build/recommendation/planRanker.test.d.ts +0 -1
  161. package/build/recommendation/planRanker.test.js +0 -110
  162. package/build/resources/testbotResource.test.d.ts +0 -1
  163. package/build/resources/testbotResource.test.js +0 -44
  164. package/build/services/AnalyticsService.test.d.ts +0 -1
  165. package/build/services/AnalyticsService.test.js +0 -86
  166. package/build/services/ScenarioGenerationService.integration.test.d.ts +0 -1
  167. package/build/services/ScenarioGenerationService.integration.test.js +0 -162
  168. package/build/services/ScenarioGenerationService.test.d.ts +0 -1
  169. package/build/services/ScenarioGenerationService.test.js +0 -414
  170. package/build/services/TestDiscoveryService.test.d.ts +0 -1
  171. package/build/services/TestDiscoveryService.test.js +0 -983
  172. package/build/services/TestExecutionService.test.d.ts +0 -1
  173. package/build/services/TestExecutionService.test.js +0 -1032
  174. package/build/services/TestGenerationService.test.d.ts +0 -1
  175. package/build/services/TestGenerationService.test.js +0 -578
  176. package/build/tool-phase-coverage.test.d.ts +0 -1
  177. package/build/tool-phase-coverage.test.js +0 -49
  178. package/build/tools/code-refactor/codeReuseTool.test.d.ts +0 -1
  179. package/build/tools/code-refactor/codeReuseTool.test.js +0 -572
  180. package/build/tools/generate-tests/generateBatchScenarioRestTool.test.d.ts +0 -1
  181. package/build/tools/generate-tests/generateBatchScenarioRestTool.test.js +0 -433
  182. package/build/tools/generate-tests/generateContractRestTool.test.d.ts +0 -1
  183. package/build/tools/generate-tests/generateContractRestTool.test.js +0 -142
  184. package/build/tools/generate-tests/generateIntegrationRestTool.test.d.ts +0 -1
  185. package/build/tools/generate-tests/generateIntegrationRestTool.test.js +0 -159
  186. package/build/tools/generate-tests/generateLoadRestTool.test.d.ts +0 -1
  187. package/build/tools/generate-tests/generateLoadRestTool.test.js +0 -169
  188. package/build/tools/generate-tests/generateUIRestTool.test.d.ts +0 -1
  189. package/build/tools/generate-tests/generateUIRestTool.test.js +0 -32
  190. package/build/tools/generate-tests/planGuard.test.d.ts +0 -1
  191. package/build/tools/generate-tests/planGuard.test.js +0 -185
  192. package/build/tools/generate-tests/scenarioLint.test.d.ts +0 -1
  193. package/build/tools/generate-tests/scenarioLint.test.js +0 -100
  194. package/build/tools/runExistingTestsTool.test.d.ts +0 -1
  195. package/build/tools/runExistingTestsTool.test.js +0 -379
  196. package/build/tools/submitReportTool.test.d.ts +0 -1
  197. package/build/tools/submitReportTool.test.js +0 -1428
  198. package/build/tools/test-management/actionsTool.test.d.ts +0 -1
  199. package/build/tools/test-management/actionsTool.test.js +0 -436
  200. package/build/tools/test-management/analyzeChangesTool.test.d.ts +0 -1
  201. package/build/tools/test-management/analyzeChangesTool.test.js +0 -522
  202. package/build/tools/test-management/analyzeTestHealthTool.test.d.ts +0 -1
  203. package/build/tools/test-management/analyzeTestHealthTool.test.js +0 -385
  204. package/build/tools/test-management/registerTestPlanTool.test.d.ts +0 -1
  205. package/build/tools/test-management/registerTestPlanTool.test.js +0 -296
  206. package/build/tools/trace/resolveSaveStoragePath.test.d.ts +0 -1
  207. package/build/tools/trace/resolveSaveStoragePath.test.js +0 -17
  208. package/build/tools/trace/resolveSessionPaths.test.d.ts +0 -1
  209. package/build/tools/trace/resolveSessionPaths.test.js +0 -104
  210. package/build/tools/trace/sessionState.test.d.ts +0 -1
  211. package/build/tools/trace/sessionState.test.js +0 -17
  212. package/build/tools/workspace/initializeWorkspaceTool.test.d.ts +0 -1
  213. package/build/tools/workspace/initializeWorkspaceTool.test.js +0 -139
  214. package/build/tools/workspace/serviceUpsert.test.d.ts +0 -1
  215. package/build/tools/workspace/serviceUpsert.test.js +0 -50
  216. package/build/utils/AnalysisStateManager.test.d.ts +0 -1
  217. package/build/utils/AnalysisStateManager.test.js +0 -134
  218. package/build/utils/dartRouteExtractor.test.d.ts +0 -1
  219. package/build/utils/dartRouteExtractor.test.js +0 -307
  220. package/build/utils/docker.test.d.ts +0 -1
  221. package/build/utils/docker.test.js +0 -114
  222. package/build/utils/featureFlags.test.d.ts +0 -1
  223. package/build/utils/featureFlags.test.js +0 -81
  224. package/build/utils/fileWalk.test.d.ts +0 -1
  225. package/build/utils/fileWalk.test.js +0 -252
  226. package/build/utils/frontendIntegration.test.d.ts +0 -1
  227. package/build/utils/frontendIntegration.test.js +0 -229
  228. package/build/utils/frontendSelectors.test.d.ts +0 -1
  229. package/build/utils/frontendSelectors.test.js +0 -118
  230. package/build/utils/gitStaging.test.d.ts +0 -1
  231. package/build/utils/gitStaging.test.js +0 -111
  232. package/build/utils/httpDefaults.test.d.ts +0 -1
  233. package/build/utils/httpDefaults.test.js +0 -21
  234. package/build/utils/importerHop.test.d.ts +0 -1
  235. package/build/utils/importerHop.test.js +0 -469
  236. package/build/utils/pathAffinityClassification.test.d.ts +0 -1
  237. package/build/utils/pathAffinityClassification.test.js +0 -208
  238. package/build/utils/planMatchKeys.test.d.ts +0 -1
  239. package/build/utils/planMatchKeys.test.js +0 -123
  240. package/build/utils/pom-scope/index.test.d.ts +0 -1
  241. package/build/utils/pom-scope/index.test.js +0 -278
  242. package/build/utils/pom-scope/pom-files.test.d.ts +0 -1
  243. package/build/utils/pom-scope/pom-files.test.js +0 -29
  244. package/build/utils/pom-scope/scoring.test.d.ts +0 -1
  245. package/build/utils/pom-scope/scoring.test.js +0 -39
  246. package/build/utils/pom-scope/selector-extractor.test.d.ts +0 -1
  247. package/build/utils/pom-scope/selector-extractor.test.js +0 -67
  248. package/build/utils/pom-verify/bindings.test.d.ts +0 -1
  249. package/build/utils/pom-verify/bindings.test.js +0 -164
  250. package/build/utils/pom-verify/calls.test.d.ts +0 -1
  251. package/build/utils/pom-verify/calls.test.js +0 -61
  252. package/build/utils/pom-verify/resolve.test.d.ts +0 -1
  253. package/build/utils/pom-verify/resolve.test.js +0 -114
  254. package/build/utils/pom-verify/verify.test.d.ts +0 -1
  255. package/build/utils/pom-verify/verify.test.js +0 -374
  256. package/build/utils/pr-comment-parser.test.d.ts +0 -1
  257. package/build/utils/pr-comment-parser.test.js +0 -428
  258. package/build/utils/progress.test.d.ts +0 -1
  259. package/build/utils/progress.test.js +0 -37
  260. package/build/utils/projectMetadata.test.d.ts +0 -1
  261. package/build/utils/projectMetadata.test.js +0 -172
  262. package/build/utils/pythonMountPrefixes.test.d.ts +0 -1
  263. package/build/utils/pythonMountPrefixes.test.js +0 -113
  264. package/build/utils/repoScanner.test.d.ts +0 -1
  265. package/build/utils/repoScanner.test.js +0 -190
  266. package/build/utils/reportVerification.test.d.ts +0 -1
  267. package/build/utils/reportVerification.test.js +0 -185
  268. package/build/utils/routeParsers.test.d.ts +0 -1
  269. package/build/utils/routeParsers.test.js +0 -1011
  270. package/build/utils/scenarioDrafting.test.d.ts +0 -1
  271. package/build/utils/scenarioDrafting.test.js +0 -876
  272. package/build/utils/sourceRouteExtractor.test.d.ts +0 -1
  273. package/build/utils/sourceRouteExtractor.test.js +0 -738
  274. package/build/utils/telemetry.test.d.ts +0 -1
  275. package/build/utils/telemetry.test.js +0 -70
  276. package/build/utils/trace-parser.test.d.ts +0 -6
  277. package/build/utils/trace-parser.test.js +0 -140
  278. package/build/utils/uiPageEnumerator.test.d.ts +0 -1
  279. package/build/utils/uiPageEnumerator.test.js +0 -824
  280. package/build/utils/utils.test.d.ts +0 -1
  281. package/build/utils/utils.test.js +0 -103
  282. package/build/utils/walkerCharacterization.test.d.ts +0 -1
  283. package/build/utils/walkerCharacterization.test.js +0 -233
  284. package/build/utils/workspaceAuth.test.d.ts +0 -1
  285. package/build/utils/workspaceAuth.test.js +0 -260
  286. package/build/workspace/testSuites.test.d.ts +0 -1
  287. package/build/workspace/testSuites.test.js +0 -23
  288. package/build/workspace/workspace.test.d.ts +0 -1
  289. package/build/workspace/workspace.test.js +0 -264
@@ -1,4 +1,8 @@
1
- import { joinRoutePrefix } from "./pythonMountPrefixes.js";
1
+ import * as fs from "fs";
2
+ import * as os from "os";
3
+ import * as path from "path";
4
+ import { execFileSync } from "child_process";
5
+ import { joinRoutePrefix, resolvePythonMountPrefixes } from "./pythonMountPrefixes.js";
2
6
  import { logger } from "./logger.js";
3
7
  export function nextjsFileToApiPath(filePath) {
4
8
  const pagesMatch = filePath.match(/(?:^|\/)pages\/(api\/.+)\.[jt]sx?$/);
@@ -577,9 +581,80 @@ export function selectRemovalCandidateFiles(diffData) {
577
581
  * `classifyEndpointsByChangedFiles`, whose moved/still-present filter drops any
578
582
  * endpoint that survives in the current catalog, leaving only genuine removals.
579
583
  */
580
- export async function recoverRemovedEndpointsFromBase(candidateFiles, fetchBaseContent) {
584
+ /**
585
+ * Materialize just the `.py` files of a git ref into a fresh temp directory
586
+ * via `git archive` (no full checkout/worktree) — lets `resolvePythonMountPrefixes`
587
+ * run against the BASE tree unmodified. Best-effort: returns null on any
588
+ * failure (shallow clone missing the ref, git/tar unavailable, etc.) so the
589
+ * caller can fall back rather than abort removal recovery.
590
+ */
591
+ function materializePythonFilesFromRef(repositoryPath, ref) {
592
+ let tmpDir;
593
+ try {
594
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "skyramp-base-py-"));
595
+ }
596
+ catch {
597
+ return null;
598
+ }
599
+ const archivePath = path.join(tmpDir, "archive.tar");
600
+ try {
601
+ execFileSync("git", ["-C", repositoryPath, "archive", "--format=tar", "-o", archivePath, ref, "--", "*.py"], {
602
+ stdio: ["ignore", "ignore", "ignore"],
603
+ });
604
+ execFileSync("tar", ["-xf", archivePath, "-C", tmpDir], { stdio: ["ignore", "ignore", "ignore"] });
605
+ fs.rmSync(archivePath, { force: true });
606
+ return tmpDir;
607
+ }
608
+ catch (err) {
609
+ logger.warning("Failed to materialize base-branch Python files for mount-prefix resolution — falling back to current working tree", {
610
+ ref,
611
+ error: err instanceof Error ? err.message : String(err),
612
+ });
613
+ try {
614
+ fs.rmSync(tmpDir, { recursive: true, force: true });
615
+ }
616
+ catch {
617
+ // best-effort cleanup
618
+ }
619
+ return null;
620
+ }
621
+ }
622
+ export async function recoverRemovedEndpointsFromBase(candidateFiles, fetchBaseContent, repositoryPath, baseBranch) {
581
623
  const routeFiles = candidateFiles.filter(isRouteLikeFile);
582
624
  const endpointMap = new Map();
625
+ // Cross-file FastAPI mount-prefix resolution, mirroring the main scan
626
+ // (repoScanner.ts). Without it, a route file whose prefix is applied
627
+ // externally (app.include_router(router, prefix=...)) yields unmounted
628
+ // paths here that can never match the fully-mounted current-catalog
629
+ // paths in classifyEndpointsByChangedFiles's "still exists" check — every
630
+ // endpoint in that file gets misreported as removed, not just the one
631
+ // actually deleted (SKYR-4026).
632
+ //
633
+ // Resolved from the BASE tree when possible (via a `.py`-only git-archive
634
+ // extraction), not the current working tree — if a PR also renames the
635
+ // mount prefix itself (not just the recovered route), head-state prefixes
636
+ // would rewrite the recovered base endpoint onto the NEW prefix, which
637
+ // could mask a real removal or misattribute the path. Falls back to the
638
+ // current working tree if base-tree materialization isn't possible (e.g.
639
+ // shallow clone, git/tar unavailable) — still strictly better than no
640
+ // mount-prefix resolution at all.
641
+ let mountPrefixesByFile;
642
+ if (repositoryPath && routeFiles.some((f) => f.endsWith(".py"))) {
643
+ const baseTreeDir = baseBranch ? materializePythonFilesFromRef(repositoryPath, baseBranch) : null;
644
+ try {
645
+ mountPrefixesByFile = resolvePythonMountPrefixes(baseTreeDir ?? repositoryPath);
646
+ }
647
+ finally {
648
+ if (baseTreeDir) {
649
+ try {
650
+ fs.rmSync(baseTreeDir, { recursive: true, force: true });
651
+ }
652
+ catch {
653
+ // best-effort cleanup
654
+ }
655
+ }
656
+ }
657
+ }
583
658
  for (const file of routeFiles) {
584
659
  let content;
585
660
  try {
@@ -597,7 +672,7 @@ export async function recoverRemovedEndpointsFromBase(candidateFiles, fetchBaseC
597
672
  });
598
673
  continue;
599
674
  }
600
- for (const ep of parseFileEndpoints(content, file)) {
675
+ for (const ep of parseFileEndpoints(content, file, mountPrefixesByFile?.get(file))) {
601
676
  // parseFileEndpoints already normalizes paths to a leading slash.
602
677
  const key = `${file}::${ep.path}`;
603
678
  const existing = endpointMap.get(key);
@@ -620,7 +695,7 @@ export async function recoverRemovedEndpointsFromBase(candidateFiles, fetchBaseC
620
695
  }));
621
696
  }
622
697
  /** Strip git's `a/` / `b/` diff-path prefix and normalize separators. */
623
- function normalizeDiffPath(spec) {
698
+ export function normalizeDiffPath(spec) {
624
699
  let p = spec.replace(/\\/g, "/");
625
700
  if (p.startsWith("a/") || p.startsWith("b/"))
626
701
  p = p.slice(2);
@@ -69,7 +69,7 @@ export function getPathParameterValidationError(requiredPathParams) {
69
69
  return (`Please specify value for the following required path parameter:\n` +
70
70
  `${requiredPathParams
71
71
  .split(",")
72
- .map((param, index) => `- \`${param.trim()}\``)
72
+ .map((param) => `- \`${param.trim()}\``)
73
73
  .join("\n")}\n\n`);
74
74
  }
75
75
  }
@@ -150,7 +150,7 @@ export function validateRequestData(value) {
150
150
  JSON.parse(value);
151
151
  return value;
152
152
  }
153
- catch (e) {
153
+ catch (_e) {
154
154
  logger.warning("Request data is not a valid JSON string", { value });
155
155
  }
156
156
  const isAbsolute = path.isAbsolute(value);
@@ -1,3 +1,4 @@
1
- export declare const SKYRAMP_IMAGE_VERSION = "v1.3.36";
2
- export declare const EXECUTOR_DOCKER_IMAGE = "skyramp/executor:v1.3.36";
3
- export declare const WORKER_DOCKER_IMAGE = "skyramp/worker:v1.3.36";
1
+ export declare const SKYRAMP_IMAGE_VERSION = "v1.3.37";
2
+ export declare const EXECUTOR_DOCKER_IMAGE = "skyramp/executor:v1.3.37";
3
+ export declare const WORKER_DOCKER_IMAGE = "skyramp/worker:v1.3.37";
4
+ export declare const WORKER_CONTROL_PORT = 35142;
@@ -1,3 +1,5 @@
1
- export const SKYRAMP_IMAGE_VERSION = "v1.3.36";
1
+ export const SKYRAMP_IMAGE_VERSION = "v1.3.37";
2
2
  export const EXECUTOR_DOCKER_IMAGE = `skyramp/executor:${SKYRAMP_IMAGE_VERSION}`;
3
3
  export const WORKER_DOCKER_IMAGE = `skyramp/worker:${SKYRAMP_IMAGE_VERSION}`;
4
+ // Control port the Skyramp worker listens on (SDK `CONTAINER_PORT`).
5
+ export const WORKER_CONTROL_PORT = 35142;
@@ -133,3 +133,49 @@ export declare function getWorkspaceAuthConfig(repositoryPath: string): Promise<
133
133
  /** True when any workspace service declares api.skipTLSVerify — the SUT serves
134
134
  * self-signed TLS and generated tests must skip cert verification (SKYR-3961). */
135
135
  export declare function getWorkspaceSkipTLSVerify(repositoryPath: string): Promise<boolean>;
136
+ /**
137
+ * Resolve api.defaultQueryParams for test generation — query params always
138
+ * attached to every generated request for this service (e.g. RBAC context
139
+ * an authorization layer requires beyond the auth header). Same
140
+ * first-matching-service convention as getWorkspaceAuthConfig (SKYR-4050).
141
+ *
142
+ * Unlike readWorkspaceConfigRaw (which delegates to WorkspaceConfigManager and
143
+ * resolves EXACTLY `<repositoryPath>/.skyramp/workspace.yml`), this walks up
144
+ * from `repositoryPath` to find the nearest `.skyramp/workspace.yml` — both
145
+ * call sites pass a nested test-output directory (e.g. `<repo>/tests/skyramp`),
146
+ * not the repo root, so an exact-match lookup would silently never find the
147
+ * config. Mirrors the sync fs.existsSync walk-up in
148
+ * generateBatchScenarioRestTool.ts.
149
+ */
150
+ /**
151
+ * Walk up from `startDir` to find the nearest `.skyramp/workspace.yml`, checking
152
+ * `startDir` itself first and continuing through every ancestor INCLUDING the
153
+ * filesystem root — a naive `while (dir !== path.dirname(dir))` loop exits
154
+ * before ever checking the root candidate, since that equality only becomes
155
+ * true once `dir` already IS the root. Returns the full config path, or null.
156
+ * `existsSync` is injectable for testing; defaults to the real filesystem.
157
+ */
158
+ export declare function findWorkspaceConfigPath(startDir: string, existsSync?: (p: string) => boolean): string | null;
159
+ export declare function getWorkspaceDefaultQueryParams(repositoryPath: string): Promise<Record<string, string> | undefined>;
160
+ /**
161
+ * Merge workspace-declared default query params into a comma-separated
162
+ * "key=value,key2=value2" queryParams string (the format used by
163
+ * baseTestSchema.queryParams). Existing keys always win on collision.
164
+ */
165
+ export declare function mergeQueryParamsString(existing: string | undefined, defaults: Record<string, string>): string;
166
+ /**
167
+ * Merge workspace-declared default query params into a JSON-object queryParams
168
+ * string (the format used by batch-scenario step queryParams). Existing keys
169
+ * always win on collision. A malformed existingJson is left untouched — the
170
+ * caller's own JSON.parse warning path still fires downstream.
171
+ */
172
+ export declare function mergeQueryParamsJson(existingJson: string | undefined, defaults: Record<string, string>): string;
173
+ /**
174
+ * Resolve auth header and scheme from workspace config for test generation.
175
+ * Returns null when auth should be skipped (authType absent or "none").
176
+ * Single source of truth — used by both TestGenerationService and batch scenario tool.
177
+ */
178
+ export declare function resolveAuthFromWorkspace(repoPath: string, existingAuthHeader?: string, existingAuthScheme?: string): Promise<{
179
+ authHeader: string;
180
+ authScheme?: string;
181
+ } | null>;
@@ -89,7 +89,20 @@ export async function getWorkspaceBaseUrl(repositoryPath, testFile, language, te
89
89
  return absTestFile.startsWith(absTestDirectory + path.sep) || absTestFile === absTestDirectory;
90
90
  });
91
91
  });
92
- // Step 2: narrow by language if still ambiguous
92
+ // Step 2: longest-prefix match — when multiple services match (e.g.
93
+ // tests/skyramp is a prefix of tests/skyramp/cart), pick the service
94
+ // whose testDirectory is the most specific (longest) prefix of the test file.
95
+ if (matches.length > 1) {
96
+ matches.sort((a, b) => {
97
+ const aLen = path.resolve(repositoryPath, a.testDirectory).length;
98
+ const bLen = path.resolve(repositoryPath, b.testDirectory).length;
99
+ return bLen - aLen; // longest first
100
+ });
101
+ // Keep only services with the longest matching testDirectory length.
102
+ const longestLen = path.resolve(repositoryPath, matches[0].testDirectory).length;
103
+ matches = matches.filter((s) => path.resolve(repositoryPath, s.testDirectory).length === longestLen);
104
+ }
105
+ // Step 3: narrow by language if still ambiguous, but don't eliminate all matches
93
106
  if (matches.length > 1 && language) {
94
107
  const byLanguage = matches.filter((s) => s.language?.toLowerCase() === language.toLowerCase());
95
108
  if (byLanguage.length > 0)
@@ -350,3 +363,145 @@ export async function getWorkspaceSkipTLSVerify(repositoryPath) {
350
363
  return false;
351
364
  return (rawConfig.services ?? []).some((s) => s.api?.skipTLSVerify === true);
352
365
  }
366
+ /**
367
+ * Resolve api.defaultQueryParams for test generation — query params always
368
+ * attached to every generated request for this service (e.g. RBAC context
369
+ * an authorization layer requires beyond the auth header). Same
370
+ * first-matching-service convention as getWorkspaceAuthConfig (SKYR-4050).
371
+ *
372
+ * Unlike readWorkspaceConfigRaw (which delegates to WorkspaceConfigManager and
373
+ * resolves EXACTLY `<repositoryPath>/.skyramp/workspace.yml`), this walks up
374
+ * from `repositoryPath` to find the nearest `.skyramp/workspace.yml` — both
375
+ * call sites pass a nested test-output directory (e.g. `<repo>/tests/skyramp`),
376
+ * not the repo root, so an exact-match lookup would silently never find the
377
+ * config. Mirrors the sync fs.existsSync walk-up in
378
+ * generateBatchScenarioRestTool.ts.
379
+ */
380
+ /**
381
+ * Walk up from `startDir` to find the nearest `.skyramp/workspace.yml`, checking
382
+ * `startDir` itself first and continuing through every ancestor INCLUDING the
383
+ * filesystem root — a naive `while (dir !== path.dirname(dir))` loop exits
384
+ * before ever checking the root candidate, since that equality only becomes
385
+ * true once `dir` already IS the root. Returns the full config path, or null.
386
+ * `existsSync` is injectable for testing; defaults to the real filesystem.
387
+ */
388
+ export function findWorkspaceConfigPath(startDir, existsSync = fs.existsSync) {
389
+ const WS_SUBPATH = path.join(".skyramp", "workspace.yml");
390
+ let searchDir = path.resolve(startDir);
391
+ while (true) {
392
+ const candidate = path.join(searchDir, WS_SUBPATH);
393
+ if (existsSync(candidate))
394
+ return candidate;
395
+ const parentDir = path.dirname(searchDir);
396
+ if (parentDir === searchDir)
397
+ return null; // reached the filesystem root; already checked above
398
+ searchDir = parentDir;
399
+ }
400
+ }
401
+ export async function getWorkspaceDefaultQueryParams(repositoryPath) {
402
+ const wsConfigPath = findWorkspaceConfigPath(repositoryPath);
403
+ if (!wsConfigPath)
404
+ return undefined;
405
+ try {
406
+ const raw = fs.readFileSync(wsConfigPath, "utf-8");
407
+ const parsed = yaml.load(raw);
408
+ const svc = parsed?.services?.find((s) => s.api?.defaultQueryParams !== undefined);
409
+ return svc?.api?.defaultQueryParams;
410
+ }
411
+ catch {
412
+ return undefined;
413
+ }
414
+ }
415
+ /**
416
+ * Merge workspace-declared default query params into a comma-separated
417
+ * "key=value,key2=value2" queryParams string (the format used by
418
+ * baseTestSchema.queryParams). Existing keys always win on collision.
419
+ */
420
+ export function mergeQueryParamsString(existing, defaults) {
421
+ const pairs = new Map();
422
+ if (existing) {
423
+ for (const pair of existing.split(",")) {
424
+ const eqIndex = pair.indexOf("=");
425
+ if (eqIndex === -1)
426
+ continue;
427
+ const key = pair.slice(0, eqIndex).trim();
428
+ const value = pair.slice(eqIndex + 1).trim();
429
+ if (key)
430
+ pairs.set(key, value);
431
+ }
432
+ }
433
+ for (const [key, value] of Object.entries(defaults)) {
434
+ if (typeof value !== "string") {
435
+ logger.warning("Skipping workspace defaultQueryParams entry with a non-string value", { key });
436
+ continue;
437
+ }
438
+ if (key.includes(",") || key.includes("=") || value.includes(",") || value.includes("=")) {
439
+ logger.warning("Skipping workspace defaultQueryParams entry with invalid characters", { key });
440
+ continue;
441
+ }
442
+ if (!pairs.has(key))
443
+ pairs.set(key, value);
444
+ }
445
+ return Array.from(pairs.entries())
446
+ .map(([key, value]) => `${key}=${value}`)
447
+ .join(",");
448
+ }
449
+ /**
450
+ * Merge workspace-declared default query params into a JSON-object queryParams
451
+ * string (the format used by batch-scenario step queryParams). Existing keys
452
+ * always win on collision. A malformed existingJson is left untouched — the
453
+ * caller's own JSON.parse warning path still fires downstream.
454
+ */
455
+ export function mergeQueryParamsJson(existingJson, defaults) {
456
+ let parsed = {};
457
+ if (existingJson) {
458
+ try {
459
+ const candidate = JSON.parse(existingJson);
460
+ if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) {
461
+ return existingJson;
462
+ }
463
+ parsed = candidate;
464
+ }
465
+ catch {
466
+ return existingJson;
467
+ }
468
+ }
469
+ return JSON.stringify({ ...defaults, ...parsed });
470
+ }
471
+ /**
472
+ * Resolve auth header and scheme from workspace config for test generation.
473
+ * Returns null when auth should be skipped (authType absent or "none").
474
+ * Single source of truth — used by both TestGenerationService and batch scenario tool.
475
+ */
476
+ export async function resolveAuthFromWorkspace(repoPath, existingAuthHeader, existingAuthScheme) {
477
+ if (existingAuthHeader !== undefined)
478
+ return null; // caller already specified
479
+ const wsAuth = await getWorkspaceAuthConfig(repoPath);
480
+ // Skip auth when explicitly none. When authType is absent, still resolve if
481
+ // authHeader or authScheme is set (some workspaces specify only the header).
482
+ if (wsAuth.authType === WorkspaceAuthType.None)
483
+ return null;
484
+ if (!wsAuth.authType && !wsAuth.authHeader && !wsAuth.authScheme)
485
+ return null;
486
+ let resolvedHeader = wsAuth.authHeader ?? getDefaultAuthHeader(wsAuth.authType);
487
+ if (!resolvedHeader && wsAuth.authScheme !== undefined) {
488
+ resolvedHeader = "Authorization";
489
+ }
490
+ if (wsAuth.authType === WorkspaceAuthType.ApiKey && !resolvedHeader) {
491
+ logger.warning("workspace.yml has authType: apiKey but no authHeader is set — " +
492
+ "requests will be sent without an auth header and will likely receive 401/403. " +
493
+ "Add authHeader: <X-Your-Key-Header> to .skyramp/workspace.yml.");
494
+ return null;
495
+ }
496
+ if (!resolvedHeader)
497
+ return null;
498
+ logger.info("authHeader resolved from workspace config", {
499
+ authHeader: resolvedHeader,
500
+ authType: wsAuth.authType,
501
+ });
502
+ let authScheme = existingAuthScheme;
503
+ if (isAuthorizationHeaderName(resolvedHeader)) {
504
+ authScheme = authScheme ?? wsAuth.authScheme ?? getAuthScheme(wsAuth.authType);
505
+ }
506
+ return { authHeader: resolvedHeader, authScheme };
507
+ }
@@ -9,7 +9,8 @@ export interface NormalizedSuite {
9
9
  framework?: string;
10
10
  testRunCommand: string;
11
11
  testEnv?: Record<string, string>;
12
- selectorStyle?: string;
12
+ /** Repo-relative globs this suite owns, for selector→suite routing. */
13
+ pathGlobs?: string[];
13
14
  }
14
15
  /**
15
16
  * Normalizes a service's runtimeDetails.testSuites into a flat list of suites
@@ -12,6 +12,6 @@ export function resolveSuites(service) {
12
12
  framework: suite.framework ?? service.framework,
13
13
  testRunCommand: suite.testRunCommand,
14
14
  testEnv: suite.testEnv,
15
- selectorStyle: suite.selectorStyle,
15
+ pathGlobs: suite.pathGlobs,
16
16
  }));
17
17
  }