@kb-labs/review-entry 2.47.0 → 2.53.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.
@@ -128,8 +128,16 @@ var run_default = defineCommand({
128
128
  });
129
129
  files = scopedFiles.files;
130
130
  } else if (flags.files) {
131
- const filePaths = Array.isArray(flags.files) ? flags.files : [flags.files];
132
- const safeFilePaths = await filterSecurePaths(filePaths, cwd);
131
+ const filePatterns = Array.isArray(flags.files) ? flags.files : [flags.files];
132
+ const expanded = [];
133
+ for (const pattern of filePatterns) {
134
+ const matches = await ctx.runtime.fs.glob(pattern, {
135
+ cwd,
136
+ ignore: [...SECURITY_IGNORE_PATTERNS]
137
+ });
138
+ expanded.push(...matches);
139
+ }
140
+ const safeFilePaths = await filterSecurePaths(expanded, cwd);
133
141
  const fileReadResults = await Promise.allSettled(
134
142
  safeFilePaths.map(async (filePath) => ({
135
143
  path: filePath,
@@ -141,13 +149,7 @@ var run_default = defineCommand({
141
149
  let filePaths = [];
142
150
  switch (scope) {
143
151
  case "all":
144
- const [tsFiles, tsxFiles, jsFiles, jsxFiles] = await Promise.all([
145
- ctx.runtime.fs.glob("**/*.ts", { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),
146
- ctx.runtime.fs.glob("**/*.tsx", { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),
147
- ctx.runtime.fs.glob("**/*.js", { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),
148
- ctx.runtime.fs.glob("**/*.jsx", { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] })
149
- ]);
150
- filePaths = [...tsFiles, ...tsxFiles, ...jsFiles, ...jsxFiles];
152
+ filePaths = await ctx.runtime.fs.glob("**/*", { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] });
151
153
  break;
152
154
  case "staged":
153
155
  const reposWithChanges = await getReposWithChanges(cwd);
@@ -161,14 +163,6 @@ var run_default = defineCommand({
161
163
  });
162
164
  files = scopedFiles.files;
163
165
  repoScope = reposWithChanges;
164
- } else {
165
- const [tsF, tsxF, jsF, jsxF] = await Promise.all([
166
- ctx.runtime.fs.glob("**/*.ts", { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),
167
- ctx.runtime.fs.glob("**/*.tsx", { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),
168
- ctx.runtime.fs.glob("**/*.js", { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),
169
- ctx.runtime.fs.glob("**/*.jsx", { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] })
170
- ]);
171
- filePaths = [...tsF, ...tsxF, ...jsF, ...jsxF];
172
166
  }
173
167
  break;
174
168
  case "changed":
@@ -180,18 +174,10 @@ var run_default = defineCommand({
180
174
  repos: changedRepos,
181
175
  includeStaged: true,
182
176
  includeUnstaged: true,
183
- includeUntracked: false
177
+ includeUntracked: true
184
178
  });
185
179
  files = scopedFiles.files;
186
180
  repoScope = changedRepos;
187
- } else {
188
- const [tsC, tsxC, jsC, jsxC] = await Promise.all([
189
- ctx.runtime.fs.glob("**/*.ts", { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),
190
- ctx.runtime.fs.glob("**/*.tsx", { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),
191
- ctx.runtime.fs.glob("**/*.js", { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),
192
- ctx.runtime.fs.glob("**/*.jsx", { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] })
193
- ]);
194
- filePaths = [...tsC, ...tsxC, ...jsC, ...jsxC];
195
181
  }
196
182
  break;
197
183
  }
@@ -206,6 +192,12 @@ var run_default = defineCommand({
206
192
  files = fileReadResults.filter((r) => r.status === "fulfilled").map((r) => r.value);
207
193
  }
208
194
  }
195
+ if (files.length === 0) {
196
+ loader.fail("No files to review");
197
+ const hint = scope === "staged" ? "No staged files found. Stage files with `git add` first, or use `--scope=changed`." : "No changed files found. Use `--scope=all` to review all files, or `--files` to specify files explicitly.";
198
+ ctx.ui?.error?.(hint);
199
+ return { exitCode: 1, result: { passed: false, issues: [], summary: hint } };
200
+ }
209
201
  const result = await runReview({
210
202
  files,
211
203
  mode,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/run.ts"],"names":["relative"],"mappings":"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","file":"run.js","sourcesContent":["/**\n * review:run command\n * Run code review analysis\n */\n\nimport {\n defineCommand,\n useLoader,\n useConfig,\n type PluginContextV3,\n type CLIInput,\n type CommandResult,\n} from '@kb-labs/sdk';\nimport type { ReviewMode, ReviewResult, InputFile } from '@kb-labs/review-contracts';\nimport { runReview, resolveGitScope, getReposWithChanges } from '@kb-labs/review-core';\nimport * as path from 'node:path';\nimport { realpath } from 'node:fs/promises';\n\n/**\n * Flags for review:run command\n */\ntype RunFlags = {\n mode?: ReviewMode;\n scope?: 'all' | 'changed' | 'staged';\n repos?: string[];\n task?: string;\n preset?: string;\n files?: string[];\n eslintConfig?: string;\n cwd?: string;\n json?: boolean;\n agent?: boolean;\n};\n\n/**\n * Agent-friendly review report.\n * Simplified format for automated workflows.\n */\ninterface AgentReviewReport {\n /** Can the agent proceed (commit/merge)? */\n passed: boolean;\n /** Issues that must be fixed before proceeding */\n issues: Array<{\n file: string;\n line: number;\n problem: string;\n fix: string;\n severity: 'blocker' | 'high' | 'medium' | 'low' | 'info';\n /** Rule ID (e.g., \"rule:security/no-eval\" or \"llm-lite:security\") */\n ruleId: string;\n /** Source: \"rule\" (matched project rule) or \"llm\" (ad-hoc finding) */\n source: 'rule' | 'llm';\n /** Confidence score (0.0-1.0) from verification engine */\n confidence: number;\n }>;\n /** One-line summary for logs */\n summary: string;\n}\n\n/**\n * Severity order for sorting (lower = more critical)\n */\nconst SEVERITY_ORDER: Record<string, number> = {\n blocker: 0,\n high: 1,\n medium: 2,\n low: 3,\n info: 4,\n};\n\n/**\n * Security-sensitive patterns for file filtering.\n * Shared across all file filtering operations for consistency.\n */\nconst SECURITY_IGNORE_PATTERNS = [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n '**/.git/**',\n '**/.kb/analytics/**',\n '**/.kb/cache/**',\n '**/.kb/storage/**',\n '**/.kb/database/**',\n '**/.env',\n '**/.env.*',\n '**/.ssh/**',\n '**/credentials/**',\n '**/password/**',\n '**/*.pem',\n '**/*.key',\n '**/*.secret',\n] as const;\n\n/**\n * Regex patterns for additional security filtering.\n * Used as a second layer of defense after glob ignore.\n */\nconst SECURITY_REGEX_PATTERNS = [\n /node_modules/,\n /\\.git\\//,\n /\\.env$/,\n /\\.env\\./,\n /\\.ssh/,\n /\\/etc\\//,\n /\\/usr\\//,\n /\\/var\\//,\n /credentials/i,\n /password/i,\n /\\.pem$/,\n /\\.key$/,\n /\\.secret$/,\n] as const;\n\n/**\n * Validate that a file path is within the allowed directory.\n * Prevents path traversal attacks including symlink bypass.\n * Uses fs.realpath() to resolve symlinks and path.relative() for cross-platform safety.\n */\nasync function isPathWithinCwd(filePath: string, cwd: string): Promise<boolean> {\n try {\n const resolvedPath = path.resolve(cwd, filePath);\n const resolvedCwd = path.resolve(cwd);\n\n // Resolve symlinks to prevent symlink bypass attacks\n const realPath = await realpath(resolvedPath).catch(() => resolvedPath);\n const realCwd = await realpath(resolvedCwd).catch(() => resolvedCwd);\n\n const relative = path.relative(realCwd, realPath);\n // Path is within cwd if relative path exists, doesn't start with '..', and isn't absolute\n return relative !== '' && !relative.startsWith('..') && !path.isAbsolute(relative);\n } catch {\n // If path doesn't exist or can't be resolved, reject it\n return false;\n }\n}\n\n/**\n * Filter file paths for security concerns.\n */\nasync function filterSecurePaths(filePaths: string[], cwd: string): Promise<string[]> {\n const results = await Promise.all(\n filePaths.map(async filePath => {\n // Path traversal check (including symlink resolution)\n if (!await isPathWithinCwd(filePath, cwd)) {\n return null;\n }\n // Security pattern check\n if (SECURITY_REGEX_PATTERNS.some(pattern => pattern.test(filePath))) {\n return null;\n }\n return filePath;\n })\n );\n return results.filter((p): p is string => p !== null);\n}\n\n/**\n * Transform ReviewResult to agent-friendly format\n */\nfunction toAgentReport(result: ReviewResult): AgentReviewReport {\n // Blocking issues = blocker and high severity only\n // Medium/low/info are acceptable and don't block the review\n const blockingIssues = result.findings.filter(\n f => f.severity === 'blocker' || f.severity === 'high'\n );\n\n // Pass when no blocking issues (medium and below are acceptable)\n const passed = blockingIssues.length === 0;\n\n // Sort by severity: blocker > high > medium > low > info\n const sortedFindings = [...result.findings].sort((a, b) => {\n const aOrder = SEVERITY_ORDER[a.severity] ?? 5;\n const bOrder = SEVERITY_ORDER[b.severity] ?? 5;\n return aOrder - bOrder;\n });\n\n const issues = sortedFindings.map(f => ({\n file: f.file,\n line: f.line,\n problem: f.message,\n fix: f.suggestion ?? 'Review and fix manually',\n severity: f.severity as 'blocker' | 'high' | 'medium' | 'low' | 'info',\n ruleId: f.ruleId ?? 'unknown',\n source: (f.ruleId?.startsWith('rule:') ? 'rule' : 'llm') as 'rule' | 'llm',\n // Map categorical confidence to numeric score (default 0.5 for undefined/unknown)\n confidence: f.confidence === 'certain' ? 1.0\n : f.confidence === 'likely' ? 0.8\n : f.confidence === 'heuristic' ? 0.6\n : 0.5,\n }));\n\n // Count non-blocking issues for summary\n const mediumCount = result.findings.filter(f => f.severity === 'medium').length;\n const lowCount = result.findings.filter(f => f.severity === 'low').length;\n const infoCount = result.findings.filter(f => f.severity === 'info').length;\n const nonBlockingCount = mediumCount + lowCount + infoCount;\n\n const summary = passed\n ? nonBlockingCount > 0\n ? `Review passed. ${nonBlockingCount} non-blocking issue(s) found (${mediumCount} medium, ${lowCount} low, ${infoCount} info).`\n : 'Review passed. No issues found.'\n : `Review failed. ${blockingIssues.length} blocking issue(s) must be fixed.`;\n\n return { passed, issues, summary };\n}\n\nexport default defineCommand<unknown, CLIInput<RunFlags>, AgentReviewReport>({\n id: 'review:run',\n description: 'Run code review analysis',\n\n handler: {\n // eslint-disable-next-line sonarjs/cognitive-complexity -- Main orchestration handler: coordinates input modes (repos/files/scope), git resolution, security filtering, output formats (agent/json/human), and severity-based exit codes\n async execute(ctx: PluginContextV3, input: CLIInput<RunFlags>): Promise<CommandResult<AgentReviewReport>> {\n const startTime = Date.now();\n\n // Extract flags from input\n const flags = input.flags;\n\n // Parse input\n const mode = flags.mode ?? 'heuristic';\n const scope = flags.scope ?? 'changed';\n\n // Use --cwd flag if provided, otherwise use current directory where command was run\n const cwd = flags.cwd ?? ctx.cwd ?? process.cwd();\n\n // Load config\n const fileConfig = await useConfig<{ eslintConfig?: string }>();\n\n // Show progress\n const loader = useLoader(`Running ${mode} analysis...`);\n loader.start();\n\n try {\n // Collect files based on scope\n let files: InputFile[] = [];\n let repoScope: string[] | undefined;\n\n // If --repos flag is provided, use git-scope resolver\n // Normalize repos to array (may come as string from CLI)\n const reposInput = flags.repos\n ? (Array.isArray(flags.repos) ? flags.repos : [flags.repos])\n : undefined;\n\n if (reposInput && reposInput.length > 0) {\n repoScope = reposInput;\n\n const scopedFiles = await resolveGitScope({\n cwd,\n repos: repoScope,\n includeStaged: scope === 'staged' || scope === 'changed',\n includeUnstaged: scope === 'changed',\n // Include untracked (new) files when explicitly scoping to repos\n includeUntracked: true,\n });\n\n files = scopedFiles.files;\n } else if (flags.files) {\n // Use explicitly provided files (with security validation)\n const filePaths = Array.isArray(flags.files) ? flags.files : [flags.files];\n const safeFilePaths = await filterSecurePaths(filePaths, cwd);\n\n const fileReadResults = await Promise.allSettled(\n safeFilePaths.map(async (filePath) => ({\n path: filePath,\n content: await ctx.runtime.fs.readFile(filePath, 'utf-8'),\n }))\n );\n\n files = fileReadResults\n .filter((r): r is PromiseFulfilledResult<InputFile> => r.status === 'fulfilled')\n .map(r => r.value);\n } else {\n // Resolve files based on file scope (all/changed/staged)\n let filePaths: string[] = [];\n\n switch (scope) {\n case 'all':\n // All TypeScript/JavaScript files\n // Run multiple globs in parallel since ctx.runtime.fs.glob might not support brace expansion\n const [tsFiles, tsxFiles, jsFiles, jsxFiles] = await Promise.all([\n ctx.runtime.fs.glob('**/*.ts', { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),\n ctx.runtime.fs.glob('**/*.tsx', { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),\n ctx.runtime.fs.glob('**/*.js', { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),\n ctx.runtime.fs.glob('**/*.jsx', { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),\n ]);\n filePaths = [...tsFiles, ...tsxFiles, ...jsFiles, ...jsxFiles];\n break;\n\n case 'staged':\n // Git staged files - try to detect repos with changes\n const reposWithChanges = await getReposWithChanges(cwd);\n if (reposWithChanges.length > 0) {\n const scopedFiles = await resolveGitScope({\n cwd,\n repos: reposWithChanges,\n includeStaged: true,\n includeUnstaged: false,\n includeUntracked: false,\n });\n files = scopedFiles.files;\n repoScope = reposWithChanges;\n } else {\n // Fallback to glob — run separately since glob may not support brace expansion\n const [tsF, tsxF, jsF, jsxF] = await Promise.all([\n ctx.runtime.fs.glob('**/*.ts', { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),\n ctx.runtime.fs.glob('**/*.tsx', { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),\n ctx.runtime.fs.glob('**/*.js', { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),\n ctx.runtime.fs.glob('**/*.jsx', { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),\n ]);\n filePaths = [...tsF, ...tsxF, ...jsF, ...jsxF];\n }\n break;\n\n case 'changed':\n default:\n // Changed files - try to detect repos with changes\n const changedRepos = await getReposWithChanges(cwd);\n if (changedRepos.length > 0) {\n const scopedFiles = await resolveGitScope({\n cwd,\n repos: changedRepos,\n includeStaged: true,\n includeUnstaged: true,\n includeUntracked: false,\n });\n files = scopedFiles.files;\n repoScope = changedRepos;\n } else {\n // Fallback to glob — run separately since glob may not support brace expansion\n const [tsC, tsxC, jsC, jsxC] = await Promise.all([\n ctx.runtime.fs.glob('**/*.ts', { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),\n ctx.runtime.fs.glob('**/*.tsx', { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),\n ctx.runtime.fs.glob('**/*.js', { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),\n ctx.runtime.fs.glob('**/*.jsx', { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] }),\n ]);\n filePaths = [...tsC, ...tsxC, ...jsC, ...jsxC];\n }\n break;\n }\n\n // If we used glob fallback, read file contents\n if (files.length === 0 && filePaths.length > 0) {\n // Apply security filtering (path traversal + pattern matching)\n const safeFilePaths = await filterSecurePaths(filePaths, cwd);\n\n // Read files with individual error handling\n const fileReadResults = await Promise.allSettled(\n safeFilePaths.map(async (filePath) => ({\n path: filePath,\n content: await ctx.runtime.fs.readFile(filePath, 'utf-8'),\n }))\n );\n\n // Collect successful reads, skip failed ones\n files = fileReadResults\n .filter((r): r is PromiseFulfilledResult<InputFile> => r.status === 'fulfilled')\n .map(r => r.value);\n }\n }\n\n // Run review\n const result = await runReview({\n files,\n mode,\n presetId: flags.preset ?? 'default',\n cwd,\n taskContext: flags.task,\n repoScope,\n config: {\n eslintConfig: flags.eslintConfig ?? fileConfig?.eslintConfig,\n },\n });\n\n loader.succeed(`Found ${result.findings.length} issue(s)`);\n\n // Output results\n if (flags.json) {\n ctx.ui?.json?.(result);\n } else {\n // Build sections\n const sections: Array<{ header?: string; items: string[] }> = [];\n\n // Summary section\n const counts = {\n blocker: result.findings.filter((f) => f.severity === 'blocker').length,\n high: result.findings.filter((f) => f.severity === 'high').length,\n medium: result.findings.filter((f) => f.severity === 'medium').length,\n low: result.findings.filter((f) => f.severity === 'low').length,\n info: result.findings.filter((f) => f.severity === 'info').length,\n };\n\n const summaryItems: string[] = [\n `Files: ${result.metadata.analyzedFiles}`,\n `Findings: ${result.findings.length}`,\n ];\n\n // Show task context if provided\n if (flags.task) {\n summaryItems.push(`Task: ${flags.task}`);\n }\n\n // Show repo scope if used\n if (repoScope && repoScope.length > 0) {\n summaryItems.push(`Repos: ${repoScope.join(', ')}`);\n }\n\n if (counts.blocker > 0) {\n summaryItems.push(`Blocker: ${counts.blocker}`);\n }\n if (counts.high > 0) {\n summaryItems.push(`High: ${counts.high}`);\n }\n if (counts.medium > 0) {\n summaryItems.push(`Medium: ${counts.medium}`);\n }\n if (counts.low > 0) {\n summaryItems.push(`Low: ${counts.low}`);\n }\n if (counts.info > 0) {\n summaryItems.push(`Info: ${counts.info}`);\n }\n\n summaryItems.push(`Engines: ${result.metadata.engines.join(', ')}`);\n\n // Show incremental stats if available (LLM modes with caching)\n const incr = result.metadata.incremental;\n if (incr) {\n if (incr.cachedFiles > 0) {\n summaryItems.push(`Cached: ${incr.cachedFiles} file(s) skipped`);\n }\n if (incr.newFindings > 0 || incr.knownFindings > 0 || incr.cachedFindings > 0) {\n const parts: string[] = [];\n if (incr.newFindings > 0) {\n parts.push(`${incr.newFindings} new`);\n }\n if (incr.knownFindings > 0) {\n parts.push(`${incr.knownFindings} known`);\n }\n if (incr.cachedFindings > 0) {\n parts.push(`${incr.cachedFindings} cached`);\n }\n summaryItems.push(`Breakdown: ${parts.join(', ')}`);\n }\n }\n\n sections.push({\n header: 'Summary',\n items: summaryItems,\n });\n\n // Findings section (top 10, sorted by severity)\n if (result.findings.length > 0) {\n // Sort by severity: blocker > high > medium > low > info\n const sortedFindings = [...result.findings].sort((a, b) => {\n const aOrder = SEVERITY_ORDER[a.severity] ?? 5;\n const bOrder = SEVERITY_ORDER[b.severity] ?? 5;\n return aOrder - bOrder;\n });\n\n const topFindings = sortedFindings.slice(0, 10);\n const findingsItems = topFindings.map((f) => {\n const loc = `${f.file}:${f.line}`;\n const severity = f.severity.toUpperCase();\n return `[${severity}] ${loc} - ${f.message}`;\n });\n\n if (result.findings.length > 10) {\n findingsItems.push(`... and ${result.findings.length - 10} more`);\n }\n\n sections.push({\n header: 'Findings',\n items: findingsItems,\n });\n }\n\n const timing = Date.now() - startTime;\n\n if (result.findings.length === 0) {\n ctx.ui?.success?.('No issues found', {\n title: 'Code Review',\n sections,\n timing,\n });\n } else {\n ctx.ui?.warn?.(`Found ${result.findings.length} issue(s)`, {\n title: 'Code Review',\n sections,\n timing,\n });\n }\n }\n\n // Exit code based on severity\n const blockerCount = result.findings.filter((f) => f.severity === 'blocker').length;\n const highCount = result.findings.filter((f) => f.severity === 'high').length;\n const agentReport = toAgentReport(result);\n\n if (blockerCount > 0) {\n return { exitCode: 1, result: agentReport };\n }\n\n if (mode === 'heuristic' && highCount > 0) {\n // In CI mode (heuristic), fail on high severity\n return { exitCode: 1, result: agentReport };\n }\n\n return { exitCode: 0, result: agentReport };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n loader.fail(`Review failed: ${message}`);\n ctx.ui?.error?.(message);\n ctx.platform.logger?.error?.('review:run failed', error instanceof Error ? error : new Error(message));\n const errorReport: AgentReviewReport = {\n passed: false,\n issues: [],\n summary: `Review error: ${message}`,\n };\n return { exitCode: 1, result: errorReport };\n }\n },\n },\n});\n"]}
1
+ {"version":3,"sources":["../../src/commands/run.ts"],"names":["relative"],"mappings":";;;;;;AA8DA,IAAM,cAAA,GAAyC;AAAA,EAC7C,OAAA,EAAS,CAAA;AAAA,EACT,IAAA,EAAM,CAAA;AAAA,EACN,MAAA,EAAQ,CAAA;AAAA,EACR,GAAA,EAAK,CAAA;AAAA,EACL,IAAA,EAAM;AACR,CAAA;AAMA,IAAM,wBAAA,GAA2B;AAAA,EAC/B,oBAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,qBAAA;AAAA,EACA,iBAAA;AAAA,EACA,mBAAA;AAAA,EACA,oBAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AAAA,EACA,YAAA;AAAA,EACA,mBAAA;AAAA,EACA,gBAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAA;AAMA,IAAM,uBAAA,GAA0B;AAAA,EAC9B,cAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,cAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA;AAOA,eAAe,eAAA,CAAgB,UAAkB,GAAA,EAA+B;AAC9E,EAAA,IAAI;AACF,IAAA,MAAM,YAAA,GAAoB,IAAA,CAAA,OAAA,CAAQ,GAAA,EAAK,QAAQ,CAAA;AAC/C,IAAA,MAAM,WAAA,GAAmB,aAAQ,GAAG,CAAA;AAGpC,IAAA,MAAM,WAAW,MAAM,QAAA,CAAS,YAAY,CAAA,CAAE,KAAA,CAAM,MAAM,YAAY,CAAA;AACtE,IAAA,MAAM,UAAU,MAAM,QAAA,CAAS,WAAW,CAAA,CAAE,KAAA,CAAM,MAAM,WAAW,CAAA;AAEnE,IAAA,MAAMA,SAAAA,GAAgB,IAAA,CAAA,QAAA,CAAS,OAAA,EAAS,QAAQ,CAAA;AAEhD,IAAA,OAAOA,SAAAA,KAAa,MAAM,CAACA,SAAAA,CAAS,WAAW,IAAI,CAAA,IAAK,CAAM,IAAA,CAAA,UAAA,CAAWA,SAAQ,CAAA;AAAA,EACnF,CAAA,CAAA,MAAQ;AAEN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAKA,eAAe,iBAAA,CAAkB,WAAqB,GAAA,EAAgC;AACpF,EAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,GAAA;AAAA,IAC5B,SAAA,CAAU,GAAA,CAAI,OAAM,QAAA,KAAY;AAE9B,MAAA,IAAI,CAAC,MAAM,eAAA,CAAgB,QAAA,EAAU,GAAG,CAAA,EAAG;AACzC,QAAA,OAAO,IAAA;AAAA,MACT;AAEA,MAAA,IAAI,wBAAwB,IAAA,CAAK,CAAA,OAAA,KAAW,QAAQ,IAAA,CAAK,QAAQ,CAAC,CAAA,EAAG;AACnE,QAAA,OAAO,IAAA;AAAA,MACT;AACA,MAAA,OAAO,QAAA;AAAA,IACT,CAAC;AAAA,GACH;AACA,EAAA,OAAO,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAmB,MAAM,IAAI,CAAA;AACtD;AAKA,SAAS,cAAc,MAAA,EAAyC;AAG9D,EAAA,MAAM,cAAA,GAAiB,OAAO,QAAA,CAAS,MAAA;AAAA,IACrC,CAAA,CAAA,KAAK,CAAA,CAAE,QAAA,KAAa,SAAA,IAAa,EAAE,QAAA,KAAa;AAAA,GAClD;AAGA,EAAA,MAAM,MAAA,GAAS,eAAe,MAAA,KAAW,CAAA;AAGzC,EAAA,MAAM,cAAA,GAAiB,CAAC,GAAG,MAAA,CAAO,QAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM;AACzD,IAAA,MAAM,MAAA,GAAS,cAAA,CAAe,CAAA,CAAE,QAAQ,CAAA,IAAK,CAAA;AAC7C,IAAA,MAAM,MAAA,GAAS,cAAA,CAAe,CAAA,CAAE,QAAQ,CAAA,IAAK,CAAA;AAC7C,IAAA,OAAO,MAAA,GAAS,MAAA;AAAA,EAClB,CAAC,CAAA;AAED,EAAA,MAAM,MAAA,GAAS,cAAA,CAAe,GAAA,CAAI,CAAA,CAAA,MAAM;AAAA,IACtC,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,SAAS,CAAA,CAAE,OAAA;AAAA,IACX,GAAA,EAAK,EAAE,UAAA,IAAc,yBAAA;AAAA,IACrB,UAAU,CAAA,CAAE,QAAA;AAAA,IACZ,MAAA,EAAQ,EAAE,MAAA,IAAU,SAAA;AAAA,IACpB,QAAS,CAAA,CAAE,MAAA,EAAQ,UAAA,CAAW,OAAO,IAAI,MAAA,GAAS,KAAA;AAAA;AAAA,IAElD,UAAA,EAAY,CAAA,CAAE,UAAA,KAAe,SAAA,GAAY,CAAA,GACrC,CAAA,CAAE,UAAA,KAAe,QAAA,GAAW,GAAA,GAC5B,CAAA,CAAE,UAAA,KAAe,WAAA,GAAc,GAAA,GAC/B;AAAA,GACN,CAAE,CAAA;AAGF,EAAA,MAAM,WAAA,GAAc,OAAO,QAAA,CAAS,MAAA,CAAO,OAAK,CAAA,CAAE,QAAA,KAAa,QAAQ,CAAA,CAAE,MAAA;AACzE,EAAA,MAAM,QAAA,GAAW,OAAO,QAAA,CAAS,MAAA,CAAO,OAAK,CAAA,CAAE,QAAA,KAAa,KAAK,CAAA,CAAE,MAAA;AACnE,EAAA,MAAM,SAAA,GAAY,OAAO,QAAA,CAAS,MAAA,CAAO,OAAK,CAAA,CAAE,QAAA,KAAa,MAAM,CAAA,CAAE,MAAA;AACrE,EAAA,MAAM,gBAAA,GAAmB,cAAc,QAAA,GAAW,SAAA;AAElD,EAAA,MAAM,UAAU,MAAA,GACZ,gBAAA,GAAmB,CAAA,GACjB,CAAA,eAAA,EAAkB,gBAAgB,CAAA,8BAAA,EAAiC,WAAW,CAAA,SAAA,EAAY,QAAQ,SAAS,SAAS,CAAA,OAAA,CAAA,GACpH,iCAAA,GACF,CAAA,eAAA,EAAkB,eAAe,MAAM,CAAA,iCAAA,CAAA;AAE3C,EAAA,OAAO,EAAE,MAAA,EAAQ,MAAA,EAAQ,OAAA,EAAQ;AACnC;AAEA,IAAO,cAAQ,aAAA,CAA8D;AAAA,EAC3E,EAAA,EAAI,YAAA;AAAA,EACJ,WAAA,EAAa,0BAAA;AAAA,EAEb,OAAA,EAAS;AAAA;AAAA,IAEP,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAAsE;AACxG,MAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAG3B,MAAA,MAAM,QAAQ,KAAA,CAAM,KAAA;AAGpB,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,IAAQ,WAAA;AAC3B,MAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,IAAS,SAAA;AAG7B,MAAA,MAAM,MAAM,KAAA,CAAM,GAAA,IAAO,GAAA,CAAI,GAAA,IAAO,QAAQ,GAAA,EAAI;AAGhD,MAAA,MAAM,UAAA,GAAa,MAAM,SAAA,EAAqC;AAG9D,MAAA,MAAM,MAAA,GAAS,SAAA,CAAU,CAAA,QAAA,EAAW,IAAI,CAAA,YAAA,CAAc,CAAA;AACtD,MAAA,MAAA,CAAO,KAAA,EAAM;AAEb,MAAA,IAAI;AAEF,QAAA,IAAI,QAAqB,EAAC;AAC1B,QAAA,IAAI,SAAA;AAIJ,QAAA,MAAM,UAAA,GAAa,KAAA,CAAM,KAAA,GACpB,KAAA,CAAM,OAAA,CAAQ,KAAA,CAAM,KAAK,CAAA,GAAI,KAAA,CAAM,KAAA,GAAQ,CAAC,KAAA,CAAM,KAAK,CAAA,GACxD,KAAA,CAAA;AAEJ,QAAA,IAAI,UAAA,IAAc,UAAA,CAAW,MAAA,GAAS,CAAA,EAAG;AACvC,UAAA,SAAA,GAAY,UAAA;AAEZ,UAAA,MAAM,WAAA,GAAc,MAAM,eAAA,CAAgB;AAAA,YACxC,GAAA;AAAA,YACA,KAAA,EAAO,SAAA;AAAA,YACP,aAAA,EAAe,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,SAAA;AAAA,YAC/C,iBAAiB,KAAA,KAAU,SAAA;AAAA;AAAA,YAE3B,gBAAA,EAAkB;AAAA,WACnB,CAAA;AAED,UAAA,KAAA,GAAQ,WAAA,CAAY,KAAA;AAAA,QACtB,CAAA,MAAA,IAAW,MAAM,KAAA,EAAO;AAEtB,UAAA,MAAM,YAAA,GAAe,KAAA,CAAM,OAAA,CAAQ,KAAA,CAAM,KAAK,IAAI,KAAA,CAAM,KAAA,GAAQ,CAAC,KAAA,CAAM,KAAK,CAAA;AAC5E,UAAA,MAAM,WAAqB,EAAC;AAC5B,UAAA,KAAA,MAAW,WAAW,YAAA,EAAc;AAClC,YAAA,MAAM,UAAU,MAAM,GAAA,CAAI,OAAA,CAAQ,EAAA,CAAG,KAAK,OAAA,EAAS;AAAA,cACjD,GAAA;AAAA,cACA,MAAA,EAAQ,CAAC,GAAG,wBAAwB;AAAA,aACrC,CAAA;AACD,YAAA,QAAA,CAAS,IAAA,CAAK,GAAG,OAAO,CAAA;AAAA,UAC1B;AACA,UAAA,MAAM,aAAA,GAAgB,MAAM,iBAAA,CAAkB,QAAA,EAAU,GAAG,CAAA;AAE3D,UAAA,MAAM,eAAA,GAAkB,MAAM,OAAA,CAAQ,UAAA;AAAA,YACpC,aAAA,CAAc,GAAA,CAAI,OAAO,QAAA,MAAc;AAAA,cACrC,IAAA,EAAM,QAAA;AAAA,cACN,SAAS,MAAM,GAAA,CAAI,QAAQ,EAAA,CAAG,QAAA,CAAS,UAAU,OAAO;AAAA,aAC1D,CAAE;AAAA,WACJ;AAEA,UAAA,KAAA,GAAQ,eAAA,CACL,MAAA,CAAO,CAAC,CAAA,KAA8C,CAAA,CAAE,MAAA,KAAW,WAAW,CAAA,CAC9E,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,KAAK,CAAA;AAAA,QACrB,CAAA,MAAO;AAEL,UAAA,IAAI,YAAsB,EAAC;AAE3B,UAAA,QAAQ,KAAA;AAAO,YACb,KAAK,KAAA;AACH,cAAA,SAAA,GAAY,MAAM,GAAA,CAAI,OAAA,CAAQ,EAAA,CAAG,IAAA,CAAK,MAAA,EAAQ,EAAE,GAAA,EAAK,MAAA,EAAQ,CAAC,GAAG,wBAAwB,GAAG,CAAA;AAC5F,cAAA;AAAA,YAEF,KAAK,QAAA;AACH,cAAA,MAAM,gBAAA,GAAmB,MAAM,mBAAA,CAAoB,GAAG,CAAA;AACtD,cAAA,IAAI,gBAAA,CAAiB,SAAS,CAAA,EAAG;AAC/B,gBAAA,MAAM,WAAA,GAAc,MAAM,eAAA,CAAgB;AAAA,kBACxC,GAAA;AAAA,kBACA,KAAA,EAAO,gBAAA;AAAA,kBACP,aAAA,EAAe,IAAA;AAAA,kBACf,eAAA,EAAiB,KAAA;AAAA,kBACjB,gBAAA,EAAkB;AAAA,iBACnB,CAAA;AACD,gBAAA,KAAA,GAAQ,WAAA,CAAY,KAAA;AACpB,gBAAA,SAAA,GAAY,gBAAA;AAAA,cACd;AACA,cAAA;AAAA,YAEF,KAAK,SAAA;AAAA,YACL;AACE,cAAA,MAAM,YAAA,GAAe,MAAM,mBAAA,CAAoB,GAAG,CAAA;AAClD,cAAA,IAAI,YAAA,CAAa,SAAS,CAAA,EAAG;AAC3B,gBAAA,MAAM,WAAA,GAAc,MAAM,eAAA,CAAgB;AAAA,kBACxC,GAAA;AAAA,kBACA,KAAA,EAAO,YAAA;AAAA,kBACP,aAAA,EAAe,IAAA;AAAA,kBACf,eAAA,EAAiB,IAAA;AAAA,kBACjB,gBAAA,EAAkB;AAAA,iBACnB,CAAA;AACD,gBAAA,KAAA,GAAQ,WAAA,CAAY,KAAA;AACpB,gBAAA,SAAA,GAAY,YAAA;AAAA,cACd;AACA,cAAA;AAAA;AAIJ,UAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,IAAK,SAAA,CAAU,SAAS,CAAA,EAAG;AAE9C,YAAA,MAAM,aAAA,GAAgB,MAAM,iBAAA,CAAkB,SAAA,EAAW,GAAG,CAAA;AAG5D,YAAA,MAAM,eAAA,GAAkB,MAAM,OAAA,CAAQ,UAAA;AAAA,cACpC,aAAA,CAAc,GAAA,CAAI,OAAO,QAAA,MAAc;AAAA,gBACrC,IAAA,EAAM,QAAA;AAAA,gBACN,SAAS,MAAM,GAAA,CAAI,QAAQ,EAAA,CAAG,QAAA,CAAS,UAAU,OAAO;AAAA,eAC1D,CAAE;AAAA,aACJ;AAGA,YAAA,KAAA,GAAQ,eAAA,CACL,MAAA,CAAO,CAAC,CAAA,KAA8C,CAAA,CAAE,MAAA,KAAW,WAAW,CAAA,CAC9E,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,KAAK,CAAA;AAAA,UACrB;AAAA,QACF;AAGA,QAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,UAAA,MAAA,CAAO,KAAK,oBAAoB,CAAA;AAChC,UAAA,MAAM,IAAA,GAAO,KAAA,KAAU,QAAA,GACnB,oFAAA,GACA,0GAAA;AACJ,UAAA,GAAA,CAAI,EAAA,EAAI,QAAQ,IAAI,CAAA;AACpB,UAAA,OAAO,EAAE,QAAA,EAAU,CAAA,EAAG,MAAA,EAAQ,EAAE,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,EAAC,EAAG,OAAA,EAAS,IAAA,EAAK,EAAE;AAAA,QAC7E;AAGA,QAAA,MAAM,MAAA,GAAS,MAAM,SAAA,CAAU;AAAA,UAC7B,KAAA;AAAA,UACA,IAAA;AAAA,UACA,QAAA,EAAU,MAAM,MAAA,IAAU,SAAA;AAAA,UAC1B,GAAA;AAAA,UACA,aAAa,KAAA,CAAM,IAAA;AAAA,UACnB,SAAA;AAAA,UACA,MAAA,EAAQ;AAAA,YACN,YAAA,EAAc,KAAA,CAAM,YAAA,IAAgB,UAAA,EAAY;AAAA;AAClD,SACD,CAAA;AAED,QAAA,MAAA,CAAO,OAAA,CAAQ,CAAA,MAAA,EAAS,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA,SAAA,CAAW,CAAA;AAGzD,QAAA,IAAI,MAAM,IAAA,EAAM;AACd,UAAA,GAAA,CAAI,EAAA,EAAI,OAAO,MAAM,CAAA;AAAA,QACvB,CAAA,MAAO;AAEL,UAAA,MAAM,WAAwD,EAAC;AAG/D,UAAA,MAAM,MAAA,GAAS;AAAA,YACb,OAAA,EAAS,OAAO,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,KAAa,SAAS,CAAA,CAAE,MAAA;AAAA,YACjE,IAAA,EAAM,OAAO,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,KAAa,MAAM,CAAA,CAAE,MAAA;AAAA,YAC3D,MAAA,EAAQ,OAAO,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,KAAa,QAAQ,CAAA,CAAE,MAAA;AAAA,YAC/D,GAAA,EAAK,OAAO,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,KAAa,KAAK,CAAA,CAAE,MAAA;AAAA,YACzD,IAAA,EAAM,OAAO,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,KAAa,MAAM,CAAA,CAAE;AAAA,WAC7D;AAEA,UAAA,MAAM,YAAA,GAAyB;AAAA,YAC7B,CAAA,OAAA,EAAU,MAAA,CAAO,QAAA,CAAS,aAAa,CAAA,CAAA;AAAA,YACvC,CAAA,UAAA,EAAa,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA;AAAA,WACrC;AAGA,UAAA,IAAI,MAAM,IAAA,EAAM;AACd,YAAA,YAAA,CAAa,IAAA,CAAK,CAAA,MAAA,EAAS,KAAA,CAAM,IAAI,CAAA,CAAE,CAAA;AAAA,UACzC;AAGA,UAAA,IAAI,SAAA,IAAa,SAAA,CAAU,MAAA,GAAS,CAAA,EAAG;AACrC,YAAA,YAAA,CAAa,KAAK,CAAA,OAAA,EAAU,SAAA,CAAU,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,UACpD;AAEA,UAAA,IAAI,MAAA,CAAO,UAAU,CAAA,EAAG;AACtB,YAAA,YAAA,CAAa,IAAA,CAAK,CAAA,SAAA,EAAY,MAAA,CAAO,OAAO,CAAA,CAAE,CAAA;AAAA,UAChD;AACA,UAAA,IAAI,MAAA,CAAO,OAAO,CAAA,EAAG;AACnB,YAAA,YAAA,CAAa,IAAA,CAAK,CAAA,MAAA,EAAS,MAAA,CAAO,IAAI,CAAA,CAAE,CAAA;AAAA,UAC1C;AACA,UAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,YAAA,YAAA,CAAa,IAAA,CAAK,CAAA,QAAA,EAAW,MAAA,CAAO,MAAM,CAAA,CAAE,CAAA;AAAA,UAC9C;AACA,UAAA,IAAI,MAAA,CAAO,MAAM,CAAA,EAAG;AAClB,YAAA,YAAA,CAAa,IAAA,CAAK,CAAA,KAAA,EAAQ,MAAA,CAAO,GAAG,CAAA,CAAE,CAAA;AAAA,UACxC;AACA,UAAA,IAAI,MAAA,CAAO,OAAO,CAAA,EAAG;AACnB,YAAA,YAAA,CAAa,IAAA,CAAK,CAAA,MAAA,EAAS,MAAA,CAAO,IAAI,CAAA,CAAE,CAAA;AAAA,UAC1C;AAEA,UAAA,YAAA,CAAa,IAAA,CAAK,YAAY,MAAA,CAAO,QAAA,CAAS,QAAQ,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAGlE,UAAA,MAAM,IAAA,GAAO,OAAO,QAAA,CAAS,WAAA;AAC7B,UAAA,IAAI,IAAA,EAAM;AACR,YAAA,IAAI,IAAA,CAAK,cAAc,CAAA,EAAG;AACxB,cAAA,YAAA,CAAa,IAAA,CAAK,CAAA,QAAA,EAAW,IAAA,CAAK,WAAW,CAAA,gBAAA,CAAkB,CAAA;AAAA,YACjE;AACA,YAAA,IAAI,IAAA,CAAK,cAAc,CAAA,IAAK,IAAA,CAAK,gBAAgB,CAAA,IAAK,IAAA,CAAK,iBAAiB,CAAA,EAAG;AAC7E,cAAA,MAAM,QAAkB,EAAC;AACzB,cAAA,IAAI,IAAA,CAAK,cAAc,CAAA,EAAG;AACxB,gBAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAG,IAAA,CAAK,WAAW,CAAA,IAAA,CAAM,CAAA;AAAA,cACtC;AACA,cAAA,IAAI,IAAA,CAAK,gBAAgB,CAAA,EAAG;AAC1B,gBAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAG,IAAA,CAAK,aAAa,CAAA,MAAA,CAAQ,CAAA;AAAA,cAC1C;AACA,cAAA,IAAI,IAAA,CAAK,iBAAiB,CAAA,EAAG;AAC3B,gBAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAG,IAAA,CAAK,cAAc,CAAA,OAAA,CAAS,CAAA;AAAA,cAC5C;AACA,cAAA,YAAA,CAAa,KAAK,CAAA,WAAA,EAAc,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,YACpD;AAAA,UACF;AAEA,UAAA,QAAA,CAAS,IAAA,CAAK;AAAA,YACZ,MAAA,EAAQ,SAAA;AAAA,YACR,KAAA,EAAO;AAAA,WACR,CAAA;AAGD,UAAA,IAAI,MAAA,CAAO,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG;AAE9B,YAAA,MAAM,cAAA,GAAiB,CAAC,GAAG,MAAA,CAAO,QAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM;AACzD,cAAA,MAAM,MAAA,GAAS,cAAA,CAAe,CAAA,CAAE,QAAQ,CAAA,IAAK,CAAA;AAC7C,cAAA,MAAM,MAAA,GAAS,cAAA,CAAe,CAAA,CAAE,QAAQ,CAAA,IAAK,CAAA;AAC7C,cAAA,OAAO,MAAA,GAAS,MAAA;AAAA,YAClB,CAAC,CAAA;AAED,YAAA,MAAM,WAAA,GAAc,cAAA,CAAe,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAC9C,YAAA,MAAM,aAAA,GAAgB,WAAA,CAAY,GAAA,CAAI,CAAC,CAAA,KAAM;AAC3C,cAAA,MAAM,MAAM,CAAA,EAAG,CAAA,CAAE,IAAI,CAAA,CAAA,EAAI,EAAE,IAAI,CAAA,CAAA;AAC/B,cAAA,MAAM,QAAA,GAAW,CAAA,CAAE,QAAA,CAAS,WAAA,EAAY;AACxC,cAAA,OAAO,IAAI,QAAQ,CAAA,EAAA,EAAK,GAAG,CAAA,GAAA,EAAM,EAAE,OAAO,CAAA,CAAA;AAAA,YAC5C,CAAC,CAAA;AAED,YAAA,IAAI,MAAA,CAAO,QAAA,CAAS,MAAA,GAAS,EAAA,EAAI;AAC/B,cAAA,aAAA,CAAc,KAAK,CAAA,QAAA,EAAW,MAAA,CAAO,QAAA,CAAS,MAAA,GAAS,EAAE,CAAA,KAAA,CAAO,CAAA;AAAA,YAClE;AAEA,YAAA,QAAA,CAAS,IAAA,CAAK;AAAA,cACZ,MAAA,EAAQ,UAAA;AAAA,cACR,KAAA,EAAO;AAAA,aACR,CAAA;AAAA,UACH;AAEA,UAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAE5B,UAAA,IAAI,MAAA,CAAO,QAAA,CAAS,MAAA,KAAW,CAAA,EAAG;AAChC,YAAA,GAAA,CAAI,EAAA,EAAI,UAAU,iBAAA,EAAmB;AAAA,cACnC,KAAA,EAAO,aAAA;AAAA,cACP,QAAA;AAAA,cACA;AAAA,aACD,CAAA;AAAA,UACH,CAAA,MAAO;AACL,YAAA,GAAA,CAAI,IAAI,IAAA,GAAO,CAAA,MAAA,EAAS,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA,SAAA,CAAA,EAAa;AAAA,cACzD,KAAA,EAAO,aAAA;AAAA,cACP,QAAA;AAAA,cACA;AAAA,aACD,CAAA;AAAA,UACH;AAAA,QACF;AAGA,QAAA,MAAM,YAAA,GAAe,OAAO,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,KAAa,SAAS,CAAA,CAAE,MAAA;AAC7E,QAAA,MAAM,SAAA,GAAY,OAAO,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,KAAa,MAAM,CAAA,CAAE,MAAA;AACvE,QAAA,MAAM,WAAA,GAAc,cAAc,MAAM,CAAA;AAExC,QAAA,IAAI,eAAe,CAAA,EAAG;AACpB,UAAA,OAAO,EAAE,QAAA,EAAU,CAAA,EAAG,MAAA,EAAQ,WAAA,EAAY;AAAA,QAC5C;AAEA,QAAA,IAAI,IAAA,KAAS,WAAA,IAAe,SAAA,GAAY,CAAA,EAAG;AAEzC,UAAA,OAAO,EAAE,QAAA,EAAU,CAAA,EAAG,MAAA,EAAQ,WAAA,EAAY;AAAA,QAC5C;AAEA,QAAA,OAAO,EAAE,QAAA,EAAU,CAAA,EAAG,MAAA,EAAQ,WAAA,EAAY;AAAA,MAC5C,SAAS,KAAA,EAAO;AACd,QAAA,MAAM,UAAU,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AACrE,QAAA,MAAA,CAAO,IAAA,CAAK,CAAA,eAAA,EAAkB,OAAO,CAAA,CAAE,CAAA;AACvC,QAAA,GAAA,CAAI,EAAA,EAAI,QAAQ,OAAO,CAAA;AACvB,QAAA,GAAA,CAAI,QAAA,CAAS,MAAA,EAAQ,KAAA,GAAQ,mBAAA,EAAqB,KAAA,YAAiB,QAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,OAAO,CAAC,CAAA;AACrG,QAAA,MAAM,WAAA,GAAiC;AAAA,UACrC,MAAA,EAAQ,KAAA;AAAA,UACR,QAAQ,EAAC;AAAA,UACT,OAAA,EAAS,iBAAiB,OAAO,CAAA;AAAA,SACnC;AACA,QAAA,OAAO,EAAE,QAAA,EAAU,CAAA,EAAG,MAAA,EAAQ,WAAA,EAAY;AAAA,MAC5C;AAAA,IACF;AAAA;AAEJ,CAAC","file":"run.js","sourcesContent":["/**\n * review:run command\n * Run code review analysis\n */\n\nimport {\n defineCommand,\n useLoader,\n useConfig,\n type PluginContextV3,\n type CLIInput,\n type CommandResult,\n} from '@kb-labs/sdk';\nimport type { ReviewMode, ReviewResult, InputFile } from '@kb-labs/review-contracts';\nimport { runReview, resolveGitScope, getReposWithChanges } from '@kb-labs/review-core';\nimport * as path from 'node:path';\nimport { realpath } from 'node:fs/promises';\n\n/**\n * Flags for review:run command\n */\ntype RunFlags = {\n mode?: ReviewMode;\n scope?: 'all' | 'changed' | 'staged';\n repos?: string[];\n task?: string;\n preset?: string;\n files?: string[];\n eslintConfig?: string;\n cwd?: string;\n json?: boolean;\n agent?: boolean;\n};\n\n/**\n * Agent-friendly review report.\n * Simplified format for automated workflows.\n */\ninterface AgentReviewReport {\n /** Can the agent proceed (commit/merge)? */\n passed: boolean;\n /** Issues that must be fixed before proceeding */\n issues: Array<{\n file: string;\n line: number;\n problem: string;\n fix: string;\n severity: 'blocker' | 'high' | 'medium' | 'low' | 'info';\n /** Rule ID (e.g., \"rule:security/no-eval\" or \"llm-lite:security\") */\n ruleId: string;\n /** Source: \"rule\" (matched project rule) or \"llm\" (ad-hoc finding) */\n source: 'rule' | 'llm';\n /** Confidence score (0.0-1.0) from verification engine */\n confidence: number;\n }>;\n /** One-line summary for logs */\n summary: string;\n}\n\n/**\n * Severity order for sorting (lower = more critical)\n */\nconst SEVERITY_ORDER: Record<string, number> = {\n blocker: 0,\n high: 1,\n medium: 2,\n low: 3,\n info: 4,\n};\n\n/**\n * Security-sensitive patterns for file filtering.\n * Shared across all file filtering operations for consistency.\n */\nconst SECURITY_IGNORE_PATTERNS = [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n '**/.git/**',\n '**/.kb/analytics/**',\n '**/.kb/cache/**',\n '**/.kb/storage/**',\n '**/.kb/database/**',\n '**/.env',\n '**/.env.*',\n '**/.ssh/**',\n '**/credentials/**',\n '**/password/**',\n '**/*.pem',\n '**/*.key',\n '**/*.secret',\n] as const;\n\n/**\n * Regex patterns for additional security filtering.\n * Used as a second layer of defense after glob ignore.\n */\nconst SECURITY_REGEX_PATTERNS = [\n /node_modules/,\n /\\.git\\//,\n /\\.env$/,\n /\\.env\\./,\n /\\.ssh/,\n /\\/etc\\//,\n /\\/usr\\//,\n /\\/var\\//,\n /credentials/i,\n /password/i,\n /\\.pem$/,\n /\\.key$/,\n /\\.secret$/,\n] as const;\n\n/**\n * Validate that a file path is within the allowed directory.\n * Prevents path traversal attacks including symlink bypass.\n * Uses fs.realpath() to resolve symlinks and path.relative() for cross-platform safety.\n */\nasync function isPathWithinCwd(filePath: string, cwd: string): Promise<boolean> {\n try {\n const resolvedPath = path.resolve(cwd, filePath);\n const resolvedCwd = path.resolve(cwd);\n\n // Resolve symlinks to prevent symlink bypass attacks\n const realPath = await realpath(resolvedPath).catch(() => resolvedPath);\n const realCwd = await realpath(resolvedCwd).catch(() => resolvedCwd);\n\n const relative = path.relative(realCwd, realPath);\n // Path is within cwd if relative path exists, doesn't start with '..', and isn't absolute\n return relative !== '' && !relative.startsWith('..') && !path.isAbsolute(relative);\n } catch {\n // If path doesn't exist or can't be resolved, reject it\n return false;\n }\n}\n\n/**\n * Filter file paths for security concerns.\n */\nasync function filterSecurePaths(filePaths: string[], cwd: string): Promise<string[]> {\n const results = await Promise.all(\n filePaths.map(async filePath => {\n // Path traversal check (including symlink resolution)\n if (!await isPathWithinCwd(filePath, cwd)) {\n return null;\n }\n // Security pattern check\n if (SECURITY_REGEX_PATTERNS.some(pattern => pattern.test(filePath))) {\n return null;\n }\n return filePath;\n })\n );\n return results.filter((p): p is string => p !== null);\n}\n\n/**\n * Transform ReviewResult to agent-friendly format\n */\nfunction toAgentReport(result: ReviewResult): AgentReviewReport {\n // Blocking issues = blocker and high severity only\n // Medium/low/info are acceptable and don't block the review\n const blockingIssues = result.findings.filter(\n f => f.severity === 'blocker' || f.severity === 'high'\n );\n\n // Pass when no blocking issues (medium and below are acceptable)\n const passed = blockingIssues.length === 0;\n\n // Sort by severity: blocker > high > medium > low > info\n const sortedFindings = [...result.findings].sort((a, b) => {\n const aOrder = SEVERITY_ORDER[a.severity] ?? 5;\n const bOrder = SEVERITY_ORDER[b.severity] ?? 5;\n return aOrder - bOrder;\n });\n\n const issues = sortedFindings.map(f => ({\n file: f.file,\n line: f.line,\n problem: f.message,\n fix: f.suggestion ?? 'Review and fix manually',\n severity: f.severity as 'blocker' | 'high' | 'medium' | 'low' | 'info',\n ruleId: f.ruleId ?? 'unknown',\n source: (f.ruleId?.startsWith('rule:') ? 'rule' : 'llm') as 'rule' | 'llm',\n // Map categorical confidence to numeric score (default 0.5 for undefined/unknown)\n confidence: f.confidence === 'certain' ? 1.0\n : f.confidence === 'likely' ? 0.8\n : f.confidence === 'heuristic' ? 0.6\n : 0.5,\n }));\n\n // Count non-blocking issues for summary\n const mediumCount = result.findings.filter(f => f.severity === 'medium').length;\n const lowCount = result.findings.filter(f => f.severity === 'low').length;\n const infoCount = result.findings.filter(f => f.severity === 'info').length;\n const nonBlockingCount = mediumCount + lowCount + infoCount;\n\n const summary = passed\n ? nonBlockingCount > 0\n ? `Review passed. ${nonBlockingCount} non-blocking issue(s) found (${mediumCount} medium, ${lowCount} low, ${infoCount} info).`\n : 'Review passed. No issues found.'\n : `Review failed. ${blockingIssues.length} blocking issue(s) must be fixed.`;\n\n return { passed, issues, summary };\n}\n\nexport default defineCommand<unknown, CLIInput<RunFlags>, AgentReviewReport>({\n id: 'review:run',\n description: 'Run code review analysis',\n\n handler: {\n // eslint-disable-next-line sonarjs/cognitive-complexity -- Main orchestration handler: coordinates input modes (repos/files/scope), git resolution, security filtering, output formats (agent/json/human), and severity-based exit codes\n async execute(ctx: PluginContextV3, input: CLIInput<RunFlags>): Promise<CommandResult<AgentReviewReport>> {\n const startTime = Date.now();\n\n // Extract flags from input\n const flags = input.flags;\n\n // Parse input\n const mode = flags.mode ?? 'heuristic';\n const scope = flags.scope ?? 'changed';\n\n // Use --cwd flag if provided, otherwise use current directory where command was run\n const cwd = flags.cwd ?? ctx.cwd ?? process.cwd();\n\n // Load config\n const fileConfig = await useConfig<{ eslintConfig?: string }>();\n\n // Show progress\n const loader = useLoader(`Running ${mode} analysis...`);\n loader.start();\n\n try {\n // Collect files based on scope\n let files: InputFile[] = [];\n let repoScope: string[] | undefined;\n\n // If --repos flag is provided, use git-scope resolver\n // Normalize repos to array (may come as string from CLI)\n const reposInput = flags.repos\n ? (Array.isArray(flags.repos) ? flags.repos : [flags.repos])\n : undefined;\n\n if (reposInput && reposInput.length > 0) {\n repoScope = reposInput;\n\n const scopedFiles = await resolveGitScope({\n cwd,\n repos: repoScope,\n includeStaged: scope === 'staged' || scope === 'changed',\n includeUnstaged: scope === 'changed',\n // Include untracked (new) files when explicitly scoping to repos\n includeUntracked: true,\n });\n\n files = scopedFiles.files;\n } else if (flags.files) {\n // Expand glob patterns first, then read files\n const filePatterns = Array.isArray(flags.files) ? flags.files : [flags.files];\n const expanded: string[] = [];\n for (const pattern of filePatterns) {\n const matches = await ctx.runtime.fs.glob(pattern, {\n cwd,\n ignore: [...SECURITY_IGNORE_PATTERNS],\n });\n expanded.push(...matches);\n }\n const safeFilePaths = await filterSecurePaths(expanded, cwd);\n\n const fileReadResults = await Promise.allSettled(\n safeFilePaths.map(async (filePath) => ({\n path: filePath,\n content: await ctx.runtime.fs.readFile(filePath, 'utf-8'),\n }))\n );\n\n files = fileReadResults\n .filter((r): r is PromiseFulfilledResult<InputFile> => r.status === 'fulfilled')\n .map(r => r.value);\n } else {\n // Resolve files based on file scope (all/changed/staged)\n let filePaths: string[] = [];\n\n switch (scope) {\n case 'all':\n filePaths = await ctx.runtime.fs.glob('**/*', { cwd, ignore: [...SECURITY_IGNORE_PATTERNS] });\n break;\n\n case 'staged':\n const reposWithChanges = await getReposWithChanges(cwd);\n if (reposWithChanges.length > 0) {\n const scopedFiles = await resolveGitScope({\n cwd,\n repos: reposWithChanges,\n includeStaged: true,\n includeUnstaged: false,\n includeUntracked: false,\n });\n files = scopedFiles.files;\n repoScope = reposWithChanges;\n }\n break;\n\n case 'changed':\n default:\n const changedRepos = await getReposWithChanges(cwd);\n if (changedRepos.length > 0) {\n const scopedFiles = await resolveGitScope({\n cwd,\n repos: changedRepos,\n includeStaged: true,\n includeUnstaged: true,\n includeUntracked: true,\n });\n files = scopedFiles.files;\n repoScope = changedRepos;\n }\n break;\n }\n\n // If we used glob fallback, read file contents\n if (files.length === 0 && filePaths.length > 0) {\n // Apply security filtering (path traversal + pattern matching)\n const safeFilePaths = await filterSecurePaths(filePaths, cwd);\n\n // Read files with individual error handling\n const fileReadResults = await Promise.allSettled(\n safeFilePaths.map(async (filePath) => ({\n path: filePath,\n content: await ctx.runtime.fs.readFile(filePath, 'utf-8'),\n }))\n );\n\n // Collect successful reads, skip failed ones\n files = fileReadResults\n .filter((r): r is PromiseFulfilledResult<InputFile> => r.status === 'fulfilled')\n .map(r => r.value);\n }\n }\n\n // No files found — give a clear, actionable message instead of a cryptic engine error\n if (files.length === 0) {\n loader.fail('No files to review');\n const hint = scope === 'staged'\n ? 'No staged files found. Stage files with `git add` first, or use `--scope=changed`.'\n : 'No changed files found. Use `--scope=all` to review all files, or `--files` to specify files explicitly.';\n ctx.ui?.error?.(hint);\n return { exitCode: 1, result: { passed: false, issues: [], summary: hint } };\n }\n\n // Run review\n const result = await runReview({\n files,\n mode,\n presetId: flags.preset ?? 'default',\n cwd,\n taskContext: flags.task,\n repoScope,\n config: {\n eslintConfig: flags.eslintConfig ?? fileConfig?.eslintConfig,\n },\n });\n\n loader.succeed(`Found ${result.findings.length} issue(s)`);\n\n // Output results\n if (flags.json) {\n ctx.ui?.json?.(result);\n } else {\n // Build sections\n const sections: Array<{ header?: string; items: string[] }> = [];\n\n // Summary section\n const counts = {\n blocker: result.findings.filter((f) => f.severity === 'blocker').length,\n high: result.findings.filter((f) => f.severity === 'high').length,\n medium: result.findings.filter((f) => f.severity === 'medium').length,\n low: result.findings.filter((f) => f.severity === 'low').length,\n info: result.findings.filter((f) => f.severity === 'info').length,\n };\n\n const summaryItems: string[] = [\n `Files: ${result.metadata.analyzedFiles}`,\n `Findings: ${result.findings.length}`,\n ];\n\n // Show task context if provided\n if (flags.task) {\n summaryItems.push(`Task: ${flags.task}`);\n }\n\n // Show repo scope if used\n if (repoScope && repoScope.length > 0) {\n summaryItems.push(`Repos: ${repoScope.join(', ')}`);\n }\n\n if (counts.blocker > 0) {\n summaryItems.push(`Blocker: ${counts.blocker}`);\n }\n if (counts.high > 0) {\n summaryItems.push(`High: ${counts.high}`);\n }\n if (counts.medium > 0) {\n summaryItems.push(`Medium: ${counts.medium}`);\n }\n if (counts.low > 0) {\n summaryItems.push(`Low: ${counts.low}`);\n }\n if (counts.info > 0) {\n summaryItems.push(`Info: ${counts.info}`);\n }\n\n summaryItems.push(`Engines: ${result.metadata.engines.join(', ')}`);\n\n // Show incremental stats if available (LLM modes with caching)\n const incr = result.metadata.incremental;\n if (incr) {\n if (incr.cachedFiles > 0) {\n summaryItems.push(`Cached: ${incr.cachedFiles} file(s) skipped`);\n }\n if (incr.newFindings > 0 || incr.knownFindings > 0 || incr.cachedFindings > 0) {\n const parts: string[] = [];\n if (incr.newFindings > 0) {\n parts.push(`${incr.newFindings} new`);\n }\n if (incr.knownFindings > 0) {\n parts.push(`${incr.knownFindings} known`);\n }\n if (incr.cachedFindings > 0) {\n parts.push(`${incr.cachedFindings} cached`);\n }\n summaryItems.push(`Breakdown: ${parts.join(', ')}`);\n }\n }\n\n sections.push({\n header: 'Summary',\n items: summaryItems,\n });\n\n // Findings section (top 10, sorted by severity)\n if (result.findings.length > 0) {\n // Sort by severity: blocker > high > medium > low > info\n const sortedFindings = [...result.findings].sort((a, b) => {\n const aOrder = SEVERITY_ORDER[a.severity] ?? 5;\n const bOrder = SEVERITY_ORDER[b.severity] ?? 5;\n return aOrder - bOrder;\n });\n\n const topFindings = sortedFindings.slice(0, 10);\n const findingsItems = topFindings.map((f) => {\n const loc = `${f.file}:${f.line}`;\n const severity = f.severity.toUpperCase();\n return `[${severity}] ${loc} - ${f.message}`;\n });\n\n if (result.findings.length > 10) {\n findingsItems.push(`... and ${result.findings.length - 10} more`);\n }\n\n sections.push({\n header: 'Findings',\n items: findingsItems,\n });\n }\n\n const timing = Date.now() - startTime;\n\n if (result.findings.length === 0) {\n ctx.ui?.success?.('No issues found', {\n title: 'Code Review',\n sections,\n timing,\n });\n } else {\n ctx.ui?.warn?.(`Found ${result.findings.length} issue(s)`, {\n title: 'Code Review',\n sections,\n timing,\n });\n }\n }\n\n // Exit code based on severity\n const blockerCount = result.findings.filter((f) => f.severity === 'blocker').length;\n const highCount = result.findings.filter((f) => f.severity === 'high').length;\n const agentReport = toAgentReport(result);\n\n if (blockerCount > 0) {\n return { exitCode: 1, result: agentReport };\n }\n\n if (mode === 'heuristic' && highCount > 0) {\n // In CI mode (heuristic), fail on high severity\n return { exitCode: 1, result: agentReport };\n }\n\n return { exitCode: 0, result: agentReport };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n loader.fail(`Review failed: ${message}`);\n ctx.ui?.error?.(message);\n ctx.platform.logger?.error?.('review:run failed', error instanceof Error ? error : new Error(message));\n const errorReport: AgentReviewReport = {\n passed: false,\n issues: [],\n summary: `Review error: ${message}`,\n };\n return { exitCode: 1, result: errorReport };\n }\n },\n },\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kb-labs/review-entry",
3
- "version": "2.47.0",
3
+ "version": "2.53.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -13,10 +13,10 @@
13
13
  ],
14
14
  "dependencies": {
15
15
  "chalk": "^5.3.0",
16
- "@kb-labs/review-contracts": "2.47.0",
17
- "@kb-labs/shared-cli-ui": "2.47.0",
18
- "@kb-labs/sdk": "2.21.0",
19
- "@kb-labs/review-core": "2.47.0"
16
+ "@kb-labs/review-contracts": "2.53.0",
17
+ "@kb-labs/sdk": "2.21.1",
18
+ "@kb-labs/review-core": "2.53.0",
19
+ "@kb-labs/shared-cli-ui": "2.53.0"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/node": "^24.3.3",
@@ -24,7 +24,7 @@
24
24
  "tsup": "^8.5.0",
25
25
  "typescript": "^5.6.3",
26
26
  "vitest": "^3.2.4",
27
- "@kb-labs/devkit": "2.47.0"
27
+ "@kb-labs/devkit": "2.53.0"
28
28
  },
29
29
  "engines": {
30
30
  "node": ">=20.0.0",