@skyramp/mcp 0.4.3 → 0.4.4-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/build/index.js +239 -210
  2. package/build/playwright/PlaywrightTraceService.d.ts +1 -1
  3. package/build/playwright/blueprintDigestStore.d.ts +1 -1
  4. package/build/playwright/registerPlaywrightTools.d.ts +1 -1
  5. package/build/playwright/traceRecordingPrompt.d.ts +1 -1
  6. package/build/playwright/traceRecordingPrompt.js +4 -3
  7. package/build/prompts/local-dev/local-dev-prompts.d.ts +1 -1
  8. package/build/prompts/local-dev/local-dev-prompts.js +2 -2
  9. package/build/prompts/orderAssertionRule.d.ts +9 -0
  10. package/build/prompts/orderAssertionRule.js +9 -0
  11. package/build/prompts/startTraceCollectionPrompts.d.ts +1 -1
  12. package/build/prompts/startTraceCollectionPrompts.js +2 -3
  13. package/build/prompts/test-maintenance/driftAnalysisShared.js +2 -0
  14. package/build/prompts/test-recommendation/registerRecommendTestsPrompt.d.ts +1 -1
  15. package/build/prompts/test-recommendation/registerRecommendTestsPrompt.js +2 -2
  16. package/build/prompts/testbot/testbot-prompts.d.ts +1 -1
  17. package/build/prompts/testbot/testbot-prompts.js +9 -9
  18. package/build/recommendation/answers.d.ts +3 -3
  19. package/build/recommendation/answers.js +3 -2
  20. package/build/recommendation/verifierContracts.d.ts +4 -4
  21. package/build/recommendation/verifierContracts.js +6 -5
  22. package/build/recommendation/verifiers/coverage.js +25 -25
  23. package/build/recommendation/verifiers/deliveredMatchesPlan.js +3 -3
  24. package/build/resources/analysisResources.d.ts +1 -1
  25. package/build/resources/analysisResources.js +1 -1
  26. package/build/resources/progressResource.d.ts +1 -1
  27. package/build/resources/sutSetupResource.d.ts +1 -1
  28. package/build/resources/sutSetupResource.js +1 -1
  29. package/build/resources/testbotResource.d.ts +1 -1
  30. package/build/resources/testbotResource.js +1 -1
  31. package/build/services/AnalyticsService.d.ts +1 -1
  32. package/build/services/FleetExecutionService.d.ts +130 -0
  33. package/build/services/FleetExecutionService.js +391 -0
  34. package/build/services/ModularizationService.d.ts +1 -1
  35. package/build/services/TestExecutionService.d.ts +7 -0
  36. package/build/services/TestExecutionService.js +21 -0
  37. package/build/services/TestGenerationService.d.ts +1 -1
  38. package/build/tool-phases.js +2 -0
  39. package/build/tools/auth/loginTool.d.ts +1 -1
  40. package/build/tools/auth/loginTool.js +2 -2
  41. package/build/tools/auth/logoutTool.d.ts +1 -1
  42. package/build/tools/auth/logoutTool.js +2 -2
  43. package/build/tools/code-refactor/alignAssertionsTool.d.ts +1 -1
  44. package/build/tools/code-refactor/alignAssertionsTool.js +1 -1
  45. package/build/tools/code-refactor/assertionSkillTools.d.ts +1 -1
  46. package/build/tools/code-refactor/assertionSkillTools.js +2 -2
  47. package/build/tools/code-refactor/codeReuseTool.d.ts +1 -1
  48. package/build/tools/code-refactor/codeReuseTool.js +2 -2
  49. package/build/tools/code-refactor/enhanceAssertionsTool.d.ts +1 -1
  50. package/build/tools/code-refactor/enhanceAssertionsTool.js +1 -1
  51. package/build/tools/code-refactor/modularizationTool.d.ts +1 -1
  52. package/build/tools/code-refactor/modularizationTool.js +2 -2
  53. package/build/tools/enrichTestWithMocksTool.d.ts +1 -1
  54. package/build/tools/enrichTestWithMocksTool.js +2 -2
  55. package/build/tools/executeFleetTool.d.ts +28 -0
  56. package/build/tools/executeFleetTool.js +107 -0
  57. package/build/tools/executeSkyrampTestTool.d.ts +8 -5
  58. package/build/tools/executeSkyrampTestTool.js +13 -5
  59. package/build/tools/fixErrorTool.d.ts +1 -1
  60. package/build/tools/fixErrorTool.js +1 -1
  61. package/build/tools/generate-tests/batchMockGenerationTool.d.ts +6 -57
  62. package/build/tools/generate-tests/batchMockGenerationTool.js +3 -3
  63. package/build/tools/generate-tests/generateBatchScenarioRestTool.d.ts +9 -45
  64. package/build/tools/generate-tests/generateBatchScenarioRestTool.js +29 -11
  65. package/build/tools/generate-tests/generateContractRestTool.d.ts +1 -2
  66. package/build/tools/generate-tests/generateContractRestTool.js +1 -1
  67. package/build/tools/generate-tests/generateE2ERestTool.d.ts +2 -2
  68. package/build/tools/generate-tests/generateE2ERestTool.js +10 -2
  69. package/build/tools/generate-tests/generateFuzzRestTool.d.ts +1 -1
  70. package/build/tools/generate-tests/generateFuzzRestTool.js +1 -1
  71. package/build/tools/generate-tests/generateIntegrationRestTool.d.ts +1 -2
  72. package/build/tools/generate-tests/generateIntegrationRestTool.js +1 -1
  73. package/build/tools/generate-tests/generateLoadRestTool.d.ts +1 -2
  74. package/build/tools/generate-tests/generateLoadRestTool.js +2 -1
  75. package/build/tools/generate-tests/generateMockRestTool.d.ts +1 -2
  76. package/build/tools/generate-tests/generateMockRestTool.js +3 -3
  77. package/build/tools/generate-tests/generateSmokeRestTool.d.ts +1 -1
  78. package/build/tools/generate-tests/generateSmokeRestTool.js +1 -1
  79. package/build/tools/generate-tests/generateUILoadRestTool.d.ts +64 -0
  80. package/build/tools/generate-tests/generateUILoadRestTool.js +512 -0
  81. package/build/tools/generate-tests/generateUIRestTool.d.ts +8 -7
  82. package/build/tools/generate-tests/generateUIRestTool.js +10 -2
  83. package/build/tools/generate-tests/loadTestSchema.d.ts +15 -15
  84. package/build/tools/generate-tests/trace-reuse-guard.d.ts +1 -1
  85. package/build/tools/generateEnrichedIntegrationTestTool.d.ts +1 -2
  86. package/build/tools/generateEnrichedIntegrationTestTool.js +1 -1
  87. package/build/tools/localDevWorkerComposeTool.d.ts +1 -1
  88. package/build/tools/localDevWorkerComposeTool.js +2 -2
  89. package/build/tools/one-click/oneClickTool.d.ts +1 -1
  90. package/build/tools/one-click/oneClickTool.js +1 -1
  91. package/build/tools/preflightMockCheckTool.d.ts +1 -1
  92. package/build/tools/preflightMockCheckTool.js +3 -3
  93. package/build/tools/queryProxyMocksTool.d.ts +1 -1
  94. package/build/tools/queryProxyMocksTool.js +3 -3
  95. package/build/tools/submitReportTool.d.ts +111 -414
  96. package/build/tools/submitReportTool.js +88 -38
  97. package/build/tools/test-management/actionsTool.d.ts +1 -1
  98. package/build/tools/test-management/actionsTool.js +7 -7
  99. package/build/tools/test-management/analyzeChangesTool.d.ts +22 -118
  100. package/build/tools/test-management/analyzeChangesTool.js +4 -4
  101. package/build/tools/test-management/analyzeTestHealthTool.d.ts +1 -1
  102. package/build/tools/test-management/analyzeTestHealthTool.js +4 -4
  103. package/build/tools/test-management/registerTestPlanTool.d.ts +107 -733
  104. package/build/tools/test-management/registerTestPlanTool.js +12 -12
  105. package/build/tools/test-management/resolveScreenTool.d.ts +1 -1
  106. package/build/tools/test-management/resolveScreenTool.js +6 -2
  107. package/build/tools/trace/startTraceCollectionTool.d.ts +1 -1
  108. package/build/tools/trace/startTraceCollectionTool.js +4 -4
  109. package/build/tools/trace/stopTraceCollectionTool.d.ts +1 -1
  110. package/build/tools/trace/stopTraceCollectionTool.js +2 -2
  111. package/build/tools/verifyTestDependenciesTool.d.ts +1 -1
  112. package/build/tools/verifyTestDependenciesTool.js +1 -1
  113. package/build/tools/workspace/initScanWorkspaceTool.d.ts +1 -1
  114. package/build/tools/workspace/initScanWorkspaceTool.js +1 -1
  115. package/build/tools/workspace/initializeWorkspaceTool.d.ts +1 -1
  116. package/build/tools/workspace/initializeWorkspaceTool.js +1 -1
  117. package/build/types/RepositoryAnalysis.d.ts +164 -1170
  118. package/build/types/RepositoryAnalysis.js +12 -10
  119. package/build/types/StepMethod.d.ts +24 -1
  120. package/build/types/StepMethod.js +1 -1
  121. package/build/types/TestTypes.d.ts +41 -133
  122. package/build/types/TestTypes.js +25 -3
  123. package/build/types/TestbotReport.d.ts +4 -1
  124. package/build/utils/assertion-verify/metrics.js +12 -0
  125. package/build/utils/docker.d.ts +29 -7
  126. package/build/utils/docker.js +83 -27
  127. package/build/utils/findUp.d.ts +20 -0
  128. package/build/utils/findUp.js +59 -0
  129. package/build/utils/initAgent.d.ts +3 -3
  130. package/build/utils/initAgent.js +58 -26
  131. package/build/utils/language-helper.js +1 -1
  132. package/build/utils/progress.d.ts +3 -4
  133. package/build/utils/progress.js +4 -4
  134. package/build/utils/repoSdkVersion.d.ts +16 -0
  135. package/build/utils/repoSdkVersion.js +88 -0
  136. package/build/utils/testDependencyPolicy.d.ts +20 -0
  137. package/build/utils/testDependencyPolicy.js +64 -4
  138. package/build/utils/utils-verify/typecheck.js +3 -18
  139. package/build/utils/utils.d.ts +1 -1
  140. package/build/utils/versions.d.ts +3 -3
  141. package/build/utils/versions.js +1 -1
  142. package/build/workspace/workspace.d.ts +117 -538
  143. package/build/workspace/workspace.js +2 -2
  144. package/node_modules/playwright/lib/mcp/skyramp/assertOrder.js +66 -0
  145. package/node_modules/playwright/lib/mcp/skyramp/assertTool.js +12 -3
  146. package/node_modules/playwright/lib/mcp/skyramp/common/liveReadError.js +40 -0
  147. package/node_modules/playwright/lib/mcp/skyramp/loadTraceTool.js +21 -0
  148. package/node_modules/playwright/lib/mcp/skyramp/skyRampImport.js +2 -1
  149. package/node_modules/playwright/lib/mcp/skyramp/traceRecordingBackend.js +96 -16
  150. package/node_modules/playwright/lib/mcp/test/skyRampExport.js +10 -0
  151. package/node_modules/playwright/node_modules/playwright-core/lib/server/codegen/skyramp/jsonlReader.js +1 -0
  152. package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/recorderRunner.js +22 -0
  153. package/node_modules/playwright/node_modules/playwright-core/lib/utils/isomorphic/elementOrder.js +57 -0
  154. package/node_modules/playwright/node_modules/playwright-core/lib/utils.js +2 -0
  155. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/{index.uiPTFncY.js → index.0MJW0uG7.js} +1 -1
  156. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.html +1 -1
  157. package/node_modules/playwright/node_modules/playwright-core/package.json +1 -1
  158. package/node_modules/playwright/node_modules/playwright-core/src/server/codegen/skyramp/jsonlReader.ts +1 -1
  159. package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/recorderRunner.ts +26 -1
  160. package/node_modules/playwright/node_modules/playwright-core/src/utils/isomorphic/elementOrder.ts +83 -0
  161. package/node_modules/playwright/node_modules/playwright-core/src/utils.ts +1 -0
  162. package/node_modules/playwright/package.json +1 -1
  163. package/package.json +9 -6
  164. package/plugin/prompts/plan-tests.md +9 -17
  165. package/plugin/skills/enhance-assertions/reference/shared-rules.md +1 -1
  166. package/plugin/skills/enhance-assertions/reference/ui.md +2 -2
  167. package/plugin/skills/fix-test-import-errors/SKILL.md +1 -1
  168. package/plugin/skills/repair-staged-files/SKILL.md +17 -0
@@ -20,7 +20,7 @@ export var ScenarioSource;
20
20
  ScenarioSource["AgentEnriched"] = "agent-enriched";
21
21
  })(ScenarioSource || (ScenarioSource = {}));
22
22
  // ── Zod schemas ──
23
- export const analysisScopeSchema = z.nativeEnum(AnalysisScope);
23
+ export const analysisScopeSchema = z.enum(AnalysisScope);
24
24
  export const paramInfoSchema = z.object({
25
25
  name: z.string(),
26
26
  type: z.string(),
@@ -40,15 +40,15 @@ export const endpointInteractionSchema = z.object({
40
40
  type: z.enum(["success", "error", "edge-case"]),
41
41
  request: z.object({
42
42
  contentType: z.string().optional(),
43
- body: z.record(z.any()).optional(),
44
- headers: z.record(z.string()).optional(),
45
- queryParams: z.record(z.any()).optional(),
43
+ body: z.record(z.string(), z.any()).optional(),
44
+ headers: z.record(z.string(), z.string()).optional(),
45
+ queryParams: z.record(z.string(), z.any()).optional(),
46
46
  }),
47
47
  response: z.object({
48
48
  statusCode: z.number(),
49
49
  description: z.string(),
50
- body: z.record(z.any()).optional(),
51
- headers: z.record(z.string()).optional(),
50
+ body: z.record(z.string(), z.any()).optional(),
51
+ headers: z.record(z.string(), z.string()).optional(),
52
52
  cookies: z.array(cookieInfoSchema).optional(),
53
53
  }),
54
54
  });
@@ -83,9 +83,11 @@ export const scenarioStepSchema = z.object({
83
83
  path: z.string(),
84
84
  description: z.string(),
85
85
  interactionType: z.enum(["success", "error", "edge-case"]),
86
- requestBody: z.record(z.any()).optional(),
87
- queryParams: z.record(z.any()).optional(),
88
- responseBody: z.union([z.record(z.any()), z.array(z.any())]).optional(),
86
+ requestBody: z.record(z.string(), z.any()).optional(),
87
+ queryParams: z.record(z.string(), z.any()).optional(),
88
+ responseBody: z
89
+ .union([z.record(z.string(), z.any()), z.array(z.any())])
90
+ .optional(),
89
91
  expectedStatusCode: z.number(),
90
92
  expectedResponseFields: z.array(z.string()).optional(),
91
93
  chainsFrom: z
@@ -192,7 +194,7 @@ export const repositoryAnalysisSchema = z.object({
192
194
  contract: z.number(),
193
195
  smoke: z.number(),
194
196
  }),
195
- testLocations: z.record(z.string()),
197
+ testLocations: z.record(z.string(), z.string()),
196
198
  hasCoverageReports: z.boolean(),
197
199
  estimatedCoverage: z.number().optional(),
198
200
  relevantExternalTestPaths: z.array(z.string()).optional(),
@@ -37,4 +37,27 @@ export declare const STEP_METHOD_DESCRIPTION: string;
37
37
  * The field itself: normalised first, then checked, so a rejection is about the
38
38
  * verb and never about its capitalisation.
39
39
  */
40
- export declare const stepMethodSchema: z.ZodEffects<z.ZodEnum<["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "TRACE", "CONNECT", "assert", "click", "drag", "drag-hold", "hover", "inspect", "navigate", "press", "release", "tap", "type", "wait", "OPERATION"]>, "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS" | "type" | "TRACE" | "CONNECT" | "assert" | "click" | "drag" | "drag-hold" | "hover" | "inspect" | "navigate" | "press" | "release" | "tap" | "wait" | "OPERATION", unknown>;
40
+ export declare const stepMethodSchema: z.ZodPreprocess<z.ZodEnum<{
41
+ GET: "GET";
42
+ POST: "POST";
43
+ PUT: "PUT";
44
+ DELETE: "DELETE";
45
+ PATCH: "PATCH";
46
+ HEAD: "HEAD";
47
+ OPTIONS: "OPTIONS";
48
+ type: "type";
49
+ TRACE: "TRACE";
50
+ CONNECT: "CONNECT";
51
+ assert: "assert";
52
+ click: "click";
53
+ drag: "drag";
54
+ "drag-hold": "drag-hold";
55
+ hover: "hover";
56
+ inspect: "inspect";
57
+ navigate: "navigate";
58
+ press: "press";
59
+ release: "release";
60
+ tap: "tap";
61
+ wait: "wait";
62
+ OPERATION: "OPERATION";
63
+ }>, unknown>;
@@ -87,5 +87,5 @@ export const STEP_METHOD_DESCRIPTION = "What this step does to the system: an HT
87
87
  export const stepMethodSchema = z.preprocess((value) => typeof value === "string"
88
88
  ? (normalizeStepMethod(value) ?? value.trim())
89
89
  : value, z.enum(STEP_METHODS, {
90
- errorMap: () => ({ message: `method ${STEP_METHOD_HELP}` }),
90
+ error: () => `method ${STEP_METHOD_HELP}`,
91
91
  }));
@@ -51,28 +51,22 @@ export declare enum RuntimeEnvironment {
51
51
  DOCKER = "docker",
52
52
  KUBERNETES = "k8s"
53
53
  }
54
- export declare const runtimeEnvironmentSchema: z.ZodNativeEnum<typeof RuntimeEnvironment>;
55
- export declare const runtimeEnvironmentInputSchema: z.ZodEffects<z.ZodNativeEnum<typeof RuntimeEnvironment>, RuntimeEnvironment, unknown>;
54
+ export declare const runtimeEnvironmentSchema: z.ZodEnum<typeof RuntimeEnvironment>;
55
+ export declare const runtimeEnvironmentInputSchema: z.ZodPreprocess<z.ZodEnum<typeof RuntimeEnvironment>, unknown>;
56
56
  export declare function normalizeRuntimeEnvironment(value: RuntimeEnvironment | "kubernetes"): RuntimeEnvironment;
57
57
  export interface TestConfig {
58
58
  testType: TestType;
59
59
  toolName: string;
60
60
  description: string;
61
- additionalFields?: Record<string, z.ZodSchema>;
61
+ additionalFields?: Record<string, z.ZodType>;
62
62
  }
63
63
  export declare const languageSchema: z.ZodObject<{
64
- language: z.ZodNativeEnum<typeof ProgrammingLanguage>;
64
+ language: z.ZodEnum<typeof ProgrammingLanguage>;
65
65
  framework: z.ZodString;
66
- }, "strip", z.ZodTypeAny, {
67
- language: ProgrammingLanguage;
68
- framework: string;
69
- }, {
70
- language: ProgrammingLanguage;
71
- framework: string;
72
- }>;
66
+ }, z.core.$strip>;
73
67
  export declare const baseSchema: z.ZodObject<{
74
68
  deployDashboard: z.ZodDefault<z.ZodBoolean>;
75
- runtime: z.ZodDefault<z.ZodEffects<z.ZodNativeEnum<typeof RuntimeEnvironment>, RuntimeEnvironment, unknown>>;
69
+ runtime: z.ZodDefault<z.ZodPreprocess<z.ZodEnum<typeof RuntimeEnvironment>, unknown>>;
76
70
  dockerNetwork: z.ZodDefault<z.ZodString>;
77
71
  dockerWorkerPort: z.ZodDefault<z.ZodNumber>;
78
72
  k8sNamespace: z.ZodDefault<z.ZodString>;
@@ -81,78 +75,35 @@ export declare const baseSchema: z.ZodObject<{
81
75
  authHeader: z.ZodDefault<z.ZodString>;
82
76
  authScheme: z.ZodDefault<z.ZodString>;
83
77
  insecure: z.ZodDefault<z.ZodBoolean>;
84
- output: z.ZodEffects<z.ZodOptional<z.ZodString>, string | undefined, string | undefined>;
78
+ output: z.ZodOptional<z.ZodString>;
85
79
  outputDir: z.ZodString;
86
80
  force: z.ZodDefault<z.ZodBoolean>;
87
81
  mockPort: z.ZodDefault<z.ZodNumber>;
88
82
  optionalFields: z.ZodDefault<z.ZodBoolean>;
89
83
  prompt: z.ZodString;
90
- language: z.ZodNativeEnum<typeof ProgrammingLanguage>;
84
+ language: z.ZodEnum<typeof ProgrammingLanguage>;
91
85
  framework: z.ZodString;
92
- }, "strip", z.ZodTypeAny, {
93
- language: ProgrammingLanguage;
94
- framework: string;
95
- deployDashboard: boolean;
96
- runtime: RuntimeEnvironment;
97
- dockerNetwork: string;
98
- dockerWorkerPort: number;
99
- k8sNamespace: string;
100
- k8sConfig: string;
101
- k8sContext: string;
102
- authHeader: string;
103
- authScheme: string;
104
- insecure: boolean;
105
- outputDir: string;
106
- force: boolean;
107
- mockPort: number;
108
- optionalFields: boolean;
109
- prompt: string;
110
- output?: string | undefined;
111
- }, {
112
- language: ProgrammingLanguage;
113
- framework: string;
114
- outputDir: string;
115
- prompt: string;
116
- deployDashboard?: boolean | undefined;
117
- runtime?: unknown;
118
- dockerNetwork?: string | undefined;
119
- dockerWorkerPort?: number | undefined;
120
- k8sNamespace?: string | undefined;
121
- k8sConfig?: string | undefined;
122
- k8sContext?: string | undefined;
123
- authHeader?: string | undefined;
124
- authScheme?: string | undefined;
125
- insecure?: boolean | undefined;
126
- output?: string | undefined;
127
- force?: boolean | undefined;
128
- mockPort?: number | undefined;
129
- optionalFields?: boolean | undefined;
130
- }>;
86
+ }, z.core.$strip>;
131
87
  export declare const basePlaywrightSchema: z.ZodObject<{
132
88
  playwrightInput: z.ZodString;
133
89
  playwrightStoragePath: z.ZodOptional<z.ZodString>;
134
90
  playwrightSaveStoragePath: z.ZodOptional<z.ZodString>;
135
- playwrightViewportSize: z.ZodDefault<z.ZodUnion<[z.ZodEnum<["", "hd", "full-hd", "2k"]>, z.ZodString]>>;
136
- browser: z.ZodDefault<z.ZodEnum<["chromium", "firefox", "webkit"]>>;
91
+ playwrightViewportSize: z.ZodDefault<z.ZodUnion<readonly [z.ZodEnum<{
92
+ "": "";
93
+ hd: "hd";
94
+ "full-hd": "full-hd";
95
+ "2k": "2k";
96
+ }>, z.ZodString]>>;
97
+ browser: z.ZodDefault<z.ZodEnum<{
98
+ chromium: "chromium";
99
+ firefox: "firefox";
100
+ webkit: "webkit";
101
+ }>>;
137
102
  device: z.ZodDefault<z.ZodString>;
138
- }, "strip", z.ZodTypeAny, {
139
- playwrightInput: string;
140
- playwrightViewportSize: string;
141
- browser: "chromium" | "firefox" | "webkit";
142
- device: string;
143
- playwrightStoragePath?: string | undefined;
144
- playwrightSaveStoragePath?: string | undefined;
145
- }, {
146
- playwrightInput: string;
147
- playwrightStoragePath?: string | undefined;
148
- playwrightSaveStoragePath?: string | undefined;
149
- playwrightViewportSize?: string | undefined;
150
- browser?: "chromium" | "firefox" | "webkit" | undefined;
151
- device?: string | undefined;
152
- }>;
103
+ }, z.core.$strip>;
153
104
  export declare const baseTraceSchema: z.ZodObject<{
154
105
  deployDashboard: z.ZodDefault<z.ZodBoolean>;
155
- runtime: z.ZodDefault<z.ZodEffects<z.ZodNativeEnum<typeof RuntimeEnvironment>, RuntimeEnvironment, unknown>>;
106
+ runtime: z.ZodDefault<z.ZodPreprocess<z.ZodEnum<typeof RuntimeEnvironment>, unknown>>;
156
107
  dockerNetwork: z.ZodDefault<z.ZodString>;
157
108
  dockerWorkerPort: z.ZodDefault<z.ZodNumber>;
158
109
  k8sNamespace: z.ZodDefault<z.ZodString>;
@@ -161,65 +112,21 @@ export declare const baseTraceSchema: z.ZodObject<{
161
112
  authHeader: z.ZodDefault<z.ZodString>;
162
113
  authScheme: z.ZodDefault<z.ZodString>;
163
114
  insecure: z.ZodDefault<z.ZodBoolean>;
164
- output: z.ZodEffects<z.ZodOptional<z.ZodString>, string | undefined, string | undefined>;
115
+ output: z.ZodOptional<z.ZodString>;
165
116
  outputDir: z.ZodString;
166
117
  force: z.ZodDefault<z.ZodBoolean>;
167
118
  mockPort: z.ZodDefault<z.ZodNumber>;
168
119
  optionalFields: z.ZodDefault<z.ZodBoolean>;
169
120
  prompt: z.ZodString;
170
- language: z.ZodNativeEnum<typeof ProgrammingLanguage>;
121
+ language: z.ZodEnum<typeof ProgrammingLanguage>;
171
122
  framework: z.ZodString;
172
123
  trace: z.ZodString;
173
- include: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
174
- exclude: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
175
- }, "strip", z.ZodTypeAny, {
176
- language: ProgrammingLanguage;
177
- framework: string;
178
- deployDashboard: boolean;
179
- runtime: RuntimeEnvironment;
180
- dockerNetwork: string;
181
- dockerWorkerPort: number;
182
- k8sNamespace: string;
183
- k8sConfig: string;
184
- k8sContext: string;
185
- authHeader: string;
186
- authScheme: string;
187
- insecure: boolean;
188
- outputDir: string;
189
- force: boolean;
190
- mockPort: number;
191
- optionalFields: boolean;
192
- prompt: string;
193
- trace: string;
194
- include: string[];
195
- exclude: string[];
196
- output?: string | undefined;
197
- }, {
198
- language: ProgrammingLanguage;
199
- framework: string;
200
- outputDir: string;
201
- prompt: string;
202
- trace: string;
203
- deployDashboard?: boolean | undefined;
204
- runtime?: unknown;
205
- dockerNetwork?: string | undefined;
206
- dockerWorkerPort?: number | undefined;
207
- k8sNamespace?: string | undefined;
208
- k8sConfig?: string | undefined;
209
- k8sContext?: string | undefined;
210
- authHeader?: string | undefined;
211
- authScheme?: string | undefined;
212
- insecure?: boolean | undefined;
213
- output?: string | undefined;
214
- force?: boolean | undefined;
215
- mockPort?: number | undefined;
216
- optionalFields?: boolean | undefined;
217
- include?: string[] | undefined;
218
- exclude?: string[] | undefined;
219
- }>;
124
+ include: z.ZodDefault<z.ZodArray<z.ZodString>>;
125
+ exclude: z.ZodDefault<z.ZodArray<z.ZodString>>;
126
+ }, z.core.$strip>;
220
127
  export declare const baseTestSchema: {
221
128
  deployDashboard: z.ZodDefault<z.ZodBoolean>;
222
- runtime: z.ZodDefault<z.ZodEffects<z.ZodNativeEnum<typeof RuntimeEnvironment>, RuntimeEnvironment, unknown>>;
129
+ runtime: z.ZodDefault<z.ZodPreprocess<z.ZodEnum<typeof RuntimeEnvironment>, unknown>>;
223
130
  dockerNetwork: z.ZodDefault<z.ZodString>;
224
131
  dockerWorkerPort: z.ZodDefault<z.ZodNumber>;
225
132
  k8sNamespace: z.ZodDefault<z.ZodString>;
@@ -228,33 +135,34 @@ export declare const baseTestSchema: {
228
135
  authHeader: z.ZodDefault<z.ZodString>;
229
136
  authScheme: z.ZodDefault<z.ZodString>;
230
137
  insecure: z.ZodDefault<z.ZodBoolean>;
231
- output: z.ZodEffects<z.ZodOptional<z.ZodString>, string | undefined, string | undefined>;
138
+ output: z.ZodOptional<z.ZodString>;
232
139
  outputDir: z.ZodString;
233
140
  force: z.ZodDefault<z.ZodBoolean>;
234
141
  mockPort: z.ZodDefault<z.ZodNumber>;
235
142
  optionalFields: z.ZodDefault<z.ZodBoolean>;
236
143
  prompt: z.ZodString;
237
- language: z.ZodNativeEnum<typeof ProgrammingLanguage>;
144
+ language: z.ZodEnum<typeof ProgrammingLanguage>;
238
145
  framework: z.ZodString;
239
146
  endpointURL: z.ZodString;
240
- method: z.ZodDefault<z.ZodUnion<[z.ZodNativeEnum<typeof HttpMethod>, z.ZodLiteral<"">]>>;
147
+ method: z.ZodDefault<z.ZodUnion<readonly [z.ZodEnum<typeof HttpMethod>, z.ZodLiteral<"">]>>;
241
148
  apiSchema: z.ZodDefault<z.ZodString>;
242
149
  pathParams: z.ZodDefault<z.ZodString>;
243
150
  queryParams: z.ZodDefault<z.ZodString>;
244
151
  formParams: z.ZodDefault<z.ZodString>;
245
- requestData: z.ZodEffects<z.ZodDefault<z.ZodString>, string, string | undefined>;
246
- responseStatusCode: z.ZodEffects<z.ZodDefault<z.ZodString>, string, string | undefined>;
152
+ requestData: z.ZodDefault<z.ZodString>;
153
+ responseStatusCode: z.ZodDefault<z.ZodString>;
247
154
  };
248
155
  export declare const codeRefactoringSchema: z.ZodObject<{
249
156
  codeReuse: z.ZodDefault<z.ZodBoolean>;
250
157
  modularizeCode: z.ZodDefault<z.ZodBoolean>;
251
- }, "strip", z.ZodTypeAny, {
252
- codeReuse: boolean;
253
- modularizeCode: boolean;
254
- }, {
255
- codeReuse?: boolean | undefined;
256
- modularizeCode?: boolean | undefined;
257
- }>;
158
+ }, z.core.$strip>;
159
+ /** The `testName` field for a recording-driven generation tool.
160
+ *
161
+ * Single-sourced because the description is prompt text: it is the only thing
162
+ * steering the agent's choice of title, it gets re-tuned against eval results,
163
+ * and two copies would let the UI and E2E tools drift apart silently. Each
164
+ * tool passes the title its own generator falls back to (SKYR-4468). */
165
+ export declare const testNameField: (fallbackTitle: string) => z.ZodOptional<z.ZodString>;
258
166
  /** Test types skyramp_enhance_assertions supports — single-sourced so the
259
167
  * tool's schema enum and generation-time baseline seeding cannot drift
260
168
  * (contract additionally requires provider mode at the seeding site). */
@@ -64,14 +64,14 @@ export var RuntimeEnvironment;
64
64
  RuntimeEnvironment["DOCKER"] = "docker";
65
65
  RuntimeEnvironment["KUBERNETES"] = "k8s";
66
66
  })(RuntimeEnvironment || (RuntimeEnvironment = {}));
67
- export const runtimeEnvironmentSchema = z.nativeEnum(RuntimeEnvironment);
67
+ export const runtimeEnvironmentSchema = z.enum(RuntimeEnvironment);
68
68
  export const runtimeEnvironmentInputSchema = z.preprocess((value) => (value === "kubernetes" ? RuntimeEnvironment.KUBERNETES : value), runtimeEnvironmentSchema);
69
69
  export function normalizeRuntimeEnvironment(value) {
70
70
  return value === "kubernetes" ? RuntimeEnvironment.KUBERNETES : value;
71
71
  }
72
72
  export const languageSchema = z.object({
73
73
  language: z
74
- .nativeEnum(ProgrammingLanguage)
74
+ .enum(ProgrammingLanguage)
75
75
  .describe("Programming language for the generated test (default: python). Must be one of: python, typescript, javascript, java"),
76
76
  framework: z
77
77
  .string()
@@ -217,7 +217,7 @@ export const baseTestSchema = {
217
217
  "(e.g., https://demoshop.skyramp.dev/api/v1/products). " +
218
218
  "MUST include both the base URL and the endpoint path — never just the base URL alone."),
219
219
  method: z
220
- .union([z.nativeEnum(HttpMethod), z.literal("")])
220
+ .union([z.enum(HttpMethod), z.literal("")])
221
221
  .default("")
222
222
  .describe('HTTP method to use. DEFAULT: Use empty string ("") to test ALL available methods from OpenAPI schema (recommended). Only specify a specific method (GET, POST, PUT, DELETE, etc.) if user explicitly requests testing a single method only.'),
223
223
  apiSchema: z
@@ -291,6 +291,28 @@ export const codeRefactoringSchema = z.object({
291
291
  .default(false)
292
292
  .describe("Whether to modularize the code"),
293
293
  });
294
+ /** The `testName` field for a recording-driven generation tool.
295
+ *
296
+ * Single-sourced because the description is prompt text: it is the only thing
297
+ * steering the agent's choice of title, it gets re-tuned against eval results,
298
+ * and two copies would let the UI and E2E tools drift apart silently. Each
299
+ * tool passes the title its own generator falls back to (SKYR-4468). */
300
+ export const testNameField = (fallbackTitle) => z
301
+ .string()
302
+ // .trim() normalises incidental whitespace and, combined with .min(1),
303
+ // rejects a whitespace-only title, which would otherwise produce a
304
+ // meaningless test title and identifier (SKYR-4468).
305
+ .trim()
306
+ .min(1)
307
+ .optional()
308
+ .describe("Title for the generated test. Name the BEHAVIOUR this recording verifies, " +
309
+ "taken from the recommendation the recording came from — not the page it happens on. " +
310
+ "Keep it to one short phrase, under about 60 characters. " +
311
+ 'Example: "Add to cart from search results", not "Search page". ' +
312
+ "Skyramp emits it verbatim as the Playwright test title for TypeScript/JavaScript. " +
313
+ "Python and Java get it as a comment above the test, and a function name built from " +
314
+ "its ASCII words and cut at 80 characters. " +
315
+ `Omit it and the test stays titled \`${fallbackTitle}\`, which claims nothing.`);
294
316
  /** Test types skyramp_enhance_assertions supports — single-sourced so the
295
317
  * tool's schema enum and generation-time baseline seeding cannot drift
296
318
  * (contract additionally requires provider mode at the seeding site). */
@@ -227,7 +227,10 @@ export interface TestbotReport {
227
227
  /** Files an UPDATE or REGENERATE verdict edited, minus any already counted as
228
228
  * generated — one file owes one run however it was written. */
229
229
  updated: number;
230
- /** How many of those `generated + updated` files were passed to
230
+ /** Files a VERIFY verdict names in the primary repository, minus any already
231
+ * counted above. Never edited, but each owes one run. */
232
+ verified: number;
233
+ /** How many of those `generated + updated + verified` files were passed to
231
234
  * skyramp_execute_test. The file reached the runner; that is not proof a test
232
235
  * ran, because a runner can exit 0 having executed nothing. */
233
236
  executed: number;
@@ -197,6 +197,18 @@ function expectSites(raw, stripped) {
197
197
  matcher = link[1];
198
198
  break;
199
199
  }
200
+ // `expect(async () => { ... }).toPass()` is a retry wrapper, not an
201
+ // assertion: the assertions are the expect() calls inside it. Record none
202
+ // for the wrapper and resume scanning inside its argument, so the inner
203
+ // ones are scored for what they check (the generated order assertion
204
+ // compares boundingBox() geometry inside toPass()).
205
+ // `.not.toPass()` inverts the block (it must keep failing), so its inner
206
+ // assertions are not positive checks: it falls through to ordinary wrapper
207
+ // scoring (weight 1). Python's Playwright has no to_pass equivalent.
208
+ if (matcher === "toPass" && !links.includes("not")) {
209
+ re.lastIndex = openIdx + 1;
210
+ continue;
211
+ }
200
212
  let matcherArgs;
201
213
  if (matcher !== undefined) {
202
214
  const matcherOpen = /^\s*\(/.exec(stripped.slice(cursor));
@@ -1,15 +1,37 @@
1
+ /**
2
+ * Whether a pull failed because the image has nothing for the requested platform. The
3
+ * wording depends on the daemon and its image store: a Windows daemon answers a linux-only
4
+ * image, even a multi-platform one, with "image operating system ... cannot be used on this
5
+ * platform" (observed on Windows Server 2022, Docker 29.7.2); a manifest list without the
6
+ * platform gives "no matching manifest"; the containerd image store says "no match for
7
+ * platform in manifest". Anything else -- the network, a rate limit, a full disk -- is not
8
+ * this.
9
+ */
10
+ export declare function isPlatformUnavailableError(err: unknown): boolean;
11
+ /**
12
+ * Returns the Docker platform string for the current host architecture.
13
+ * Mirrors the backend's getDockerPlatform() in cmd/libs/init.go.
14
+ */
15
+ export declare function getDockerPlatform(): string;
1
16
  /**
2
17
  * Pull a Docker image by name.
3
18
  *
4
- * When `dockerPlatform` is provided, pulls with that exact platform — no
5
- * fallback logic runs. Use this for images whose platform is known ahead
6
- * of time (e.g. executor is amd64-only).
7
- *
8
- * When `dockerPlatform` is omitted, uses the host architecture and falls
9
- * back to linux/amd64 if the arm64 pull fails or the image doesn't land
10
- * locally (Docker Desktop quirk on Apple Silicon).
19
+ * `dockerPlatform` defaults to the host architecture. Whether given or
20
+ * defaulted, a `linux/arm64` pull falls back to `linux/amd64` when the arm64
21
+ * pull reports no matching manifest or completes without the image landing
22
+ * locally (Docker Desktop quirk on Apple Silicon). Any other platform is
23
+ * pulled exactly, with no fallback.
11
24
  */
12
25
  export declare function pullDockerImage(imageName: string, dockerPlatform?: string): Promise<void>;
26
+ /**
27
+ * The default daemon's operating system ("windows" or "linux"), or undefined when it
28
+ * cannot be determined. The startup prefetch pulls each image for this OS; when it is
29
+ * undefined the executor is pulled as linux/amd64 and the worker for the host's own
30
+ * architecture (getDockerPlatform). Guessing is acceptable there because the prefetch is
31
+ * best-effort: a wrong guess costs a download, and the run itself refuses to guess
32
+ * (resolvePlatform in FleetExecutionService).
33
+ */
34
+ export declare function dockerDaemonOsType(): Promise<string | undefined>;
13
35
  /**
14
36
  * Check if a Docker image exists locally for the given reference (repo:tag or digest).
15
37
  * Uses image inspect (daemon name resolution), not listImages tag scanning.
@@ -26,11 +26,26 @@ function isManifestMismatchError(err) {
26
26
  const msg = err?.message ?? "";
27
27
  return msg.includes("no matching manifest");
28
28
  }
29
+ /**
30
+ * Whether a pull failed because the image has nothing for the requested platform. The
31
+ * wording depends on the daemon and its image store: a Windows daemon answers a linux-only
32
+ * image, even a multi-platform one, with "image operating system ... cannot be used on this
33
+ * platform" (observed on Windows Server 2022, Docker 29.7.2); a manifest list without the
34
+ * platform gives "no matching manifest"; the containerd image store says "no match for
35
+ * platform in manifest". Anything else -- the network, a rate limit, a full disk -- is not
36
+ * this.
37
+ */
38
+ export function isPlatformUnavailableError(err) {
39
+ const msg = err?.message ?? "";
40
+ return (msg.includes("no matching manifest") ||
41
+ msg.includes("cannot be used on this platform") ||
42
+ msg.includes("no match for platform in manifest"));
43
+ }
29
44
  /**
30
45
  * Returns the Docker platform string for the current host architecture.
31
46
  * Mirrors the backend's getDockerPlatform() in cmd/libs/init.go.
32
47
  */
33
- function getDockerPlatform() {
48
+ export function getDockerPlatform() {
34
49
  return process.arch === "arm64" ? "linux/arm64" : "linux/amd64";
35
50
  }
36
51
  async function doPull(docker, imageName, platform) {
@@ -40,14 +55,27 @@ async function doPull(docker, imageName, platform) {
40
55
  return reject(err);
41
56
  if (!stream)
42
57
  return reject(new Error("No stream received from docker pull"));
58
+ // A pull can fail INSIDE the progress stream: followProgress still finishes
59
+ // without an error object, and the failure appears only as an `error` field on
60
+ // one of the messages. Without reading them, a pull that stored nothing is
61
+ // logged as a success. The Go side guards the same thing (`message.Error` in
62
+ // RunSkyrampWorker).
63
+ let streamError;
43
64
  docker.modem.followProgress(stream, (err) => {
44
65
  if (err)
45
66
  return reject(err);
67
+ if (streamError) {
68
+ return reject(new Error(`docker pull ${imageName} (${platform}) failed: ${streamError}`));
69
+ }
46
70
  logger.info("Docker image pulled successfully", {
47
71
  image: imageName,
48
72
  platform,
49
73
  });
50
74
  resolve();
75
+ }, (msg) => {
76
+ if (msg?.error && streamError === undefined) {
77
+ streamError = msg.errorDetail?.message ?? msg.error;
78
+ }
51
79
  });
52
80
  });
53
81
  });
@@ -55,39 +83,67 @@ async function doPull(docker, imageName, platform) {
55
83
  /**
56
84
  * Pull a Docker image by name.
57
85
  *
58
- * When `dockerPlatform` is provided, pulls with that exact platform — no
59
- * fallback logic runs. Use this for images whose platform is known ahead
60
- * of time (e.g. executor is amd64-only).
61
- *
62
- * When `dockerPlatform` is omitted, uses the host architecture and falls
63
- * back to linux/amd64 if the arm64 pull fails or the image doesn't land
64
- * locally (Docker Desktop quirk on Apple Silicon).
86
+ * `dockerPlatform` defaults to the host architecture. Whether given or
87
+ * defaulted, a `linux/arm64` pull falls back to `linux/amd64` when the arm64
88
+ * pull reports no matching manifest or completes without the image landing
89
+ * locally (Docker Desktop quirk on Apple Silicon). Any other platform is
90
+ * pulled exactly, with no fallback.
65
91
  */
66
92
  export async function pullDockerImage(imageName, dockerPlatform) {
67
93
  const client = new Dockerode();
68
- if (dockerPlatform) {
69
- await doPull(client, imageName, dockerPlatform);
70
- return;
94
+ const platform = dockerPlatform ?? getDockerPlatform();
95
+ // Docker Desktop on Apple Silicon serves amd64-only images under emulation, but an arm64
96
+ // pull of one either reports no matching manifest or completes and stores nothing. Those
97
+ // are the same rule, not two special cases: try these platforms in order until one
98
+ // actually lands.
99
+ const candidates = platform === "linux/arm64" ? [platform, "linux/amd64"] : [platform];
100
+ for (let i = 0; i < candidates.length; i++) {
101
+ const candidate = candidates[i];
102
+ const next = candidates[i + 1];
103
+ try {
104
+ await doPull(client, imageName, candidate);
105
+ }
106
+ catch (err) {
107
+ // A manifest mismatch is the one failure another platform can answer.
108
+ if (next === undefined || !isManifestMismatchError(err))
109
+ throw err;
110
+ logger.info("pull failed, retrying on the next platform", {
111
+ image: imageName,
112
+ failed: candidate,
113
+ next,
114
+ });
115
+ continue;
116
+ }
117
+ // A pull can end its stream cleanly and store nothing, so success is the image being
118
+ // present -- not the pull returning.
119
+ if (await dockerImageExistsLocally(imageName))
120
+ return;
121
+ if (next === undefined)
122
+ break;
123
+ logger.info("pull completed but the image is absent, retrying on the next platform", {
124
+ image: imageName,
125
+ failed: candidate,
126
+ next,
127
+ });
71
128
  }
72
- const platform = getDockerPlatform();
129
+ throw new Error(`docker pull ${imageName} (${candidates.join(", ")}) reported success but the image is not present locally`);
130
+ }
131
+ /**
132
+ * The default daemon's operating system ("windows" or "linux"), or undefined when it
133
+ * cannot be determined. The startup prefetch pulls each image for this OS; when it is
134
+ * undefined the executor is pulled as linux/amd64 and the worker for the host's own
135
+ * architecture (getDockerPlatform). Guessing is acceptable there because the prefetch is
136
+ * best-effort: a wrong guess costs a download, and the run itself refuses to guess
137
+ * (resolvePlatform in FleetExecutionService).
138
+ */
139
+ export async function dockerDaemonOsType() {
73
140
  try {
74
- await doPull(client, imageName, platform);
141
+ const info = (await new Dockerode().info());
142
+ return info?.OSType;
75
143
  }
76
144
  catch (err) {
77
- if (platform === "linux/arm64" && isManifestMismatchError(err)) {
78
- logger.info("arm64 pull failed, retrying with linux/amd64 (emulation on Apple Silicon)", { image: imageName });
79
- await doPull(client, imageName, "linux/amd64");
80
- return;
81
- }
82
- throw err;
83
- }
84
- // On Docker Desktop/Mac, pulling an amd64-only image with linux/arm64 can
85
- // complete the stream without error yet not store the image locally.
86
- // Verify it actually landed, and fall back to amd64 if not.
87
- if (platform === "linux/arm64" &&
88
- !(await dockerImageExistsLocally(imageName))) {
89
- logger.info("arm64 pull completed but image not found locally, retrying with linux/amd64", { image: imageName });
90
- await doPull(client, imageName, "linux/amd64");
145
+ logger.warning("Could not determine the Docker daemon OS", { error: err });
146
+ return undefined;
91
147
  }
92
148
  }
93
149
  /**
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The first `<dir>/<candidate>` that exists, checking `from` and then each
3
+ * ancestor, or undefined.
4
+ *
5
+ * With `stopAtRepoRoot`, only the directories up to the nearest one holding
6
+ * `.git` (a directory or a file, so worktrees count) are searched, and a `from`
7
+ * outside any checkout searches nothing: a parent directory is not the
8
+ * repository's to answer for. The walk never passes the filesystem root or
9
+ * MAX_LEVELS.
10
+ */
11
+ export declare function findUp(from: string, candidates: readonly string[], { stopAtRepoRoot }?: {
12
+ stopAtRepoRoot?: boolean;
13
+ }): string | undefined;
14
+ /** The package's manifest as Node would find it from `from`: the nearest
15
+ * `node_modules/<pkg>/package.json` walking UP from there. Node's own lookup
16
+ * never reads NODE_PATH for this, and neither does this one. A manifest that
17
+ * does not parse is logged and treated as absent. */
18
+ export declare function installedManifest(pkg: string, from: string, options?: {
19
+ stopAtRepoRoot?: boolean;
20
+ }): Record<string, unknown> | undefined;