@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.
- package/build/commands/commandLibrary.d.ts +1 -0
- package/build/commands/commandLibrary.js +19 -13
- package/build/commands/localDevTestChangesCommand.d.ts +15 -0
- package/build/commands/localDevTestChangesCommand.js +201 -0
- package/build/index.js +80 -6
- package/build/prompts/code-reuse.js +3 -0
- package/build/prompts/enhance-assertions/sharedAssertionRules.d.ts +1 -0
- package/build/prompts/enhance-assertions/sharedAssertionRules.js +17 -0
- package/build/prompts/initialize-workspace/initializeWorkspacePrompt.js +11 -9
- package/build/prompts/local-dev/local-dev-plan.d.ts +35 -0
- package/build/prompts/local-dev/local-dev-plan.js +429 -0
- package/build/prompts/local-dev/local-dev-prompts.d.ts +4 -0
- package/build/prompts/local-dev/local-dev-prompts.js +190 -0
- package/build/prompts/pom-aware-code-reuse.js +12 -0
- package/build/prompts/prompt-utils.d.ts +8 -0
- package/build/prompts/prompt-utils.js +33 -0
- package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.js +37 -14
- package/build/prompts/sut-setup/shared.js +16 -12
- package/build/prompts/test-recommendation/analysisOutputPrompt.js +21 -29
- package/build/prompts/test-recommendation/scopeAssessment.d.ts +24 -7
- package/build/prompts/test-recommendation/scopeAssessment.js +111 -12
- package/build/prompts/test-recommendation/test-recommendation-prompt.js +41 -4
- package/build/prompts/testbot/testbot-prompts.d.ts +0 -5
- package/build/prompts/testbot/testbot-prompts.js +32 -52
- package/build/recommendation/planRanker.d.ts +15 -2
- package/build/recommendation/planRanker.js +76 -5
- package/build/resources/testbotResource.js +2 -1
- package/build/services/AnalyticsService.d.ts +1 -1
- package/build/services/TestExecutionService.d.ts +2 -1
- package/build/services/TestExecutionService.js +8 -3
- package/build/services/TestGenerationService.d.ts +2 -2
- package/build/services/TestGenerationService.js +39 -21
- package/build/services/containerEnv.js +3 -1
- package/build/tool-phases.js +6 -0
- package/build/tools/code-refactor/codeReuseTool.js +43 -4
- package/build/tools/code-refactor/enhanceAssertionsTool.js +68 -18
- package/build/tools/code-refactor/reuse-outcome.d.ts +109 -0
- package/build/tools/code-refactor/reuse-outcome.js +158 -0
- package/build/tools/code-refactor/reuse-state.d.ts +45 -0
- package/build/tools/code-refactor/reuse-state.js +140 -0
- package/build/tools/enrichTestWithMocksTool.d.ts +28 -0
- package/build/tools/enrichTestWithMocksTool.js +726 -0
- package/build/tools/executeSkyrampTestTool.d.ts +11 -0
- package/build/tools/executeSkyrampTestTool.js +62 -21
- package/build/tools/generate-tests/batchMockGenerationTool.d.ts +106 -0
- package/build/tools/generate-tests/batchMockGenerationTool.js +545 -0
- package/build/tools/generate-tests/generateBatchScenarioRestTool.js +25 -23
- package/build/tools/generate-tests/generateContractRestTool.js +2 -2
- package/build/tools/generate-tests/generateE2ERestTool.d.ts +1 -1
- package/build/tools/generate-tests/generateE2ERestTool.js +1 -1
- package/build/tools/generate-tests/generateLoadRestTool.d.ts +1 -1
- package/build/tools/generate-tests/generateLoadRestTool.js +1 -1
- package/build/tools/generate-tests/generateMockRestTool.d.ts +179 -6
- package/build/tools/generate-tests/generateMockRestTool.js +391 -22
- package/build/tools/generate-tests/loadTestSchema.d.ts +1 -1
- package/build/tools/generate-tests/planGuard.js +2 -22
- package/build/tools/generateEnrichedIntegrationTestTool.d.ts +25 -0
- package/build/tools/generateEnrichedIntegrationTestTool.js +235 -0
- package/build/tools/localDevWorkerComposeTool.d.ts +24 -0
- package/build/tools/localDevWorkerComposeTool.js +264 -0
- package/build/tools/one-click/oneClickTool.d.ts +13 -0
- package/build/tools/one-click/oneClickTool.js +195 -24
- package/build/tools/preflightMockCheckTool.d.ts +2 -0
- package/build/tools/preflightMockCheckTool.js +96 -0
- package/build/tools/queryProxyMocksTool.d.ts +70 -0
- package/build/tools/queryProxyMocksTool.js +522 -0
- package/build/tools/runExistingTestsTool.d.ts +31 -0
- package/build/tools/runExistingTestsTool.js +214 -13
- package/build/tools/submitReportTool.js +38 -3
- package/build/tools/test-management/analyzeChangesTool.d.ts +2 -1
- package/build/tools/test-management/analyzeChangesTool.js +63 -40
- package/build/tools/test-management/registerTestPlanTool.js +55 -7
- package/build/tools/trace/startTraceCollectionTool.js +3 -3
- package/build/types/FrontendIntegration.d.ts +3 -0
- package/build/types/FrontendIntegration.js +3 -0
- package/build/types/OneClickCommands.d.ts +1 -1
- package/build/types/Recommendation.d.ts +20 -0
- package/build/types/Recommendation.js +32 -6
- package/build/types/RepositoryAnalysis.d.ts +131 -14
- package/build/types/RepositoryAnalysis.js +16 -2
- package/build/types/ReuseOutcome.d.ts +63 -0
- package/build/types/ReuseOutcome.js +33 -0
- package/build/types/TestExecution.d.ts +1 -0
- package/build/types/TestTypes.d.ts +25 -7
- package/build/types/TestTypes.js +22 -6
- package/build/types/TestbotReport.d.ts +7 -0
- package/build/types/index.d.ts +2 -0
- package/build/types/index.js +1 -0
- package/build/utils/AnalysisStateManager.d.ts +26 -0
- package/build/utils/AnalysisStateManager.js +31 -1
- package/build/utils/analyze-openapi.js +18 -1
- package/build/utils/branchDiff.d.ts +17 -1
- package/build/utils/branchDiff.js +99 -14
- package/build/utils/featureFlags.d.ts +31 -0
- package/build/utils/featureFlags.js +37 -0
- package/build/utils/frontendIntegration.js +8 -1
- package/build/utils/grpcMockValidation.d.ts +1 -0
- package/build/utils/grpcMockValidation.js +49 -0
- package/build/utils/httpMethodValidation.d.ts +4 -0
- package/build/utils/httpMethodValidation.js +15 -0
- package/build/utils/logger.js +1 -1
- package/build/utils/mockCompatibility.d.ts +49 -0
- package/build/utils/mockCompatibility.js +82 -0
- package/build/utils/pom-scope/pom-files.js +7 -0
- package/build/utils/pom-verify/bindings.js +11 -1
- package/build/utils/pom-verify/re-exports.d.ts +10 -0
- package/build/utils/pom-verify/re-exports.js +61 -0
- package/build/utils/pom-verify/resolve.d.ts +4 -1
- package/build/utils/pom-verify/resolve.js +7 -4
- package/build/utils/pom-verify/verify.d.ts +5 -0
- package/build/utils/pom-verify/verify.js +25 -3
- package/build/utils/progress.js +10 -5
- package/build/utils/proxy-terminal.js +3 -3
- package/build/utils/routeParsers.d.ts +3 -9
- package/build/utils/routeParsers.js +79 -4
- package/build/utils/utils.js +2 -2
- package/build/utils/versions.d.ts +4 -3
- package/build/utils/versions.js +3 -1
- package/build/utils/workspaceAuth.d.ts +46 -0
- package/build/utils/workspaceAuth.js +156 -1
- package/build/workspace/testSuites.d.ts +2 -1
- package/build/workspace/testSuites.js +1 -1
- package/build/workspace/workspace.d.ts +108 -32
- package/build/workspace/workspace.js +32 -4
- package/package.json +5 -2
- package/build/adapters/jestAdapter.test.d.ts +0 -1
- package/build/adapters/jestAdapter.test.js +0 -93
- package/build/adapters/mochaAdapter.test.d.ts +0 -1
- package/build/adapters/mochaAdapter.test.js +0 -63
- package/build/adapters/playwrightAdapter.test.d.ts +0 -1
- package/build/adapters/playwrightAdapter.test.js +0 -169
- package/build/adapters/pytestAdapter.test.d.ts +0 -1
- package/build/adapters/pytestAdapter.test.js +0 -90
- package/build/prompts/code-reuse.test.d.ts +0 -1
- package/build/prompts/code-reuse.test.js +0 -62
- package/build/prompts/pom-aware-code-reuse.test.d.ts +0 -1
- package/build/prompts/pom-aware-code-reuse.test.js +0 -11
- package/build/prompts/test-maintenance/drift-analysis-prompt.test.d.ts +0 -1
- package/build/prompts/test-maintenance/drift-analysis-prompt.test.js +0 -51
- package/build/prompts/test-recommendation/analysisOutputPrompt.test.d.ts +0 -1
- package/build/prompts/test-recommendation/analysisOutputPrompt.test.js +0 -264
- package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.d.ts +0 -1
- package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.js +0 -126
- package/build/prompts/test-recommendation/promptPlan.test.d.ts +0 -1
- package/build/prompts/test-recommendation/promptPlan.test.js +0 -336
- package/build/prompts/test-recommendation/scopeAssessment.test.d.ts +0 -1
- package/build/prompts/test-recommendation/scopeAssessment.test.js +0 -371
- package/build/prompts/test-recommendation/test-recommendation-prompt.test.d.ts +0 -1
- package/build/prompts/test-recommendation/test-recommendation-prompt.test.js +0 -1925
- package/build/prompts/testbot/testbot-prompts.test.d.ts +0 -1
- package/build/prompts/testbot/testbot-prompts.test.js +0 -451
- package/build/recommendation/budgeters/diversityBalancedBudgeter.test.d.ts +0 -1
- package/build/recommendation/budgeters/diversityBalancedBudgeter.test.js +0 -138
- package/build/recommendation/budgeters/fixedNBudgeter.test.d.ts +0 -1
- package/build/recommendation/budgeters/fixedNBudgeter.test.js +0 -66
- package/build/recommendation/discriminators.test.d.ts +0 -1
- package/build/recommendation/discriminators.test.js +0 -324
- package/build/recommendation/diversity.test.d.ts +0 -1
- package/build/recommendation/diversity.test.js +0 -77
- package/build/recommendation/planRanker.test.d.ts +0 -1
- package/build/recommendation/planRanker.test.js +0 -110
- package/build/resources/testbotResource.test.d.ts +0 -1
- package/build/resources/testbotResource.test.js +0 -44
- package/build/services/AnalyticsService.test.d.ts +0 -1
- package/build/services/AnalyticsService.test.js +0 -86
- package/build/services/ScenarioGenerationService.integration.test.d.ts +0 -1
- package/build/services/ScenarioGenerationService.integration.test.js +0 -162
- package/build/services/ScenarioGenerationService.test.d.ts +0 -1
- package/build/services/ScenarioGenerationService.test.js +0 -414
- package/build/services/TestDiscoveryService.test.d.ts +0 -1
- package/build/services/TestDiscoveryService.test.js +0 -983
- package/build/services/TestExecutionService.test.d.ts +0 -1
- package/build/services/TestExecutionService.test.js +0 -1032
- package/build/services/TestGenerationService.test.d.ts +0 -1
- package/build/services/TestGenerationService.test.js +0 -578
- package/build/tool-phase-coverage.test.d.ts +0 -1
- package/build/tool-phase-coverage.test.js +0 -49
- package/build/tools/code-refactor/codeReuseTool.test.d.ts +0 -1
- package/build/tools/code-refactor/codeReuseTool.test.js +0 -572
- package/build/tools/generate-tests/generateBatchScenarioRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateBatchScenarioRestTool.test.js +0 -433
- package/build/tools/generate-tests/generateContractRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateContractRestTool.test.js +0 -142
- package/build/tools/generate-tests/generateIntegrationRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateIntegrationRestTool.test.js +0 -159
- package/build/tools/generate-tests/generateLoadRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateLoadRestTool.test.js +0 -169
- package/build/tools/generate-tests/generateUIRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateUIRestTool.test.js +0 -32
- package/build/tools/generate-tests/planGuard.test.d.ts +0 -1
- package/build/tools/generate-tests/planGuard.test.js +0 -185
- package/build/tools/generate-tests/scenarioLint.test.d.ts +0 -1
- package/build/tools/generate-tests/scenarioLint.test.js +0 -100
- package/build/tools/runExistingTestsTool.test.d.ts +0 -1
- package/build/tools/runExistingTestsTool.test.js +0 -379
- package/build/tools/submitReportTool.test.d.ts +0 -1
- package/build/tools/submitReportTool.test.js +0 -1428
- package/build/tools/test-management/actionsTool.test.d.ts +0 -1
- package/build/tools/test-management/actionsTool.test.js +0 -436
- package/build/tools/test-management/analyzeChangesTool.test.d.ts +0 -1
- package/build/tools/test-management/analyzeChangesTool.test.js +0 -522
- package/build/tools/test-management/analyzeTestHealthTool.test.d.ts +0 -1
- package/build/tools/test-management/analyzeTestHealthTool.test.js +0 -385
- package/build/tools/test-management/registerTestPlanTool.test.d.ts +0 -1
- package/build/tools/test-management/registerTestPlanTool.test.js +0 -296
- package/build/tools/trace/resolveSaveStoragePath.test.d.ts +0 -1
- package/build/tools/trace/resolveSaveStoragePath.test.js +0 -17
- package/build/tools/trace/resolveSessionPaths.test.d.ts +0 -1
- package/build/tools/trace/resolveSessionPaths.test.js +0 -104
- package/build/tools/trace/sessionState.test.d.ts +0 -1
- package/build/tools/trace/sessionState.test.js +0 -17
- package/build/tools/workspace/initializeWorkspaceTool.test.d.ts +0 -1
- package/build/tools/workspace/initializeWorkspaceTool.test.js +0 -139
- package/build/tools/workspace/serviceUpsert.test.d.ts +0 -1
- package/build/tools/workspace/serviceUpsert.test.js +0 -50
- package/build/utils/AnalysisStateManager.test.d.ts +0 -1
- package/build/utils/AnalysisStateManager.test.js +0 -134
- package/build/utils/dartRouteExtractor.test.d.ts +0 -1
- package/build/utils/dartRouteExtractor.test.js +0 -307
- package/build/utils/docker.test.d.ts +0 -1
- package/build/utils/docker.test.js +0 -114
- package/build/utils/featureFlags.test.d.ts +0 -1
- package/build/utils/featureFlags.test.js +0 -81
- package/build/utils/fileWalk.test.d.ts +0 -1
- package/build/utils/fileWalk.test.js +0 -252
- package/build/utils/frontendIntegration.test.d.ts +0 -1
- package/build/utils/frontendIntegration.test.js +0 -229
- package/build/utils/frontendSelectors.test.d.ts +0 -1
- package/build/utils/frontendSelectors.test.js +0 -118
- package/build/utils/gitStaging.test.d.ts +0 -1
- package/build/utils/gitStaging.test.js +0 -111
- package/build/utils/httpDefaults.test.d.ts +0 -1
- package/build/utils/httpDefaults.test.js +0 -21
- package/build/utils/importerHop.test.d.ts +0 -1
- package/build/utils/importerHop.test.js +0 -469
- package/build/utils/pathAffinityClassification.test.d.ts +0 -1
- package/build/utils/pathAffinityClassification.test.js +0 -208
- package/build/utils/planMatchKeys.test.d.ts +0 -1
- package/build/utils/planMatchKeys.test.js +0 -123
- package/build/utils/pom-scope/index.test.d.ts +0 -1
- package/build/utils/pom-scope/index.test.js +0 -278
- package/build/utils/pom-scope/pom-files.test.d.ts +0 -1
- package/build/utils/pom-scope/pom-files.test.js +0 -29
- package/build/utils/pom-scope/scoring.test.d.ts +0 -1
- package/build/utils/pom-scope/scoring.test.js +0 -39
- package/build/utils/pom-scope/selector-extractor.test.d.ts +0 -1
- package/build/utils/pom-scope/selector-extractor.test.js +0 -67
- package/build/utils/pom-verify/bindings.test.d.ts +0 -1
- package/build/utils/pom-verify/bindings.test.js +0 -164
- package/build/utils/pom-verify/calls.test.d.ts +0 -1
- package/build/utils/pom-verify/calls.test.js +0 -61
- package/build/utils/pom-verify/resolve.test.d.ts +0 -1
- package/build/utils/pom-verify/resolve.test.js +0 -114
- package/build/utils/pom-verify/verify.test.d.ts +0 -1
- package/build/utils/pom-verify/verify.test.js +0 -374
- package/build/utils/pr-comment-parser.test.d.ts +0 -1
- package/build/utils/pr-comment-parser.test.js +0 -428
- package/build/utils/progress.test.d.ts +0 -1
- package/build/utils/progress.test.js +0 -37
- package/build/utils/projectMetadata.test.d.ts +0 -1
- package/build/utils/projectMetadata.test.js +0 -172
- package/build/utils/pythonMountPrefixes.test.d.ts +0 -1
- package/build/utils/pythonMountPrefixes.test.js +0 -113
- package/build/utils/repoScanner.test.d.ts +0 -1
- package/build/utils/repoScanner.test.js +0 -190
- package/build/utils/reportVerification.test.d.ts +0 -1
- package/build/utils/reportVerification.test.js +0 -185
- package/build/utils/routeParsers.test.d.ts +0 -1
- package/build/utils/routeParsers.test.js +0 -1011
- package/build/utils/scenarioDrafting.test.d.ts +0 -1
- package/build/utils/scenarioDrafting.test.js +0 -876
- package/build/utils/sourceRouteExtractor.test.d.ts +0 -1
- package/build/utils/sourceRouteExtractor.test.js +0 -738
- package/build/utils/telemetry.test.d.ts +0 -1
- package/build/utils/telemetry.test.js +0 -70
- package/build/utils/trace-parser.test.d.ts +0 -6
- package/build/utils/trace-parser.test.js +0 -140
- package/build/utils/uiPageEnumerator.test.d.ts +0 -1
- package/build/utils/uiPageEnumerator.test.js +0 -824
- package/build/utils/utils.test.d.ts +0 -1
- package/build/utils/utils.test.js +0 -103
- package/build/utils/walkerCharacterization.test.d.ts +0 -1
- package/build/utils/walkerCharacterization.test.js +0 -233
- package/build/utils/workspaceAuth.test.d.ts +0 -1
- package/build/utils/workspaceAuth.test.js +0 -260
- package/build/workspace/testSuites.test.d.ts +0 -1
- package/build/workspace/testSuites.test.js +0 -23
- package/build/workspace/workspace.test.d.ts +0 -1
- package/build/workspace/workspace.test.js +0 -264
|
@@ -288,11 +288,11 @@ The ranked test recommendation catalog is pre-built and shown below (after the s
|
|
|
288
288
|
**If** Steps 1–2 revealed additional scenarios the catalog does not cover (e.g. a computed formula or foreign-key relationship that was missed), you may optionally call \`skyramp_recommend_tests\` with \`stateFile: "${p.stateFile ?? p.sessionId}"\` and \`enrichedScenarios\` to regenerate a more complete catalog — but only after presenting the current one.`;
|
|
289
289
|
const hasJavaFiles = p.candidateRouteFiles?.some((f) => /\.(java|kt)$/.test(f)) ?? false;
|
|
290
290
|
const routeFilesSection = p.candidateRouteFiles && p.candidateRouteFiles.length > 0
|
|
291
|
-
? `\
|
|
291
|
+
? `\nCandidate route/controller files for LLM inspection (read these to discover endpoints; static parser output is only a hint):\n${p.candidateRouteFiles.map((f) => `- ${f}`).join("\n")}\n`
|
|
292
292
|
: "";
|
|
293
293
|
const resolvePathsNote = p.routerMountContext.length
|
|
294
|
-
? `**Resolve nested paths** using your Step ${ANALYSIS_STEP_RESOLVE_PATHS} table
|
|
295
|
-
: `**Resolve full paths** using the prefixes you
|
|
294
|
+
? `**Resolve nested paths** using your Step ${ANALYSIS_STEP_RESOLVE_PATHS} table. The table you build from source/router context is authoritative over static parser hints.`
|
|
295
|
+
: `**Resolve full paths** using the prefixes, mounts, annotations, decorators, or routing DSL you identify in Step ${ANALYSIS_STEP_READ_FILES}.`;
|
|
296
296
|
return `## Your Task — Fill in and Present the Catalog (full repo)
|
|
297
297
|
|
|
298
298
|
### Step ${ANALYSIS_STEP_READ_FILES}: Read key files
|
|
@@ -335,36 +335,28 @@ ${p.routerFileContents?.length
|
|
|
335
335
|
p.routerMountContext.map((f) => `- \`${f}\``).join("\n")}`
|
|
336
336
|
: "";
|
|
337
337
|
const enrichment = buildEnrichmentInstructions(p);
|
|
338
|
-
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
: "The heuristic endpoint scanner found **0 endpoints**";
|
|
343
|
-
const scannerFallbackInstruction = scannerFallbackHasCatalog
|
|
344
|
-
? "Treat this as a supplemental gap check: merge only HTTP endpoints that are visibly missing from the existing catalog/spec data, and keep the existing catalog as the primary endpoint source."
|
|
345
|
-
: "Build a table of discovered endpoints (method, full path, source file) and use it as the authoritative endpoint list for all subsequent steps.";
|
|
346
|
-
const llmFallbackSection = (isDiffScope || p.scannedEndpoints.length === 0) &&
|
|
347
|
-
p.candidateRouteFiles &&
|
|
348
|
-
p.candidateRouteFiles.length > 0
|
|
338
|
+
const staticHintCount = p.scannedEndpoints.length;
|
|
339
|
+
const routeDiscoverySection = isDiffScope ||
|
|
340
|
+
staticHintCount > 0 ||
|
|
341
|
+
(p.candidateRouteFiles?.length ?? 0) > 0
|
|
349
342
|
? `
|
|
350
|
-
##
|
|
343
|
+
## LLM Route Discovery Inputs
|
|
351
344
|
|
|
352
|
-
|
|
345
|
+
Static endpoint scan results are **best-effort hints only**. Do not assume the scanner supports this repository's language, framework, routing DSL, or helper abstractions.
|
|
353
346
|
|
|
354
|
-
|
|
347
|
+
${staticHintCount > 0 ? `Static hints available: ${staticHintCount}. Verify every hinted method/path against source before using it.` : "Static hints available: 0. Build the endpoint list from source, router context, spec, and diff."}
|
|
355
348
|
|
|
356
|
-
${p.candidateRouteFiles
|
|
357
|
-
|
|
349
|
+
${p.candidateRouteFiles && p.candidateRouteFiles.length > 0
|
|
350
|
+
? `Candidate files to inspect:\n${p.candidateRouteFiles
|
|
351
|
+
.slice(0, 15)
|
|
352
|
+
.map((f) => `- \`${f}\``)
|
|
353
|
+
.join("\n")}${p.candidateRouteFiles.length > 15 ? `\n_(${p.candidateRouteFiles.length - 15} more files not shown)_` : ""}`
|
|
354
|
+
: staticHintCount > 0
|
|
355
|
+
? "Candidate files to inspect: none identified by static scanning. Verify the static hints against their source files, changed files, router context, and specs above."
|
|
356
|
+
: "Candidate files to inspect: use the changed files and routing entry-point files above."}
|
|
358
357
|
|
|
359
|
-
For each file,
|
|
360
|
-
|
|
361
|
-
- FastAPI/Flask: \`@router.<method>('/path')\` or \`@app.route('/path', ...)\`
|
|
362
|
-
- Spring/NestJS: \`@GetMapping\`, \`@PostMapping\`, \`@Controller\`, etc.
|
|
363
|
-
- Go (Gin/Echo/Chi): \`r.GET("/path", ...)\`, \`r.Group("/prefix")\`
|
|
364
|
-
- GraphQL: schema/resolver artifacts are unsupported for REST test generation; do not invent REST endpoints from them
|
|
365
|
-
- Any other framework-specific route registration pattern
|
|
366
|
-
|
|
367
|
-
${scannerFallbackInstruction}`
|
|
358
|
+
For each candidate file, infer route registrations from the source's actual framework or DSL. Record method, full path, and source file. Resolve mount prefixes through the routing entry-point files. If a file is GraphQL-only, do not invent REST endpoints from it.
|
|
359
|
+
`
|
|
368
360
|
: "";
|
|
369
361
|
return `# Repository Analysis
|
|
370
362
|
|
|
@@ -373,7 +365,7 @@ ${scannerFallbackInstruction}`
|
|
|
373
365
|
**Analysis Scope**: \`${p.analysisScope}\`
|
|
374
366
|
${isDiffScope ? `**Diff endpoints**: ${(p.parsedDiff?.newEndpoints.length ?? 0) + (p.parsedDiff?.modifiedEndpoints.length ?? 0) + (p.parsedDiff?.removedEndpoints?.length ?? 0)}` : `**Pre-scanned endpoints**: ${p.scannedEndpoints.length}`}
|
|
375
367
|
${routerSection}
|
|
376
|
-
${
|
|
368
|
+
${routeDiscoverySection}
|
|
377
369
|
${enrichment}
|
|
378
370
|
|
|
379
371
|
**CRITICAL**: No .json/.md file creation. Prioritize cross-resource workflows.`;
|
|
@@ -1,14 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns true if the file path looks like i18n/locale content (a JSON/YAML
|
|
3
|
+
* file under an i18n/, locale(s)/, lang/, or translation(s)/ directory).
|
|
4
|
+
* Exported so callers outside the frontend/backend classification itself
|
|
5
|
+
* (e.g. the production-importer integration check, which greps for static
|
|
6
|
+
* quoted imports) can special-case these files: real i18n loaders commonly
|
|
7
|
+
* fetch locale content by a templated runtime path rather than a static
|
|
8
|
+
* import, so the grep-based check would otherwise misreport them as
|
|
9
|
+
* unintegrated dead code (SKYR-3977).
|
|
10
|
+
*/
|
|
11
|
+
export declare function isI18nLocaleFile(filePath: string): boolean;
|
|
1
12
|
export declare function hasFlutterSdkDep(repositoryPath: string): boolean;
|
|
2
13
|
/**
|
|
3
14
|
* Returns true if the file path is a frontend file.
|
|
4
15
|
*
|
|
5
|
-
*
|
|
16
|
+
* Five tiers:
|
|
6
17
|
* 1. .vue / .svelte — always frontend; these file types cannot be route handlers.
|
|
7
18
|
* 2. .dart — always frontend IFF `hasFlutterSdkDep` is true (Flutter project).
|
|
8
|
-
* Sits
|
|
9
|
-
* when the Flutter SDK dep is present
|
|
10
|
-
* 3.
|
|
11
|
-
*
|
|
19
|
+
* Sits above `STRICT_API_DIR_PATTERN` because there's no server-side Dart
|
|
20
|
+
* web framework in scope when the Flutter SDK dep is present.
|
|
21
|
+
* 3. i18n/locale JSON/YAML (e.g. locales/en/common.json) — frontend UNLESS in
|
|
22
|
+
* an API/backend directory (e.g. an i18n content API under api/), since
|
|
23
|
+
* unlike tiers 1-2 a locale file CAN be served by a backend route (SKYR-3977).
|
|
24
|
+
* 4. .tsx / .jsx — frontend unless in an API/backend directory (e.g. pages/api/).
|
|
25
|
+
* 5. Ambiguous extensions (.ts, .js, .css, .html, …) — require a recognised
|
|
12
26
|
* frontend directory AND must not be in an API/backend directory.
|
|
13
27
|
*
|
|
14
28
|
* The `hasFlutterSdkDep` opt is passed in by the budget-driving caller
|
|
@@ -40,8 +54,11 @@ export declare function isTestFile(filePath: string): boolean;
|
|
|
40
54
|
/**
|
|
41
55
|
* Builds the PR scope assessment section.
|
|
42
56
|
*
|
|
43
|
-
* When `precomputedUIPct` is provided (0 = backend-only, 100 = UI-only) the server
|
|
44
|
-
*
|
|
57
|
+
* When `precomputedUIPct` is provided (0 = backend-only, 100 = UI-only) the server has
|
|
58
|
+
* already determined the split unambiguously, so Steps A–C are skipped. Backend-only
|
|
59
|
+
* (0) renders a single Budget Plan line; UI-only (100) renders that line plus the
|
|
60
|
+
* zero-new-surface override (SKYR-4099), because the budget is a default there rather
|
|
61
|
+
* than a mandate and a diff that adds no new surface must be able to abstain.
|
|
45
62
|
*
|
|
46
63
|
* For mixed PRs (`precomputedUIPct` is undefined, `hasFrontendChanges` is true) skip
|
|
47
64
|
* Steps A–C but keep Step D so the LLM can apply judgment to determine the UI%.
|
|
@@ -18,6 +18,25 @@ const STRICT_API_DIR_PATTERN = /\/(api)\//i;
|
|
|
18
18
|
// a .tsx file in routes/ is a page component, not a route handler.
|
|
19
19
|
const FRAMEWORK_ROUTE_DIR_PATTERN = /\/(routes?|controllers?|routers?|handlers?|endpoints?|server)\//i;
|
|
20
20
|
const FRONTEND_DIR_PATTERN = /(^|\/)(components?|pages?|views?|layouts?|app|src\/app|frontend|client|public|styles?|templates?)\//i;
|
|
21
|
+
// A .json (or .yaml/.yml) file nested under an i18n/locale directory holds only
|
|
22
|
+
// user-facing copy — frontend regardless of nesting depth (subject to the
|
|
23
|
+
// /api/ check above), unlike generic JSON (package.json, tsconfig.json, data
|
|
24
|
+
// fixtures) which needs no such carve-out since it's never under one of these
|
|
25
|
+
// directory names.
|
|
26
|
+
const I18N_LOCALE_FILE_PATTERN = /(^|\/)(i18n|locales?|lang|translations?)\/.*\.(json|ya?ml)$/i;
|
|
27
|
+
/**
|
|
28
|
+
* Returns true if the file path looks like i18n/locale content (a JSON/YAML
|
|
29
|
+
* file under an i18n/, locale(s)/, lang/, or translation(s)/ directory).
|
|
30
|
+
* Exported so callers outside the frontend/backend classification itself
|
|
31
|
+
* (e.g. the production-importer integration check, which greps for static
|
|
32
|
+
* quoted imports) can special-case these files: real i18n loaders commonly
|
|
33
|
+
* fetch locale content by a templated runtime path rather than a static
|
|
34
|
+
* import, so the grep-based check would otherwise misreport them as
|
|
35
|
+
* unintegrated dead code (SKYR-3977).
|
|
36
|
+
*/
|
|
37
|
+
export function isI18nLocaleFile(filePath) {
|
|
38
|
+
return I18N_LOCALE_FILE_PATTERN.test(filePath);
|
|
39
|
+
}
|
|
21
40
|
/**
|
|
22
41
|
* Returns true if the repository root's `pubspec.yaml` declares a Flutter
|
|
23
42
|
* SDK dependency (i.e., a `flutter:` key with `sdk: flutter` under
|
|
@@ -105,13 +124,16 @@ function checkPubspec(pubspecPath) {
|
|
|
105
124
|
/**
|
|
106
125
|
* Returns true if the file path is a frontend file.
|
|
107
126
|
*
|
|
108
|
-
*
|
|
127
|
+
* Five tiers:
|
|
109
128
|
* 1. .vue / .svelte — always frontend; these file types cannot be route handlers.
|
|
110
129
|
* 2. .dart — always frontend IFF `hasFlutterSdkDep` is true (Flutter project).
|
|
111
|
-
* Sits
|
|
112
|
-
* when the Flutter SDK dep is present
|
|
113
|
-
* 3.
|
|
114
|
-
*
|
|
130
|
+
* Sits above `STRICT_API_DIR_PATTERN` because there's no server-side Dart
|
|
131
|
+
* web framework in scope when the Flutter SDK dep is present.
|
|
132
|
+
* 3. i18n/locale JSON/YAML (e.g. locales/en/common.json) — frontend UNLESS in
|
|
133
|
+
* an API/backend directory (e.g. an i18n content API under api/), since
|
|
134
|
+
* unlike tiers 1-2 a locale file CAN be served by a backend route (SKYR-3977).
|
|
135
|
+
* 4. .tsx / .jsx — frontend unless in an API/backend directory (e.g. pages/api/).
|
|
136
|
+
* 5. Ambiguous extensions (.ts, .js, .css, .html, …) — require a recognised
|
|
115
137
|
* frontend directory AND must not be in an API/backend directory.
|
|
116
138
|
*
|
|
117
139
|
* The `hasFlutterSdkDep` opt is passed in by the budget-driving caller
|
|
@@ -126,8 +148,13 @@ export function isFrontendFile(filePath, { hasFlutterSdkDep = false } = {}) {
|
|
|
126
148
|
if (hasFlutterSdkDep && FLUTTER_DART_EXT.test(filePath))
|
|
127
149
|
return true;
|
|
128
150
|
// /api/ always means backend regardless of extension (Next.js API routes use .tsx).
|
|
151
|
+
// Must run before I18N_LOCALE_FILE_PATTERN — unlike .vue/.svelte/.dart, a locale
|
|
152
|
+
// JSON/YAML file CAN be served by a backend route (e.g. an i18n content API), so
|
|
153
|
+
// it doesn't get the same always-frontend exemption as those extensions.
|
|
129
154
|
if (STRICT_API_DIR_PATTERN.test(filePath))
|
|
130
155
|
return false;
|
|
156
|
+
if (isI18nLocaleFile(filePath))
|
|
157
|
+
return true;
|
|
131
158
|
// routes/, controllers/ etc. block .ts/.js but not .tsx/.jsx — Medusa Admin and
|
|
132
159
|
// React Router place page components under routes/, not API handlers.
|
|
133
160
|
if (!LIKELY_FRONTEND_EXT.test(filePath) && FRAMEWORK_ROUTE_DIR_PATTERN.test(filePath))
|
|
@@ -161,11 +188,77 @@ export function isTestFile(filePath) {
|
|
|
161
188
|
/(?:^|\/)__tests__\//.test(filePath));
|
|
162
189
|
}
|
|
163
190
|
// ── LLM scope assessment ──────────────────────────────────────────────────────
|
|
191
|
+
/**
|
|
192
|
+
* The zero-new-surface abstention rule, shared by every branch that can see a frontend
|
|
193
|
+
* diff (SKYR-4099).
|
|
194
|
+
*
|
|
195
|
+
* It previously existed only on the mixed-PR branch, so a frontend-ONLY diff — which
|
|
196
|
+
* takes the precomputed branch — had no sanctioned path to zero tests and the agent
|
|
197
|
+
* generated unnecessary UI tests while stating in its own reasoning that the change was
|
|
198
|
+
* cosmetic. Two copies then meant two definitions, and the mixed-PR one carved out
|
|
199
|
+
* "changes that alter visibility, layout, or state", which classifies a spacing-token
|
|
200
|
+
* change as non-cosmetic and made the override inert for exactly the diffs it should
|
|
201
|
+
* catch. One definition, both branches.
|
|
202
|
+
*
|
|
203
|
+
* Scoped to match `testbot-prompts.ts`'s "Do not fabricate tests outside the GENERATE
|
|
204
|
+
* list", which names three zero-test cases — deletion-only, cosmetic, and
|
|
205
|
+
* modification-of-existing-with-no-new-surface — under one principle: a new spec covers
|
|
206
|
+
* NEW observable surface only. An earlier revision of this section implemented cosmetic
|
|
207
|
+
* alone, and its keep-the-budget list contradicted the other two (an element being
|
|
208
|
+
* removed, or a `data-testid` being renamed, both forced the budget to stand). The test
|
|
209
|
+
* is coverage, not the kind of edit: does an existing test already reach this surface?
|
|
210
|
+
*
|
|
211
|
+
* `skipClause` is appended to the opening paragraph: the mixed-PR branch has a UI%
|
|
212
|
+
* step that becomes irrelevant once the budget is 0, the precomputed branch does not.
|
|
213
|
+
*/
|
|
214
|
+
/**
|
|
215
|
+
* The zero-new-surface abstention rule, shared by every branch that can see a frontend
|
|
216
|
+
* diff (SKYR-4099).
|
|
217
|
+
*
|
|
218
|
+
* It previously existed only on the mixed-PR branch, so a frontend-ONLY diff — which
|
|
219
|
+
* takes the precomputed branch — had no sanctioned path to zero tests and the agent
|
|
220
|
+
* generated unnecessary UI tests while stating in its own reasoning that the change was
|
|
221
|
+
* cosmetic. Two copies then meant two definitions, and the mixed-PR one carved out
|
|
222
|
+
* "changes that alter visibility, layout, or state", which classifies a spacing-token
|
|
223
|
+
* change as non-cosmetic and made the override inert for exactly the diffs it should
|
|
224
|
+
* catch. One definition, both branches.
|
|
225
|
+
*
|
|
226
|
+
* Scoped to match `testbot-prompts.ts`'s "Do not fabricate tests outside the GENERATE
|
|
227
|
+
* list", which names three zero-test cases — deletion-only, cosmetic, and
|
|
228
|
+
* modification-of-existing-with-no-new-surface — under one principle: a new spec covers
|
|
229
|
+
* NEW observable surface only. The test is coverage, not the kind of edit: does an
|
|
230
|
+
* existing test already reach this surface?
|
|
231
|
+
*
|
|
232
|
+
* `skipClause` is appended to the opening paragraph: the mixed-PR branch has a UI% step
|
|
233
|
+
* that becomes irrelevant once the budget is 0, the precomputed branch does not.
|
|
234
|
+
*/
|
|
235
|
+
function zeroSurfaceSection(skipClause = "") {
|
|
236
|
+
return `**Zero-new-surface override:** The total above is a default, not a mandate. A new spec exists to cover **new observable surface** — a component, route, page or flow that no existing test reaches. If your code review finds the diff adds none, set your Budget Plan to **0 total** and abstain — recommend and generate zero tests${skipClause}.
|
|
237
|
+
|
|
238
|
+
Abstain — the diff adds no new surface:
|
|
239
|
+
- **Cosmetic.** A styling-only value change (a spacing, size, color or font token, or a utility class swap such as \`size-4\`→\`size-5\`), or a \`.css\`/\`.scss\` reformat (property reordering, comment or whitespace edits, \`0px\`→\`0\`).
|
|
240
|
+
- **Deletion-only.** A component, route, element or feature was removed. The work is DELETING the tests that covered it — a removed surface cannot be the subject of a new spec.
|
|
241
|
+
- **Modification of an already-covered surface.** A renamed or moved selector, \`data-testid\`, \`aria-*\` or role; changed copy; an added field; a reordered or conditionally hidden element — where an existing test already reaches it. The work is UPDATING that test in place.
|
|
242
|
+
|
|
243
|
+
Keep the budget only for surface no existing test covers:
|
|
244
|
+
- A newly added component, route, page or flow.
|
|
245
|
+
- A component that was previously unintegrated and now has an integration point.
|
|
246
|
+
- New interactive behavior, state or validation on a surface no existing test reaches.
|
|
247
|
+
|
|
248
|
+
Two things that are NOT evidence of new surface: a frontend file appearing in the diff, and a large diff. Judge by whether an existing test already reaches the changed surface.
|
|
249
|
+
|
|
250
|
+
With a 0-total Budget Plan the work this diff needs is maintenance of the tests that already cover the affected surface — update the ones whose selectors or copy moved, and delete the ones that covered something this diff removed. Do NOT add a spec asserting that a removed feature is absent: the tests that covered it are the ones to delete, and an "is not present" assertion breaks the next time an unrelated sibling element changes.
|
|
251
|
+
|
|
252
|
+
If nothing currently covers the changed surface, there is no maintenance to do — and still no new spec to write, because a test added now would assert behavior this diff did not change. The missing coverage is a pre-existing gap, not something this PR introduced. Record it in \`additionalRecommendations\` in recommendatory voice ("would verify …") so the gap is visible without claiming a test was written.`;
|
|
253
|
+
}
|
|
164
254
|
/**
|
|
165
255
|
* Builds the PR scope assessment section.
|
|
166
256
|
*
|
|
167
|
-
* When `precomputedUIPct` is provided (0 = backend-only, 100 = UI-only) the server
|
|
168
|
-
*
|
|
257
|
+
* When `precomputedUIPct` is provided (0 = backend-only, 100 = UI-only) the server has
|
|
258
|
+
* already determined the split unambiguously, so Steps A–C are skipped. Backend-only
|
|
259
|
+
* (0) renders a single Budget Plan line; UI-only (100) renders that line plus the
|
|
260
|
+
* zero-new-surface override (SKYR-4099), because the budget is a default there rather
|
|
261
|
+
* than a mandate and a diff that adds no new surface must be able to abstain.
|
|
169
262
|
*
|
|
170
263
|
* For mixed PRs (`precomputedUIPct` is undefined, `hasFrontendChanges` is true) skip
|
|
171
264
|
* Steps A–C but keep Step D so the LLM can apply judgment to determine the UI%.
|
|
@@ -200,14 +293,20 @@ Budget Plan: 0 total — no new, modified, or removed endpoints were classified
|
|
|
200
293
|
|
|
201
294
|
With a 0-total Budget Plan: generate zero tests, recommend zero tests, and follow the zero-test report path. Do NOT draft baseline or generic tests for unchanged endpoints to fill a budget — an empty diff surface is a valid, expected outcome.
|
|
202
295
|
|
|
203
|
-
**Exception — claim the ceiling only with evidence:** if your code review of the changed files shows an observable API behavior change the classifier missed (e.g. a DTO/serializer/service change that alters a response shape, a deployment/config change that newly exposes or removes endpoints, or a schema-defined API contract change — a CRD type/kubebuilder validation marker, GraphQL schema, or gRPC proto edit that adds, removes, or re-validates what the server accepts or returns), raise your Budget Plan to cover exactly those affected endpoints, up to ${maxTotal} total (${effectiveGenerate} generate + ${additional} additional), 0% UI/E2E. Note: repositories whose entire API surface is schema-defined (e.g. a Kubernetes operator serving CRDs through the kube-apiserver) ALWAYS classify zero endpoints — for these, a schema change in the diff IS the endpoint change; evaluate this exception against the schema files instead of concluding there is nothing to test. Every test must name the changed file that justifies it. State your raised plan now in the canonical format — \`Budget Plan: <total> total (<generate> generate + <additional> additional), 0% UI/E2E\` — and use those exact numbers throughout the rest of the prompt; the raised generate count is your committed generate count.`;
|
|
296
|
+
**Exception — claim the ceiling only with evidence:** if your code review of the changed files shows an observable API behavior change the classifier missed (e.g. a DTO/serializer/service change that alters a response shape, a shared library/default-value or business-rule constant change that alters the behavior of an existing, unchanged endpoint (e.g. a default schedule, threshold, or config constant imported by a route handler elsewhere in the codebase), a deployment/config change that newly exposes or removes endpoints, or a schema-defined API contract change — a CRD type/kubebuilder validation marker, GraphQL schema, or gRPC proto edit that adds, removes, or re-validates what the server accepts or returns), raise your Budget Plan to cover exactly those affected endpoints, up to ${maxTotal} total (${effectiveGenerate} generate + ${additional} additional), 0% UI/E2E. Note: repositories whose entire API surface is schema-defined (e.g. a Kubernetes operator serving CRDs through the kube-apiserver) ALWAYS classify zero endpoints — for these, a schema change in the diff IS the endpoint change; evaluate this exception against the schema files instead of concluding there is nothing to test. Similarly, a changed file with zero classified endpoints is not by itself evidence of "no testable surface" — trace what imports the changed export (grep for its name) to check whether it feeds an existing endpoint's behavior before concluding the diff has no test value. Every test must name the changed file that justifies it. State your raised plan now in the canonical format — \`Budget Plan: <total> total (<generate> generate + <additional> additional), 0% UI/E2E\` — and use those exact numbers throughout the rest of the prompt; the raised generate count is your committed generate count.`;
|
|
204
297
|
}
|
|
205
|
-
// Unambiguous backend-only or UI-only:
|
|
298
|
+
// Unambiguous backend-only or UI-only: no LLM counting needed. Backend-only emits just
|
|
299
|
+
// the Budget Plan line; UI-only appends the zero-new-surface override (see below).
|
|
206
300
|
if (precomputedUIPct !== undefined) {
|
|
301
|
+
const uiSuffix = precomputedUIPct > 0 ? `, ${precomputedUIPct}% UI/E2E` : "";
|
|
302
|
+
// Ordered ahead of the "use these exact numbers" line — that line reads as final, so
|
|
303
|
+
// an override printed after it cannot fire. Backend-only (precomputedUIPct === 0) has
|
|
304
|
+
// no frontend file to call cosmetic, so it gets no override.
|
|
305
|
+
const cosmeticOverride = precomputedUIPct > 0 ? `${zeroSurfaceSection()}\n\n` : "";
|
|
207
306
|
return `### PR Scope Assessment
|
|
208
|
-
Budget Plan: ${maxTotal} total (${effectiveGenerate} generate + ${additional} additional)
|
|
307
|
+
Budget Plan: ${maxTotal} total (${effectiveGenerate} generate + ${additional} additional)${uiSuffix}
|
|
209
308
|
|
|
210
|
-
Use these exact numbers throughout the rest of the prompt.`;
|
|
309
|
+
${cosmeticOverride}Use these exact numbers throughout the rest of the prompt.`;
|
|
211
310
|
}
|
|
212
311
|
// Mixed PR: server can pre-compute the total but not the UI/E2E split — keep Step D.
|
|
213
312
|
if (hasFrontendChanges) {
|
|
@@ -215,7 +314,7 @@ Use these exact numbers throughout the rest of the prompt.`;
|
|
|
215
314
|
|
|
216
315
|
Budget Plan (total already determined): **${maxTotal} total (${effectiveGenerate} generate + ${additional} additional)**
|
|
217
316
|
|
|
218
|
-
|
|
317
|
+
${zeroSurfaceSection(", and skip Step D below")}
|
|
219
318
|
|
|
220
319
|
**Step D — Determine UI vs backend split for the budget above:**
|
|
221
320
|
- Non-UI slots are backend tests; start from file-count ratio for UI%, then apply judgment:
|
|
@@ -178,6 +178,9 @@ Write UI recommendation \`reasoning\` fields in **natural prose** that names ele
|
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
180
|
const fmtEndpoint = (m, ep) => ` ${m.method} ${ep.path}${m.authRequired ? " [auth]" : ""} (${(m.interactions ?? []).length} interactions)`;
|
|
181
|
+
// In diff scope, cap the reference endpoint list to prevent context overflow.
|
|
182
|
+
// Changed endpoints are always shown in full; only the "other" list is capped.
|
|
183
|
+
const DIFF_SCOPE_OTHER_ENDPOINT_CAP = 20;
|
|
181
184
|
let endpointLines;
|
|
182
185
|
if (isDiffScope && changedEndpointKeys.size > 0) {
|
|
183
186
|
const changedLines = [];
|
|
@@ -201,7 +204,25 @@ Write UI recommendation \`reasoning\` fields in **natural prose** that names ele
|
|
|
201
204
|
changedLines.push(` ${m.method} ${ep.path} [removed]`);
|
|
202
205
|
}
|
|
203
206
|
}
|
|
204
|
-
|
|
207
|
+
const cappedOther = otherLines.slice(0, DIFF_SCOPE_OTHER_ENDPOINT_CAP);
|
|
208
|
+
const hiddenOtherCount = otherLines.length - cappedOther.length;
|
|
209
|
+
const otherSuffix = hiddenOtherCount > 0
|
|
210
|
+
? `\n ... and ${hiddenOtherCount} more (full endpoint list in state file)`
|
|
211
|
+
: "";
|
|
212
|
+
const otherLabel = hiddenOtherCount > 0
|
|
213
|
+
? `Other endpoints (reference only, ${cappedOther.length} of ${otherLines.length} shown)`
|
|
214
|
+
: "Other endpoints (reference only)";
|
|
215
|
+
endpointLines = `**Likely changed in this PR (from static file→endpoint mapping — verify against diff in Step ${ANALYSIS_STEP_EXTRACT}):**\n${changedLines.join("\n") || " none"}\n\n**${otherLabel}:**\n${cappedOther.join("\n") || " none"}${otherSuffix}`;
|
|
216
|
+
}
|
|
217
|
+
else if (isDiffScope) {
|
|
218
|
+
// Diff scope but no changed endpoints detected — cap to avoid dumping the full catalog.
|
|
219
|
+
const allMethodLines = allEndpoints.flatMap((ep) => (ep.methods ?? []).map((m) => fmtEndpoint(m, ep)));
|
|
220
|
+
const cappedLines = allMethodLines.slice(0, DIFF_SCOPE_OTHER_ENDPOINT_CAP);
|
|
221
|
+
const hiddenCount = allMethodLines.length - cappedLines.length;
|
|
222
|
+
const suffix = hiddenCount > 0
|
|
223
|
+
? `\n ... and ${hiddenCount} more (full endpoint list in state file — trace changed files directly from the diff to find affected endpoints)`
|
|
224
|
+
: "";
|
|
225
|
+
endpointLines = `${cappedLines.join("\n") || " none"}${suffix}`;
|
|
205
226
|
}
|
|
206
227
|
else {
|
|
207
228
|
endpointLines = allEndpoints
|
|
@@ -230,9 +251,22 @@ Write UI recommendation \`reasoning\` fields in **natural prose** that names ele
|
|
|
230
251
|
}
|
|
231
252
|
}
|
|
232
253
|
const { authSchemeSnippet } = getAuthSnippets(authHeaderValue, authTypeValue, workspaceAuthScheme);
|
|
254
|
+
const routeDiscovery = analysis.routeDiscovery;
|
|
255
|
+
const routeDiscoverySection = routeDiscovery
|
|
256
|
+
? `
|
|
257
|
+
## LLM Route Discovery Inputs
|
|
258
|
+
Static endpoint data below is a best-effort hint, not a complete parser for every framework.
|
|
259
|
+
Authoritative endpoint extraction must come from reading the changed source files, router/module context, OpenAPI paths when available, and the diff.
|
|
260
|
+
Candidate files to inspect: ${routeDiscovery.candidateFiles.length > 0 ? routeDiscovery.candidateFiles.join(", ") : "none"}
|
|
261
|
+
Router/module context files: ${routeDiscovery.routerMountContext.length > 0 ? routeDiscovery.routerMountContext.join(", ") : "none"}
|
|
262
|
+
OpenAPI paths available: ${routeDiscovery.openApiPaths.length}
|
|
263
|
+
Static hints available: ${routeDiscovery.staticHints.length}
|
|
264
|
+
${routeDiscovery.diffFilePath ? `Diff file: ${routeDiscovery.diffFilePath}` : ""}
|
|
265
|
+
`.trim()
|
|
266
|
+
: "";
|
|
233
267
|
const sourcePriority = `
|
|
234
268
|
## Source Priority
|
|
235
|
-
When information conflicts, prefer: **Traces** (actual behavior) > **
|
|
269
|
+
When information conflicts, prefer: **Traces** (actual behavior) > **Source code read by the LLM** (implemented behavior) > **OpenAPI spec/docs** (documented behavior) > **Static parser hints** (best-effort, may be incomplete or framework-blind).
|
|
236
270
|
`;
|
|
237
271
|
// Compact fingerprint of tests already covering endpoints in this repo (Skyramp + external).
|
|
238
272
|
// Re-derived fresh each run from test files on disk — no separate persistence needed.
|
|
@@ -274,8 +308,11 @@ Framework: ${analysis.projectClassification.primaryFramework} (${analysis.projec
|
|
|
274
308
|
Project type: ${analysis.projectClassification.projectType}
|
|
275
309
|
Auth: ${authMethod} (header: ${authHeaderValue}${authTypeValue ? `, type: ${authTypeValue}` : ""})
|
|
276
310
|
Base URL: ${analysis.apiEndpoints.baseUrl}
|
|
277
|
-
Candidate
|
|
311
|
+
Candidate endpoint hints from static scan — unverified and non-exhaustive; confirm paths by reading source/router context before use (${analysis.apiEndpoints.totalCount}):
|
|
278
312
|
${endpointLines}${testFingerprint}
|
|
313
|
+
${routeDiscoverySection ? `
|
|
314
|
+
|
|
315
|
+
${routeDiscoverySection}` : ""}
|
|
279
316
|
`.trim();
|
|
280
317
|
// ── Branch diff ──
|
|
281
318
|
let diffSection = "";
|
|
@@ -295,7 +332,7 @@ Affected services: ${diffContext.affectedServices.join(", ") || "N/A"}
|
|
|
295
332
|
|
|
296
333
|
Focus on tests that validate these changes and how they interact with existing resources.
|
|
297
334
|
For removed endpoints: verify they now return 404 or the appropriate deprecation status code.
|
|
298
|
-
|
|
335
|
+
Treat the endpoint lists above as static hints. If source/diff inspection finds a different changed endpoint set, prefer the source-grounded set and use other endpoints only as setup steps.
|
|
299
336
|
`;
|
|
300
337
|
}
|
|
301
338
|
// ── Interactions ──
|
|
@@ -17,10 +17,5 @@ export interface RelatedRepository {
|
|
|
17
17
|
export declare function parseRelatedRepositories(raw: string | undefined): RelatedRepository[] | undefined;
|
|
18
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
19
|
prNumber?: number, userPrompt?: string, services?: Service[], uiCredentials?: string, testsRepoDir?: string, relatedRepositories?: RelatedRepository[], primaryRepo?: string, planOnly?: boolean, language?: 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
20
|
export declare function buildWorkspaceRecoveryPrefix(repositoryPath: string): string;
|
|
26
21
|
export declare function registerTestbotPrompt(server: McpServer): void;
|