@skyramp/mcp 0.0.64 → 0.0.65
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/prompts/test-recommendation/test-recommendation-prompt.js +7 -13
- package/build/services/TestExecutionService.js +1 -1
- package/build/services/TestGenerationService.js +1 -0
- package/build/tools/generate-tests/generateMockRestTool.js +1 -0
- package/build/tools/submitReportTool.js +3 -2
- package/build/types/RepositoryAnalysis.js +2 -12
- package/build/types/TestRecommendation.js +43 -1
- package/build/types/TestTypes.js +4 -0
- package/package.json +2 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as crypto from "crypto";
|
|
2
2
|
import { WorkspaceAuthType } from "../../utils/workspaceAuth.js";
|
|
3
3
|
import { buildToolWorkflows, buildTestPatternGuidelines, buildTestQualityCriteria, buildTestExamples, buildGenerationRules, getAuthSnippets, MAX_TESTS_TO_GENERATE, MAX_RECOMMENDATIONS, MAX_CRITICAL_TESTS, } from "./recommendationSections.js";
|
|
4
|
+
import { CATEGORY_PRIORITY, TEST_CATEGORIES } from "../../types/TestRecommendation.js";
|
|
4
5
|
function formatTestLocations(locs) {
|
|
5
6
|
const entries = Object.entries(locs || {});
|
|
6
7
|
if (entries.length === 0)
|
|
@@ -9,18 +10,11 @@ function formatTestLocations(locs) {
|
|
|
9
10
|
" If a GENERATE item's resource path matches a path listed here, UPDATE that file instead of creating a new one.\n" +
|
|
10
11
|
entries.map(([type, files]) => " - [" + type + "] " + files).join("\n");
|
|
11
12
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
breaking_change: "HIGH",
|
|
18
|
-
auth: "HIGH",
|
|
19
|
-
workflow: "MEDIUM",
|
|
20
|
-
"error-handling": "MEDIUM",
|
|
21
|
-
"data-validation": "MEDIUM",
|
|
22
|
-
crud: "LOW",
|
|
23
|
-
};
|
|
13
|
+
// ── Priority-tier ordering (replaces numeric CATEGORY_WEIGHTS) ──
|
|
14
|
+
// Categories map to HIGH / MEDIUM / LOW tiers.
|
|
15
|
+
// Within a tier, novelty (new > modified > existing) breaks ties,
|
|
16
|
+
// then cross-resource, step count, and finally the deterministic SHA-256 seed.
|
|
17
|
+
// CATEGORY_PRIORITY and PriorityTier imported from ../../types/TestRecommendation.js
|
|
24
18
|
const PRIORITY_ORDER = { CRITICAL: 4, HIGH: 3, MEDIUM: 2, LOW: 1 };
|
|
25
19
|
const NOVELTY_ORDER = { new: 3, modified: 2, existing: 1 };
|
|
26
20
|
function classifyNovelty(scenario, diffContext) {
|
|
@@ -227,7 +221,7 @@ Quality gate — ask all three questions:
|
|
|
227
221
|
2. "Does this test exercise a real workflow or catch a real bug?" → YES = at least MEDIUM
|
|
228
222
|
3. "Does this test cover a mutation that modifies child items and triggers total/amount recalculation?" → YES = HIGH priority, and prefer it for GENERATE over simple single-field update tests for the same endpoint
|
|
229
223
|
|
|
230
|
-
Assign category:
|
|
224
|
+
Assign category: ${TEST_CATEGORIES.join(" | ")}
|
|
231
225
|
|
|
232
226
|
${buildTestPatternGuidelines()}
|
|
233
227
|
|
|
@@ -8,7 +8,7 @@ import { logger } from "../utils/logger.js";
|
|
|
8
8
|
import { buildContainerEnv } from "./containerEnv.js";
|
|
9
9
|
const DEFAULT_TIMEOUT = 300000; // 5 minutes
|
|
10
10
|
const MAX_CONCURRENT_EXECUTIONS = 5;
|
|
11
|
-
export const EXECUTOR_DOCKER_IMAGE = "skyramp/executor:v1.3.
|
|
11
|
+
export const EXECUTOR_DOCKER_IMAGE = "skyramp/executor:v1.3.18";
|
|
12
12
|
const DOCKER_PLATFORM = "linux/amd64";
|
|
13
13
|
const EXECUTION_PROGRESS_INTERVAL = 10000; // 10 seconds between progress updates during execution
|
|
14
14
|
// Temp file with valid empty JSON — used instead of /dev/null for .json config files
|
|
@@ -3,6 +3,7 @@ import { logger } from "../utils/logger.js";
|
|
|
3
3
|
import * as fs from "fs/promises";
|
|
4
4
|
import * as path from "path";
|
|
5
5
|
import { AnalyticsService } from "../services/AnalyticsService.js";
|
|
6
|
+
import { TEST_CATEGORIES, externalCategory } from "../types/TestRecommendation.js";
|
|
6
7
|
const TOOL_NAME = "skyramp_submit_report";
|
|
7
8
|
const DEFAULT_COMMIT_MESSAGE = "Added recommendations by Skyramp Testbot.";
|
|
8
9
|
const testResultSchema = z.object({
|
|
@@ -14,7 +15,7 @@ const testResultSchema = z.object({
|
|
|
14
15
|
const newTestSchema = z.object({
|
|
15
16
|
testId: z.string().describe("Human-readable kebab-case identifier, e.g. 'contract-get-products' or 'integration-users-orders-workflow'. Format: '<testType>-<method>-<resource>' for single-endpoint tests or '<testType>-<scenario-slug>' for multi-step tests. Must be unique within the report."),
|
|
16
17
|
testType: z.string().describe("Type of test created: Smoke, Contract, Integration, etc. Do not include priority or other metadata in this field."),
|
|
17
|
-
category: z.
|
|
18
|
+
category: z.preprocess((val) => externalCategory(val), z.enum(TEST_CATEGORIES)).describe("Test category — critical categories (security_boundary, business_rule, data_integrity, breaking_change) get generation priority over workflow"),
|
|
18
19
|
endpoint: z.string().describe("HTTP verb and path, e.g. 'GET /api/v1/products'"),
|
|
19
20
|
fileName: z.string().describe("Name of the generated test file"),
|
|
20
21
|
description: z.string().optional().describe("What the test does — the steps and assertions, not the bugs it finds. e.g. 'Creates a collection, adds a link, then verifies the link exists'. Do NOT describe expected failures or bugs here — those belong in issuesFound."),
|
|
@@ -43,7 +44,7 @@ const scenarioStepSchema = z.object({
|
|
|
43
44
|
const additionalRecommendationSchema = z.object({
|
|
44
45
|
testId: z.string().describe("Human-readable kebab-case identifier, e.g. 'integration-products-orders-workflow' or 'e2e-checkout-flow'. Format: '<testType>-<scenario-slug>'. Must be unique within the report."),
|
|
45
46
|
testType: z.string().describe("Type of test: Integration, E2E, Contract, UI, etc. Do not include priority or other metadata in this field."),
|
|
46
|
-
category: z.
|
|
47
|
+
category: z.preprocess((val) => externalCategory(val), z.enum(TEST_CATEGORIES)).describe("Test category — critical categories get generation priority over workflow"),
|
|
47
48
|
scenarioName: z.string().describe("Name of the scenario, e.g. 'products_orders_workflow'"),
|
|
48
49
|
steps: z.array(scenarioStepSchema).describe("Ordered sequence of API/UI steps in this test scenario"),
|
|
49
50
|
description: z.string().describe("Why this test is valuable and what it would cover"),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { SCENARIO_CATEGORIES } from "./TestRecommendation.js";
|
|
2
3
|
// ── Zod schemas ──
|
|
3
4
|
export const analysisScopeSchema = z.enum(["full_repo", "current_branch_diff"]);
|
|
4
5
|
export const paramInfoSchema = z.object({
|
|
@@ -76,18 +77,7 @@ export const scenarioStepSchema = z.object({
|
|
|
76
77
|
export const draftedScenarioSchema = z.object({
|
|
77
78
|
scenarioName: z.string(),
|
|
78
79
|
description: z.string(),
|
|
79
|
-
category: z.enum(
|
|
80
|
-
"crud",
|
|
81
|
-
"workflow",
|
|
82
|
-
"auth",
|
|
83
|
-
"error-handling",
|
|
84
|
-
"data-validation",
|
|
85
|
-
"security_boundary",
|
|
86
|
-
"business_rule",
|
|
87
|
-
"data_integrity",
|
|
88
|
-
"breaking_change",
|
|
89
|
-
"new_endpoint",
|
|
90
|
-
]),
|
|
80
|
+
category: z.enum(SCENARIO_CATEGORIES),
|
|
91
81
|
priority: z.enum(["high", "medium", "low"]),
|
|
92
82
|
steps: z.array(scenarioStepSchema),
|
|
93
83
|
chainingKeys: z.array(z.string()),
|
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { TestType } from "./TestTypes.js";
|
|
3
|
+
/** Internal-only categories (not submitted to tools). */
|
|
4
|
+
const INTERNAL_CATEGORIES = [
|
|
5
|
+
"new_endpoint", // CRITICAL - diff-direct scenarios always fill GENERATE slots first
|
|
6
|
+
];
|
|
7
|
+
/** External categories valid for tool submissions, ordered by priority. */
|
|
8
|
+
const CATEGORIES = [
|
|
9
|
+
// HIGH priority
|
|
10
|
+
"security_boundary", // auth, permission, cross-user isolation, idempotency
|
|
11
|
+
"business_rule", // unique constraints, range validation, state machines
|
|
12
|
+
"data_integrity", // cascade deletes, orphan prevention, referential integrity
|
|
13
|
+
"breaking_change", // route renames, auth migration, response shape changes
|
|
14
|
+
"auth", // authentication and authorization flows
|
|
15
|
+
// MEDIUM priority
|
|
16
|
+
"workflow", // cross-resource integration, user journeys
|
|
17
|
+
"error_handling", // error responses and edge cases
|
|
18
|
+
"data_validation", // input validation and schema enforcement
|
|
19
|
+
// LOW priority
|
|
20
|
+
"crud", // basic create/read/update/delete operations
|
|
21
|
+
];
|
|
22
|
+
/** All categories including internal ones. */
|
|
23
|
+
export const SCENARIO_CATEGORIES = [...INTERNAL_CATEGORIES, ...CATEGORIES];
|
|
24
|
+
/** Categories valid for tool submissions (excludes internal-only categories). */
|
|
25
|
+
export const TEST_CATEGORIES = CATEGORIES;
|
|
26
|
+
/** Priority assignment for each category. */
|
|
27
|
+
export const CATEGORY_PRIORITY = {
|
|
28
|
+
new_endpoint: "CRITICAL",
|
|
29
|
+
security_boundary: "HIGH",
|
|
30
|
+
business_rule: "HIGH",
|
|
31
|
+
data_integrity: "HIGH",
|
|
32
|
+
breaking_change: "HIGH",
|
|
33
|
+
auth: "HIGH",
|
|
34
|
+
workflow: "MEDIUM",
|
|
35
|
+
error_handling: "MEDIUM",
|
|
36
|
+
data_validation: "MEDIUM",
|
|
37
|
+
crud: "LOW",
|
|
38
|
+
};
|
|
39
|
+
/** Map internal-only categories to their external equivalent for tool submission. */
|
|
40
|
+
export function externalCategory(cat) {
|
|
41
|
+
if (cat === "new_endpoint")
|
|
42
|
+
return "crud";
|
|
43
|
+
return cat;
|
|
44
|
+
}
|
|
3
45
|
// Test type to documentation URL mapping
|
|
4
46
|
export const TEST_TYPE_DOCS = {
|
|
5
47
|
[TestType.SMOKE]: "https://www.skyramp.dev/docs/smoke-tests",
|
|
@@ -33,7 +75,7 @@ export const specificTestSchema = z.object({
|
|
|
33
75
|
export const testTypeRecommendationSchema = z.object({
|
|
34
76
|
priority: z.enum(["high", "medium", "low"]),
|
|
35
77
|
testType: z.nativeEnum(TestType),
|
|
36
|
-
category: z.enum(
|
|
78
|
+
category: z.enum(TEST_CATEGORIES),
|
|
37
79
|
rationale: z.string(),
|
|
38
80
|
reasoning: z.string(),
|
|
39
81
|
specificTests: z.array(specificTestSchema),
|
package/build/types/TestTypes.js
CHANGED
|
@@ -101,6 +101,10 @@ export const baseSchema = z.object({
|
|
|
101
101
|
.number()
|
|
102
102
|
.default(0)
|
|
103
103
|
.describe("Port number for the mock server"),
|
|
104
|
+
optionalFields: z
|
|
105
|
+
.boolean()
|
|
106
|
+
.default(false)
|
|
107
|
+
.describe("Whether to include optional fields in the generated test/mock"),
|
|
104
108
|
prompt: z.string().describe("The prompt user provided to generate the test"),
|
|
105
109
|
});
|
|
106
110
|
export const basePlaywrightSchema = z.object({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skyramp/mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.65",
|
|
4
4
|
"main": "build/index.js",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./build/index.js",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@modelcontextprotocol/sdk": "^1.24.3",
|
|
56
56
|
"@playwright/test": "^1.55.0",
|
|
57
|
-
"@skyramp/skyramp": "1.3.
|
|
57
|
+
"@skyramp/skyramp": "1.3.18",
|
|
58
58
|
"dockerode": "^4.0.6",
|
|
59
59
|
"fast-glob": "^3.3.3",
|
|
60
60
|
"playwright": "file:vendor/skyramp-playwright-1.58.2-skyramp.8.9.0.tgz",
|