@skyramp/mcp 0.3.8 → 0.4.0-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.
- package/build/commands/commandLibrary.d.ts +1 -1
- package/build/commands/commandLibrary.js +3 -3
- package/build/commands/recommendTestsAndExecuteCommand.d.ts +1 -1
- package/build/commands/recommendTestsAndExecuteCommand.js +35 -20
- package/build/commands/testThisEndpointCommand.js +35 -19
- package/build/index.js +9 -3
- package/build/playwright/blueprintDigest.d.ts +15 -0
- package/build/playwright/blueprintDigest.js +152 -0
- package/build/playwright/blueprintDigestStore.d.ts +31 -0
- package/build/playwright/blueprintDigestStore.js +117 -0
- package/build/playwright/registerPlaywrightTools.js +60 -12
- package/build/playwright/traceRecordingPrompt.js +8 -7
- package/build/prompts/enhance-assertions/sharedAssertionRules.js +9 -8
- package/build/prompts/enhance-assertions/uiAssertionsPrompt.js +24 -2
- package/build/prompts/promptAssets.d.ts +20 -0
- package/build/prompts/promptAssets.js +55 -0
- package/build/prompts/sut-setup/modes/dockerComposePrompt.js +19 -5
- package/build/prompts/test-maintenance/actionsInstructions.d.ts +4 -0
- package/build/prompts/test-maintenance/actionsInstructions.js +14 -2
- package/build/prompts/test-maintenance/drift-analysis-prompt.d.ts +0 -10
- package/build/prompts/test-maintenance/drift-analysis-prompt.js +2 -11
- package/build/prompts/test-maintenance/uiDriftAnalysisSections.js +8 -4
- package/build/prompts/test-recommendation/diffExecutionPlan.d.ts +5 -22
- package/build/prompts/test-recommendation/diffExecutionPlan.js +37 -465
- package/build/prompts/test-recommendation/recommendationSections.d.ts +7 -17
- package/build/prompts/test-recommendation/recommendationSections.js +67 -309
- package/build/prompts/test-recommendation/recommendationShared.d.ts +19 -47
- package/build/prompts/test-recommendation/recommendationShared.js +49 -155
- package/build/prompts/test-recommendation/registerRecommendTestsPrompt.d.ts +0 -5
- package/build/prompts/test-recommendation/registerRecommendTestsPrompt.js +10 -153
- package/build/prompts/test-recommendation/test-recommendation-prompt.d.ts +2 -29
- package/build/prompts/test-recommendation/test-recommendation-prompt.js +32 -457
- package/build/prompts/testbot/planDeclarations.d.ts +6 -0
- package/build/prompts/testbot/planDeclarations.js +9 -0
- package/build/prompts/testbot/testbot-prompts.d.ts +8 -0
- package/build/prompts/testbot/testbot-prompts.js +256 -381
- package/build/recommendation/answers.d.ts +35 -0
- package/build/recommendation/answers.js +96 -0
- package/build/recommendation/registerPlan.d.ts +49 -0
- package/build/recommendation/registerPlan.js +117 -0
- package/build/recommendation/runVerifiers.d.ts +10 -0
- package/build/recommendation/runVerifiers.js +49 -0
- package/build/recommendation/subjectStep.d.ts +42 -0
- package/build/recommendation/subjectStep.js +86 -0
- package/build/recommendation/types.d.ts +163 -0
- package/build/recommendation/types.js +20 -0
- package/build/recommendation/verifierContracts.d.ts +382 -0
- package/build/recommendation/verifierContracts.js +263 -0
- package/build/recommendation/verifiers/changedFile.d.ts +2 -0
- package/build/recommendation/verifiers/changedFile.js +82 -0
- package/build/recommendation/verifiers/citedPath.d.ts +12 -0
- package/build/recommendation/verifiers/citedPath.js +35 -0
- package/build/recommendation/verifiers/coverage.d.ts +7 -0
- package/build/recommendation/verifiers/coverage.js +617 -0
- package/build/recommendation/verifiers/deliveredMatchesPlan.d.ts +11 -0
- package/build/recommendation/verifiers/deliveredMatchesPlan.js +33 -0
- package/build/recommendation/verifiers/endpointGrounded.d.ts +17 -0
- package/build/recommendation/verifiers/endpointGrounded.js +128 -0
- package/build/recommendation/verifiers/existingCoverage.d.ts +6 -0
- package/build/recommendation/verifiers/existingCoverage.js +51 -0
- package/build/recommendation/verifiers/expectedOutcome.d.ts +31 -0
- package/build/recommendation/verifiers/expectedOutcome.js +105 -0
- package/build/recommendation/verifiers/removedElementGuarded.d.ts +2 -0
- package/build/recommendation/verifiers/removedElementGuarded.js +57 -0
- package/build/recommendation/verifiers/reportedCategory.d.ts +26 -0
- package/build/recommendation/verifiers/reportedCategory.js +84 -0
- package/build/recommendation/verifiers/screenRoute.d.ts +10 -0
- package/build/recommendation/verifiers/screenRoute.js +118 -0
- package/build/recommendation/verifiers/statedDifference.d.ts +6 -0
- package/build/recommendation/verifiers/statedDifference.js +140 -0
- package/build/recommendation/verifiers/uiElementGrounded.d.ts +7 -0
- package/build/recommendation/verifiers/uiElementGrounded.js +318 -0
- package/build/resources/analysisResources.js +1 -114
- package/build/resources/testbotResource.js +23 -13
- package/build/services/ModularizationService.js +2 -1
- package/build/services/TestDiscoveryService.d.ts +3 -72
- package/build/services/TestDiscoveryService.js +10 -303
- package/build/services/containerEnv.d.ts +1 -1
- package/build/services/containerEnv.js +12 -0
- package/build/skills/fixTestImportErrorsSkill.d.ts +13 -0
- package/build/skills/fixTestImportErrorsSkill.js +20 -0
- package/build/toolNames.d.ts +1 -0
- package/build/toolNames.js +1 -0
- package/build/tools/code-refactor/enhanceAssertionsTool.js +3 -3
- package/build/tools/code-refactor/modularizationTool.js +2 -1
- package/build/tools/executeSkyrampTestTool.d.ts +80 -0
- package/build/tools/executeSkyrampTestTool.js +246 -19
- package/build/tools/generate-tests/generateBatchScenarioRestTool.js +6 -0
- package/build/tools/generate-tests/generateContractRestTool.js +3 -3
- package/build/tools/generate-tests/planGuard.d.ts +2 -2
- package/build/tools/generate-tests/planGuard.js +78 -18
- package/build/tools/one-click/oneClickTool.d.ts +0 -1
- package/build/tools/one-click/oneClickTool.js +0 -5
- package/build/tools/submitReportTool.d.ts +48 -42
- package/build/tools/submitReportTool.js +576 -193
- package/build/tools/test-management/actionsTool.js +72 -4
- package/build/tools/test-management/analyzeChangesTool.d.ts +144 -48
- package/build/tools/test-management/analyzeChangesTool.js +212 -1219
- package/build/tools/test-management/analyzeTestHealthTool.js +13 -24
- package/build/tools/test-management/index.d.ts +1 -0
- package/build/tools/test-management/index.js +1 -0
- package/build/tools/test-management/registerTestPlanTool.d.ts +795 -172
- package/build/tools/test-management/registerTestPlanTool.js +609 -542
- package/build/tools/test-management/resolveScreenTool.d.ts +75 -0
- package/build/tools/test-management/resolveScreenTool.js +289 -0
- package/build/types/BlueprintDigest.d.ts +34 -0
- package/build/types/BlueprintDigest.js +1 -0
- package/build/types/RepositoryAnalysis.d.ts +20 -1559
- package/build/types/RepositoryAnalysis.js +2 -58
- package/build/types/StepMethod.d.ts +40 -0
- package/build/types/StepMethod.js +77 -0
- package/build/types/TestAnalysis.d.ts +12 -0
- package/build/types/TestExecution.d.ts +4 -0
- package/build/types/TestRecommendation.d.ts +24 -24
- package/build/types/TestRecommendation.js +91 -89
- package/build/types/TestbotPromptOptions.d.ts +0 -4
- package/build/types/TestbotReport.d.ts +64 -2
- package/build/utils/AnalysisStateManager.d.ts +79 -113
- package/build/utils/AnalysisStateManager.js +147 -57
- package/build/utils/assertion-verify/api-shared-lints.js +1 -1
- package/build/utils/assertion-verify/metrics.js +85 -36
- package/build/utils/assertion-verify/ui-lints.d.ts +0 -5
- package/build/utils/assertion-verify/ui-lints.js +32 -0
- package/build/utils/branchDiff.d.ts +63 -31
- package/build/utils/branchDiff.js +242 -94
- package/build/utils/containedPath.d.ts +18 -0
- package/build/utils/containedPath.js +73 -0
- package/build/utils/dartRouteExtractor.d.ts +18 -34
- package/build/utils/dartRouteExtractor.js +101 -173
- package/build/utils/featureFlags.d.ts +12 -0
- package/build/utils/featureFlags.js +14 -0
- package/build/utils/frontendSelectors.d.ts +48 -27
- package/build/utils/frontendSelectors.js +241 -80
- package/build/utils/pathMatching.d.ts +2 -4
- package/build/utils/pathMatching.js +2 -4
- package/build/utils/planMatchKeys.d.ts +38 -47
- package/build/utils/planMatchKeys.js +143 -81
- package/build/utils/rebaselineSnapshots.d.ts +24 -0
- package/build/utils/rebaselineSnapshots.js +65 -0
- package/build/utils/removedUiElements.d.ts +22 -0
- package/build/utils/removedUiElements.js +106 -0
- package/build/utils/reportVerification.d.ts +2 -6
- package/build/utils/reportVerification.js +61 -2
- package/build/utils/screenRoutes.d.ts +66 -0
- package/build/utils/screenRoutes.js +727 -0
- package/build/utils/sourceRouteExtractor.js +320 -112
- package/build/utils/testFileClassification.d.ts +11 -2
- package/build/utils/testFileClassification.js +44 -2
- package/build/utils/testFixtures.d.ts +5 -0
- package/build/utils/testFixtures.js +13 -0
- package/build/utils/utils.d.ts +0 -1
- package/build/utils/utils.js +0 -11
- package/build/utils/versions.d.ts +3 -3
- package/build/utils/versions.js +1 -1
- package/build/workspace/workspace.d.ts +12 -12
- package/node_modules/playwright/lib/mcp/skyramp/assertHiddenTool.js +56 -0
- package/node_modules/playwright/lib/mcp/skyramp/assertTool.js +2 -1
- package/node_modules/playwright/lib/mcp/skyramp/loadTraceTool.js +10 -0
- package/node_modules/playwright/lib/mcp/skyramp/skyRampImport.js +4 -1
- package/node_modules/playwright/lib/mcp/skyramp/traceRecordingBackend.js +160 -1
- package/node_modules/playwright/lib/mcp/test/skyRampExport.js +4 -2
- package/node_modules/playwright/node_modules/playwright-core/lib/server/codegen/skyramp/jsonlReader.js +1 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/recorderSignalProcessor.js +2 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder.js +5 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/{index.-Id052Lr.js → index.B7KbSQcC.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.html +1 -1
- package/node_modules/playwright/node_modules/playwright-core/package.json +1 -1
- package/node_modules/playwright/node_modules/playwright-core/src/server/codegen/skyramp/jsonlReader.ts +1 -1
- package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/recorderSignalProcessor.ts +7 -0
- package/node_modules/playwright/node_modules/playwright-core/src/server/recorder.ts +6 -1
- package/node_modules/playwright/package.json +1 -1
- package/package.json +4 -3
- package/plugin/.claude-plugin/plugin.json +8 -0
- package/plugin/plugin.json +6 -0
- package/plugin/prompts/declaring-a-plan.md +20 -0
- package/plugin/prompts/generate-tests/context-fetching.md +4 -0
- package/plugin/prompts/generate-tests/execution-plan.md +63 -0
- package/plugin/prompts/generate-tests/generation.md +108 -0
- package/plugin/prompts/generate-tests/path-parameters.md +1 -0
- package/plugin/prompts/generate-tests/reasoning-protocol.md +17 -0
- package/plugin/prompts/generate-tests/tool-workflow-variants.md +61 -0
- package/plugin/prompts/generate-tests/tool-workflows.md +65 -0
- package/plugin/prompts/plan-tests.md +42 -0
- package/plugin/prompts/testbot-task1.md +82 -0
- package/plugin/skills/fix-test-import-errors/SKILL.md +98 -0
- package/build/prompts/test-recommendation/analysisOutputPrompt.d.ts +0 -84
- package/build/prompts/test-recommendation/analysisOutputPrompt.js +0 -369
- package/build/prompts/test-recommendation/fullRepoCatalog.d.ts +0 -7
- package/build/prompts/test-recommendation/fullRepoCatalog.js +0 -283
- package/build/prompts/test-recommendation/scopeAssessment.d.ts +0 -81
- package/build/prompts/test-recommendation/scopeAssessment.js +0 -359
- package/build/recommendation/budgeters/diversityBalancedBudgeter.d.ts +0 -7
- package/build/recommendation/budgeters/diversityBalancedBudgeter.js +0 -105
- package/build/recommendation/budgeters/fixedNBudgeter.d.ts +0 -7
- package/build/recommendation/budgeters/fixedNBudgeter.js +0 -11
- package/build/recommendation/budgeters/shared.d.ts +0 -32
- package/build/recommendation/budgeters/shared.js +0 -246
- package/build/recommendation/discriminators.d.ts +0 -37
- package/build/recommendation/discriminators.js +0 -379
- package/build/recommendation/diversity.d.ts +0 -47
- package/build/recommendation/diversity.js +0 -101
- package/build/recommendation/planRanker.d.ts +0 -65
- package/build/recommendation/planRanker.js +0 -83
- package/build/recommendation/testFixtures.d.ts +0 -25
- package/build/recommendation/testFixtures.js +0 -45
- package/build/types/FrontendIntegration.d.ts +0 -28
- package/build/types/FrontendIntegration.js +0 -22
- package/build/types/Recommendation.d.ts +0 -146
- package/build/types/Recommendation.js +0 -74
- package/build/utils/changedRoutes.d.ts +0 -29
- package/build/utils/changedRoutes.js +0 -87
- package/build/utils/frontendIntegration.d.ts +0 -9
- package/build/utils/frontendIntegration.js +0 -243
- package/build/utils/importerHop.d.ts +0 -135
- package/build/utils/importerHop.js +0 -489
- package/build/utils/pathAffinityClassification.d.ts +0 -49
- package/build/utils/pathAffinityClassification.js +0 -180
- package/build/utils/pythonMountPrefixes.d.ts +0 -25
- package/build/utils/pythonMountPrefixes.js +0 -347
- package/build/utils/repoScanner.d.ts +0 -34
- package/build/utils/repoScanner.js +0 -300
- package/build/utils/routeParsers.d.ts +0 -95
- package/build/utils/routeParsers.js +0 -951
- package/build/utils/scenarioDrafting.d.ts +0 -92
- package/build/utils/scenarioDrafting.js +0 -951
- package/build/utils/subjectEndpoints.d.ts +0 -19
- package/build/utils/subjectEndpoints.js +0 -98
- package/build/utils/uiPageEnumerator.d.ts +0 -172
- package/build/utils/uiPageEnumerator.js +0 -474
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fix-test-import-errors
|
|
3
|
+
description: Fix errors in refactored or generated test code — parameter passing, undefined references, import paths, circular imports, and unused imports. Use after modularization or generation when a test file has errors. Takes the test file path, language, and framework as arguments.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Fix errors in refactored code
|
|
7
|
+
|
|
8
|
+
`$ARGUMENTS` is a positional list: `$0` is the test file, `$1` is the language (`python`, `typescript`, `javascript`, or `java`), and `$2` is the testing framework.
|
|
9
|
+
|
|
10
|
+
Apply the following to `$0`.
|
|
11
|
+
|
|
12
|
+
1. **Parameter Passing:** Identify functions using variables from outside scope (like 'page' object). Pass these as parameters.
|
|
13
|
+
2. **Validate Correctness:** Ensure code is free of reference errors, undefined variables, runtime issues.
|
|
14
|
+
3. **Import Paths:** Ensure import paths are correct and there are no circular imports.
|
|
15
|
+
4. **Import Validation:** Ensure all remaining imports are necessary and no missing imports cause reference errors.
|
|
16
|
+
5. **Unused Import Cleanup:** Verify that unused imports were properly removed without breaking functionality.
|
|
17
|
+
6. **UI State Management:** Check for UI state conflicts, modal interference, or element interaction issues.
|
|
18
|
+
7. **Sequential Operations:** Ensure UI operations don't interfere with each other when called in sequence.
|
|
19
|
+
|
|
20
|
+
**IMPORT ERROR DEBUGGING:**
|
|
21
|
+
|
|
22
|
+
- Check for missing imports that cause undefined reference errors
|
|
23
|
+
- Verify that import removal didn't break existing functionality
|
|
24
|
+
- Ensure all imported modules are actually available in the project
|
|
25
|
+
- Confirm that import syntax is correct for the target language
|
|
26
|
+
|
|
27
|
+
**CRITICAL CONSTRAINTS:**
|
|
28
|
+
|
|
29
|
+
- DO NOT CREATE/UPDATE package.json or requirements.txt or pom.xml or build.gradle file
|
|
30
|
+
- NEVER create dependency management files, even when linting errors suggest missing dependencies
|
|
31
|
+
- Focus on fixing code errors within existing files only
|
|
32
|
+
|
|
33
|
+
**KEY: Variables not defined within function scope MUST be passed as parameters.**
|
|
34
|
+
**UI KEY: Helper functions that perform UI operations must be self-contained and not leave modals/dialogs open.**
|
|
35
|
+
**IMPORT KEY: All imports must be either used in the code or properly removed.**
|
|
36
|
+
**DEPENDENCY KEY: DO NOT create package.json, requirements.txt, or any dependency files regardless of linting errors.**
|
|
37
|
+
|
|
38
|
+
## Steps for `$1`
|
|
39
|
+
|
|
40
|
+
Use the block that matches `$1`. Where `$2` is given, prefer its runner.
|
|
41
|
+
|
|
42
|
+
### python
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
# Install skyramp dependency
|
|
46
|
+
pip3 install skyramp
|
|
47
|
+
|
|
48
|
+
# For an e2e or ui test, also install the playwright dependencies
|
|
49
|
+
pip3 install pytest-playwright
|
|
50
|
+
python3 -m pytest --browser chromium $0
|
|
51
|
+
|
|
52
|
+
# framework pytest
|
|
53
|
+
pip3 install pytest
|
|
54
|
+
python3 -m pytest $0
|
|
55
|
+
|
|
56
|
+
# framework robot
|
|
57
|
+
pip3 install robotframework
|
|
58
|
+
python3 -m robot <robot-file>.robot
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### typescript
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
# install dependencies for package.json
|
|
65
|
+
npm install @skyramp/skyramp @playwright/test
|
|
66
|
+
|
|
67
|
+
# Execution of test file
|
|
68
|
+
npx playwright test $0 --reporter=list
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### javascript
|
|
72
|
+
|
|
73
|
+
```sh
|
|
74
|
+
# install dependencies for package.json
|
|
75
|
+
npm install @skyramp/skyramp @playwright/test
|
|
76
|
+
|
|
77
|
+
# Execution of test file
|
|
78
|
+
npx playwright test $0 --reporter=list
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### java
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
# Prerequisites
|
|
85
|
+
# Compile the test file
|
|
86
|
+
javac -cp "./lib/*" -d target $0
|
|
87
|
+
|
|
88
|
+
# Execution of test file
|
|
89
|
+
JUNIT_PLATFORM_VER="1.9.3"
|
|
90
|
+
classpath="target:$(echo ./lib/*.jar | tr ' ' ':')"
|
|
91
|
+
java -jar "./lib/junit-platform-console-standalone-${JUNIT_PLATFORM_VER}.jar" \
|
|
92
|
+
--classpath "$classpath" \
|
|
93
|
+
--include-engine=junit-jupiter \
|
|
94
|
+
--select-class=$0 \
|
|
95
|
+
--reports-dir=target/test-results
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
You can also use the **Execute with Skyramp** tool to run the test. The first execution may take longer than usual because the image is built for the first time.
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { WorkspaceAuthType } from "../../utils/workspaceAuth.js";
|
|
2
|
-
import { ScannedEndpoint } from "../../utils/repoScanner.js";
|
|
3
|
-
/** Lightweight diff summary for the analysis output prompt. */
|
|
4
|
-
interface DiffSummary {
|
|
5
|
-
changedFiles: string[];
|
|
6
|
-
newEndpoints: Array<{
|
|
7
|
-
method: string;
|
|
8
|
-
path: string;
|
|
9
|
-
sourceFile: string;
|
|
10
|
-
}>;
|
|
11
|
-
modifiedEndpoints: Array<{
|
|
12
|
-
method: string;
|
|
13
|
-
path: string;
|
|
14
|
-
sourceFile: string;
|
|
15
|
-
}>;
|
|
16
|
-
removedEndpoints?: Array<{
|
|
17
|
-
method: string;
|
|
18
|
-
path: string;
|
|
19
|
-
sourceFile: string;
|
|
20
|
-
}>;
|
|
21
|
-
}
|
|
22
|
-
interface AnalysisOutputParams {
|
|
23
|
-
sessionId: string;
|
|
24
|
-
stateFile?: string;
|
|
25
|
-
repositoryPath: string;
|
|
26
|
-
analysisScope: string;
|
|
27
|
-
parsedDiff?: DiffSummary;
|
|
28
|
-
/** Path to temp file containing the full unified diff.
|
|
29
|
-
* Content is read once in buildAnalysisOutputText via readDiffFile — callers do not pass diffContent. */
|
|
30
|
-
diffFilePath?: string;
|
|
31
|
-
/** Resolved diff content — populated internally by buildAnalysisOutputText, not by callers. */
|
|
32
|
-
diffContent?: string;
|
|
33
|
-
/**
|
|
34
|
-
* Relative paths of all files whose names look like route/controller definitions.
|
|
35
|
-
* For full-repo scope: the LLM reads these to find endpoints from frameworks the
|
|
36
|
-
* static regex doesn't cover (Django, Axum, Ktor, FastAPI without prefix, etc.).
|
|
37
|
-
*/
|
|
38
|
-
candidateRouteFiles?: string[];
|
|
39
|
-
scannedEndpoints: ScannedEndpoint[];
|
|
40
|
-
wsBaseUrl: string;
|
|
41
|
-
wsAuthHeader: string;
|
|
42
|
-
wsAuthType: WorkspaceAuthType | "";
|
|
43
|
-
wsSchemaPath: string;
|
|
44
|
-
/** True when wsSchemaPath was successfully fetched and parsed at analysis time */
|
|
45
|
-
specFetchSucceeded?: boolean;
|
|
46
|
-
routerMountContext: string[];
|
|
47
|
-
/** Content of key routing/mount files, read server-side (size-capped).
|
|
48
|
-
* Present when no spec is available — inlined so LLM doesn't need an extra read step. */
|
|
49
|
-
routerFileContents?: Array<{
|
|
50
|
-
file: string;
|
|
51
|
-
content: string;
|
|
52
|
-
}>;
|
|
53
|
-
nextTool?: string;
|
|
54
|
-
/**
|
|
55
|
-
* Changed files that contain no HTTP endpoint registrations (utilities, helpers,
|
|
56
|
-
* services, models). When non-empty the LLM is instructed to trace callers of
|
|
57
|
-
* the changed functions to find the correct HTTP surface (Fix 2 / Bug 5).
|
|
58
|
-
* Only meaningful in CurrentBranchDiff scope.
|
|
59
|
-
*/
|
|
60
|
-
unmatchedFiles?: string[];
|
|
61
|
-
}
|
|
62
|
-
/** "1" — Read source files / changed files */
|
|
63
|
-
export declare const ANALYSIS_STEP_READ_FILES: string;
|
|
64
|
-
/** "1.1" — Verify/build/validate endpoint path resolution table */
|
|
65
|
-
export declare const ANALYSIS_STEP_RESOLVE_PATHS: string;
|
|
66
|
-
/** "2" — Extract or map endpoints */
|
|
67
|
-
export declare const ANALYSIS_STEP_EXTRACT: string;
|
|
68
|
-
/** "3" — Draft scenarios / present catalog / identify drift */
|
|
69
|
-
export declare const ANALYSIS_STEP_DRAFT: string;
|
|
70
|
-
/** "4" — Call the downstream tool (recommend_tests / analyze_test_health) */
|
|
71
|
-
export declare const ANALYSIS_STEP_CALL_TOOL: string;
|
|
72
|
-
/**
|
|
73
|
-
* Returns the step label for the trace-callers sub-step given runtime params.
|
|
74
|
-
* Returns "2.1" when the step is active (non-frontend unmatched backend files
|
|
75
|
-
* present in diff scope), or null when the step is absent.
|
|
76
|
-
*
|
|
77
|
-
* Use in tests instead of hardcoding "2.1":
|
|
78
|
-
* const label = getStepTraceCallers(params);
|
|
79
|
-
* if (label) expect(output).toContain(`### Step ${label}: Trace callers`);
|
|
80
|
-
* else expect(output).not.toContain("Trace callers");
|
|
81
|
-
*/
|
|
82
|
-
export declare function getStepTraceCallers(p: AnalysisOutputParams): string | null;
|
|
83
|
-
export declare function buildAnalysisOutputText(p: AnalysisOutputParams): string;
|
|
84
|
-
export {};
|
|
@@ -1,369 +0,0 @@
|
|
|
1
|
-
import { AnalysisScope } from "../../types/RepositoryAnalysis.js";
|
|
2
|
-
import { PromptPlan } from "./promptPlan.js";
|
|
3
|
-
import { isFrontendFile } from "./scopeAssessment.js";
|
|
4
|
-
import { readDiffFile } from "../../utils/utils.js";
|
|
5
|
-
// ── Step label constants ─────────────────────────────────────────────────────
|
|
6
|
-
// Derived from the PromptPlan declaration below. Non-conditional steps export
|
|
7
|
-
// static string constants (safe to use in tests without passing params).
|
|
8
|
-
// The one conditional sub-step (TRACE_CALLERS) exports a function accessor.
|
|
9
|
-
//
|
|
10
|
-
// Labels:
|
|
11
|
-
// READ_FILES → "1" (main step, always present)
|
|
12
|
-
// RESOLVE_PATHS → "1.1" (sub-step of 1, always present)
|
|
13
|
-
// EXTRACT → "2" (main step, always present)
|
|
14
|
-
// TRACE_CALLERS → "2.1" (sub-step of 2, conditional — use getStepTraceCallers())
|
|
15
|
-
// DRAFT → "3" (main step, always present)
|
|
16
|
-
// CALL_TOOL → "4" (main step, always present)
|
|
17
|
-
// Extensions that indicate a backend code file (has symbols/functions to trace).
|
|
18
|
-
// Used to filter unmatchedFiles before emitting the trace-callers sub-step.
|
|
19
|
-
const BACKEND_CODE_EXT = /\.(ts|js|mjs|cjs|py|java|kt|rb|go|cs|php|rs|scala|swift|c|cpp|h|hpp)$/i;
|
|
20
|
-
// ── Inline note for Java Spring route resolution ──────────────────────────────
|
|
21
|
-
// Appended to any step where the LLM reads Java source files. Java Spring has no
|
|
22
|
-
// router-mounting file — each controller defines its own class-level prefix, and
|
|
23
|
-
// that prefix may reference a constant defined elsewhere.
|
|
24
|
-
const JAVA_SPRING_NOTE = `For Java Spring: full URL = class-level \`@RequestMapping\` prefix + method-level path. If the prefix is a constant reference (e.g. \`@RequestMapping(Url.PAGE_URL)\`), find the constant — same file, inner class, or a separate \`Url.java\` — and resolve it (including \`+\` concatenation).`;
|
|
25
|
-
const INLINE_DIFF_LIMIT = 12_000;
|
|
26
|
-
function _deriveContext(p) {
|
|
27
|
-
const diffFiles = p.parsedDiff?.changedFiles ?? [];
|
|
28
|
-
const preDetectedEndpoints = !!(p.parsedDiff &&
|
|
29
|
-
(p.parsedDiff.newEndpoints.length > 0 ||
|
|
30
|
-
p.parsedDiff.modifiedEndpoints.length > 0 ||
|
|
31
|
-
(p.parsedDiff.removedEndpoints?.length ?? 0) > 0));
|
|
32
|
-
const isUIOnly = diffFiles.length > 0 &&
|
|
33
|
-
!preDetectedEndpoints &&
|
|
34
|
-
diffFiles.every((f) => isFrontendFile(f));
|
|
35
|
-
const canInline = !!(p.diffContent && p.diffContent.length <= INLINE_DIFF_LIMIT);
|
|
36
|
-
return { diffFiles, preDetectedEndpoints, isUIOnly, canInline };
|
|
37
|
-
}
|
|
38
|
-
// ── Private step title / body helpers ────────────────────────────────────────
|
|
39
|
-
// Each function receives AnalysisOutputParams and returns either the step title
|
|
40
|
-
// string or the step body text (WITHOUT the "### Step N: Title" header — that is
|
|
41
|
-
// added by PromptPlan.render()). Using function declarations so they are hoisted
|
|
42
|
-
// and can be referenced in the _plan definition below.
|
|
43
|
-
function _readFilesBody(p) {
|
|
44
|
-
const changedFiles = p.parsedDiff?.changedFiles.join(", ") ?? "";
|
|
45
|
-
const { canInline } = _deriveContext(p);
|
|
46
|
-
const diffFileRef = canInline
|
|
47
|
-
? `\n<diff>\n${p.diffContent}\n</diff>\n`
|
|
48
|
-
: p.diffFilePath
|
|
49
|
-
? `\n**Full diff file**: \`${p.diffFilePath}\` — **you MUST read this file before proceeding to Step ${ANALYSIS_STEP_EXTRACT}.** It contains the complete unified diff for this PR.\n`
|
|
50
|
-
: "";
|
|
51
|
-
return `${changedFiles}${diffFileRef}`;
|
|
52
|
-
}
|
|
53
|
-
function _resolvePathsTitle(p) {
|
|
54
|
-
if (p.wsSchemaPath && p.specFetchSucceeded) {
|
|
55
|
-
return "Validate all endpoint paths against the OpenAPI spec";
|
|
56
|
-
}
|
|
57
|
-
if (p.routerMountContext.length) {
|
|
58
|
-
return "Build path resolution table";
|
|
59
|
-
}
|
|
60
|
-
return "Verify endpoint paths from source files";
|
|
61
|
-
}
|
|
62
|
-
function _resolvePathsBody(p) {
|
|
63
|
-
if (p.wsSchemaPath && p.specFetchSucceeded) {
|
|
64
|
-
return `Fetch \`${p.wsSchemaPath}\` and extract all keys from \`spec.paths\`.
|
|
65
|
-
**Before placing any path in a tool call**, confirm it exists in that list.
|
|
66
|
-
If a path is NOT in the spec **and it did not come from the PR diff**, find the correct spelling by matching resource name — do NOT use it unverified.
|
|
67
|
-
Paths the PR explicitly added or modified may not yet appear in the spec (spec lag) — treat those as valid.`;
|
|
68
|
-
}
|
|
69
|
-
if (p.routerMountContext.length) {
|
|
70
|
-
const hasInlined = (p.routerFileContents?.length ?? 0) > 0;
|
|
71
|
-
return `${hasInlined
|
|
72
|
-
? "The **Routing entry-point files** section above contains the inlined file contents — use them directly to trace every router mount call"
|
|
73
|
-
: "The **Routing entry-point files** section above lists the files to read.\n\n**Read each of those files** and trace every router mount call"} to understand nesting — the pattern varies by framework but the structure is universal: a parent attaches a child router with an optional extra prefix segment. If a prefix is a variable (e.g. \`prefix=api_prefix\`), resolve the variable's value by reading the assignment or the config/settings file it comes from. Examples of what to look for (non-exhaustive):
|
|
74
|
-
- Python (FastAPI/Flask): \`parent.include_router(child, prefix="...")\`, \`app.register_blueprint(...)\`
|
|
75
|
-
- JS/TS (Express/Fastify/Hapi): \`app.use('/path', childRouter)\`, \`router.use('/path', sub)\`
|
|
76
|
-
- NestJS: \`@Module({ imports: [FeatureModule] })\` — trace the module import chain; each \`@Controller('prefix')\` contributes a segment
|
|
77
|
-
- Go (Gin/Echo/Chi): \`r.Group('/path')\`, \`r.Mount('/path', sub)\`
|
|
78
|
-
- Ruby (Rails): \`namespace\`, \`scope\`, \`resources ... do\`
|
|
79
|
-
- Django: \`path('prefix/', include(urls))\`
|
|
80
|
-
|
|
81
|
-
Chain all segments from the app root down through every intermediate mount to each leaf router file. Build a table:
|
|
82
|
-
|
|
83
|
-
| Source file | Full URL prefix |
|
|
84
|
-
|-------------|----------------|
|
|
85
|
-
| (leaf router file) | (fully chained prefix, e.g. /api/v1/products/{id}/reviews) |
|
|
86
|
-
|
|
87
|
-
**This table is authoritative.** Before placing any URL in a tool call, look up the source file. If the pre-built catalog shows a different path, use the table value.`;
|
|
88
|
-
}
|
|
89
|
-
const specFailedNote = p.wsSchemaPath && !p.specFetchSucceeded
|
|
90
|
-
? `\n> ⚠️ A spec was configured (\`${p.wsSchemaPath}\`) but could not be loaded at analysis time — treat all paths as unverified until confirmed against source.`
|
|
91
|
-
: "";
|
|
92
|
-
return `The endpoint catalog below was produced by static regex analysis and is **unverified**.
|
|
93
|
-
Before using any path in a tool call, read the route definition file identified in the "Source" column and confirm the path string exactly.
|
|
94
|
-
Pay special attention to mount prefixes — a router at \`/api/v1\` + route \`/version\` → path is \`/api/v1/version\`, not \`/api/server-version\`.${specFailedNote}`;
|
|
95
|
-
}
|
|
96
|
-
function _extractTitle(p) {
|
|
97
|
-
const { isUIOnly, canInline } = _deriveContext(p);
|
|
98
|
-
if (isUIOnly)
|
|
99
|
-
return "Identify consumed API endpoints and integration status";
|
|
100
|
-
if (canInline || p.diffFilePath)
|
|
101
|
-
return "Extract new, modified, and removed API endpoints from the diff";
|
|
102
|
-
return "Extract new, modified, and removed API endpoints from source files";
|
|
103
|
-
}
|
|
104
|
-
function _extractBody(p) {
|
|
105
|
-
const { diffFiles, isUIOnly, canInline, preDetectedEndpoints } = _deriveContext(p);
|
|
106
|
-
const diffHasJavaFiles = diffFiles.some((f) => /\.(java|kt)$/.test(f));
|
|
107
|
-
if (isUIOnly) {
|
|
108
|
-
return `UI-only PR — perform two checks:
|
|
109
|
-
1. Read changed frontend files to find API calls (fetch, axios, hooks).
|
|
110
|
-
2. For each changed component file (skip CSS/HTML/style-only files — they have no exported component name to search for): check whether any production source file imports, re-exports, or renders it.
|
|
111
|
-
- Search for both the component's exported name AND its module path/filename to catch aliased and default imports (e.g. \`import Foo from './CartLine'\`).
|
|
112
|
-
- Derive the exported name from the file itself: use the default export name, a named exported PascalCase component, or the PascalCase file basename when no clearer name exists.
|
|
113
|
-
- Exclude test/story files from the search: ignore matches in \`*.test.*\`, \`*.spec.*\`, \`*.stories.*\`, and \`__tests__/\` directories — only production code imports count as integration.
|
|
114
|
-
|
|
115
|
-
If no production file imports, re-exports, or renders a changed component, mark it as **unintegrated** in the Execution Plan output.
|
|
116
|
-
Exception: if the same PR also adds a route/page file (e.g. under Next.js \`pages/\` or \`app/\`) that imports the component, the route IS the integration point — do NOT mark it as unintegrated.
|
|
117
|
-
Do NOT apply the unintegrated heuristic to route/entrypoint files themselves — those are always reachable by convention.
|
|
118
|
-
An unintegrated non-route component has no DOM node in the running app and cannot be browser-tested — it qualifies as a dead-code / unintegrated-component no-surface PR regardless of how complex the component logic is.
|
|
119
|
-
|
|
120
|
-
**While reading, also note these patterns** (tag findings with their category for Step ${ANALYSIS_STEP_DRAFT}):
|
|
121
|
-
- **Unique constraints**: \`@unique\`, \`unique: true\`, unique indexes, \`.refine()\` uniqueness checks, \`UNIQUE\` in SQL migrations → _data_integrity_
|
|
122
|
-
- **Cascade deletes**: \`ON DELETE CASCADE\`, \`.onDelete("cascade")\`, manual cascade logic in delete handlers → _data_integrity_
|
|
123
|
-
- **Permission checks**: auth middleware, ownership guards (\`req.user.id === resource.ownerId\`), role-based access control, \`isOwner\` assertions → _security_boundary_
|
|
124
|
-
- **Breaking changes in diff**: route renames, deleted route definitions, auth header changes, removed required fields, changed status codes → _breaking_change_`;
|
|
125
|
-
}
|
|
126
|
-
if (canInline || p.diffFilePath) {
|
|
127
|
-
return `${canInline ? "Read the \`<diff>\` above" : `Read the diff file at \`${p.diffFilePath}\``} and identify every new or modified API endpoint — route registrations, handler methods, controller annotations. Then use the **Router Mounting / Nesting** section above to reconstruct the full URL path for each endpoint by chaining all parent router prefixes down to the handler (e.g. a handler in a file with \`prefix="/reviews"\` that is mounted at \`/{product_id}\` under a router mounted at \`/api/v1/products\` → full path \`/api/v1/products/{product_id}/reviews\`).
|
|
128
|
-
${diffHasJavaFiles ? JAVA_SPRING_NOTE : ""}
|
|
129
|
-
For each endpoint found: note the HTTP method, full path, and source file.
|
|
130
|
-
${preDetectedEndpoints ? "The endpoint catalog above already lists some changed endpoints — verify and augment with anything it missed. **If a changed file contains many endpoints (hub/routing files like api.go, routes.py, router.ts), cross-reference against the diff hunks to identify only the endpoints whose handler code actually changed — do not include neighboring routes whose code was untouched.**" : "No endpoints were pre-detected in the changed files — extract them from the diff."}
|
|
131
|
-
**Also identify removed endpoints**: Look for deleted route annotations (lines starting with \`-\` in the diff) in modified files (files that still exist but had routes deleted). A removed endpoint is a route definition present in the base branch but absent in the current branch. Cross-reference against the scanned endpoint listing below — if a deleted route annotation's endpoint still appears there (e.g. moved to another file), it is NOT removed. Only flag endpoints that are truly gone from the codebase.
|
|
132
|
-
**CRITICAL — Query params vs body:** For GET endpoints (especially search/filter/list),
|
|
133
|
-
identify which parameters are URL query params vs request body. Look at framework-specific
|
|
134
|
-
annotations (FastAPI \`Query()\`, Express \`req.query\`, Spring \`@RequestParam\`, etc.).
|
|
135
|
-
Pass these as \`queryParams\` (not \`requestBody\`) when generating scenarios.
|
|
136
|
-
|
|
137
|
-
**While reading, also note these patterns** (tag findings with their category for Step ${ANALYSIS_STEP_DRAFT}):
|
|
138
|
-
- **Unique constraints**: \`@unique\`, \`unique: true\`, unique indexes, \`.refine()\` uniqueness checks, \`UNIQUE\` in SQL migrations → _data_integrity_
|
|
139
|
-
- **Cascade deletes**: \`ON DELETE CASCADE\`, \`.onDelete("cascade")\`, manual cascade logic in delete handlers → _data_integrity_
|
|
140
|
-
- **Permission checks**: auth middleware, ownership guards (\`req.user.id === resource.ownerId\`), role-based access control, \`isOwner\` assertions → _security_boundary_
|
|
141
|
-
- **Breaking changes in diff**: route renames, deleted route definitions, auth header changes, removed required fields, changed status codes → _breaking_change_`;
|
|
142
|
-
}
|
|
143
|
-
return `No diff was available — read the changed source files listed above directly to identify new or modified API endpoints. Use the **Router Mounting / Nesting** section to reconstruct full paths.
|
|
144
|
-
${diffHasJavaFiles ? JAVA_SPRING_NOTE : ""}
|
|
145
|
-
For each endpoint found: note the HTTP method, full path, and source file.
|
|
146
|
-
Also compare against the endpoint catalog to identify any endpoints that appear in the catalog but are no longer present in the source files — these are removed endpoints.
|
|
147
|
-
|
|
148
|
-
**While reading, also note these patterns** (tag findings with their category for Step ${ANALYSIS_STEP_DRAFT}):
|
|
149
|
-
- **Unique constraints**: \`@unique\`, \`unique: true\`, unique indexes, \`.refine()\` uniqueness checks, \`UNIQUE\` in SQL migrations → _data_integrity_
|
|
150
|
-
- **Cascade deletes**: \`ON DELETE CASCADE\`, \`.onDelete("cascade")\`, manual cascade logic in delete handlers → _data_integrity_
|
|
151
|
-
- **Permission checks**: auth middleware, ownership guards (\`req.user.id === resource.ownerId\`), role-based access control, \`isOwner\` assertions → _security_boundary_
|
|
152
|
-
- **Breaking changes in diff**: route renames, deleted route definitions, auth header changes, removed required fields, changed status codes → _breaking_change_`;
|
|
153
|
-
}
|
|
154
|
-
function _traceCallersCondition(p) {
|
|
155
|
-
// Only emit in diff scope — the plan may be preview()'d with full-repo params.
|
|
156
|
-
const isDiffScope = p.analysisScope === AnalysisScope.CurrentBranchDiff;
|
|
157
|
-
const { isUIOnly } = _deriveContext(p);
|
|
158
|
-
const traceableUnmatched = (p.unmatchedFiles ?? []).filter((f) => BACKEND_CODE_EXT.test(f));
|
|
159
|
-
return isDiffScope && !isUIOnly && traceableUnmatched.length > 0;
|
|
160
|
-
}
|
|
161
|
-
function _traceCallersBody(p) {
|
|
162
|
-
const traceableUnmatched = (p.unmatchedFiles ?? []).filter((f) => BACKEND_CODE_EXT.test(f));
|
|
163
|
-
return `The following changed files contain **no HTTP endpoint registrations** (no route annotations, controller mappings, or handler decorators). Their changes will only be tested if you find and target the HTTP endpoints that *call* them:
|
|
164
|
-
|
|
165
|
-
${traceableUnmatched.map((f) => `- \`${f}\``).join("\n")}
|
|
166
|
-
|
|
167
|
-
For each file above:
|
|
168
|
-
1. **Find the changed symbols** — read the diff (or the file) to identify which functions, methods, or classes were modified.
|
|
169
|
-
2. **Search for callers** — look for import statements and call sites of those symbols across service, handler, and controller files. Use fully qualified names (e.g. \`DataUtils.addFileData\`, not just \`addFileData\`) to avoid false matches in large monorepos.
|
|
170
|
-
3. **Trace to HTTP registration** — from each caller, follow up to the route/controller registration (Spring \`@PostMapping\`, Express \`router.post\`, FastAPI \`@router.post\`, etc.) to identify the endpoint(s) that invoke the changed logic.
|
|
171
|
-
4. **Augment the endpoint list** from Step ${ANALYSIS_STEP_EXTRACT} with these execution-path endpoints.
|
|
172
|
-
5. If an execution or processing endpoint is found (path ending in \`/execute\`, \`/run\`, \`/trigger\`, \`/process\`, \`/invoke\`, or similar), it **MUST** be included in the test candidates. Do not produce coverage consisting solely of CRUD endpoints when an execution-path endpoint was found — CRUD tests may still be included but must not be the only coverage.`;
|
|
173
|
-
}
|
|
174
|
-
function _draftTitle(p) {
|
|
175
|
-
return p.nextTool === "skyramp_analyze_test_health"
|
|
176
|
-
? "Identify tests at risk of drift"
|
|
177
|
-
: "Draft integration scenarios";
|
|
178
|
-
}
|
|
179
|
-
function _draftBody(p) {
|
|
180
|
-
if (p.nextTool === "skyramp_analyze_test_health") {
|
|
181
|
-
return "Assess which existing tests may be broken by the changes in this diff.";
|
|
182
|
-
}
|
|
183
|
-
return `Draft multi-step scenarios simulating realistic user workflows:
|
|
184
|
-
- **Cross-resource data flow**: Foreign key relationships, parent→child creation, verification
|
|
185
|
-
- **Search/filter verification**: Create data, search for it using \`queryParams\`, verify results
|
|
186
|
-
- **Negative/error paths**: Invalid references → appropriate errors
|
|
187
|
-
- **UI user journeys**: Concrete browser steps for frontend changes
|
|
188
|
-
|
|
189
|
-
**Quality:** Realistic request bodies for POST/PUT/PATCH, \`queryParams\` for GET search/filter,
|
|
190
|
-
response data verification, actual field names for chaining.
|
|
191
|
-
**Parameter placement:** GET search/filter endpoints MUST use \`queryParams\`, not \`requestBody\`.
|
|
192
|
-
|
|
193
|
-
**No duplicate scenarios.** Each scenario must cover a distinct code path (unique method + path + expected status). Do NOT draft two scenarios that differ only in request body values but hit the same code path (e.g. discount=10% vs discount=25% — both succeed with 200, same logic). A negative-case variant with a different expected status (e.g. discount=-10% → 422) IS a distinct scenario — use a single-step contract test for it (see below).
|
|
194
|
-
|
|
195
|
-
**For each new or modified endpoint, ensure at least one error-path scenario is drafted** — a single-step contract test that triggers a specific error (404 for a missing resource ID, 422 for an invalid field value) that the source code explicitly handles. One auth-boundary scenario (missing auth → 401/403) is enough across all endpoints — do not repeat it per endpoint.
|
|
196
|
-
|
|
197
|
-
**For every scenario you draft, fill \`bugCatchingTarget\`** with the specific formula, constraint, or failure mode the test is designed to expose. Examples:
|
|
198
|
-
- \`"discount formula: total_amount = subtotal * (1 - discount_value / 100) — wrong if addition is used instead of subtraction"\`
|
|
199
|
-
- \`"items not recalculated after PATCH — total_amount stays at old value if collection update is ignored"\`
|
|
200
|
-
- \`"missing 404 guard on resource ID — returns 500 instead of 404 for unknown IDs"\`
|
|
201
|
-
This field is used at test generation time to compute exact assertion values. Leave it empty only if no specific formula or constraint applies.`;
|
|
202
|
-
}
|
|
203
|
-
function _callToolTitle(p) {
|
|
204
|
-
return p.nextTool === "skyramp_analyze_test_health"
|
|
205
|
-
? "Call analyze test health"
|
|
206
|
-
: "Call recommend tests";
|
|
207
|
-
}
|
|
208
|
-
function _callToolBody(p) {
|
|
209
|
-
if (p.nextTool === "skyramp_analyze_test_health") {
|
|
210
|
-
return `Call \`skyramp_analyze_test_health\` with \`stateFile: "${p.stateFile ?? p.sessionId}"\``;
|
|
211
|
-
}
|
|
212
|
-
return `Call \`skyramp_recommend_tests\` with:
|
|
213
|
-
- \`stateFile: "${p.stateFile}"\`
|
|
214
|
-
- \`enrichedScenarios\`: (optional) JSON array of your Step ${ANALYSIS_STEP_DRAFT} scenarios — see the tool's inputSchema for the exact shape. Your enriched scenarios override server-side ones with the same \`scenarioName\` and are prioritized in ranking. Omit if you drafted nothing in Step ${ANALYSIS_STEP_DRAFT}.`;
|
|
215
|
-
}
|
|
216
|
-
// ── PromptPlan declaration ─────────────────────────────────────────────────────
|
|
217
|
-
// Defines the diff-scope prompt structure: phases, steps, sub-steps, and conditions.
|
|
218
|
-
// Used to:
|
|
219
|
-
// 1. Derive the exported step label constants below.
|
|
220
|
-
// 2. Render the diff-scope prompt via _plan.render(p).
|
|
221
|
-
// 3. Enable developer review via _plan.preview(p).
|
|
222
|
-
const _plan = new PromptPlan()
|
|
223
|
-
.addPhase("analysis", "Your Task — Enrich & Recommend (PR-scoped)", {
|
|
224
|
-
headerLevel: "##",
|
|
225
|
-
stepFormat: "hash",
|
|
226
|
-
})
|
|
227
|
-
.step("READ_FILES", "Read the changed files and diff", _readFilesBody)
|
|
228
|
-
.subStep("RESOLVE_PATHS", _resolvePathsTitle, _resolvePathsBody)
|
|
229
|
-
.step("EXTRACT", _extractTitle, _extractBody)
|
|
230
|
-
.subStep("TRACE_CALLERS", "Trace callers of changed non-route files", _traceCallersBody, {
|
|
231
|
-
when: _traceCallersCondition,
|
|
232
|
-
whenDesc: "non-frontend unmatched backend files present in diff scope",
|
|
233
|
-
})
|
|
234
|
-
.step("DRAFT", _draftTitle, _draftBody)
|
|
235
|
-
.step("CALL_TOOL", _callToolTitle, _callToolBody)
|
|
236
|
-
.done();
|
|
237
|
-
// ── Exported step label constants ─────────────────────────────────────────────
|
|
238
|
-
/** "1" — Read source files / changed files */
|
|
239
|
-
export const ANALYSIS_STEP_READ_FILES = _plan.labels.READ_FILES; // "1"
|
|
240
|
-
/** "1.1" — Verify/build/validate endpoint path resolution table */
|
|
241
|
-
export const ANALYSIS_STEP_RESOLVE_PATHS = _plan.labels.RESOLVE_PATHS; // "1.1"
|
|
242
|
-
/** "2" — Extract or map endpoints */
|
|
243
|
-
export const ANALYSIS_STEP_EXTRACT = _plan.labels.EXTRACT; // "2"
|
|
244
|
-
/** "3" — Draft scenarios / present catalog / identify drift */
|
|
245
|
-
export const ANALYSIS_STEP_DRAFT = _plan.labels.DRAFT; // "3"
|
|
246
|
-
/** "4" — Call the downstream tool (recommend_tests / analyze_test_health) */
|
|
247
|
-
export const ANALYSIS_STEP_CALL_TOOL = _plan.labels.CALL_TOOL; // "4"
|
|
248
|
-
/**
|
|
249
|
-
* Returns the step label for the trace-callers sub-step given runtime params.
|
|
250
|
-
* Returns "2.1" when the step is active (non-frontend unmatched backend files
|
|
251
|
-
* present in diff scope), or null when the step is absent.
|
|
252
|
-
*
|
|
253
|
-
* Use in tests instead of hardcoding "2.1":
|
|
254
|
-
* const label = getStepTraceCallers(params);
|
|
255
|
-
* if (label) expect(output).toContain(`### Step ${label}: Trace callers`);
|
|
256
|
-
* else expect(output).not.toContain("Trace callers");
|
|
257
|
-
*/
|
|
258
|
-
export function getStepTraceCallers(p) {
|
|
259
|
-
return _plan.labelFor("TRACE_CALLERS", p);
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* Returns the full "### Step N.N: Title\nbody" block for the path resolution
|
|
263
|
-
* sub-step. Used by the full-repo scope path which builds its prompt manually
|
|
264
|
-
* rather than calling _plan.render().
|
|
265
|
-
*/
|
|
266
|
-
function buildPathResolutionTableSection(p) {
|
|
267
|
-
const label = ANALYSIS_STEP_RESOLVE_PATHS;
|
|
268
|
-
const title = _resolvePathsTitle(p);
|
|
269
|
-
const body = _resolvePathsBody(p);
|
|
270
|
-
return `### Step ${label}: ${title}\n${body}\n`;
|
|
271
|
-
}
|
|
272
|
-
function buildEnrichmentInstructions(p) {
|
|
273
|
-
const isDiffScope = p.analysisScope === AnalysisScope.CurrentBranchDiff;
|
|
274
|
-
const useHealthFlow = p.nextTool === "skyramp_analyze_test_health";
|
|
275
|
-
if (!isDiffScope) {
|
|
276
|
-
const nextStep = useHealthFlow
|
|
277
|
-
? `### Step ${ANALYSIS_STEP_DRAFT}: Identify tests at risk of drift
|
|
278
|
-
Call \`skyramp_analyze_test_health\` with \`stateFile: "${p.stateFile ?? p.sessionId}"\``
|
|
279
|
-
: `### Step ${ANALYSIS_STEP_DRAFT}: Present the catalog
|
|
280
|
-
The ranked test recommendation catalog is pre-built and shown below (after the separator line).
|
|
281
|
-
|
|
282
|
-
**Your only job is to present it.**
|
|
283
|
-
|
|
284
|
-
1. Fill in every \`<…from source>\` placeholder using the field names, computed formulas, and auth details you found in Steps 1–2.
|
|
285
|
-
2. Output the completed catalog **exactly as formatted — grouped by test type (### E2E / ### UI / ### Integration / ### Contract)**. Do NOT restructure, reorder, rename sections, or generate a new format.
|
|
286
|
-
3. Do NOT call any Skyramp generation tools. The catalog shows ready-to-use tool calls that can be executed on demand.
|
|
287
|
-
|
|
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
|
-
const hasJavaFiles = p.candidateRouteFiles?.some((f) => /\.(java|kt)$/.test(f)) ?? false;
|
|
290
|
-
const routeFilesSection = p.candidateRouteFiles && p.candidateRouteFiles.length > 0
|
|
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
|
-
: "";
|
|
293
|
-
const resolvePathsNote = p.routerMountContext.length
|
|
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
|
-
return `## Your Task — Fill in and Present the Catalog (full repo)
|
|
297
|
-
|
|
298
|
-
### Step ${ANALYSIS_STEP_READ_FILES}: Read key files
|
|
299
|
-
${routeFilesSection}Read the route/controller files above **and** model/schema files (Pydantic models, Zod schemas, DTOs) to find: required request body fields, computed response fields and formulas, auth middleware type, storage backend, and how sub-routers are mounted (cross-check against Router Mounting section above).
|
|
300
|
-
${hasJavaFiles ? JAVA_SPRING_NOTE : ""}
|
|
301
|
-
If the endpoint catalog below is missing endpoints visible in these files (e.g. from a framework the static scanner doesn't recognise), extract them now${useHealthFlow ? "." : " and include them in Step ${ANALYSIS_STEP_DRAFT}'s `enrichedScenarios`."}
|
|
302
|
-
|
|
303
|
-
${buildPathResolutionTableSection(p)}### Step ${ANALYSIS_STEP_EXTRACT}: Map cross-resource relationships and resolve endpoint paths
|
|
304
|
-
(Distinct from Step ${ANALYSIS_STEP_READ_FILES} — Step ${ANALYSIS_STEP_READ_FILES} reads individual schemas; Step ${ANALYSIS_STEP_EXTRACT} maps how endpoints relate to each other.)
|
|
305
|
-
For each endpoint: which POST creates resources consumed by other endpoints?
|
|
306
|
-
${resolvePathsNote}
|
|
307
|
-
For GET list endpoints: identify query params (\`limit\`, \`offset\`, \`order\`, \`orderBy\`) from framework annotations (FastAPI \`Query()\`, Express \`req.query\`, etc.).
|
|
308
|
-
|
|
309
|
-
${nextStep}`;
|
|
310
|
-
}
|
|
311
|
-
// Diff scope — delegate entirely to the plan.
|
|
312
|
-
return _plan.render(p);
|
|
313
|
-
}
|
|
314
|
-
export function buildAnalysisOutputText(p) {
|
|
315
|
-
// Centralize diff reading here — resolve content from file once so helpers don't each read it.
|
|
316
|
-
p = { ...p, diffContent: readDiffFile(p.diffFilePath) };
|
|
317
|
-
const isDiffScope = p.analysisScope === AnalysisScope.CurrentBranchDiff;
|
|
318
|
-
// Router mounting context is unique to this prompt; shown whenever mount context
|
|
319
|
-
// is available, regardless of whether a spec is configured.
|
|
320
|
-
const routerSection = p.routerMountContext.length
|
|
321
|
-
? `
|
|
322
|
-
## Routing entry-point files
|
|
323
|
-
${p.routerFileContents?.length
|
|
324
|
-
? p.routerFileContents
|
|
325
|
-
.map(({ file, content }) => `### \`${file}\`\n\`\`\`\n${content}\n\`\`\``)
|
|
326
|
-
.join("\n\n") +
|
|
327
|
-
(p.routerMountContext.length > (p.routerFileContents?.length ?? 0)
|
|
328
|
-
? `\n\nAdditional files (too large to inline — read manually if needed):\n` +
|
|
329
|
-
p.routerMountContext
|
|
330
|
-
.filter((f) => !(p.routerFileContents ?? []).some((r) => r.file === f))
|
|
331
|
-
.map((f) => `- \`${f}\``)
|
|
332
|
-
.join("\n")
|
|
333
|
-
: "")
|
|
334
|
-
: `Read these in Step ${ANALYSIS_STEP_RESOLVE_PATHS} to trace the full router/module hierarchy:\n` +
|
|
335
|
-
p.routerMountContext.map((f) => `- \`${f}\``).join("\n")}`
|
|
336
|
-
: "";
|
|
337
|
-
const enrichment = buildEnrichmentInstructions(p);
|
|
338
|
-
const staticHintCount = p.scannedEndpoints.length;
|
|
339
|
-
const routeDiscoverySection = isDiffScope ||
|
|
340
|
-
staticHintCount > 0 ||
|
|
341
|
-
(p.candidateRouteFiles?.length ?? 0) > 0
|
|
342
|
-
? `
|
|
343
|
-
## LLM Route Discovery Inputs
|
|
344
|
-
|
|
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.
|
|
346
|
-
|
|
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."}
|
|
348
|
-
|
|
349
|
-
${p.candidateRouteFiles && p.candidateRouteFiles.length > 0
|
|
350
|
-
? ""
|
|
351
|
-
: staticHintCount > 0
|
|
352
|
-
? "Candidate files to inspect: none identified by static scanning. Verify the static hints against their source files, changed files, router context, and specs above."
|
|
353
|
-
: "Candidate files to inspect: use the changed files and routing entry-point files above."}
|
|
354
|
-
|
|
355
|
-
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.
|
|
356
|
-
`
|
|
357
|
-
: "";
|
|
358
|
-
return `# Repository Analysis
|
|
359
|
-
|
|
360
|
-
**Session ID**: \`${p.sessionId}\`
|
|
361
|
-
**Repository**: \`${p.repositoryPath}\`
|
|
362
|
-
**Analysis Scope**: \`${p.analysisScope}\`
|
|
363
|
-
${isDiffScope ? `**Diff endpoints**: ${(p.parsedDiff?.newEndpoints.length ?? 0) + (p.parsedDiff?.modifiedEndpoints.length ?? 0) + (p.parsedDiff?.removedEndpoints?.length ?? 0)}` : `**Pre-scanned endpoints**: ${p.scannedEndpoints.length}`}
|
|
364
|
-
${routerSection}
|
|
365
|
-
${routeDiscoverySection}
|
|
366
|
-
${enrichment}
|
|
367
|
-
|
|
368
|
-
**CRITICAL**: No .json/.md file creation. Prioritize cross-resource workflows.`;
|
|
369
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { DraftedScenario } from "../../types/RepositoryAnalysis.js";
|
|
2
|
-
import { Novelty, PriorityTier } from "../../types/TestRecommendation.js";
|
|
3
|
-
export declare function buildFullRepoRecommendations(scored: Array<{
|
|
4
|
-
scenario: DraftedScenario;
|
|
5
|
-
priority: PriorityTier;
|
|
6
|
-
novelty: Novelty;
|
|
7
|
-
}>, topN: number, baseUrl: string, authHeaderValue: string, authSchemeSnippet: string, authTypeValue: string, isFrontendProject?: boolean, isFrontendOnlyProject?: boolean, externalCoverage?: Set<string>): string;
|