@skyramp/mcp 0.0.38 → 0.0.39

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.
@@ -18,6 +18,13 @@ export function registerTestGenerationPrompt(mcpServer) {
18
18
  - CRITICAL: UI, INTEGRATION, E2E TESTS MUST BE MODULARIZED USING skyramp_modularization TOOL. ALWAYS ADD A TASK TO MODULARIZE THE TEST USING skyramp_modularization TOOL AFTER GENERATING THESE(UI, INTEGRATION, E2E) TESTS.
19
19
  - **CRITICAL: skyramp_reuse_code TOOL MUST BE CALLED IF DURING THE TEST GENERATION THE CODE REUSE FLAG IS SET TO TRUE EXPLICITLY BY THE USER.**
20
20
 
21
+ **MANDATORY RULES**:
22
+ 1. **Priority Scores Must Remain Unchanged**: When a test type is missing required inputs (e.g., Playwright recordings, traces), **DO NOT**:
23
+ - Mark the test as "blocked" in the output
24
+ - Adjust or reduce the priority score
25
+ - Exclude it from recommendations if it ranks in the top 7
26
+ 2. DO NOT CREATE ANY .json or .md file during repository analysis, test mapping, or test recommendation.
27
+
21
28
  **CONTRACT TEST:**
22
29
  - Purpose: Ensures a service is properly communicating with another service
23
30
  - Requirements: At least ONE of the following combinations:
@@ -1,6 +1,5 @@
1
1
  import { SkyrampClient } from "@skyramp/skyramp";
2
2
  import { analyzeOpenAPIWithGivenEndpoint } from "../utils/analyze-openapi.js";
3
- import * as fs from "fs";
4
3
  import { getPathParameterValidationError, OUTPUT_DIR_FIELD_NAME, PATH_PARAMS_FIELD_NAME, QUERY_PARAMS_FIELD_NAME, FORM_PARAMS_FIELD_NAME, validateParams, validatePath, validateRequestData, TELEMETRY_entrypoint_FIELD_NAME, } from "../utils/utils.js";
5
4
  import { getLanguageSteps } from "../utils/language-helper.js";
6
5
  import { logger } from "../utils/logger.js";
@@ -27,11 +26,6 @@ export class TestGenerationService {
27
26
  if (apiAnalysisResult) {
28
27
  return apiAnalysisResult;
29
28
  }
30
- if (params.scenarioFile) {
31
- //read file and convert and pass to generateOptions as `rawTrace`
32
- const scenarioFile = await fs.promises.readFile(params.scenarioFile, "utf8");
33
- generateOptions.rawTrace = scenarioFile;
34
- }
35
29
  const result = await this.executeGeneration(generateOptions);
36
30
  const testType = this.getTestType();
37
31
  const languageSteps = getLanguageSteps({
@@ -105,6 +105,12 @@ For detailed documentation visit: https://www.skyramp.dev/docs/quickstart`,
105
105
  "SKYRAMP_TEST_TOKEN=" + params.token,
106
106
  "SKYRAMP_IN_DOCKER=true",
107
107
  ];
108
+ if (process.env.SKYRAMP_DEBUG) {
109
+ env.push("SKYRAMP_DEBUG=" + process.env.SKYRAMP_DEBUG);
110
+ }
111
+ if (process.env.API_KEY) {
112
+ env.push("API_KEY=" + process.env.API_KEY);
113
+ }
108
114
  var output = "";
109
115
  class DockerStream extends Writable {
110
116
  _write(data, encode, cb) {
@@ -11,12 +11,13 @@ const integrationTestSchema = z
11
11
  trace: baseTraceSchema.shape.trace.optional(),
12
12
  include: baseTraceSchema.shape.include.optional(),
13
13
  exclude: baseTraceSchema.shape.exclude.optional(),
14
- endpointURL: baseTestSchema.endpointURL.default(""),
15
- ...codeRefactoringSchema.shape,
16
14
  scenarioFile: z
17
15
  .string()
18
16
  .describe("Path to the scenario file to be used for test generation. This file is generated by the skyramp_scenario_test_generation tool.")
19
17
  .optional(),
18
+ ...codeRefactoringSchema.shape,
19
+ ...baseTestSchema,
20
+ endpointURL: baseTestSchema.endpointURL.default(""),
20
21
  })
21
22
  .omit({ method: true }).shape;
22
23
  export class IntegrationTestService extends TestGenerationService {
@@ -28,7 +29,7 @@ export class IntegrationTestService extends TestGenerationService {
28
29
  ...super.buildBaseGenerationOptions(params),
29
30
  responseData: params.responseData,
30
31
  playwrightInput: params.playwrightInput,
31
- scenarioFile: params.scenarioFile,
32
+ trace: params.scenarioFile,
32
33
  };
33
34
  }
34
35
  async handleApiAnalysis(params, generateOptions) {
@@ -0,0 +1,96 @@
1
+ import { z } from "zod";
2
+ import { logger } from "../../utils/logger.js";
3
+ import { getRepositoryAnalysisPrompt } from "../../prompts/test-recommendation/repository-analysis-prompt.js";
4
+ /**
5
+ * Analyze Repository Tool
6
+ * MCP tool for comprehensive repository analysis
7
+ */
8
+ const analyzeRepositorySchema = z.object({
9
+ repositoryPath: z
10
+ .string()
11
+ .describe("Absolute path to the repository to analyze (e.g., /path/to/my-repo)"),
12
+ scanDepth: z
13
+ .enum(["quick", "full"])
14
+ .default("full")
15
+ .describe("Analysis depth: 'quick' for basic info, 'full' for comprehensive analysis"),
16
+ focusAreas: z
17
+ .array(z.string())
18
+ .optional()
19
+ .describe("Optional: Specific areas to focus on (e.g., ['api', 'frontend', 'infrastructure'])"),
20
+ });
21
+ export function registerAnalyzeRepositoryTool(server) {
22
+ server.registerTool("skyramp_analyze_repository", {
23
+ description: `Analyze a code repository to understand its structure, technology stack, and testing readiness.
24
+
25
+ This tool performs comprehensive repository analysis including:
26
+ - Project type classification (REST API, Frontend, Full-stack, Microservices, etc.)
27
+ - Technology stack identification (languages, frameworks, dependencies)
28
+ - Artifact discovery (OpenAPI specs, Playwright recordings, trace files)
29
+ - API endpoint detection and cataloging
30
+ - Authentication mechanism analysis
31
+ - Infrastructure configuration (Docker, Kubernetes, CI/CD)
32
+ - Existing test coverage assessment
33
+
34
+ The analysis provides structured data that can be used by skyramp_map_tests to calculate test priorities.
35
+
36
+ Example usage:
37
+ \`\`\`
38
+ {
39
+ "repositoryPath": "/Users/dev/my-api",
40
+ "scanDepth": "full"
41
+ }
42
+ \`\`\`
43
+
44
+ **CRITICAL RULES**:
45
+ - DO NOT CREATE ANY .json or .md file during repository analysis.
46
+
47
+ Output: Detailed RepositoryAnalysis JSON object with all repository characteristics.`,
48
+ inputSchema: analyzeRepositorySchema.shape,
49
+ }, async (params) => {
50
+ try {
51
+ logger.info("Analyze repository tool invoked", {
52
+ repositoryPath: params.repositoryPath,
53
+ scanDepth: params.scanDepth,
54
+ });
55
+ // Return prompt for LLM to execute
56
+ const analysisPrompt = getRepositoryAnalysisPrompt(params.repositoryPath);
57
+ return {
58
+ content: [
59
+ {
60
+ type: "text",
61
+ text: `# Repository Analysis Request
62
+
63
+ Please analyze the repository at: \`${params.repositoryPath}\`
64
+
65
+ ${params.focusAreas ? `Focus on: ${params.focusAreas.join(", ")}\n` : ""}
66
+
67
+ Use the following tools to gather information:
68
+ - \`codebase_search\` - to understand code patterns and structure
69
+ - \`grep\` - to find specific patterns (route definitions, dependencies, etc.)
70
+ - \`glob_file_search\` - to find files by pattern (OpenAPI specs, config files, trace files, etc.)
71
+ - \`read_file\` - to read specific files (package.json, requirements.txt, etc.)
72
+ - \`list_dir\` - to explore directory structure
73
+
74
+ ${analysisPrompt}
75
+
76
+ After gathering all information, return a JSON object matching the RepositoryAnalysis structure shown in the prompt above.`,
77
+ },
78
+ ],
79
+ isError: false,
80
+ };
81
+ }
82
+ catch (error) {
83
+ const errorMessage = error instanceof Error ? error.message : String(error);
84
+ logger.error("Analyze repository tool failed", { error: errorMessage });
85
+ return {
86
+ content: [
87
+ {
88
+ type: "text",
89
+ text: `Error analyzing repository: ${errorMessage}`,
90
+ },
91
+ ],
92
+ isError: true,
93
+ };
94
+ }
95
+ });
96
+ }
@@ -0,0 +1,195 @@
1
+ import { z } from "zod";
2
+ import { repositoryAnalysisSchema } from "../../types/RepositoryAnalysis.js";
3
+ import { TestType } from "../../types/TestTypes.js";
4
+ import { ScoringEngine } from "../../utils/scoring-engine.js";
5
+ import { logger } from "../../utils/logger.js";
6
+ /**
7
+ * Map Tests Tool
8
+ * MCP tool for calculating test priority scores
9
+ */
10
+ const mapTestsSchema = z.object({
11
+ analysisReport: z
12
+ .union([z.string(), repositoryAnalysisSchema])
13
+ .describe("Repository analysis result (JSON string or object from skyramp_analyze_repository)"),
14
+ customWeights: z
15
+ .record(z.number())
16
+ .optional()
17
+ .describe("Optional: Custom weight multipliers for specific test types (e.g., {'load': 1.5, 'fuzz': 1.3})"),
18
+ focusTestTypes: z
19
+ .array(z.nativeEnum(TestType))
20
+ .optional()
21
+ .describe("Optional: Only evaluate specific test types (e.g., ['integration', 'smoke'])"),
22
+ });
23
+ export function registerMapTestsTool(server) {
24
+ server.registerTool("skyramp_map_tests", {
25
+ description: `Calculate priority scores for Skyramp test types based on repository analysis.
26
+
27
+ This tool evaluates all test types (E2E, UI, Integration, Load, Fuzz, Contract, Smoke) and calculates priority scores using:
28
+ - Base impact scores (E2E: 100, UI: 95, Integration: 85, etc.)
29
+ - Context multipliers based on repository characteristics
30
+ - Feasibility assessment based on available artifacts
31
+
32
+ The scoring algorithm considers:
33
+ - Project type (full-stack, microservices, REST API, etc.)
34
+ - Infrastructure (Kubernetes, Docker Compose, CI/CD)
35
+ - Existing test coverage gaps
36
+ - Available artifacts (OpenAPI specs, Playwright recordings)
37
+ - Security requirements (authentication, sensitive data)
38
+
39
+ Example usage:
40
+ \`\`\`
41
+ {
42
+ "analysisReport": "<RepositoryAnalysis JSON from skyramp_analyze_repository>",
43
+ "customWeights": {
44
+ "load": 1.5,
45
+ "fuzz": 1.3
46
+ }
47
+ }
48
+ \`\`\`
49
+
50
+ **CRITICAL RULES**:
51
+ - DO NOT CREATE ANY .json or .md file during test mapping.
52
+
53
+ Output: TestMappingResult JSON with priority scores, feasibility, and reasoning for each test type.`,
54
+ inputSchema: mapTestsSchema.shape,
55
+ }, async (params) => {
56
+ try {
57
+ logger.info("Map tests tool invoked");
58
+ // Parse and validate analysis report
59
+ let analysis = params.analysisReport;
60
+ if (typeof analysis === "string") {
61
+ try {
62
+ analysis = JSON.parse(analysis);
63
+ }
64
+ catch (error) {
65
+ throw new Error("analysisReport must be valid JSON string or RepositoryAnalysis object. JSON parsing failed.");
66
+ }
67
+ }
68
+ // Validate the analysis object against the schema
69
+ const validationResult = repositoryAnalysisSchema.safeParse(analysis);
70
+ if (!validationResult.success) {
71
+ const errors = validationResult.error.errors
72
+ .map((e) => `${e.path.join(".")}: ${e.message}`)
73
+ .join("; ");
74
+ throw new Error(`analysisReport validation failed: ${errors}`);
75
+ }
76
+ analysis = validationResult.data;
77
+ // Determine which test types to evaluate
78
+ const testTypesToEvaluate = params.focusTestTypes ||
79
+ Object.values(TestType).filter((t) => typeof t === "string");
80
+ // Calculate scores for each test type
81
+ const priorityScores = [];
82
+ for (const testType of testTypesToEvaluate) {
83
+ const score = ScoringEngine.calculateTestScore(testType, analysis);
84
+ // Apply custom weights if provided
85
+ if (params.customWeights && params.customWeights[testType]) {
86
+ score._finalScore *= params.customWeights[testType];
87
+ score.contextMultiplier *= params.customWeights[testType];
88
+ score.reasoning += ` (custom weight: ×${params.customWeights[testType]})`;
89
+ }
90
+ priorityScores.push(score);
91
+ }
92
+ // Sort by final score (descending)
93
+ priorityScores.sort((a, b) => b._finalScore - a._finalScore);
94
+ // Create summary
95
+ const highPriority = [];
96
+ const mediumPriority = [];
97
+ const lowPriority = [];
98
+ for (const score of priorityScores) {
99
+ if (score.feasibility === "not-applicable")
100
+ continue;
101
+ if (score._finalScore >= 80) {
102
+ highPriority.push(score.testType);
103
+ }
104
+ else if (score._finalScore >= 60) {
105
+ mediumPriority.push(score.testType);
106
+ }
107
+ else {
108
+ lowPriority.push(score.testType);
109
+ }
110
+ }
111
+ // Extract context factors
112
+ const contextFactors = { applied: [] };
113
+ if (analysis.infrastructure.hasKubernetes) {
114
+ contextFactors.applied.push({
115
+ factor: "hasKubernetes",
116
+ impact: "Increases load and integration test importance",
117
+ multiplier: 1.2,
118
+ });
119
+ }
120
+ if (analysis.infrastructure.hasDockerCompose) {
121
+ contextFactors.applied.push({
122
+ factor: "hasDockerCompose",
123
+ impact: "Suggests scaled infrastructure",
124
+ multiplier: 1.1,
125
+ });
126
+ }
127
+ if (analysis.infrastructure.hasCiCd) {
128
+ contextFactors.applied.push({
129
+ factor: "hasCiCd",
130
+ impact: "Increases smoke test importance",
131
+ multiplier: 1.1,
132
+ });
133
+ }
134
+ const mapping = {
135
+ priorityScores,
136
+ contextFactors,
137
+ summary: { highPriority, mediumPriority, lowPriority },
138
+ };
139
+ // Format output
140
+ const output = `# Test Priority Mapping
141
+
142
+ ## Summary
143
+ - **High Priority**: ${mapping.summary.highPriority.join(", ") || "None"}
144
+ - **Medium Priority**: ${mapping.summary.mediumPriority.join(", ") || "None"}
145
+ - **Low Priority**: ${mapping.summary.lowPriority.join(", ") || "None"}
146
+
147
+ ## Test Type Priorities (Ordered by Score)
148
+
149
+ ${mapping.priorityScores
150
+ .map((score) => `### ${score.testType.toUpperCase()}
151
+ - **Feasibility**: ${score.feasibility}
152
+ - **Available Artifacts**: ${score.requiredArtifacts.available.join(", ") || "None"}
153
+ - **Missing Artifacts**: ${score.requiredArtifacts.missing.join(", ") || "None"}
154
+ - **Reasoning**: ${score.reasoning}
155
+ `)
156
+ .join("\n")}
157
+
158
+ ## Context Factors Applied
159
+
160
+ ${mapping.contextFactors.applied
161
+ .map((factor) => `- **${factor.factor}**: ${factor.impact} (×${factor.multiplier})`)
162
+ .join("\n")}
163
+
164
+ ## Complete Mapping Result (JSON)
165
+
166
+ \`\`\`json
167
+ ${JSON.stringify(mapping, null, 2)}
168
+ \`\`\`
169
+
170
+ **Next Step**: Use \`skyramp_recommend_tests\` with this mapping result to get actionable test recommendations.`;
171
+ return {
172
+ content: [
173
+ {
174
+ type: "text",
175
+ text: output,
176
+ },
177
+ ],
178
+ isError: false,
179
+ };
180
+ }
181
+ catch (error) {
182
+ const errorMessage = error instanceof Error ? error.message : String(error);
183
+ logger.error("Map tests tool failed", { error: errorMessage });
184
+ return {
185
+ content: [
186
+ {
187
+ type: "text",
188
+ text: `Error mapping tests: ${errorMessage}`,
189
+ },
190
+ ],
191
+ isError: true,
192
+ };
193
+ }
194
+ });
195
+ }
@@ -0,0 +1,131 @@
1
+ import { z } from "zod";
2
+ import { testMappingResultSchema } from "../../types/TestMapping.js";
3
+ import { repositoryAnalysisSchema } from "../../types/RepositoryAnalysis.js";
4
+ import { getTestRecommendationPrompt } from "../../prompts/test-recommendation/test-recommendation-prompt.js";
5
+ import { logger } from "../../utils/logger.js";
6
+ /**
7
+ * Recommend Tests Tool
8
+ * MCP tool for generating actionable test recommendations
9
+ */
10
+ const recommendTestsSchema = z.object({
11
+ priorityScores: z
12
+ .union([z.string(), testMappingResultSchema])
13
+ .describe("Test mapping result (JSON string or object from skyramp_map_tests)"),
14
+ analysisReport: z
15
+ .union([z.string(), repositoryAnalysisSchema])
16
+ .describe("Repository analysis result (JSON string or object from skyramp_analyze_repository)"),
17
+ topN: z
18
+ .number()
19
+ .default(7)
20
+ .describe("Number of top test types to recommend (default: 5)"),
21
+ minScore: z
22
+ .number()
23
+ .default(60)
24
+ .describe("Minimum score threshold for recommendations (default: 60)"),
25
+ });
26
+ export function registerRecommendTestsTool(server) {
27
+ server.registerTool("skyramp_recommend_tests", {
28
+ description: `Generate actionable test recommendations with ready-to-use generation prompts.
29
+
30
+ This tool takes test priority and repository analysis to create:
31
+ - Ordered list of recommended test types (high/medium/low priority)
32
+ - Specific test scenarios based on actual repository endpoints and flows
33
+ - Artifact availability status and guidance for missing artifacts
34
+ - Step-by-step next actions
35
+
36
+ SAMPLE OUTPUT:
37
+ \`\`\`
38
+ Recommended Tests (Prioritized)
39
+ Priority: <PRIORITY HIGH, MEDIUM, OR LOW>
40
+ 1. <TEST TYPE> Tests [**CRITICAL: NEVER MENTION THE SCORE HERE IN THE OUTPUT**]
41
+ Rationale:
42
+ Specific Tests to Create:
43
+ Test 1: <TEST NAME>
44
+ Description: <TEST DESCRIPTION>
45
+ Target Flow: <TARGET FLOW>
46
+ \`\`\`
47
+
48
+ For each recommended test type, you'll get:
49
+ - 2-3 specific tests you can create right now
50
+ - Required vs. available artifacts. THIS SHOULD NOT CHANGE PRIORITIZATION OF THE TESTS.
51
+ - Guidance for creating missing artifacts WITHOUT PROVIDING ANY CLI COMMANDS.
52
+
53
+ **CRITICAL RULES**:
54
+ - THE PRIORITY SHOULD ONLY BE DEFINED AS HIGH, MEDIUM, OR LOW NOTHING ELSE.
55
+ - DO NOT SHOW ANY PRIORITY BREAKDOWN IN THE OUTPUT.
56
+ - DON'T MARK ANY TEST BLOCKED EVEN IF REQUIRED ARTIFACTS ARE MISSING.
57
+ - DO NOT SHOW RESULTS IN .MD OR .JSON OR ANY OTHER FILE FORMAT.
58
+
59
+ Output: TestRecommendation JSON with prioritized, actionable test recommendations.`,
60
+ inputSchema: recommendTestsSchema.shape,
61
+ }, async (params) => {
62
+ try {
63
+ logger.info("Recommend tests tool invoked", {
64
+ topN: params.topN,
65
+ minScore: params.minScore,
66
+ });
67
+ // Parse inputs if they're strings
68
+ let mapping = params.priorityScores;
69
+ let analysis = params.analysisReport;
70
+ if (typeof mapping === "string") {
71
+ try {
72
+ mapping = JSON.parse(mapping);
73
+ }
74
+ catch (error) {
75
+ throw new Error("priorityScores must be valid JSON string or TestMappingResult object");
76
+ }
77
+ }
78
+ if (typeof analysis === "string") {
79
+ try {
80
+ analysis = JSON.parse(analysis);
81
+ }
82
+ catch (error) {
83
+ throw new Error("analysisReport must be valid JSON string or RepositoryAnalysis object");
84
+ }
85
+ }
86
+ // Generate the prompt for LLM to create dynamic recommendations
87
+ const prompt = getTestRecommendationPrompt(mapping, analysis, params.topN);
88
+ // Return prompt for LLM to execute
89
+ return {
90
+ content: [
91
+ {
92
+ type: "text",
93
+ text: `# Test Recommendation Request
94
+
95
+ Please generate actionable test recommendations based on the priority scores and repository analysis.
96
+
97
+ ${prompt}
98
+
99
+ **Important Guidelines:**
100
+ 1. **NO SCORES IN OUTPUT**: The numeric scores are for internal ranking only. DO NOT include "score" field in JSON and DO NOT mention numeric scores in any text (rationale, description, etc.). Use ONLY priority levels: "high", "medium", "low".
101
+ 2. Include guidance for missing artifacts with specific Skyramp tool commands
102
+ 3. Prioritize quick wins (tests with all artifacts available)
103
+ 4. Use actual endpoint paths and file paths from the repository analysis
104
+
105
+ **MANDATORY RULES**:
106
+ - THE PRIORITY SHOULD ONLY BE DEFINED AS HIGH, MEDIUM, OR LOW NOTHING ELSE.
107
+ - DO NOT SHOW ANY PRIORITY BREAKDOWN IN THE OUTPUT.
108
+ - DON'T MARK ANY TEST BLOCKED EVEN IF REQUIRED ARTIFACTS ARE MISSING.
109
+ - DO NOT SHOW RESULTS IN .MD OR .JSON OR ANY OTHER FILE FORMAT.
110
+
111
+ After analyzing the data above, return the complete JSON response following the structure defined in the prompt.`,
112
+ },
113
+ ],
114
+ isError: false,
115
+ };
116
+ }
117
+ catch (error) {
118
+ const errorMessage = error instanceof Error ? error.message : String(error);
119
+ logger.error("Recommend tests tool failed", { error: errorMessage });
120
+ return {
121
+ content: [
122
+ {
123
+ type: "text",
124
+ text: `Error generating recommendations: ${errorMessage}`,
125
+ },
126
+ ],
127
+ isError: true,
128
+ };
129
+ }
130
+ });
131
+ }
@@ -0,0 +1,106 @@
1
+ import { z } from "zod";
2
+ // Zod schemas for validation
3
+ export const analysisMetadataSchema = z.object({
4
+ repositoryName: z.string(),
5
+ analysisDate: z.string(),
6
+ scanDepth: z.enum(["quick", "full"]),
7
+ });
8
+ export const projectClassificationSchema = z.object({
9
+ projectType: z.enum([
10
+ "rest-api",
11
+ "frontend",
12
+ "full-stack",
13
+ "microservices",
14
+ "library",
15
+ "cli",
16
+ "other",
17
+ ]),
18
+ primaryLanguage: z.string(),
19
+ primaryFramework: z.string(),
20
+ deploymentPattern: z.enum([
21
+ "microservices",
22
+ "full-stack",
23
+ "containerized-monolith",
24
+ "traditional",
25
+ "unknown",
26
+ ]),
27
+ });
28
+ export const repositoryAnalysisSchema = z.object({
29
+ metadata: analysisMetadataSchema,
30
+ projectClassification: projectClassificationSchema,
31
+ technologyStack: z.object({
32
+ languages: z.array(z.string()),
33
+ frameworks: z.array(z.string()),
34
+ runtime: z.string(),
35
+ keyDependencies: z.array(z.object({
36
+ name: z.string(),
37
+ version: z.string(),
38
+ purpose: z.string(),
39
+ })),
40
+ }),
41
+ businessContext: z.object({
42
+ mainPurpose: z.string(),
43
+ userFlows: z.array(z.string()),
44
+ dataFlows: z.array(z.string()),
45
+ integrationPatterns: z.array(z.string()),
46
+ }),
47
+ artifacts: z.object({
48
+ openApiSpecs: z.array(z.object({
49
+ path: z.string(),
50
+ version: z.string(),
51
+ endpointCount: z.number(),
52
+ baseUrl: z.string(),
53
+ authType: z.string(),
54
+ })),
55
+ playwrightRecordings: z.array(z.object({
56
+ path: z.string(),
57
+ description: z.string(),
58
+ })),
59
+ traceFiles: z.array(z.object({
60
+ path: z.string(),
61
+ format: z.string(),
62
+ analyzed: z.boolean().optional(),
63
+ userFlows: z.array(z.string()).optional(),
64
+ })),
65
+ notFound: z.array(z.string()),
66
+ }),
67
+ apiEndpoints: z.object({
68
+ totalCount: z.number(),
69
+ baseUrl: z.string(),
70
+ endpoints: z.array(z.object({
71
+ path: z.string(),
72
+ method: z.string(),
73
+ resourceGroup: z.string(),
74
+ authRequired: z.boolean(),
75
+ sourceFile: z.string().optional(),
76
+ })),
77
+ }),
78
+ authentication: z.object({
79
+ method: z.enum(["bearer", "api-key", "oauth2", "basic", "jwt", "none"]),
80
+ configLocation: z.string(),
81
+ envVarsRequired: z.array(z.string()),
82
+ setupExample: z.string(),
83
+ }),
84
+ infrastructure: z.object({
85
+ isContainerized: z.boolean(),
86
+ hasDockerCompose: z.boolean(),
87
+ hasKubernetes: z.boolean(),
88
+ hasCiCd: z.boolean(),
89
+ ciCdPlatform: z.string().optional(),
90
+ }),
91
+ existingTests: z.object({
92
+ frameworks: z.array(z.string()),
93
+ coverage: z.object({
94
+ unit: z.number(),
95
+ integration: z.number(),
96
+ e2e: z.number(),
97
+ ui: z.number(),
98
+ load: z.number(),
99
+ contract: z.number(),
100
+ smoke: z.number(),
101
+ }),
102
+ testLocations: z.record(z.string()),
103
+ hasCoverageReports: z.boolean(),
104
+ estimatedCoverage: z.number().optional(),
105
+ }),
106
+ });