@vibecheckai/cli 3.9.0 → 4.0.0

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 (88) hide show
  1. package/README.md +1 -1
  2. package/bin/runners/context/generators/cursor-enhanced.js +99 -13
  3. package/bin/runners/lib/unified-cli-output.js +16 -0
  4. package/bin/runners/runCI.js +353 -0
  5. package/bin/runners/runCheckpoint.js +2 -2
  6. package/mcp-server/.eslintrc.json +24 -0
  7. package/mcp-server/README.md +425 -135
  8. package/mcp-server/SPEC.md +583 -0
  9. package/mcp-server/configs/README.md +172 -0
  10. package/mcp-server/configs/claude-desktop-pro.json +31 -0
  11. package/mcp-server/configs/claude-desktop-with-workspace.json +25 -0
  12. package/mcp-server/configs/claude-desktop.json +19 -0
  13. package/mcp-server/configs/cursor-mcp.json +21 -0
  14. package/mcp-server/configs/windsurf-mcp.json +17 -0
  15. package/mcp-server/mcp-config.example.json +9 -0
  16. package/mcp-server/package.json +49 -34
  17. package/mcp-server/src/cli.ts +185 -0
  18. package/mcp-server/src/index.ts +85 -0
  19. package/mcp-server/src/server.ts +1933 -0
  20. package/mcp-server/src/services/cache-service.ts +466 -0
  21. package/mcp-server/src/services/cli-service.ts +345 -0
  22. package/mcp-server/src/services/context-manager.ts +717 -0
  23. package/mcp-server/src/services/firewall-service.ts +662 -0
  24. package/mcp-server/src/services/git-service.ts +671 -0
  25. package/mcp-server/src/services/index.ts +52 -0
  26. package/mcp-server/src/services/prompt-builder-service.ts +1031 -0
  27. package/mcp-server/src/services/session-service.ts +550 -0
  28. package/mcp-server/src/services/tier-service.ts +470 -0
  29. package/mcp-server/src/types.ts +351 -0
  30. package/mcp-server/tsconfig.json +16 -27
  31. package/package.json +6 -6
  32. package/mcp-server/.guardrail/audit/audit.log.jsonl +0 -2
  33. package/mcp-server/.specs/architecture.mdc +0 -90
  34. package/mcp-server/.specs/security.mdc +0 -30
  35. package/mcp-server/HARDENING_SUMMARY.md +0 -299
  36. package/mcp-server/agent-checkpoint.js +0 -364
  37. package/mcp-server/agent-firewall-interceptor.js +0 -500
  38. package/mcp-server/architect-tools.js +0 -707
  39. package/mcp-server/audit-mcp.js +0 -206
  40. package/mcp-server/authority-tools.js +0 -569
  41. package/mcp-server/codebase-architect-tools.js +0 -838
  42. package/mcp-server/conductor/conflict-resolver.js +0 -588
  43. package/mcp-server/conductor/execution-planner.js +0 -544
  44. package/mcp-server/conductor/index.js +0 -377
  45. package/mcp-server/conductor/lock-manager.js +0 -615
  46. package/mcp-server/conductor/request-queue.js +0 -550
  47. package/mcp-server/conductor/session-manager.js +0 -500
  48. package/mcp-server/conductor/tools.js +0 -510
  49. package/mcp-server/consolidated-tools.js +0 -1170
  50. package/mcp-server/deprecation-middleware.js +0 -282
  51. package/mcp-server/handlers/index.ts +0 -15
  52. package/mcp-server/handlers/tool-handler.ts +0 -593
  53. package/mcp-server/hygiene-tools.js +0 -428
  54. package/mcp-server/index-v1.js +0 -698
  55. package/mcp-server/index.js +0 -2940
  56. package/mcp-server/intelligence-tools.js +0 -664
  57. package/mcp-server/intent-drift-tools.js +0 -873
  58. package/mcp-server/intent-firewall-interceptor.js +0 -529
  59. package/mcp-server/lib/api-client.cjs +0 -13
  60. package/mcp-server/lib/cache-wrapper.cjs +0 -383
  61. package/mcp-server/lib/error-envelope.js +0 -138
  62. package/mcp-server/lib/executor.ts +0 -499
  63. package/mcp-server/lib/index.ts +0 -29
  64. package/mcp-server/lib/logger.cjs +0 -30
  65. package/mcp-server/lib/rate-limiter.js +0 -166
  66. package/mcp-server/lib/sandbox.test.ts +0 -519
  67. package/mcp-server/lib/sandbox.ts +0 -395
  68. package/mcp-server/lib/types.ts +0 -267
  69. package/mcp-server/logger.js +0 -173
  70. package/mcp-server/manifest.json +0 -473
  71. package/mcp-server/mdc-generator.js +0 -298
  72. package/mcp-server/premium-tools.js +0 -1275
  73. package/mcp-server/proof-tools.js +0 -571
  74. package/mcp-server/registry/tool-registry.js +0 -586
  75. package/mcp-server/registry/tools.json +0 -619
  76. package/mcp-server/registry.test.ts +0 -340
  77. package/mcp-server/test-mcp.js +0 -108
  78. package/mcp-server/test-tools.js +0 -36
  79. package/mcp-server/tests/tier-gating.test.js +0 -297
  80. package/mcp-server/tier-auth.js +0 -767
  81. package/mcp-server/tools/index.js +0 -72
  82. package/mcp-server/tools-reorganized.ts +0 -244
  83. package/mcp-server/tools-v3.js +0 -1004
  84. package/mcp-server/truth-context.js +0 -622
  85. package/mcp-server/truth-firewall-tools.js +0 -2183
  86. package/mcp-server/vibecheck-2.0-tools.js +0 -761
  87. package/mcp-server/vibecheck-mcp-server-3.2.0.tgz +0 -0
  88. package/mcp-server/vibecheck-tools.js +0 -1075
@@ -1,395 +0,0 @@
1
- /**
2
- * Sandbox - Path Security for MCP Server
3
- *
4
- * Enforces that all tool requests resolve within an allowed workspace root.
5
- * Prevents path traversal attacks, absolute path escapes, and symlink escapes.
6
- *
7
- * @module mcp-server/lib/sandbox
8
- */
9
-
10
- import * as path from 'node:path';
11
- import * as fs from 'node:fs';
12
-
13
- /**
14
- * Default excluded directory patterns.
15
- * These are enforced at the MCP level even if CLI forgets.
16
- */
17
- export const DEFAULT_EXCLUSIONS = [
18
- 'node_modules/**',
19
- 'venv/**',
20
- '.venv/**',
21
- 'dist/**',
22
- 'build/**',
23
- '.next/**',
24
- 'out/**',
25
- 'coverage/**',
26
- '.git/**',
27
- '.cache/**',
28
- '.turbo/**',
29
- ] as const;
30
-
31
- /**
32
- * Third-party directories (can be included via config)
33
- */
34
- export const THIRD_PARTY_DIRS = ['node_modules/**', 'venv/**', '.venv/**'] as const;
35
-
36
- /**
37
- * Generated/build directories (can be included via config)
38
- */
39
- export const GENERATED_DIRS = ['dist/**', 'build/**', '.next/**', 'out/**'] as const;
40
-
41
- /**
42
- * Configuration options for sandbox path resolution
43
- */
44
- export interface SandboxConfig {
45
- /** Workspace root directory (absolute path) */
46
- workspaceRoot: string;
47
- /** Include third-party directories (node_modules, venv, etc.) */
48
- includeThirdParty?: boolean;
49
- /** Include generated/build directories (dist, build, .next, out) */
50
- includeGenerated?: boolean;
51
- /** Additional paths to exclude (glob patterns) */
52
- additionalExclusions?: string[];
53
- /** Paths to explicitly allow (overrides exclusions) */
54
- allowlist?: string[];
55
- }
56
-
57
- /**
58
- * Result of a sandbox path validation
59
- */
60
- export interface SandboxResult {
61
- /** Whether the path is valid and safe */
62
- valid: boolean;
63
- /** The resolved absolute path (if valid) */
64
- resolvedPath?: string;
65
- /** Error message (if invalid) */
66
- error?: string;
67
- /** Error code for programmatic handling */
68
- errorCode?:
69
- | 'TRAVERSAL_DETECTED'
70
- | 'ABSOLUTE_PATH_OUTSIDE_ROOT'
71
- | 'SYMLINK_ESCAPE'
72
- | 'EXCLUDED_PATH'
73
- | 'INVALID_ROOT';
74
- }
75
-
76
- /**
77
- * Checks if a path matches any of the given glob patterns.
78
- * Simple glob matching supporting ** and * wildcards.
79
- */
80
- function matchesGlob(filePath: string, patterns: readonly string[]): boolean {
81
- const normalizedPath = filePath.replace(/\\/g, '/');
82
-
83
- for (const pattern of patterns) {
84
- const normalizedPattern = pattern.replace(/\\/g, '/');
85
-
86
- // Convert glob pattern to regex
87
- const regexPattern = normalizedPattern
88
- .replace(/\*\*/g, '<<<GLOBSTAR>>>')
89
- .replace(/\*/g, '[^/]*')
90
- .replace(/<<<GLOBSTAR>>>/g, '.*')
91
- .replace(/\//g, '\\/');
92
-
93
- const regex = new RegExp(`^${regexPattern}$|^${regexPattern}\\/|\\/${regexPattern}$|\\/${regexPattern}\\/`);
94
-
95
- if (regex.test(normalizedPath)) {
96
- return true;
97
- }
98
-
99
- // Also check if the path starts with the pattern's directory
100
- const patternDir = normalizedPattern.replace(/\/?\*\*.*$/, '');
101
- if (patternDir && normalizedPath.startsWith(patternDir + '/')) {
102
- return true;
103
- }
104
- if (patternDir && normalizedPath === patternDir) {
105
- return true;
106
- }
107
- }
108
-
109
- return false;
110
- }
111
-
112
- /**
113
- * Detects path traversal attempts (../ sequences)
114
- */
115
- function hasTraversalSequence(inputPath: string): boolean {
116
- const normalized = inputPath.replace(/\\/g, '/');
117
-
118
- // Check for .. sequences
119
- if (normalized.includes('..')) {
120
- return true;
121
- }
122
-
123
- // Check for URL-encoded traversal
124
- if (normalized.includes('%2e%2e') || normalized.includes('%2E%2E')) {
125
- return true;
126
- }
127
-
128
- // Check for null byte injection
129
- if (normalized.includes('\0') || normalized.includes('%00')) {
130
- return true;
131
- }
132
-
133
- return false;
134
- }
135
-
136
- /**
137
- * Checks if a path is an absolute path
138
- */
139
- function isAbsolutePath(inputPath: string): boolean {
140
- // Windows absolute paths: C:\, D:\, etc.
141
- if (/^[a-zA-Z]:[/\\]/.test(inputPath)) {
142
- return true;
143
- }
144
-
145
- // Unix absolute paths: /
146
- if (inputPath.startsWith('/')) {
147
- return true;
148
- }
149
-
150
- // UNC paths: \\server\share
151
- if (inputPath.startsWith('\\\\')) {
152
- return true;
153
- }
154
-
155
- return false;
156
- }
157
-
158
- /**
159
- * Gets the active exclusion patterns based on config
160
- */
161
- export function getActiveExclusions(config: SandboxConfig): string[] {
162
- const exclusions: string[] = [];
163
-
164
- // Start with defaults that are always excluded
165
- exclusions.push('coverage/**', '.git/**', '.cache/**', '.turbo/**');
166
-
167
- // Add third-party dirs unless explicitly included
168
- if (!config.includeThirdParty) {
169
- exclusions.push(...THIRD_PARTY_DIRS);
170
- }
171
-
172
- // Add generated dirs unless explicitly included
173
- if (!config.includeGenerated) {
174
- exclusions.push(...GENERATED_DIRS);
175
- }
176
-
177
- // Add any additional exclusions
178
- if (config.additionalExclusions) {
179
- exclusions.push(...config.additionalExclusions);
180
- }
181
-
182
- return exclusions;
183
- }
184
-
185
- /**
186
- * Validates and resolves a path within the sandbox.
187
- *
188
- * @param inputPath - The path to validate (can be relative or absolute)
189
- * @param config - Sandbox configuration
190
- * @returns SandboxResult with validation status and resolved path
191
- */
192
- export function resolveSandboxPath(inputPath: string, config: SandboxConfig): SandboxResult {
193
- // Validate workspace root exists and is absolute
194
- if (!config.workspaceRoot || !isAbsolutePath(config.workspaceRoot)) {
195
- return {
196
- valid: false,
197
- error: 'Invalid workspace root: must be an absolute path',
198
- errorCode: 'INVALID_ROOT',
199
- };
200
- }
201
-
202
- // Normalize workspace root
203
- const normalizedRoot = path.resolve(config.workspaceRoot);
204
-
205
- // Check for traversal sequences in the input
206
- if (hasTraversalSequence(inputPath)) {
207
- return {
208
- valid: false,
209
- error: `Path traversal detected in: ${inputPath}`,
210
- errorCode: 'TRAVERSAL_DETECTED',
211
- };
212
- }
213
-
214
- // Determine the target path
215
- let targetPath: string;
216
-
217
- if (isAbsolutePath(inputPath)) {
218
- // Absolute path - check if it's within root
219
- targetPath = path.resolve(inputPath);
220
- } else {
221
- // Relative path - resolve from workspace root
222
- targetPath = path.resolve(normalizedRoot, inputPath);
223
- }
224
-
225
- // Normalize both paths for comparison
226
- const normalizedTarget = path.normalize(targetPath);
227
- const normalizedRootWithSep = normalizedRoot.endsWith(path.sep)
228
- ? normalizedRoot
229
- : normalizedRoot + path.sep;
230
-
231
- // Check if target is within workspace root
232
- if (!normalizedTarget.startsWith(normalizedRootWithSep) && normalizedTarget !== normalizedRoot) {
233
- return {
234
- valid: false,
235
- error: `Path escapes workspace root: ${inputPath}`,
236
- errorCode: 'ABSOLUTE_PATH_OUTSIDE_ROOT',
237
- };
238
- }
239
-
240
- // Check for symlink escape (if the path exists)
241
- try {
242
- if (fs.existsSync(targetPath)) {
243
- const realPath = fs.realpathSync(targetPath);
244
- const normalizedRealPath = path.normalize(realPath);
245
-
246
- if (
247
- !normalizedRealPath.startsWith(normalizedRootWithSep) &&
248
- normalizedRealPath !== normalizedRoot
249
- ) {
250
- return {
251
- valid: false,
252
- error: `Symlink escape detected: ${inputPath} resolves to ${realPath}`,
253
- errorCode: 'SYMLINK_ESCAPE',
254
- };
255
- }
256
- }
257
- } catch {
258
- // If we can't check realpath, allow it (file may not exist yet)
259
- }
260
-
261
- // Get relative path for exclusion checking
262
- const relativePath = path.relative(normalizedRoot, normalizedTarget);
263
-
264
- // Check against allowlist first (allowlist overrides exclusions)
265
- if (config.allowlist && matchesGlob(relativePath, config.allowlist)) {
266
- return {
267
- valid: true,
268
- resolvedPath: normalizedTarget,
269
- };
270
- }
271
-
272
- // Check against exclusions
273
- const activeExclusions = getActiveExclusions(config);
274
- if (matchesGlob(relativePath, activeExclusions)) {
275
- return {
276
- valid: false,
277
- error: `Path is excluded: ${relativePath}`,
278
- errorCode: 'EXCLUDED_PATH',
279
- };
280
- }
281
-
282
- return {
283
- valid: true,
284
- resolvedPath: normalizedTarget,
285
- };
286
- }
287
-
288
- /**
289
- * Validates multiple paths at once.
290
- *
291
- * @param inputPaths - Array of paths to validate
292
- * @param config - Sandbox configuration
293
- * @returns Object with overall validity and individual results
294
- */
295
- export function validateSandboxPaths(
296
- inputPaths: string[],
297
- config: SandboxConfig
298
- ): {
299
- valid: boolean;
300
- results: Map<string, SandboxResult>;
301
- errors: string[];
302
- } {
303
- const results = new Map<string, SandboxResult>();
304
- const errors: string[] = [];
305
-
306
- for (const inputPath of inputPaths) {
307
- const result = resolveSandboxPath(inputPath, config);
308
- results.set(inputPath, result);
309
-
310
- if (!result.valid && result.error) {
311
- errors.push(result.error);
312
- }
313
- }
314
-
315
- return {
316
- valid: errors.length === 0,
317
- results,
318
- errors,
319
- };
320
- }
321
-
322
- /**
323
- * Creates a sandbox-safe path resolver bound to a specific config.
324
- * Useful for creating a resolver that can be reused multiple times.
325
- *
326
- * @param config - Sandbox configuration
327
- * @returns A function that resolves paths within the sandbox
328
- */
329
- export function createSandboxResolver(config: SandboxConfig) {
330
- return (inputPath: string): SandboxResult => {
331
- return resolveSandboxPath(inputPath, config);
332
- };
333
- }
334
-
335
- /**
336
- * RunRequest interface for config overrides.
337
- * This matches the expected interface from tool requests.
338
- */
339
- export interface RunRequest {
340
- /** Path to resolve */
341
- path?: string;
342
- /** Paths to resolve */
343
- paths?: string[];
344
- /** Project path / workspace root */
345
- projectPath?: string;
346
- /** Include third-party directories (node_modules, venv) */
347
- includeThirdParty?: boolean;
348
- /** Include generated directories (dist, build, .next) */
349
- includeGenerated?: boolean;
350
- }
351
-
352
- /**
353
- * Creates a SandboxConfig from a RunRequest.
354
- *
355
- * @param request - The run request with optional overrides
356
- * @param defaultRoot - Default workspace root if not in request
357
- * @returns SandboxConfig ready for use
358
- */
359
- export function configFromRunRequest(request: RunRequest, defaultRoot: string): SandboxConfig {
360
- return {
361
- workspaceRoot: request.projectPath || defaultRoot,
362
- includeThirdParty: request.includeThirdParty ?? false,
363
- includeGenerated: request.includeGenerated ?? false,
364
- };
365
- }
366
-
367
- /**
368
- * Validates a path from a RunRequest, applying config overrides.
369
- *
370
- * @param request - The run request containing path and overrides
371
- * @param defaultRoot - Default workspace root
372
- * @returns SandboxResult
373
- */
374
- export function validateRunRequest(request: RunRequest, defaultRoot: string): SandboxResult {
375
- const config = configFromRunRequest(request, defaultRoot);
376
-
377
- if (request.path) {
378
- return resolveSandboxPath(request.path, config);
379
- }
380
-
381
- if (request.paths && request.paths.length > 0) {
382
- const multiResult = validateSandboxPaths(request.paths, config);
383
- if (!multiResult.valid) {
384
- return {
385
- valid: false,
386
- error: multiResult.errors.join('; '),
387
- errorCode: 'TRAVERSAL_DETECTED', // Use first error type
388
- };
389
- }
390
- return { valid: true };
391
- }
392
-
393
- // No path specified
394
- return { valid: true };
395
- }
@@ -1,267 +0,0 @@
1
- /**
2
- * Shared types for MCP tool handler system
3
- */
4
-
5
- // ═══════════════════════════════════════════════════════════════════════════════
6
- // REQUEST/RESPONSE TYPES
7
- // ═══════════════════════════════════════════════════════════════════════════════
8
-
9
- export interface RunRequest {
10
- /** Unique request identifier for tracing */
11
- requestId: string;
12
- /** Optional trace ID for distributed tracing */
13
- traceId?: string;
14
- /** Tool name to execute */
15
- tool: string;
16
- /** Tool arguments */
17
- args: Record<string, unknown>;
18
- /** User context */
19
- context?: RequestContext;
20
- }
21
-
22
- export interface RequestContext {
23
- /** User's subscription tier */
24
- tier?: "free" | "pro";
25
- /** User ID for audit */
26
- userId?: string;
27
- /** Project root path */
28
- projectRoot?: string;
29
- /** API key (hashed) */
30
- apiKeyHash?: string;
31
- }
32
-
33
- export interface RunResponse {
34
- /** Request ID echo */
35
- requestId: string;
36
- /** Trace ID echo */
37
- traceId?: string;
38
- /** Success indicator */
39
- ok: boolean;
40
- /** Result data (on success) */
41
- data?: ToolResult;
42
- /** Error envelope (on failure) */
43
- error?: ErrorEnvelope;
44
- /** Execution metadata */
45
- metadata: ResponseMetadata;
46
- }
47
-
48
- export interface ResponseMetadata {
49
- /** Execution start time (ISO) */
50
- startedAt: string;
51
- /** Execution end time (ISO) */
52
- completedAt: string;
53
- /** Duration in milliseconds */
54
- durationMs: number;
55
- /** Tool that was executed */
56
- tool: string;
57
- /** CLI command that was executed (if applicable) */
58
- cliCommand?: string;
59
- /** Exit code from CLI */
60
- exitCode?: number;
61
- }
62
-
63
- // ═══════════════════════════════════════════════════════════════════════════════
64
- // ERROR ENVELOPE
65
- // ═══════════════════════════════════════════════════════════════════════════════
66
-
67
- export interface ErrorEnvelope {
68
- /** Error code for programmatic handling */
69
- code: ErrorCode;
70
- /** Human-readable message */
71
- message: string;
72
- /** Suggested next steps */
73
- nextSteps?: string[];
74
- /** Evidence/receipt (file:line) */
75
- receipt?: string;
76
- /** Validation errors (for INPUT_VALIDATION) */
77
- validationErrors?: ValidationError[];
78
- /** Request ID for support */
79
- requestId?: string;
80
- /** User action to resolve (for tier errors) */
81
- userAction?: string;
82
- /** Whether the operation can be retried */
83
- retryable?: boolean;
84
- /** Current user tier (for tier errors) */
85
- tier?: string;
86
- /** Required tier (for tier errors) */
87
- required?: string;
88
- /** Tool name (for tier errors) */
89
- tool?: string;
90
- /** Blocked option (for option-level gates) */
91
- option?: string;
92
- /** Upgrade URL */
93
- upgradeUrl?: string;
94
- }
95
-
96
- export type ErrorCode =
97
- | "INPUT_VALIDATION"
98
- | "TOOL_NOT_FOUND"
99
- | "TIER_REQUIRED"
100
- | "NOT_ENTITLED" // Tool requires higher tier
101
- | "OPTION_NOT_ENTITLED" // Specific option requires higher tier
102
- | "PATH_VIOLATION"
103
- | "EXECUTOR_FAILED"
104
- | "OUTPUT_PARSE_ERROR"
105
- | "OUTPUT_VALIDATION"
106
- | "TIMEOUT"
107
- | "INTERNAL_ERROR"
108
- | "INVALID_API_KEY"
109
- | "RATE_LIMITED";
110
-
111
- export interface ValidationError {
112
- /** JSON path to the invalid field */
113
- path: string;
114
- /** Error message */
115
- message: string;
116
- /** Expected value/type */
117
- expected?: string;
118
- /** Actual value/type */
119
- actual?: string;
120
- }
121
-
122
- // ═══════════════════════════════════════════════════════════════════════════════
123
- // TOOL REGISTRY
124
- // ═══════════════════════════════════════════════════════════════════════════════
125
-
126
- export interface ToolDefinition {
127
- /** Tool name (unique identifier) */
128
- name: string;
129
- /** Human-readable description */
130
- description: string;
131
- /** Subscription tier required */
132
- tier: "free" | "pro";
133
- /** Tool category */
134
- category: ToolCategory;
135
- /** JSON Schema for input validation */
136
- inputSchema: JsonSchema;
137
- /** JSON Schema for output validation */
138
- outputSchema: JsonSchema;
139
- /** CLI command mapping */
140
- cli: CliMapping;
141
- /** Tool aliases */
142
- aliases?: string[];
143
- /** Related tools */
144
- related?: string[];
145
- }
146
-
147
- export type ToolCategory =
148
- | "scan"
149
- | "proof"
150
- | "authority"
151
- | "report"
152
- | "setup"
153
- | "account"
154
- | "conductor"
155
- | "firewall";
156
-
157
- export interface CliMapping {
158
- /** CLI command to execute */
159
- command: string;
160
- /** Argument mapping: { inputField: "--flag" } */
161
- argMap: Record<string, string>;
162
- /** Fixed flags always passed */
163
- fixedFlags?: string[];
164
- /** Timeout in milliseconds */
165
- timeoutMs?: number;
166
- }
167
-
168
- export interface JsonSchema {
169
- type: string;
170
- properties?: Record<string, JsonSchemaProperty>;
171
- required?: string[];
172
- additionalProperties?: boolean;
173
- }
174
-
175
- export interface JsonSchemaProperty {
176
- type: string;
177
- description?: string;
178
- default?: unknown;
179
- enum?: unknown[];
180
- items?: JsonSchemaProperty;
181
- properties?: Record<string, JsonSchemaProperty>;
182
- required?: string[];
183
- minimum?: number;
184
- maximum?: number;
185
- pattern?: string;
186
- }
187
-
188
- // ═══════════════════════════════════════════════════════════════════════════════
189
- // TOOL RESULT (CANONICAL OUTPUT)
190
- // ═══════════════════════════════════════════════════════════════════════════════
191
-
192
- export interface ToolResult {
193
- /** Verdict (for scan/ship tools) */
194
- verdict?: "SHIP" | "WARN" | "BLOCK" | "PASS" | "FAIL";
195
- /** Findings list */
196
- findings?: Finding[];
197
- /** Summary statistics */
198
- summary?: ResultSummary;
199
- /** Raw output (if applicable) */
200
- raw?: unknown;
201
- }
202
-
203
- export interface Finding {
204
- /** Stable finding ID: sha256(rule_id + path + line + message) */
205
- id: string;
206
- /** Rule that generated this finding */
207
- ruleId: string;
208
- /** Severity level */
209
- severity: "critical" | "high" | "medium" | "low" | "info";
210
- /** Finding message */
211
- message: string;
212
- /** File path (relative to project root) */
213
- path: string;
214
- /** Line number (1-based) */
215
- line: number;
216
- /** Column number (1-based, optional) */
217
- column?: number;
218
- /** Code snippet */
219
- snippet?: string;
220
- /** Finding category */
221
- category?: string;
222
- /** Suggested fix */
223
- fix?: string;
224
- }
225
-
226
- export interface ResultSummary {
227
- /** Total findings count */
228
- total: number;
229
- /** Findings by severity */
230
- bySeverity: Record<string, number>;
231
- /** Findings by category */
232
- byCategory?: Record<string, number>;
233
- /** Files scanned */
234
- filesScanned?: number;
235
- /** Duration of scan */
236
- scanDurationMs?: number;
237
- }
238
-
239
- // ═══════════════════════════════════════════════════════════════════════════════
240
- // EXECUTOR TYPES
241
- // ═══════════════════════════════════════════════════════════════════════════════
242
-
243
- export interface ExecutorOptions {
244
- /** Working directory */
245
- cwd: string;
246
- /** Timeout in milliseconds */
247
- timeoutMs: number;
248
- /** Environment variables to pass */
249
- env?: Record<string, string>;
250
- /** Request ID for logging */
251
- requestId: string;
252
- /** Trace ID for logging */
253
- traceId?: string;
254
- }
255
-
256
- export interface ExecutorResult {
257
- /** Exit code */
258
- exitCode: number;
259
- /** Stdout content */
260
- stdout: string;
261
- /** Stderr content */
262
- stderr: string;
263
- /** Whether command timed out */
264
- timedOut: boolean;
265
- /** Execution duration in ms */
266
- durationMs: number;
267
- }