@vibecodetown/mcp-server 2.1.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 (172) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +269 -0
  3. package/build/auth/gate.js +225 -0
  4. package/build/auth/index.js +55 -0
  5. package/build/auth/public_key.js +27 -0
  6. package/build/auth/token_cache.js +122 -0
  7. package/build/auth/token_verifier.js +103 -0
  8. package/build/bootstrap/doctor.js +115 -0
  9. package/build/bootstrap/installer.js +673 -0
  10. package/build/bootstrap/lock.js +37 -0
  11. package/build/bootstrap/platform.js +26 -0
  12. package/build/bootstrap/registry.js +37 -0
  13. package/build/cache/index.js +147 -0
  14. package/build/cli.js +101 -0
  15. package/build/contracts.js +22 -0
  16. package/build/control_plane/gate.js +161 -0
  17. package/build/control_plane/index.js +6 -0
  18. package/build/dx/activity.js +139 -0
  19. package/build/engine.js +106 -0
  20. package/build/errors.js +171 -0
  21. package/build/generated/activate_input.js +2 -0
  22. package/build/generated/activate_output.js +57 -0
  23. package/build/generated/advisory_review_input.js +2 -0
  24. package/build/generated/advisory_review_output.js +35 -0
  25. package/build/generated/auth_token_file.js +2 -0
  26. package/build/generated/briefing_input.js +2 -0
  27. package/build/generated/briefing_output.js +2 -0
  28. package/build/generated/clinic_bridge_file.js +13 -0
  29. package/build/generated/contracts_bundle_info.js +5 -0
  30. package/build/generated/create_work_order_input.js +2 -0
  31. package/build/generated/create_work_order_output.js +2 -0
  32. package/build/generated/current_work_order_file.js +2 -0
  33. package/build/generated/doctor_input.js +2 -0
  34. package/build/generated/doctor_output.js +24 -0
  35. package/build/generated/execution_result.js +2 -0
  36. package/build/generated/execution_task.js +2 -0
  37. package/build/generated/export_output_input.js +2 -0
  38. package/build/generated/export_output_output.js +2 -0
  39. package/build/generated/finalize_work_input.js +2 -0
  40. package/build/generated/finalize_work_output.js +2 -0
  41. package/build/generated/gate_input.js +2 -0
  42. package/build/generated/gate_output.js +2 -0
  43. package/build/generated/gate_result_v1.js +2 -0
  44. package/build/generated/get_decision_input.js +2 -0
  45. package/build/generated/get_decision_output.js +13 -0
  46. package/build/generated/handoff_to_clinic.js +2 -0
  47. package/build/generated/index.js +75 -0
  48. package/build/generated/inspect_code_input.js +2 -0
  49. package/build/generated/inspect_code_output.js +13 -0
  50. package/build/generated/memory_retrieve_output.js +2 -0
  51. package/build/generated/memory_state_file.js +2 -0
  52. package/build/generated/memory_status_input.js +2 -0
  53. package/build/generated/memory_status_output.js +13 -0
  54. package/build/generated/memory_sync_input.js +2 -0
  55. package/build/generated/memory_sync_output.js +13 -0
  56. package/build/generated/plugin_result.js +2 -0
  57. package/build/generated/react_perf_check_patterns_input.js +2 -0
  58. package/build/generated/react_perf_check_patterns_output.js +2 -0
  59. package/build/generated/react_perf_generate_report_input.js +2 -0
  60. package/build/generated/react_perf_generate_report_output.js +2 -0
  61. package/build/generated/repair_plan_input.js +2 -0
  62. package/build/generated/repair_plan_output.js +2 -0
  63. package/build/generated/run_app_input.js +2 -0
  64. package/build/generated/run_app_output.js +2 -0
  65. package/build/generated/run_state_file.js +13 -0
  66. package/build/generated/scaffold_input.js +2 -0
  67. package/build/generated/scaffold_output.js +2 -0
  68. package/build/generated/search_oss_input.js +2 -0
  69. package/build/generated/search_oss_output.js +2 -0
  70. package/build/generated/selection_validation_result.js +2 -0
  71. package/build/generated/signal_agent_input.js +2 -0
  72. package/build/generated/spec_high_ask_queue_items_file.js +2 -0
  73. package/build/generated/spec_high_clinic_bridge_output.js +2 -0
  74. package/build/generated/spec_high_decision_draft_output.js +2 -0
  75. package/build/generated/spec_high_validate_output.js +2 -0
  76. package/build/generated/status_input.js +2 -0
  77. package/build/generated/status_output.js +2 -0
  78. package/build/generated/submit_decision_input.js +2 -0
  79. package/build/generated/submit_decision_output.js +2 -0
  80. package/build/generated/tool_error_output.js +2 -0
  81. package/build/generated/undo_last_task_input.js +2 -0
  82. package/build/generated/undo_last_task_output.js +2 -0
  83. package/build/generated/update_input.js +2 -0
  84. package/build/generated/update_output.js +2 -0
  85. package/build/generated/vibe_pm_inspection_result.js +2 -0
  86. package/build/generated/vibe_pm_report_markdown.js +2 -0
  87. package/build/generated/vibe_pm_verdict.js +2 -0
  88. package/build/generated/vibe_repo_config.js +2 -0
  89. package/build/generated/vibecoding_helper_answer_output.js +2 -0
  90. package/build/generated/vibecoding_helper_one_loop_selection_output.js +2 -0
  91. package/build/generated/vibecoding_helper_show_ask_queue_output.js +2 -0
  92. package/build/generated/work_order_v1.js +2 -0
  93. package/build/generated/zoekt_evidence_input.js +2 -0
  94. package/build/generated/zoekt_evidence_output.js +2 -0
  95. package/build/index.js +111 -0
  96. package/build/legacy_alias.js +65 -0
  97. package/build/local-mode/bash.js +61 -0
  98. package/build/local-mode/config.js +171 -0
  99. package/build/local-mode/git.js +33 -0
  100. package/build/local-mode/init.js +110 -0
  101. package/build/local-mode/paths.js +24 -0
  102. package/build/local-mode/templates.js +856 -0
  103. package/build/local-mode/work-order.js +41 -0
  104. package/build/resources/index.js +246 -0
  105. package/build/security/input-validator.js +119 -0
  106. package/build/security/path-policy.js +289 -0
  107. package/build/security/sandbox.js +228 -0
  108. package/build/tools/react_perf/check_patterns.js +172 -0
  109. package/build/tools/react_perf/generate_report.js +337 -0
  110. package/build/tools/react_perf/index.js +119 -0
  111. package/build/tools/react_perf/rules/advanced.js +325 -0
  112. package/build/tools/react_perf/rules/async.js +104 -0
  113. package/build/tools/react_perf/rules/bundle.js +101 -0
  114. package/build/tools/react_perf/rules/client.js +186 -0
  115. package/build/tools/react_perf/rules/index.js +74 -0
  116. package/build/tools/react_perf/rules/js.js +148 -0
  117. package/build/tools/react_perf/rules/rendering.js +166 -0
  118. package/build/tools/react_perf/rules/rerender.js +161 -0
  119. package/build/tools/react_perf/rules/server.js +141 -0
  120. package/build/tools/react_perf/types.js +127 -0
  121. package/build/tools/vibe_pm/activate.js +102 -0
  122. package/build/tools/vibe_pm/advisory_review.js +77 -0
  123. package/build/tools/vibe_pm/briefing.js +178 -0
  124. package/build/tools/vibe_pm/context.js +439 -0
  125. package/build/tools/vibe_pm/create_work_order.js +271 -0
  126. package/build/tools/vibe_pm/doc_status_gate.js +370 -0
  127. package/build/tools/vibe_pm/doctor.js +262 -0
  128. package/build/tools/vibe_pm/entity_gate/preflight.js +78 -0
  129. package/build/tools/vibe_pm/export_output.js +135 -0
  130. package/build/tools/vibe_pm/finalize_work.js +393 -0
  131. package/build/tools/vibe_pm/gate.js +33 -0
  132. package/build/tools/vibe_pm/get_decision.js +281 -0
  133. package/build/tools/vibe_pm/index.js +593 -0
  134. package/build/tools/vibe_pm/inspect_code.js +828 -0
  135. package/build/tools/vibe_pm/intent/generator.js +294 -0
  136. package/build/tools/vibe_pm/intent/index.js +5 -0
  137. package/build/tools/vibe_pm/intent/prompt_density.js +227 -0
  138. package/build/tools/vibe_pm/intent/types.js +70 -0
  139. package/build/tools/vibe_pm/intent/verifier.js +237 -0
  140. package/build/tools/vibe_pm/kce/doc_usage.js +51 -0
  141. package/build/tools/vibe_pm/kce/on_finalize.js +11 -0
  142. package/build/tools/vibe_pm/kce/preflight.js +232 -0
  143. package/build/tools/vibe_pm/local_memory.js +26 -0
  144. package/build/tools/vibe_pm/memory_status.js +82 -0
  145. package/build/tools/vibe_pm/memory_sync.js +134 -0
  146. package/build/tools/vibe_pm/modules/decision_snapshot.js +29 -0
  147. package/build/tools/vibe_pm/modules/ensure.js +100 -0
  148. package/build/tools/vibe_pm/modules/fingerprint.js +30 -0
  149. package/build/tools/vibe_pm/modules/fix_dependencies.js +394 -0
  150. package/build/tools/vibe_pm/modules/planning_v1.js +110 -0
  151. package/build/tools/vibe_pm/modules/repo_context.js +56 -0
  152. package/build/tools/vibe_pm/modules/research_v1.js +114 -0
  153. package/build/tools/vibe_pm/modules/skills_v1.js +100 -0
  154. package/build/tools/vibe_pm/pm_language.js +222 -0
  155. package/build/tools/vibe_pm/repair_plan.js +199 -0
  156. package/build/tools/vibe_pm/run_app.js +597 -0
  157. package/build/tools/vibe_pm/run_app_podman.js +64 -0
  158. package/build/tools/vibe_pm/scaffold.js +550 -0
  159. package/build/tools/vibe_pm/search_oss.js +124 -0
  160. package/build/tools/vibe_pm/status.js +153 -0
  161. package/build/tools/vibe_pm/submit_decision.js +87 -0
  162. package/build/tools/vibe_pm/system_design/issue_mapping.js +47 -0
  163. package/build/tools/vibe_pm/system_design/rulebook.js +112 -0
  164. package/build/tools/vibe_pm/system_design/semgrep.js +132 -0
  165. package/build/tools/vibe_pm/types.js +229 -0
  166. package/build/tools/vibe_pm/undo_last_task.js +163 -0
  167. package/build/tools/vibe_pm/update.js +146 -0
  168. package/build/tools/vibe_pm/zoekt_evidence.js +96 -0
  169. package/build/tools.js +269 -0
  170. package/build/version-check.js +239 -0
  171. package/build/vibe-cli.js +631 -0
  172. package/package.json +76 -0
@@ -0,0 +1,228 @@
1
+ // adapters/mcp-ts/src/security/sandbox.ts
2
+ // Optional Docker sandbox for production environments
3
+ //
4
+ // Note: This is an optional security layer. The primary security
5
+ // is provided by input validation and path policy.
6
+ import { spawn } from "node:child_process";
7
+ /**
8
+ * Default sandbox configuration (no sandboxing)
9
+ */
10
+ export const DEFAULT_SANDBOX_CONFIG = {
11
+ mode: "none",
12
+ allowedPaths: [],
13
+ networkAccess: false,
14
+ memoryLimitMb: 512,
15
+ cpuLimit: 1,
16
+ timeoutMs: 120_000,
17
+ };
18
+ /**
19
+ * Check if Docker is available on the system
20
+ */
21
+ export async function isDockerAvailable() {
22
+ return new Promise((resolve) => {
23
+ const proc = spawn("docker", ["version"], {
24
+ stdio: ["ignore", "pipe", "pipe"],
25
+ });
26
+ proc.on("error", () => resolve(false));
27
+ proc.on("close", (code) => resolve(code === 0));
28
+ });
29
+ }
30
+ /**
31
+ * Check if firejail is available on the system
32
+ */
33
+ export async function isFirejailAvailable() {
34
+ return new Promise((resolve) => {
35
+ const proc = spawn("firejail", ["--version"], {
36
+ stdio: ["ignore", "pipe", "pipe"],
37
+ });
38
+ proc.on("error", () => resolve(false));
39
+ proc.on("close", (code) => resolve(code === 0));
40
+ });
41
+ }
42
+ /**
43
+ * Run command in sandbox environment
44
+ *
45
+ * @param cmd - Command to execute
46
+ * @param args - Command arguments
47
+ * @param config - Sandbox configuration
48
+ * @returns Execution result
49
+ */
50
+ export async function runInSandbox(cmd, args, config = DEFAULT_SANDBOX_CONFIG) {
51
+ switch (config.mode) {
52
+ case "docker":
53
+ return runInDocker(cmd, args, config);
54
+ case "firejail":
55
+ return runInFirejail(cmd, args, config);
56
+ case "none":
57
+ default:
58
+ return runDirect(cmd, args, config);
59
+ }
60
+ }
61
+ /**
62
+ * Run command directly (no sandboxing)
63
+ */
64
+ async function runDirect(cmd, args, config) {
65
+ return new Promise((resolve) => {
66
+ const proc = spawn(cmd, args, {
67
+ stdio: ["ignore", "pipe", "pipe"],
68
+ });
69
+ let stdout = "";
70
+ let stderr = "";
71
+ const timeout = setTimeout(() => {
72
+ try {
73
+ proc.kill("SIGKILL");
74
+ }
75
+ catch { }
76
+ resolve({ code: 124, stdout, stderr: stderr + "\n[SANDBOX TIMEOUT]" });
77
+ }, config.timeoutMs);
78
+ proc.stdout.on("data", (data) => {
79
+ stdout += data.toString();
80
+ });
81
+ proc.stderr.on("data", (data) => {
82
+ stderr += data.toString();
83
+ });
84
+ proc.on("close", (code) => {
85
+ clearTimeout(timeout);
86
+ resolve({ code: code ?? 1, stdout, stderr });
87
+ });
88
+ });
89
+ }
90
+ /**
91
+ * Run command in Docker sandbox
92
+ *
93
+ * Requirements:
94
+ * - Docker must be installed and running
95
+ * - vibecode/sandbox:latest image must exist
96
+ */
97
+ async function runInDocker(cmd, args, config) {
98
+ const dockerArgs = [
99
+ "run",
100
+ "--rm",
101
+ // Network isolation
102
+ "--network",
103
+ config.networkAccess ? "bridge" : "none",
104
+ // Resource limits
105
+ "--memory",
106
+ `${config.memoryLimitMb}m`,
107
+ "--cpus",
108
+ String(config.cpuLimit),
109
+ // Security options
110
+ "--security-opt",
111
+ "no-new-privileges:true",
112
+ "--cap-drop",
113
+ "ALL",
114
+ // Read-only root filesystem
115
+ "--read-only",
116
+ ];
117
+ // Mount allowed paths as read-only volumes
118
+ for (const allowedPath of config.allowedPaths) {
119
+ dockerArgs.push("-v", `${allowedPath}:${allowedPath}:ro`);
120
+ }
121
+ // Add tmpfs for /tmp if needed
122
+ dockerArgs.push("--tmpfs", "/tmp:rw,noexec,nosuid,size=100m");
123
+ // Image and command
124
+ dockerArgs.push("vibecode/sandbox:latest", cmd, ...args);
125
+ return new Promise((resolve) => {
126
+ const proc = spawn("docker", dockerArgs, {
127
+ stdio: ["ignore", "pipe", "pipe"],
128
+ });
129
+ let stdout = "";
130
+ let stderr = "";
131
+ const timeout = setTimeout(() => {
132
+ try {
133
+ // Kill the docker container
134
+ spawn("docker", ["kill", proc.pid?.toString() ?? ""], {
135
+ stdio: "ignore",
136
+ });
137
+ proc.kill("SIGKILL");
138
+ }
139
+ catch { }
140
+ resolve({ code: 124, stdout, stderr: stderr + "\n[DOCKER TIMEOUT]" });
141
+ }, config.timeoutMs);
142
+ proc.stdout.on("data", (data) => {
143
+ stdout += data.toString();
144
+ });
145
+ proc.stderr.on("data", (data) => {
146
+ stderr += data.toString();
147
+ });
148
+ proc.on("close", (code) => {
149
+ clearTimeout(timeout);
150
+ resolve({ code: code ?? 1, stdout, stderr });
151
+ });
152
+ });
153
+ }
154
+ /**
155
+ * Run command in firejail sandbox (Linux only)
156
+ *
157
+ * Requirements:
158
+ * - firejail must be installed
159
+ */
160
+ async function runInFirejail(cmd, args, config) {
161
+ const firejailArgs = [
162
+ // Disable network if not allowed
163
+ ...(config.networkAccess ? [] : ["--net=none"]),
164
+ // Resource limits
165
+ "--rlimit-as=" + config.memoryLimitMb * 1024 * 1024,
166
+ // Security options
167
+ "--caps.drop=all",
168
+ "--nonewprivs",
169
+ "--seccomp",
170
+ // No X11
171
+ "--x11=none",
172
+ // Read-only paths
173
+ "--read-only=/",
174
+ ];
175
+ // Whitelist allowed paths
176
+ for (const allowedPath of config.allowedPaths) {
177
+ firejailArgs.push(`--whitelist=${allowedPath}`);
178
+ }
179
+ // Allow /tmp for temporary files
180
+ firejailArgs.push("--private-tmp");
181
+ // Command to run
182
+ firejailArgs.push("--", cmd, ...args);
183
+ return new Promise((resolve) => {
184
+ const proc = spawn("firejail", firejailArgs, {
185
+ stdio: ["ignore", "pipe", "pipe"],
186
+ });
187
+ let stdout = "";
188
+ let stderr = "";
189
+ const timeout = setTimeout(() => {
190
+ try {
191
+ proc.kill("SIGKILL");
192
+ }
193
+ catch { }
194
+ resolve({ code: 124, stdout, stderr: stderr + "\n[FIREJAIL TIMEOUT]" });
195
+ }, config.timeoutMs);
196
+ proc.stdout.on("data", (data) => {
197
+ stdout += data.toString();
198
+ });
199
+ proc.stderr.on("data", (data) => {
200
+ stderr += data.toString();
201
+ });
202
+ proc.on("close", (code) => {
203
+ clearTimeout(timeout);
204
+ resolve({ code: code ?? 1, stdout, stderr });
205
+ });
206
+ });
207
+ }
208
+ /**
209
+ * Create sandbox configuration from environment
210
+ */
211
+ export function getSandboxConfigFromEnv() {
212
+ const mode = (process.env.VIBECODE_SANDBOX_MODE ?? "none");
213
+ const networkAccess = process.env.VIBECODE_SANDBOX_NETWORK === "true";
214
+ const memoryLimitMb = parseInt(process.env.VIBECODE_SANDBOX_MEMORY ?? "512", 10);
215
+ const cpuLimit = parseFloat(process.env.VIBECODE_SANDBOX_CPU ?? "1");
216
+ const timeoutMs = parseInt(process.env.VIBECODE_SANDBOX_TIMEOUT ?? "120000", 10);
217
+ const allowedPaths = (process.env.VIBECODE_SANDBOX_PATHS ?? "")
218
+ .split(":")
219
+ .filter((p) => p.length > 0);
220
+ return {
221
+ mode,
222
+ allowedPaths,
223
+ networkAccess,
224
+ memoryLimitMb,
225
+ cpuLimit,
226
+ timeoutMs,
227
+ };
228
+ }
@@ -0,0 +1,172 @@
1
+ // adapters/mcp-ts/src/tools/react_perf/check_patterns.ts
2
+ // Main implementation for react_perf.check_patterns
3
+ import * as fs from "fs";
4
+ import * as path from "path";
5
+ import { filterByMinImpact, sortByImpact, countViolationsByImpact, getTopSuggestions } from "./types.js";
6
+ import { getAllRules, getRulesByCategories } from "./rules/index.js";
7
+ // ============================================================
8
+ // File Discovery
9
+ // ============================================================
10
+ const DEFAULT_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx"];
11
+ const IGNORE_DIRS = ["node_modules", ".next", "dist", "build", ".git", "coverage"];
12
+ function shouldIgnoreDir(dirName) {
13
+ return IGNORE_DIRS.includes(dirName) || dirName.startsWith(".");
14
+ }
15
+ function shouldIncludeFile(filePath) {
16
+ const ext = path.extname(filePath);
17
+ return DEFAULT_EXTENSIONS.includes(ext);
18
+ }
19
+ function findFiles(dir, files = []) {
20
+ if (!fs.existsSync(dir)) {
21
+ return files;
22
+ }
23
+ const stat = fs.statSync(dir);
24
+ if (stat.isFile()) {
25
+ if (shouldIncludeFile(dir)) {
26
+ files.push(dir);
27
+ }
28
+ return files;
29
+ }
30
+ if (!stat.isDirectory()) {
31
+ return files;
32
+ }
33
+ const entries = fs.readdirSync(dir);
34
+ for (const entry of entries) {
35
+ if (shouldIgnoreDir(entry))
36
+ continue;
37
+ const fullPath = path.join(dir, entry);
38
+ const entryStat = fs.statSync(fullPath);
39
+ if (entryStat.isDirectory()) {
40
+ findFiles(fullPath, files);
41
+ }
42
+ else if (entryStat.isFile() && shouldIncludeFile(fullPath)) {
43
+ files.push(fullPath);
44
+ }
45
+ }
46
+ return files;
47
+ }
48
+ function findPatternMatches(content, pattern) {
49
+ const matches = [];
50
+ const lines = content.split("\n");
51
+ // Use multiline matching
52
+ const globalPattern = new RegExp(pattern.source, pattern.flags + (pattern.flags.includes("g") ? "" : "g"));
53
+ let match;
54
+ while ((match = globalPattern.exec(content)) !== null) {
55
+ // Calculate line number from index
56
+ const beforeMatch = content.substring(0, match.index);
57
+ const lineNumber = beforeMatch.split("\n").length;
58
+ const lastNewline = beforeMatch.lastIndexOf("\n");
59
+ const column = match.index - lastNewline;
60
+ // Get the line content for snippet
61
+ const lineText = lines[lineNumber - 1] || "";
62
+ matches.push({
63
+ line: lineNumber,
64
+ column,
65
+ text: lineText.trim().substring(0, 100) // Truncate long lines
66
+ });
67
+ // Prevent infinite loops on zero-length matches
68
+ if (match[0].length === 0) {
69
+ globalPattern.lastIndex++;
70
+ }
71
+ }
72
+ return matches;
73
+ }
74
+ function checkAntiPattern(content, antiPattern) {
75
+ if (!antiPattern)
76
+ return false;
77
+ return antiPattern.test(content);
78
+ }
79
+ // ============================================================
80
+ // Main Analysis
81
+ // ============================================================
82
+ function analyzeFile(filePath, rules) {
83
+ const violations = [];
84
+ let content;
85
+ try {
86
+ content = fs.readFileSync(filePath, "utf-8");
87
+ }
88
+ catch {
89
+ return violations;
90
+ }
91
+ for (const rule of rules) {
92
+ // Check file filter
93
+ if (rule.fileFilter && !rule.fileFilter.test(filePath)) {
94
+ continue;
95
+ }
96
+ // Check anti-pattern (if file has anti-pattern, skip this rule)
97
+ if (checkAntiPattern(content, rule.antiPattern)) {
98
+ continue;
99
+ }
100
+ // Find pattern matches
101
+ const matches = findPatternMatches(content, rule.pattern);
102
+ for (const match of matches) {
103
+ violations.push({
104
+ rule_id: rule.id,
105
+ category: rule.category,
106
+ file: filePath,
107
+ line: match.line,
108
+ column: match.column,
109
+ impact: rule.impact,
110
+ message: rule.message,
111
+ suggestion: rule.suggestion,
112
+ code_snippet: match.text
113
+ });
114
+ }
115
+ }
116
+ return violations;
117
+ }
118
+ // ============================================================
119
+ // Main Entry Point
120
+ // ============================================================
121
+ export async function checkPatterns(input) {
122
+ const startTime = Date.now();
123
+ // Determine target paths
124
+ const targetPaths = input.target_paths || [process.cwd()];
125
+ // Collect all files to scan
126
+ const allFiles = [];
127
+ for (const targetPath of targetPaths) {
128
+ const resolvedPath = path.resolve(targetPath);
129
+ const files = findFiles(resolvedPath);
130
+ allFiles.push(...files);
131
+ }
132
+ // Deduplicate files
133
+ const uniqueFiles = [...new Set(allFiles)];
134
+ // Get rules to check
135
+ const rules = input.rules
136
+ ? getRulesByCategories(input.rules)
137
+ : getAllRules();
138
+ // Skip if no rules
139
+ if (rules.length === 0) {
140
+ return {
141
+ status: "OK",
142
+ total_files_scanned: uniqueFiles.length,
143
+ total_violations: 0,
144
+ violations: [],
145
+ summary: { critical: 0, high: 0, medium: 0, low: 0 },
146
+ top_suggestions: [],
147
+ scan_time_ms: Date.now() - startTime
148
+ };
149
+ }
150
+ // Analyze all files
151
+ let allViolations = [];
152
+ for (const file of uniqueFiles) {
153
+ const fileViolations = analyzeFile(file, rules);
154
+ allViolations.push(...fileViolations);
155
+ }
156
+ // Filter by minimum impact
157
+ const minImpact = input.min_impact || "MEDIUM";
158
+ allViolations = filterByMinImpact(allViolations, minImpact);
159
+ // Sort by impact
160
+ allViolations = sortByImpact(allViolations);
161
+ // Build output
162
+ const output = {
163
+ status: allViolations.length > 0 ? "VIOLATIONS_FOUND" : "OK",
164
+ total_files_scanned: uniqueFiles.length,
165
+ total_violations: allViolations.length,
166
+ violations: allViolations,
167
+ summary: countViolationsByImpact(allViolations),
168
+ top_suggestions: getTopSuggestions(allViolations, 3),
169
+ scan_time_ms: Date.now() - startTime
170
+ };
171
+ return output;
172
+ }