@better-vibe/branch-narrator 1.0.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +464 -539
- package/dist/analyzers/index.d.ts +4 -0
- package/dist/analyzers/index.d.ts.map +1 -1
- package/dist/analyzers/lockfiles.d.ts.map +1 -1
- package/dist/analyzers/python-config.d.ts +26 -0
- package/dist/analyzers/python-config.d.ts.map +1 -0
- package/dist/analyzers/python-dependencies.d.ts +21 -0
- package/dist/analyzers/python-dependencies.d.ts.map +1 -0
- package/dist/analyzers/python-migrations.d.ts +26 -0
- package/dist/analyzers/python-migrations.d.ts.map +1 -0
- package/dist/analyzers/python-routes.d.ts +15 -0
- package/dist/analyzers/python-routes.d.ts.map +1 -0
- package/dist/cli.js +355 -13718
- package/dist/core/ids.d.ts.map +1 -1
- package/dist/core/types.d.ts +32 -2
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.js +286 -6631
- package/dist/profiles/index.d.ts +14 -1
- package/dist/profiles/index.d.ts.map +1 -1
- package/dist/profiles/python.d.ts +15 -0
- package/dist/profiles/python.d.ts.map +1 -0
- package/dist/render/markdown.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/cli.js.map +0 -101
- package/dist/index.js.map +0 -60
package/dist/index.js.map
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/core/change-set.ts", "../src/core/errors.ts", "../src/core/sorting.ts", "../src/git/collector.ts", "../src/git/parser.ts", "../src/core/filters.ts", "../src/analyzers/file-summary.ts", "../src/analyzers/file-category.ts", "../src/core/evidence.ts", "../src/analyzers/route-detector.ts", "../src/analyzers/supabase.ts", "../src/analyzers/env-var.ts", "../src/analyzers/cloudflare.ts", "../src/analyzers/vitest.ts", "../src/analyzers/dependencies.ts", "../src/analyzers/security-files.ts", "../src/git/batch.ts", "../src/analyzers/reactRouterRoutes.ts", "../src/analyzers/test-parity.ts", "../src/analyzers/impact.ts", "../src/analyzers/large-diff.ts", "../src/analyzers/lockfiles.ts", "../src/analyzers/test-gaps.ts", "../src/analyzers/sql-risks.ts", "../src/analyzers/ci-workflows.ts", "../src/analyzers/infra.ts", "../src/analyzers/api-contracts.ts", "../src/analyzers/stencil.ts", "../src/analyzers/next-routes.ts", "../src/analyzers/graphql.ts", "../src/analyzers/typescript-config.ts", "../src/analyzers/tailwind.ts", "../src/analyzers/monorepo.ts", "../src/analyzers/package-exports.ts", "../src/analyzers/vue-routes.ts", "../src/analyzers/astro-routes.ts", "../src/analyzers/index.ts", "../src/profiles/default.ts", "../src/profiles/sveltekit.ts", "../src/profiles/react.ts", "../src/profiles/stencil.ts", "../src/profiles/next.ts", "../src/profiles/vue.ts", "../src/profiles/astro.ts", "../src/profiles/library.ts", "../src/profiles/index.ts", "../src/render/risk-score.ts", "../src/index.ts", "../src/core/logger.ts", "../src/render/markdown.ts", "../src/render/json.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"/**\n * ChangeSet builder utilities.\n */\n\nimport type {\n ChangeSet,\n FileChange,\n FileDiff,\n FileStatus,\n Hunk,\n} from \"./types.js\";\n\n/**\n * Parse git diff --name-status output into FileChange array.\n */\nexport function parseNameStatus(output: string): FileChange[] {\n const lines = output.trim().split(\"\\n\").filter(Boolean);\n const changes: FileChange[] = [];\n\n for (const line of lines) {\n const parts = line.split(\"\\t\");\n const statusCode = parts[0];\n\n if (statusCode.startsWith(\"R\")) {\n // Rename: R100\\told\\tnew\n changes.push({\n path: parts[2],\n status: \"renamed\",\n oldPath: parts[1],\n });\n } else if (statusCode === \"A\") {\n changes.push({ path: parts[1], status: \"added\" });\n } else if (statusCode === \"M\") {\n changes.push({ path: parts[1], status: \"modified\" });\n } else if (statusCode === \"D\") {\n changes.push({ path: parts[1], status: \"deleted\" });\n }\n }\n\n return changes;\n}\n\n/**\n * Convert parse-diff File to our FileDiff structure.\n */\nexport function convertParsedDiff(\n parsed: ParseDiffFile[],\n fileChanges: FileChange[]\n): FileDiff[] {\n const statusMap = new Map<string, FileStatus>();\n const oldPathMap = new Map<string, string>();\n\n for (const fc of fileChanges) {\n statusMap.set(fc.path, fc.status);\n if (fc.oldPath) {\n oldPathMap.set(fc.path, fc.oldPath);\n statusMap.set(fc.oldPath, fc.status);\n }\n }\n\n return parsed.map((file) => {\n const path = file.to === \"/dev/null\" ? file.from! : file.to!;\n const normalizedPath = path.replace(/^[ab]\\//, \"\");\n const status = statusMap.get(normalizedPath) ?? \"modified\";\n\n const hunks: Hunk[] = (file.chunks || []).map((chunk) => {\n const additions: string[] = [];\n const deletions: string[] = [];\n\n for (const change of chunk.changes || []) {\n if (change.type === \"add\") {\n additions.push(change.content.slice(1)); // Remove leading +\n } else if (change.type === \"del\") {\n deletions.push(change.content.slice(1)); // Remove leading -\n }\n }\n\n return {\n oldStart: chunk.oldStart,\n oldLines: chunk.oldLines,\n newStart: chunk.newStart,\n newLines: chunk.newLines,\n content: chunk.content,\n additions,\n deletions,\n };\n });\n\n return {\n path: normalizedPath,\n status,\n oldPath: oldPathMap.get(normalizedPath),\n hunks,\n };\n });\n}\n\n/**\n * Build a ChangeSet from raw git outputs.\n */\nexport function buildChangeSet(params: {\n base: string;\n head: string;\n nameStatusOutput: string;\n parsedDiffs: ParseDiffFile[];\n basePackageJson?: Record<string, unknown>;\n headPackageJson?: Record<string, unknown>;\n}): ChangeSet {\n const files = parseNameStatus(params.nameStatusOutput);\n const diffs = convertParsedDiff(params.parsedDiffs, files);\n\n return {\n base: params.base,\n head: params.head,\n files,\n diffs,\n basePackageJson: params.basePackageJson,\n headPackageJson: params.headPackageJson,\n };\n}\n\n// ============================================================================\n// Type definitions for parse-diff (simplified)\n// ============================================================================\n\nexport interface ParseDiffChange {\n type: \"add\" | \"del\" | \"normal\";\n content: string;\n ln?: number;\n ln1?: number;\n ln2?: number;\n}\n\nexport interface ParseDiffChunk {\n content: string;\n oldStart: number;\n oldLines: number;\n newStart: number;\n newLines: number;\n changes: ParseDiffChange[];\n}\n\nexport interface ParseDiffFile {\n from?: string;\n to?: string;\n chunks: ParseDiffChunk[];\n deletions: number;\n additions: number;\n}\n\n// ============================================================================\n// Test Helpers\n// ============================================================================\n\n/**\n * Create a minimal ChangeSet for testing purposes.\n */\nexport function createTestChangeSet(\n overrides: Partial<ChangeSet> = {}\n): ChangeSet {\n return {\n base: \"main\",\n head: \"HEAD\",\n files: [],\n diffs: [],\n ...overrides,\n };\n}\n\n/**\n * Create a FileDiff with additions for testing.\n */\nexport function createTestFileDiff(\n path: string,\n additions: string[],\n status: FileStatus = \"modified\"\n): FileDiff {\n return {\n path,\n status,\n hunks: [\n {\n oldStart: 1,\n oldLines: 0,\n newStart: 1,\n newLines: additions.length,\n content: \"@@ -0,0 +1 @@\",\n additions,\n deletions: [],\n },\n ],\n };\n}\n\n",
|
|
6
|
-
"/**\n * Custom error classes for branch-narrator.\n */\n\nexport class BranchNarratorError extends Error {\n constructor(\n message: string,\n public readonly exitCode: number = 1\n ) {\n super(message);\n this.name = \"BranchNarratorError\";\n }\n}\n\nexport class NotAGitRepoError extends BranchNarratorError {\n constructor(path: string = process.cwd()) {\n super(\n `Not a git repository: ${path}\\n` +\n \"Please run this command from within a git repository.\",\n 1\n );\n this.name = \"NotAGitRepoError\";\n }\n}\n\nexport class InvalidRefError extends BranchNarratorError {\n constructor(ref: string) {\n super(\n `Invalid git reference: ${ref}\\n` +\n \"Please ensure the branch or commit exists.\",\n 1\n );\n this.name = \"InvalidRefError\";\n }\n}\n\nexport class NoDiffError extends BranchNarratorError {\n constructor(base: string, head: string) {\n super(\n `No differences found between ${base} and ${head}.\\n` +\n \"The branches may be identical or one may not exist.\",\n 1\n );\n this.name = \"NoDiffError\";\n }\n}\n\nexport class GitCommandError extends BranchNarratorError {\n constructor(\n command: string,\n public readonly stderr: string\n ) {\n super(`Git command failed: ${command}\\n${stderr}`, 1);\n this.name = \"GitCommandError\";\n }\n}\n\n",
|
|
7
|
-
"/**\n * Sorting utilities for deterministic output ordering.\n */\n\nimport type { Finding, RiskFlag, Evidence, RiskFlagEvidence } from \"./types.js\";\n\n/**\n * Normalize path for consistent sorting across platforms.\n * Converts backslashes to forward slashes and normalizes case.\n */\nexport function normalizePath(path: string): string {\n return path.replace(/\\\\/g, \"/\").toLowerCase();\n}\n\n/**\n * Compare two paths lexicographically.\n */\nexport function comparePaths(a: string, b: string): number {\n const normA = normalizePath(a);\n const normB = normalizePath(b);\n return normA.localeCompare(normB);\n}\n\n/**\n * Sort risk flags deterministically.\n * Order: category asc, effectiveScore desc, ruleKey asc, flagId asc\n */\nexport function sortRiskFlags(flags: RiskFlag[]): RiskFlag[] {\n return [...flags].sort((a, b) => {\n // Category ascending\n const catCompare = a.category.localeCompare(b.category);\n if (catCompare !== 0) return catCompare;\n\n // Effective score descending\n const scoreCompare = b.effectiveScore - a.effectiveScore;\n if (scoreCompare !== 0) return scoreCompare;\n\n // Rule key ascending\n const ruleCompare = a.ruleKey.localeCompare(b.ruleKey);\n if (ruleCompare !== 0) return ruleCompare;\n\n // Flag instance ID ascending\n return a.flagId.localeCompare(b.flagId);\n });\n}\n\n/**\n * Sort findings deterministically.\n * Order: type asc, file asc (if available), location asc\n */\nexport function sortFindings(findings: Finding[]): Finding[] {\n return [...findings].sort((a, b) => {\n // Type ascending\n const typeCompare = a.type.localeCompare(b.type);\n if (typeCompare !== 0) return typeCompare;\n\n // Get first file from evidence (if available)\n const getFirstFile = (f: Finding): string => {\n if (f.evidence && f.evidence.length > 0) {\n return f.evidence[0]!.file;\n }\n return \"\";\n };\n\n const fileA = getFirstFile(a);\n const fileB = getFirstFile(b);\n \n if (fileA && fileB) {\n const fileCompare = comparePaths(fileA, fileB);\n if (fileCompare !== 0) return fileCompare;\n }\n\n // Get first line number from evidence (if available)\n const getFirstLine = (f: Finding): number => {\n if (f.evidence && f.evidence.length > 0) {\n const ev = f.evidence[0]!;\n if (ev.line !== undefined) return ev.line;\n if (ev.hunk?.newStart !== undefined) return ev.hunk.newStart;\n }\n return 0;\n };\n\n const lineA = getFirstLine(a);\n const lineB = getFirstLine(b);\n \n return lineA - lineB;\n });\n}\n\n/**\n * Sort evidence deterministically.\n * Order: file asc, preserve line order within each file\n */\nexport function sortEvidence(evidence: Evidence[]): Evidence[] {\n return [...evidence].sort((a, b) => {\n // File ascending\n const fileCompare = comparePaths(a.file, b.file);\n if (fileCompare !== 0) return fileCompare;\n\n // Line number ascending (if available)\n const lineA = a.line ?? (a.hunk?.newStart ?? 0);\n const lineB = b.line ?? (b.hunk?.newStart ?? 0);\n \n return lineA - lineB;\n });\n}\n\n/**\n * Sort risk flag evidence deterministically.\n * Order: file asc, preserve line order within each file\n */\nexport function sortRiskFlagEvidence(evidence: RiskFlagEvidence[]): RiskFlagEvidence[] {\n return [...evidence].sort((a, b) => {\n // File ascending\n const fileCompare = comparePaths(a.file, b.file);\n if (fileCompare !== 0) return fileCompare;\n\n // Hunk order (if available) - extract line numbers from hunk string\n if (a.hunk && b.hunk) {\n const extractLineNum = (hunk: string): number => {\n const match = hunk.match(/\\+(\\d+)/);\n return match ? parseInt(match[1], 10) : 0;\n };\n return extractLineNum(a.hunk) - extractLineNum(b.hunk);\n }\n \n return 0;\n });\n}\n\n/**\n * Sort file paths deterministically.\n */\nexport function sortFilePaths(paths: string[]): string[] {\n return [...paths].sort(comparePaths);\n}\n\n/**\n * Create a sorted object from key-value pairs.\n * Ensures object keys are in a stable order.\n */\nexport function createSortedObject<T>(\n entries: Array<[string, T]>\n): Record<string, T> {\n const sorted = [...entries].sort((a, b) => a[0].localeCompare(b[0]));\n const result: Record<string, T> = {};\n for (const [key, value] of sorted) {\n result[key] = value;\n }\n return result;\n}\n",
|
|
8
|
-
"/**\n * Git command execution and data collection.\n */\n\nimport { execa } from \"execa\";\nimport parseDiff from \"parse-diff\";\nimport {\n buildChangeSet,\n type ParseDiffFile,\n} from \"../core/change-set.js\";\nimport {\n GitCommandError,\n InvalidRefError,\n NotAGitRepoError,\n} from \"../core/errors.js\";\nimport type { ChangeSet, DiffMode } from \"../core/types.js\";\n\n/**\n * Check if the current directory is inside a git repository.\n */\nexport async function isGitRepo(cwd: string = process.cwd()): Promise<boolean> {\n try {\n const result = await execa(\"git\", [\"rev-parse\", \"--is-inside-work-tree\"], {\n cwd,\n reject: false,\n });\n return result.exitCode === 0 && result.stdout.trim() === \"true\";\n } catch {\n return false;\n }\n}\n\n/**\n * Detect the default branch of the remote origin.\n * Falls back to \"main\" if detection fails.\n */\nexport async function getDefaultBranch(cwd: string = process.cwd()): Promise<string> {\n try {\n // Try to get the symbolic ref for origin/HEAD\n const result = await execa(\"git\", [\"symbolic-ref\", \"refs/remotes/origin/HEAD\"], {\n cwd,\n reject: false,\n });\n\n if (result.exitCode === 0) {\n // Output is like \"refs/remotes/origin/main\"\n // Split by slash and get the last part\n const parts = result.stdout.trim().split(\"/\");\n if (parts.length > 0) {\n return parts[parts.length - 1];\n }\n }\n } catch {\n // Ignore errors\n }\n\n return \"main\";\n}\n\n/**\n * Validate that a git reference exists.\n */\nexport async function refExists(\n ref: string,\n cwd: string = process.cwd()\n): Promise<boolean> {\n try {\n const result = await execa(\"git\", [\"rev-parse\", \"--verify\", ref], {\n cwd,\n reject: false,\n });\n return result.exitCode === 0;\n } catch {\n return false;\n }\n}\n\n/**\n * Build git diff --name-status arguments based on mode.\n */\nfunction buildNameStatusArgs(options: {\n mode: DiffMode;\n base?: string;\n head?: string;\n}): string[] {\n const args = [\"diff\", \"--name-status\", \"--find-renames\"];\n\n switch (options.mode) {\n case \"branch\":\n args.push(`${options.base}..${options.head}`);\n break;\n case \"unstaged\":\n // Working tree vs index (no additional args)\n break;\n case \"staged\":\n args.push(\"--staged\");\n break;\n case \"all\":\n args.push(\"HEAD\");\n break;\n }\n\n return args;\n}\n\n/**\n * Build git diff arguments based on mode.\n */\nfunction buildUnifiedDiffArgs(options: {\n mode: DiffMode;\n base?: string;\n head?: string;\n}): string[] {\n const args = [\"diff\", \"--unified=3\"];\n\n switch (options.mode) {\n case \"branch\":\n args.push(`${options.base}..${options.head}`);\n break;\n case \"unstaged\":\n // Working tree vs index (no additional args)\n break;\n case \"staged\":\n args.push(\"--staged\");\n break;\n case \"all\":\n args.push(\"HEAD\");\n break;\n }\n\n return args;\n}\n\n/**\n * Get git diff --name-status output based on mode.\n */\nexport async function getNameStatusByMode(\n options: {\n mode: DiffMode;\n base?: string;\n head?: string;\n },\n cwd: string = process.cwd()\n): Promise<string> {\n const args = buildNameStatusArgs(options);\n\n try {\n const result = await execa(\"git\", args, { cwd });\n return result.stdout;\n } catch (error) {\n if (error instanceof Error && \"stderr\" in error) {\n throw new GitCommandError(\n `git ${args.join(\" \")}`,\n String((error as { stderr: unknown }).stderr)\n );\n }\n throw error;\n }\n}\n\n/**\n * Get unified diff output based on mode.\n */\nexport async function getUnifiedDiffByMode(\n options: {\n mode: DiffMode;\n base?: string;\n head?: string;\n },\n cwd: string = process.cwd()\n): Promise<string> {\n const args = buildUnifiedDiffArgs(options);\n\n try {\n const result = await execa(\"git\", args, { cwd });\n return result.stdout;\n } catch (error) {\n if (error instanceof Error && \"stderr\" in error) {\n throw new GitCommandError(\n `git ${args.join(\" \")}`,\n String((error as { stderr: unknown }).stderr)\n );\n }\n throw error;\n }\n}\n\n/**\n * Get git diff --name-status output.\n * If head is null, compares working directory against base.\n * @deprecated Use getNameStatusByMode instead\n */\nexport async function getNameStatus(\n base: string,\n head: string | null,\n cwd: string = process.cwd()\n): Promise<string> {\n try {\n const args = head\n ? [\"diff\", \"--name-status\", \"--find-renames\", `${base}..${head}`]\n : [\"diff\", \"--name-status\", \"--find-renames\", base];\n const result = await execa(\"git\", args, { cwd });\n return result.stdout;\n } catch (error) {\n if (error instanceof Error && \"stderr\" in error) {\n const ref = head ? `${base}..${head}` : base;\n throw new GitCommandError(\n `git diff --name-status ${ref}`,\n String((error as { stderr: unknown }).stderr)\n );\n }\n throw error;\n }\n}\n\n/**\n * Get unified diff output.\n * If head is null, compares working directory against base.\n * @deprecated Use getUnifiedDiffByMode instead\n */\nexport async function getUnifiedDiff(\n base: string,\n head: string | null,\n cwd: string = process.cwd()\n): Promise<string> {\n try {\n const args = head\n ? [\"diff\", \"--unified=3\", `${base}..${head}`]\n : [\"diff\", \"--unified=3\", base];\n const result = await execa(\"git\", args, { cwd });\n return result.stdout;\n } catch (error) {\n if (error instanceof Error && \"stderr\" in error) {\n const ref = head ? `${base}..${head}` : base;\n throw new GitCommandError(\n `git diff ${ref}`,\n String((error as { stderr: unknown }).stderr)\n );\n }\n throw error;\n }\n}\n\n/**\n * Get file content at a specific ref.\n */\nexport async function getFileAtRef(\n ref: string,\n filePath: string,\n cwd: string = process.cwd()\n): Promise<string | null> {\n try {\n const result = await execa(\"git\", [\"show\", `${ref}:${filePath}`], {\n cwd,\n reject: false,\n });\n if (result.exitCode === 0) {\n return result.stdout;\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Parse package.json content safely.\n */\nfunction parsePackageJson(content: string | null): Record<string, unknown> | undefined {\n if (!content) return undefined;\n try {\n return JSON.parse(content) as Record<string, unknown>;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Get untracked files (new files not yet added to git).\n */\nexport async function getUntrackedFiles(\n cwd: string = process.cwd()\n): Promise<string[]> {\n try {\n const result = await execa(\n \"git\",\n [\"ls-files\", \"--others\", \"--exclude-standard\"],\n { cwd }\n );\n return result.stdout.trim().split(\"\\n\").filter(Boolean);\n } catch {\n return [];\n }\n}\n\n/**\n * Read file content from working directory.\n */\nasync function readWorkingFile(\n filePath: string,\n cwd: string\n): Promise<string | null> {\n try {\n const { readFile } = await import(\"node:fs/promises\");\n const { join } = await import(\"node:path\");\n return await readFile(join(cwd, filePath), \"utf-8\");\n } catch {\n return null;\n }\n}\n\n/**\n * Create synthetic diff entries for untracked files.\n */\nasync function createUntrackedDiffs(\n untrackedFiles: string[],\n cwd: string\n): Promise<{ nameStatus: string; diffs: ParseDiffFile[] }> {\n const nameStatusLines: string[] = [];\n const diffs: ParseDiffFile[] = [];\n\n for (const file of untrackedFiles) {\n // Skip binary files and very large files\n if (isBinaryFile(file)) {\n nameStatusLines.push(`A\\t${file}`);\n continue;\n }\n\n const content = await readWorkingFile(file, cwd);\n if (content === null) continue;\n\n nameStatusLines.push(`A\\t${file}`);\n\n // Create a synthetic diff for the file\n const lines = content.split(\"\\n\");\n const changes = lines.map((line, idx) => ({\n type: \"add\" as const,\n content: \"+\" + line,\n ln: idx + 1,\n }));\n\n diffs.push({\n from: \"/dev/null\",\n to: file,\n chunks: [\n {\n content: `@@ -0,0 +1,${lines.length} @@`,\n oldStart: 0,\n oldLines: 0,\n newStart: 1,\n newLines: lines.length,\n changes,\n },\n ],\n deletions: 0,\n additions: lines.length,\n });\n }\n\n return {\n nameStatus: nameStatusLines.join(\"\\n\"),\n diffs,\n };\n}\n\n/**\n * Set of binary file extensions for O(1) lookup.\n * Pre-compiled at module load time for maximum performance.\n */\nconst BINARY_EXTENSIONS = new Set([\n \".png\", \".jpg\", \".jpeg\", \".gif\", \".webp\", \".ico\", \".svg\",\n \".woff\", \".woff2\", \".ttf\", \".eot\", \".otf\",\n \".zip\", \".tar\", \".gz\", \".tgz\", \".rar\",\n \".pdf\", \".doc\", \".docx\", \".xls\", \".xlsx\",\n \".exe\", \".dll\", \".so\", \".dylib\",\n \".mp3\", \".mp4\", \".wav\", \".avi\", \".mov\",\n \".lockb\", // bun.lockb is binary\n]);\n\n/**\n * Check if a file is likely binary based on extension.\n * Uses Set lookup for O(1) performance.\n */\nfunction isBinaryFile(path: string): boolean {\n const lowerPath = path.toLowerCase();\n // Find the last dot to extract extension\n const lastDot = lowerPath.lastIndexOf(\".\");\n if (lastDot === -1) return false;\n const ext = lowerPath.slice(lastDot);\n return BINARY_EXTENSIONS.has(ext);\n}\n\n/**\n * Get current package.json from working directory.\n */\nasync function getWorkingPackageJson(\n cwd: string\n): Promise<Record<string, unknown> | undefined> {\n try {\n const { readFile } = await import(\"node:fs/promises\");\n const { join } = await import(\"node:path\");\n const content = await readFile(join(cwd, \"package.json\"), \"utf-8\");\n return JSON.parse(content) as Record<string, unknown>;\n } catch {\n return undefined;\n }\n}\n\n/**\n * @deprecated Use CollectChangeSetOptionsV2 with mode instead\n */\nexport interface CollectChangeSetOptions {\n base: string;\n head: string;\n cwd?: string;\n uncommitted?: boolean;\n}\n\nexport interface CollectChangeSetOptionsV2 {\n mode: DiffMode;\n base?: string;\n head?: string;\n cwd?: string;\n includeUntracked?: boolean;\n}\n\n/**\n * Collect all git diff data and build a ChangeSet.\n * Supports both legacy options (base/head/uncommitted) and new mode-based options.\n */\nexport async function collectChangeSet(\n baseOrOptions: string | CollectChangeSetOptions | CollectChangeSetOptionsV2,\n head?: string,\n cwd: string = process.cwd()\n): Promise<ChangeSet> {\n // Handle v2 options with mode\n if (typeof baseOrOptions === \"object\" && \"mode\" in baseOrOptions) {\n return collectChangeSetByMode(baseOrOptions);\n }\n\n // Handle both old signature and legacy options object\n let options: CollectChangeSetOptions;\n if (typeof baseOrOptions === \"string\") {\n options = { base: baseOrOptions, head: head!, cwd };\n } else {\n options = baseOrOptions;\n cwd = options.cwd ?? process.cwd();\n }\n\n const { base, uncommitted } = options;\n const headRef = uncommitted ? null : options.head;\n\n // Validate git repo\n if (!(await isGitRepo(cwd))) {\n throw new NotAGitRepoError(cwd);\n }\n\n // Validate refs\n if (!(await refExists(base, cwd))) {\n throw new InvalidRefError(base);\n }\n if (headRef && !(await refExists(headRef, cwd))) {\n throw new InvalidRefError(headRef);\n }\n\n // Collect data for tracked files\n const [nameStatusOutput, unifiedDiff, basePackageContent] = await Promise.all([\n getNameStatus(base, headRef, cwd),\n getUnifiedDiff(base, headRef, cwd),\n getFileAtRef(base, \"package.json\", cwd),\n ]);\n\n // Parse unified diff for tracked files\n let parsedDiffs = parseDiff(unifiedDiff) as ParseDiffFile[];\n let finalNameStatus = nameStatusOutput;\n\n // If uncommitted mode, also include untracked files\n if (uncommitted) {\n const untrackedFiles = await getUntrackedFiles(cwd);\n if (untrackedFiles.length > 0) {\n const untrackedData = await createUntrackedDiffs(untrackedFiles, cwd);\n\n // Merge untracked files into results\n if (untrackedData.nameStatus) {\n finalNameStatus = finalNameStatus\n ? `${finalNameStatus}\\n${untrackedData.nameStatus}`\n : untrackedData.nameStatus;\n }\n parsedDiffs = [...parsedDiffs, ...untrackedData.diffs];\n }\n }\n\n // Get head package.json (from ref or working directory)\n const headPackageContent = uncommitted\n ? await getWorkingPackageJson(cwd)\n : parsePackageJson(await getFileAtRef(headRef!, \"package.json\", cwd));\n\n // Build ChangeSet\n return buildChangeSet({\n base,\n head: uncommitted ? \"WORKING\" : options.head,\n nameStatusOutput: finalNameStatus,\n parsedDiffs,\n basePackageJson: parsePackageJson(basePackageContent),\n headPackageJson: uncommitted ? headPackageContent : parsePackageJson(\n await getFileAtRef(options.head, \"package.json\", cwd)\n ),\n });\n}\n\n/**\n * Collect all git diff data and build a ChangeSet using mode-based options.\n */\nasync function collectChangeSetByMode(\n options: CollectChangeSetOptionsV2\n): Promise<ChangeSet> {\n const cwd = options.cwd ?? process.cwd();\n const includeUntracked = options.includeUntracked ?? (options.mode === \"all\" || options.mode === \"unstaged\");\n\n // Validate git repo\n if (!(await isGitRepo(cwd))) {\n throw new NotAGitRepoError(cwd);\n }\n\n // Validate refs only for branch mode\n if (options.mode === \"branch\") {\n if (!options.base) {\n throw new InvalidRefError(\"base (required for branch mode)\");\n }\n if (!options.head) {\n throw new InvalidRefError(\"head (required for branch mode)\");\n }\n if (!(await refExists(options.base, cwd))) {\n throw new InvalidRefError(options.base);\n }\n if (!(await refExists(options.head, cwd))) {\n throw new InvalidRefError(options.head);\n }\n }\n\n // For non-branch modes that reference HEAD, validate HEAD exists\n if (options.mode === \"staged\" || options.mode === \"all\") {\n if (!(await refExists(\"HEAD\", cwd))) {\n throw new InvalidRefError(\"HEAD\");\n }\n }\n\n // Collect data based on mode\n const [nameStatusOutput, unifiedDiff] = await Promise.all([\n getNameStatusByMode(options, cwd),\n getUnifiedDiffByMode(options, cwd),\n ]);\n\n // Parse unified diff for tracked files\n let parsedDiffs = parseDiff(unifiedDiff) as ParseDiffFile[];\n let finalNameStatus = nameStatusOutput;\n\n // Include untracked files if requested (default for \"all\" mode)\n if (includeUntracked && options.mode !== \"branch\") {\n const untrackedFiles = await getUntrackedFiles(cwd);\n if (untrackedFiles.length > 0) {\n const untrackedData = await createUntrackedDiffs(untrackedFiles, cwd);\n\n // Merge untracked files into results\n if (untrackedData.nameStatus) {\n finalNameStatus = finalNameStatus\n ? `${finalNameStatus}\\n${untrackedData.nameStatus}`\n : untrackedData.nameStatus;\n }\n parsedDiffs = [...parsedDiffs, ...untrackedData.diffs];\n }\n }\n\n // Determine base/head for ChangeSet based on mode\n let base: string;\n let head: string;\n let basePackageJson: Record<string, unknown> | undefined;\n let headPackageJson: Record<string, unknown> | undefined;\n\n switch (options.mode) {\n case \"branch\":\n base = options.base!;\n head = options.head!;\n basePackageJson = parsePackageJson(await getFileAtRef(base, \"package.json\", cwd));\n headPackageJson = parsePackageJson(await getFileAtRef(head, \"package.json\", cwd));\n break;\n\n case \"unstaged\":\n base = \"INDEX\";\n head = \"WORKING\";\n // For unstaged, the \"base\" is the index - get from HEAD since that's what's staged\n basePackageJson = await getWorkingPackageJson(cwd); // Index is close to working for most cases\n headPackageJson = await getWorkingPackageJson(cwd);\n break;\n\n case \"staged\":\n base = \"HEAD\";\n head = \"INDEX\";\n basePackageJson = parsePackageJson(await getFileAtRef(\"HEAD\", \"package.json\", cwd));\n headPackageJson = await getWorkingPackageJson(cwd); // Staged content\n break;\n\n case \"all\":\n base = \"HEAD\";\n head = \"WORKING\";\n basePackageJson = parsePackageJson(await getFileAtRef(\"HEAD\", \"package.json\", cwd));\n headPackageJson = await getWorkingPackageJson(cwd);\n break;\n }\n\n // Build ChangeSet\n return buildChangeSet({\n base,\n head,\n nameStatusOutput: finalNameStatus,\n parsedDiffs,\n basePackageJson,\n headPackageJson,\n });\n}\n\n/**\n * Get git repository root.\n */\nexport async function getRepoRoot(cwd: string = process.cwd()): Promise<string> {\n try {\n const result = await execa(\"git\", [\n \"rev-parse\",\n \"--show-toplevel\",\n ], { cwd });\n return result.stdout.trim();\n } catch {\n return cwd;\n }\n}\n\n/**\n * Check if working directory is dirty.\n */\nexport async function isWorkingDirDirty(cwd: string = process.cwd()): Promise<boolean> {\n try {\n const result = await execa(\"git\", [\n \"diff-index\",\n \"--quiet\",\n \"HEAD\",\n \"--\",\n ], { cwd, reject: false });\n return result.exitCode !== 0;\n } catch {\n return false;\n }\n}\n",
|
|
9
|
-
"/**\n * Diff parsing utilities.\n */\n\nimport type { FileDiff, Hunk } from \"../core/types.js\";\n\n/**\n * Line with its position in the new file.\n */\nexport interface LineWithNumber {\n line: string;\n lineNumber: number;\n}\n\n/**\n * Get all additions from a FileDiff.\n */\nexport function getAdditions(diff: FileDiff): string[] {\n return diff.hunks.flatMap((hunk) => hunk.additions);\n}\n\n/**\n * Get all additions from a FileDiff with their line numbers in the new file.\n * This is useful for SARIF output and other tools that need precise locations.\n */\nexport function getAdditionsWithLineNumbers(diff: FileDiff): LineWithNumber[] {\n const result: LineWithNumber[] = [];\n\n for (const hunk of diff.hunks) {\n let currentLine = hunk.newStart;\n\n // Parse hunk content to track line numbers accurately\n const lines = hunk.content.split('\\n');\n for (const line of lines) {\n if (line.startsWith('@@')) {\n // Skip hunk header\n continue;\n }\n\n if (line.startsWith('+') && !line.startsWith('+++')) {\n // This is an addition\n result.push({\n line: line.slice(1), // Remove leading +\n lineNumber: currentLine,\n });\n currentLine++;\n } else if (!line.startsWith('-')) {\n // Context line or empty - increment line number\n currentLine++;\n }\n // Deletion lines don't increment the new file line number\n }\n }\n\n return result;\n}\n\n/**\n * Get all deletions from a FileDiff.\n */\nexport function getDeletions(diff: FileDiff): string[] {\n return diff.hunks.flatMap((hunk) => hunk.deletions);\n}\n\n/**\n * Get all changes (additions + deletions) from a FileDiff.\n * Optimized to iterate hunks once instead of twice.\n */\nexport function getAllChanges(diff: FileDiff): string[] {\n const changes: string[] = [];\n for (const hunk of diff.hunks) {\n changes.push(...hunk.additions, ...hunk.deletions);\n }\n return changes;\n}\n\n/**\n * Get combined content of all hunks.\n */\nexport function getHunkContent(hunks: Hunk[]): string {\n return hunks.map((h) => [...h.additions, ...h.deletions].join(\"\\n\")).join(\"\\n\");\n}\n\n/**\n * Check if a file path matches a pattern.\n */\nexport function matchesPattern(path: string, pattern: RegExp): boolean {\n return pattern.test(path);\n}\n\n/**\n * Filter diffs by path pattern.\n */\nexport function filterDiffsByPath(\n diffs: FileDiff[],\n pattern: RegExp\n): FileDiff[] {\n return diffs.filter((diff) => matchesPattern(diff.path, pattern));\n}\n\n/**\n * Check if any addition line matches a pattern.\n */\nexport function hasAdditionMatching(diff: FileDiff, pattern: RegExp): boolean {\n return getAdditions(diff).some((line) => pattern.test(line));\n}\n\n/**\n * Find all matches of a pattern in additions.\n */\nexport function findAdditionMatches(\n diff: FileDiff,\n pattern: RegExp\n): RegExpMatchArray[] {\n const matches: RegExpMatchArray[] = [];\n // Optimization: Hoist RegExp creation out of the loop\n const globalPattern = new RegExp(pattern.source, \"g\" + pattern.flags.replace(\"g\", \"\"));\n\n for (const line of getAdditions(diff)) {\n // Reset lastIndex for each line since we are reusing the same RegExp instance\n globalPattern.lastIndex = 0;\n\n let match;\n while ((match = globalPattern.exec(line)) !== null) {\n matches.push(match);\n }\n }\n return matches;\n}\n\n/**\n * Match with its line number in the new file.\n */\nexport interface MatchWithLineNumber {\n match: RegExpMatchArray;\n lineNumber: number;\n line: string;\n}\n\n/**\n * Find all matches of a pattern in additions with line numbers.\n * This is useful for SARIF output and other tools that need precise locations.\n */\nexport function findAdditionMatchesWithLineNumbers(\n diff: FileDiff,\n pattern: RegExp\n): MatchWithLineNumber[] {\n const matches: MatchWithLineNumber[] = [];\n const globalPattern = new RegExp(pattern.source, \"g\" + pattern.flags.replace(\"g\", \"\"));\n\n const additionsWithLines = getAdditionsWithLineNumbers(diff);\n\n for (const { line, lineNumber } of additionsWithLines) {\n globalPattern.lastIndex = 0;\n\n let match;\n while ((match = globalPattern.exec(line)) !== null) {\n matches.push({\n match,\n lineNumber,\n line,\n });\n }\n }\n\n return matches;\n}\n",
|
|
10
|
-
"/**\n * File filtering utilities to exclude build artifacts and generated files.\n */\n\n// Default exclusion patterns\nexport const DEFAULT_EXCLUDES = [\n \"**/*.d.ts\",\n \"**/*.map\",\n \"**/*.min.js\",\n \"**/*.min.css\",\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/.next/**\",\n \"**/.svelte-kit/**\",\n \"**/.nuxt/**\",\n \"**/out/**\",\n \"**/.cache/**\",\n \"**/.parcel-cache/**\",\n \"**/vendor/**\",\n \"**/*.log\",\n \"**/package-lock.json\",\n \"**/yarn.lock\",\n \"**/pnpm-lock.yaml\",\n \"**/bun.lock\",\n // Archive files\n \"**/*.tgz\",\n \"**/*.tar.gz\",\n \"**/*.zip\",\n];\n\n// Patterns for files that should be excluded from analysis\nconst EXCLUDED_PATTERNS: RegExp[] = [\n // Build output\n /^dist\\//,\n /^build\\//,\n /^\\.next\\//,\n /^\\.svelte-kit\\//,\n /^\\.nuxt\\//,\n /^out\\//,\n\n // Dependencies\n /^node_modules\\//,\n /^vendor\\//,\n\n // Source maps\n /\\.map$/,\n\n // Generated types\n /\\.d\\.ts$/,\n\n // Minified files\n /\\.min\\.(js|css)$/,\n\n // Bundled files\n /^\\.cache\\//,\n /^\\.parcel-cache\\//,\n];\n\n/**\n * Check if a file path should be excluded from analysis.\n */\nexport function shouldExcludeFile(path: string): boolean {\n return EXCLUDED_PATTERNS.some((pattern) => pattern.test(path));\n}\n\n/**\n * Filter out excluded files from a list of paths.\n */\nexport function filterExcludedFiles(paths: string[]): string[] {\n return paths.filter((path) => !shouldExcludeFile(path));\n}\n\n",
|
|
11
|
-
"/**\n * File summary analyzer - lists added/modified/deleted/renamed paths.\n */\n\nimport { shouldExcludeFile } from \"../core/filters.js\";\nimport type {\n Analyzer,\n ChangeSet,\n FileDiff,\n FileSummaryFinding,\n Finding,\n} from \"../core/types.js\";\n\n/**\n * Represents a detected change pattern with priority for ranking.\n */\ninterface DetectedChange {\n description: string;\n priority: number; // Higher = more significant\n}\n\n/**\n * Detect all changes in added/removed lines and return prioritized list.\n */\nfunction detectChanges(\n addedLines: string,\n removedLines: string,\n status: string\n): DetectedChange[] {\n const changes: DetectedChange[] = [];\n\n // --- Function declarations (priority 100) ---\n // Standard function declarations\n const funcAddMatches = addedLines.matchAll(/(?:export\\s+)?(?:async\\s+)?function\\s+(\\w+)/g);\n for (const match of funcAddMatches) {\n const name = match[1];\n const wasRemoved = removedLines.includes(`function ${name}`);\n if (wasRemoved) {\n changes.push({ description: `Modified function: ${name}()`, priority: 100 });\n } else if (status === \"modified\") {\n changes.push({ description: `Added function: ${name}()`, priority: 100 });\n } else {\n changes.push({ description: `Added function: ${name}()`, priority: 100 });\n }\n }\n\n // Arrow function exports: export const foo = () => {} or export const foo = async () => {}\n const arrowFuncMatches = addedLines.matchAll(/export\\s+const\\s+(\\w+)\\s*=\\s*(?:async\\s*)?\\([^)]*\\)\\s*(?::\\s*[^=]+)?\\s*=>/g);\n for (const match of arrowFuncMatches) {\n const name = match[1];\n const wasRemoved = removedLines.includes(`const ${name}`);\n if (wasRemoved) {\n changes.push({ description: `Modified: ${name}()`, priority: 95 });\n } else {\n changes.push({ description: `Added: ${name}()`, priority: 95 });\n }\n }\n\n // --- Class declarations (priority 90) ---\n const classMatches = addedLines.matchAll(/(?:export\\s+)?class\\s+(\\w+)/g);\n for (const match of classMatches) {\n const name = match[1];\n const wasRemoved = removedLines.includes(`class ${name}`);\n if (wasRemoved) {\n changes.push({ description: `Modified class: ${name}`, priority: 90 });\n } else {\n changes.push({ description: `Added class: ${name}`, priority: 90 });\n }\n }\n\n // --- Interface/type declarations (priority 80) ---\n const interfaceMatches = addedLines.matchAll(/(?:export\\s+)?interface\\s+(\\w+)/g);\n for (const match of interfaceMatches) {\n const name = match[1];\n const wasRemoved = removedLines.includes(`interface ${name}`);\n if (wasRemoved) {\n changes.push({ description: `Modified interface: ${name}`, priority: 80 });\n } else {\n changes.push({ description: `Added interface: ${name}`, priority: 80 });\n }\n }\n\n const typeMatches = addedLines.matchAll(/(?:export\\s+)?type\\s+(\\w+)\\s*=/g);\n for (const match of typeMatches) {\n const name = match[1];\n const wasRemoved = removedLines.includes(`type ${name}`);\n if (wasRemoved) {\n changes.push({ description: `Modified type: ${name}`, priority: 80 });\n } else {\n changes.push({ description: `Added type: ${name}`, priority: 80 });\n }\n }\n\n // --- Enum declarations (priority 75) ---\n const enumMatches = addedLines.matchAll(/(?:export\\s+)?enum\\s+(\\w+)/g);\n for (const match of enumMatches) {\n const name = match[1];\n const wasRemoved = removedLines.includes(`enum ${name}`);\n if (wasRemoved) {\n changes.push({ description: `Modified enum: ${name}`, priority: 75 });\n } else {\n changes.push({ description: `Added enum: ${name}`, priority: 75 });\n }\n }\n\n // --- Const exports (priority 70) ---\n // Match exported constants that are NOT arrow functions (already handled above)\n const constMatches = addedLines.matchAll(/export\\s+const\\s+(\\w+)\\s*(?::\\s*[^=]+)?\\s*=/g);\n for (const match of constMatches) {\n const name = match[1];\n // Skip if already detected as arrow function\n const isArrowFunc = new RegExp(`export\\\\s+const\\\\s+${name}\\\\s*=\\\\s*(?:async\\\\s*)?\\\\(`).test(addedLines);\n if (isArrowFunc) continue;\n \n const wasRemoved = removedLines.includes(`const ${name}`);\n if (wasRemoved) {\n changes.push({ description: `Modified const: ${name}`, priority: 70 });\n } else {\n changes.push({ description: `Added const: ${name}`, priority: 70 });\n }\n }\n\n // --- Re-exports (priority 60) ---\n // export * from \"./module\"\n const starReexportMatch = addedLines.match(/export\\s+\\*\\s+from\\s+['\"]([^'\"]+)['\"]/);\n if (starReexportMatch) {\n changes.push({ description: `Re-exports from: ${starReexportMatch[1]}`, priority: 60 });\n }\n\n // export { x, y } from \"./module\"\n const namedReexportMatch = addedLines.match(/export\\s+\\{([^}]+)\\}\\s+from\\s+['\"]([^'\"]+)['\"]/);\n if (namedReexportMatch) {\n const symbols = namedReexportMatch[1].split(\",\").map(s => s.trim().split(\" \")[0]).slice(0, 3);\n const suffix = namedReexportMatch[1].split(\",\").length > 3 ? \" ...\" : \"\";\n changes.push({ description: `Re-exports: ${symbols.join(\", \")}${suffix}`, priority: 60 });\n }\n\n // --- Object method changes (priority 65) ---\n // Detect method definitions in objects: { methodName() { } } or { methodName: function() { } }\n const methodMatches = addedLines.matchAll(/^\\s*(?:async\\s+)?(\\w+)\\s*\\([^)]*\\)\\s*\\{/gm);\n for (const match of methodMatches) {\n const name = match[1];\n // Skip common non-method patterns\n if ([\"if\", \"for\", \"while\", \"switch\", \"catch\", \"function\"].includes(name)) continue;\n const wasRemoved = new RegExp(`\\\\b${name}\\\\s*\\\\(`).test(removedLines);\n if (wasRemoved) {\n changes.push({ description: `Modified method: ${name}()`, priority: 65 });\n }\n // Only report new methods if the file is new\n else if (status === \"added\") {\n changes.push({ description: `Added method: ${name}()`, priority: 65 });\n }\n }\n\n // --- Import changes (priority 40) ---\n const importMatches = addedLines.matchAll(/^import\\s+(?:\\{[^}]+\\}|[^{}\\s]+)\\s+from\\s+['\"]([^'\"]+)['\"]/gm);\n const newImports: string[] = [];\n for (const match of importMatches) {\n const module = match[1];\n // Only report if not in removed lines (actually new)\n if (!removedLines.includes(module)) {\n newImports.push(module);\n }\n }\n if (newImports.length > 0) {\n const displayImports = newImports.slice(0, 2).map(m => m.split(\"/\").pop() || m);\n const suffix = newImports.length > 2 ? ` (+${newImports.length - 2} more)` : \"\";\n changes.push({ description: `New imports: ${displayImports.join(\", \")}${suffix}`, priority: 40 });\n }\n\n // --- Switch case changes (priority 50) ---\n const caseMatches = addedLines.matchAll(/case\\s+['\"]?([^'\":\\s]+)['\"]?\\s*:/g);\n const newCases: string[] = [];\n for (const match of caseMatches) {\n const caseName = match[1];\n if (!removedLines.includes(`case ${caseName}`) && !removedLines.includes(`case \"${caseName}\"`) && !removedLines.includes(`case '${caseName}'`)) {\n newCases.push(caseName);\n }\n }\n if (newCases.length > 0) {\n const displayCases = newCases.slice(0, 2);\n const suffix = newCases.length > 2 ? ` (+${newCases.length - 2} more)` : \"\";\n changes.push({ description: `Added cases: ${displayCases.join(\", \")}${suffix}`, priority: 50 });\n }\n\n // --- CLI option changes (priority 85) ---\n // Detect .option() calls in CLI files\n const optionMatches = addedLines.matchAll(/\\.option\\s*\\(\\s*['\"]([^'\"]+)['\"]/g);\n const newOptions: string[] = [];\n for (const match of optionMatches) {\n const optionName = match[1];\n if (!removedLines.includes(optionName)) {\n newOptions.push(optionName);\n }\n }\n if (newOptions.length > 0) {\n const displayOptions = newOptions.slice(0, 2);\n const suffix = newOptions.length > 2 ? ` (+${newOptions.length - 2} more)` : \"\";\n changes.push({ description: `Added CLI options: ${displayOptions.join(\", \")}${suffix}`, priority: 85 });\n }\n\n // --- React component changes (priority 70) ---\n // Detect JSX elements being added\n if (/<[A-Z]\\w+/.test(addedLines) && (addedLines.includes(\"return\") || addedLines.includes(\"=>\"))) {\n changes.push({ description: \"Component JSX updated\", priority: 30 });\n }\n\n return changes;\n}\n\n/**\n * Generate a heuristic-based description of what changed in a file.\n * Analyzes diff hunks to identify patterns like new exports, function changes, etc.\n */\nfunction describeChange(diff: FileDiff): string | null {\n // Collect all added lines from hunks\n const addedLines = diff.hunks.flatMap(h => h.additions).join(\"\\n\");\n const removedLines = diff.hunks.flatMap(h => h.deletions).join(\"\\n\");\n\n // --- Path-based detections (highest priority) ---\n \n // Detect new CLI command module\n if (diff.path.startsWith(\"src/commands/\") && diff.status === \"added\") {\n if (diff.path.endsWith(\"index.ts\")) {\n return \"New command module\";\n }\n return \"New command helper\";\n }\n \n // Detect new test files\n if (/\\.test\\.[jt]sx?$/.test(diff.path) || /\\.spec\\.[jt]sx?$/.test(diff.path)) {\n if (diff.status === \"added\") {\n return \"New test file\";\n }\n return \"Updated tests\";\n }\n \n // Detect documentation changes\n if (diff.path.endsWith(\".md\") || diff.path.startsWith(\"docs/\")) {\n if (diff.status === \"added\") {\n return \"New documentation\";\n }\n return \"Documentation update\";\n }\n \n // Detect config file changes\n const isConfigFile = diff.path.includes(\"config\") || \n diff.path.endsWith(\".json\") || \n diff.path.endsWith(\".yaml\") ||\n diff.path.endsWith(\".yml\") ||\n diff.path.endsWith(\".toml\") ||\n diff.path.includes(\".env\");\n if (isConfigFile) {\n if (diff.status === \"added\") {\n return \"New configuration\";\n }\n return \"Configuration update\";\n }\n\n // --- Content-based detections ---\n const changes = detectChanges(addedLines, removedLines, diff.status);\n \n if (changes.length === 0) {\n return null;\n }\n\n // Sort by priority (highest first) and take the most significant\n changes.sort((a, b) => b.priority - a.priority);\n \n // Deduplicate by description\n const seen = new Set<string>();\n const unique = changes.filter(c => {\n if (seen.has(c.description)) return false;\n seen.add(c.description);\n return true;\n });\n\n const primary = unique[0];\n \n // If there are multiple significant changes, append count\n if (unique.length > 1) {\n return `${primary.description} (+${unique.length - 1} more)`;\n }\n \n return primary.description;\n}\n\nexport const fileSummaryAnalyzer: Analyzer = {\n name: \"file-summary\",\n\n analyze(changeSet: ChangeSet): Finding[] {\n const added: string[] = [];\n const modified: string[] = [];\n const deleted: string[] = [];\n const renamed: Array<{ from: string; to: string }> = [];\n const changeDescriptions: Array<{ file: string; description: string }> = [];\n\n for (const file of changeSet.files) {\n // Skip build artifacts and generated files\n if (shouldExcludeFile(file.path)) {\n continue;\n }\n\n switch (file.status) {\n case \"added\":\n added.push(file.path);\n break;\n case \"modified\":\n modified.push(file.path);\n break;\n case \"deleted\":\n deleted.push(file.path);\n break;\n case \"renamed\":\n renamed.push({\n from: file.oldPath ?? file.path,\n to: file.path,\n });\n break;\n }\n }\n \n // Generate change descriptions from diffs\n for (const diff of changeSet.diffs) {\n if (shouldExcludeFile(diff.path)) continue;\n \n const description = describeChange(diff);\n if (description) {\n changeDescriptions.push({ file: diff.path, description });\n }\n }\n\n // Only emit if there are changes\n if (\n added.length === 0 &&\n modified.length === 0 &&\n deleted.length === 0 &&\n renamed.length === 0\n ) {\n return [];\n }\n\n const finding: FileSummaryFinding = {\n type: \"file-summary\",\n kind: \"file-summary\",\n category: \"unknown\",\n confidence: \"high\",\n evidence: [],\n added,\n modified,\n deleted,\n renamed,\n changeDescriptions: changeDescriptions.length > 0 ? changeDescriptions : undefined,\n };\n\n return [finding];\n },\n};\n\n",
|
|
12
|
-
"/**\n * File category classifier - groups files into meaningful categories.\n */\n\nimport type {\n Analyzer,\n ChangeSet,\n FileCategory,\n FileCategoryFinding,\n Finding,\n} from \"../core/types.js\";\n\n// Category detection rules (order matters - first match wins)\nconst CATEGORY_RULES: Array<{\n category: FileCategory;\n patterns: RegExp[];\n}> = [\n // Tests (check before product to exclude test files from product)\n {\n category: \"tests\",\n patterns: [\n /^tests?\\//i,\n /^__tests__\\//i,\n /\\/tests?\\//i, // matches src/tests/, lib/tests/, etc.\n /\\/__tests__\\//i,\n /\\.test\\.[jt]sx?$/i,\n /\\.spec\\.[jt]sx?$/i,\n /\\.e2e\\.[jt]sx?$/i,\n /vitest\\.config/i,\n /jest\\.config/i,\n /cypress\\//i,\n /playwright\\//i,\n ],\n },\n // CI/CD\n {\n category: \"ci\",\n patterns: [\n /^\\.github\\/workflows\\//,\n /^\\.github\\/actions\\//,\n /^\\.gitlab-ci\\.yml$/,\n /^\\.circleci\\//,\n /^Jenkinsfile$/,\n /^\\.travis\\.yml$/,\n /^azure-pipelines\\.yml$/,\n /^bitbucket-pipelines\\.yml$/,\n ],\n },\n // Infrastructure\n {\n category: \"infra\",\n patterns: [\n /^Dockerfile/i,\n /^docker-compose/i,\n /^\\.dockerignore$/,\n /^helm\\//i,\n /^charts?\\//i,\n /^terraform\\//i,\n /^\\.tf$/,\n /^k8s\\//i,\n /^kubernetes\\//i,\n /^pulumi\\//i,\n /^ansible\\//i,\n /^Vagrantfile$/,\n ],\n },\n // Database (migrations, schemas, seeds)\n {\n category: \"database\",\n patterns: [\n /^supabase\\/migrations\\//,\n /^supabase\\/seed/,\n /^prisma\\/migrations\\//,\n /^prisma\\/schema\\.prisma$/,\n /^drizzle\\/migrations\\//,\n /^drizzle\\.config/,\n /^migrations?\\//i,\n /\\/migrations?\\//i, // matches db/migrations/, database/migrations/, etc.\n /\\.sql$/i,\n ],\n },\n // Documentation\n {\n category: \"docs\",\n patterns: [\n /^docs?\\//i,\n /^documentation\\//i,\n /\\.md$/i,\n /\\.mdx$/i,\n /^README/i,\n /^CHANGELOG/i,\n /^CONTRIBUTING/i,\n /^LICENSE/i,\n /^\\.all-contributorsrc$/,\n ],\n },\n // Dependencies\n {\n category: \"dependencies\",\n patterns: [\n /^package\\.json$/,\n /^package-lock\\.json$/,\n /^yarn\\.lock$/,\n /^pnpm-lock\\.yaml$/,\n /^bun\\.lock$/,\n /^bun\\.lockb$/,\n /^requirements\\.txt$/,\n /^Pipfile(\\.lock)?$/,\n /^poetry\\.lock$/,\n /^pyproject\\.toml$/,\n /^Cargo\\.(toml|lock)$/,\n /^go\\.(mod|sum)$/,\n /^Gemfile(\\.lock)?$/,\n /^composer\\.(json|lock)$/,\n ],\n },\n // Configuration\n {\n category: \"config\",\n patterns: [\n /^\\.[a-z]+rc(\\.json|\\.js|\\.cjs|\\.mjs|\\.yaml|\\.yml)?$/i,\n /\\.config\\.[jt]s$/i,\n /\\.config\\.[a-z]+\\.[jt]s$/i, // e.g., vite.config.e2e.ts\n /^\\.env/i,\n /^wrangler\\.(toml|json)$/i,\n /^tsconfig.*\\.json$/i,\n /^\\.eslintrc/i,\n /^\\.prettierrc/i,\n /^\\.editorconfig$/,\n /^\\.gitignore$/,\n /^\\.nvmrc$/,\n /^\\.node-version$/,\n ],\n },\n // Artifacts (build outputs, packages, binaries)\n {\n category: \"artifacts\",\n patterns: [\n /\\.tgz$/i, // npm/bun pack tarballs\n /\\.tar\\.gz$/i, // compressed archives\n /\\.zip$/i, // zip archives\n /\\.whl$/i, // Python wheels\n /\\.jar$/i, // Java archives\n /\\.war$/i, // Java web archives\n /\\.gem$/i, // Ruby gems\n /\\.nupkg$/i, // NuGet packages\n /\\.deb$/i, // Debian packages\n /\\.rpm$/i, // RPM packages\n /\\.dmg$/i, // macOS disk images\n /\\.exe$/i, // Windows executables\n /\\.dll$/i, // Windows libraries\n /\\.so$/i, // Linux shared objects\n /\\.dylib$/i, // macOS dynamic libraries\n /\\.a$/i, // Static libraries\n /\\.o$/i, // Object files\n /\\.wasm$/i, // WebAssembly binaries\n ],\n },\n // Product code (src, lib, app - excluding already matched patterns)\n {\n category: \"product\",\n patterns: [\n /^src\\//,\n /^lib\\//,\n /^app\\//,\n /^pages\\//,\n /^components\\//,\n /^hooks\\//,\n /^utils\\//,\n /^services\\//,\n /^api\\//,\n /^server\\//,\n /^client\\//,\n /\\.[jt]sx?$/, // Any JS/TS file not matched above\n /\\.svelte$/,\n /\\.vue$/,\n /\\.astro$/,\n ],\n },\n];\n\n/**\n * Determine the category of a file path.\n */\nexport function categorizeFile(path: string): FileCategory {\n for (const rule of CATEGORY_RULES) {\n if (rule.patterns.some((pattern) => pattern.test(path))) {\n return rule.category;\n }\n }\n return \"other\";\n}\n\n/**\n * Get a human-readable label for a category.\n */\nexport function getCategoryLabel(category: FileCategory): string {\n const labels: Record<FileCategory, string> = {\n product: \"Product Code\",\n tests: \"Tests\",\n ci: \"CI/CD\",\n infra: \"Infrastructure\",\n database: \"Database\",\n docs: \"Documentation\",\n dependencies: \"Dependencies\",\n config: \"Configuration\",\n artifacts: \"Build Artifacts\",\n other: \"Other\",\n };\n return labels[category];\n}\n\nexport const fileCategoryAnalyzer: Analyzer = {\n name: \"file-category\",\n\n analyze(changeSet: ChangeSet): Finding[] {\n const categories: Record<FileCategory, string[]> = {\n product: [],\n tests: [],\n ci: [],\n infra: [],\n database: [],\n docs: [],\n dependencies: [],\n config: [],\n artifacts: [],\n other: [],\n };\n\n // Categorize all changed files\n for (const file of changeSet.files) {\n const category = categorizeFile(file.path);\n categories[category].push(file.path);\n }\n\n // Build summary (only categories with files)\n const summary = (Object.entries(categories) as [FileCategory, string[]][])\n .filter(([, files]) => files.length > 0)\n .map(([category, files]) => ({\n category,\n count: files.length,\n }))\n .sort((a, b) => b.count - a.count);\n\n // Only emit if there are categorized files\n if (summary.length === 0) {\n return [];\n }\n\n // Note: category is \"unknown\" because file-category is a meta-finding\n // that summarizes all files - it doesn't belong to a specific domain area.\n // This finding is skipped during category aggregation (see categories.ts).\n const finding: FileCategoryFinding = {\n type: \"file-category\",\n kind: \"file-category\",\n category: \"unknown\",\n confidence: \"high\",\n evidence: [],\n categories,\n summary,\n };\n\n return [finding as unknown as Finding];\n },\n};\n\n",
|
|
13
|
-
"/**\n * Evidence extraction and redaction utilities.\n */\n\nimport type { Evidence, Hunk } from \"./types.js\";\n\n/**\n * Create evidence from a file with excerpt.\n */\nexport function createEvidence(\n file: string,\n excerpt: string,\n options?: {\n line?: number;\n hunk?: Hunk;\n }\n): Evidence {\n return {\n file,\n excerpt: excerpt.trim(),\n line: options?.line,\n hunk: options?.hunk\n ? {\n oldStart: options.hunk.oldStart,\n oldLines: options.hunk.oldLines,\n newStart: options.hunk.newStart,\n newLines: options.hunk.newLines,\n }\n : undefined,\n };\n}\n\n/**\n * Redact obvious secrets from evidence excerpts.\n * Masks values but preserves keys for env vars.\n */\nexport function redactEvidence(evidence: Evidence): Evidence {\n return {\n ...evidence,\n excerpt: redactSecrets(evidence.excerpt),\n };\n}\n\n/**\n * Redact secrets from text.\n * Patterns:\n * - API keys: sk_live_..., pk_test_..., etc.\n * - JWT tokens: eyJ...\n * - AWS keys: AKIA...\n * - Generic secrets: password=..., secret=..., token=...\n */\nexport function redactSecrets(text: string): string {\n let redacted = text;\n\n // Stripe-like keys (must be at least 24 chars after prefix)\n redacted = redacted.replace(\n /\\b(sk|pk|rk)_(live|test)_[A-Za-z0-9]{24,}/g,\n \"$1_$2_***REDACTED***\"\n );\n\n // JWT tokens (must have 3 base64 parts separated by dots)\n redacted = redacted.replace(\n /\\beyJ[A-Za-z0-9_-]{30,}\\.[A-Za-z0-9_-]{30,}\\.[A-Za-z0-9_-]{30,}/g,\n \"eyJ***REDACTED***\"\n );\n\n // AWS keys (exactly 20 chars: AKIA + 16 alphanumeric)\n redacted = redacted.replace(\n /\\bAKIA[0-9A-Z]{16}\\b/g,\n \"AKIA***REDACTED***\"\n );\n\n // Generic secret patterns (only match assignment contexts)\n // Match: password=value, secret: value, token=\"value\", api_key='value'\n // Skip values that contain ***REDACTED*** to avoid double-redaction\n redacted = redacted.replace(\n /(password|secret|token|apikey|api_key)(\\s*[:=]\\s*)([\"'])(?!.*\\*\\*\\*REDACTED\\*\\*\\*)([^\"']+?)\\3/gi,\n \"$1$2$3***REDACTED***$3\"\n );\n \n // Also match unquoted values (skip values that contain ***REDACTED***)\n redacted = redacted.replace(\n /(password|secret|token|apikey|api_key)(\\s*[:=]\\s*)(?!.*\\*\\*\\*REDACTED\\*\\*\\*)([^\\s\"',;)]+)/gi,\n \"$1$2***REDACTED***\"\n );\n\n return redacted;\n}\n\n/**\n * Truncate excerpt to max length.\n */\nexport function truncateExcerpt(\n excerpt: string,\n maxLength: number = 200\n): string {\n if (excerpt.length <= maxLength) {\n return excerpt;\n }\n return excerpt.substring(0, maxLength - 3) + \"...\";\n}\n\n/**\n * Extract a representative excerpt from additions.\n */\nexport function extractRepresentativeExcerpt(\n additions: string[],\n maxLength: number = 200\n): string {\n if (additions.length === 0) {\n return \"\";\n }\n\n // Find first non-empty, non-comment line\n for (const line of additions) {\n const trimmed = line.trim();\n if (\n trimmed.length > 0 &&\n !trimmed.startsWith(\"//\") &&\n !trimmed.startsWith(\"/*\") &&\n !trimmed.startsWith(\"*\") &&\n !trimmed.startsWith(\"#\")\n ) {\n return truncateExcerpt(trimmed, maxLength);\n }\n }\n\n // Fallback to first line\n return truncateExcerpt(additions[0].trim(), maxLength);\n}\n",
|
|
14
|
-
"/**\n * SvelteKit route detector - detects changes under src/routes.\n */\n\nimport { getAdditions } from \"../git/parser.js\";\nimport { createEvidence, extractRepresentativeExcerpt } from \"../core/evidence.js\";\nimport type {\n Analyzer,\n ChangeSet,\n FileDiff,\n FileStatus,\n Finding,\n RouteChangeFinding,\n RouteType,\n} from \"../core/types.js\";\n\n// Route file patterns\nconst ROUTE_FILE_PATTERNS: Record<string, RouteType> = {\n \"+page.svelte\": \"page\",\n \"+page.ts\": \"page\",\n \"+page.server.ts\": \"page\",\n \"+layout.svelte\": \"layout\",\n \"+layout.ts\": \"layout\",\n \"+layout.server.ts\": \"layout\",\n \"+server.ts\": \"endpoint\",\n \"+error.svelte\": \"error\",\n};\n\n// HTTP method detection pattern\nconst METHOD_PATTERN = /export\\s+const\\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b/g;\n\n/**\n * Check if a path is a SvelteKit route file.\n */\nexport function isRouteFile(path: string): boolean {\n return path.startsWith(\"src/routes/\") && hasRouteFilePattern(path);\n}\n\n/**\n * Check if path ends with a route file pattern.\n */\nfunction hasRouteFilePattern(path: string): boolean {\n const fileName = path.split(\"/\").pop() ?? \"\";\n return Object.keys(ROUTE_FILE_PATTERNS).some((pattern) =>\n fileName.startsWith(pattern.replace(\".svelte\", \"\").replace(\".ts\", \"\")) &&\n (fileName.endsWith(\".svelte\") || fileName.endsWith(\".ts\"))\n );\n}\n\n/**\n * Get the route type from a file path.\n */\nexport function getRouteType(path: string): RouteType {\n const fileName = path.split(\"/\").pop() ?? \"\";\n for (const [pattern, type] of Object.entries(ROUTE_FILE_PATTERNS)) {\n if (fileName === pattern) {\n return type;\n }\n }\n return \"unknown\";\n}\n\n/**\n * Convert a file path to a SvelteKit route ID.\n *\n * Rules:\n * - Strip `src/routes` prefix\n * - Remove route groups `(name)` from URL (but keep in route ID)\n * - Keep param notation: [slug], [[id]], [...rest]\n * - Remove file name (the route is the directory)\n */\nexport function pathToRouteId(path: string): string {\n // Remove src/routes prefix\n let routeId = path.replace(/^src\\/routes/, \"\");\n\n // Remove the file name\n const parts = routeId.split(\"/\");\n parts.pop(); // Remove file name\n\n routeId = parts.join(\"/\");\n\n // If empty, it's the root route\n if (routeId === \"\" || routeId === \"/\") {\n return \"/\";\n }\n\n // Ensure leading slash\n if (!routeId.startsWith(\"/\")) {\n routeId = \"/\" + routeId;\n }\n\n return routeId;\n}\n\n/**\n * Convert route ID to URL path (for display).\n * Removes route groups from the path.\n */\nexport function routeIdToUrlPath(routeId: string): string {\n // Remove route groups: (name)\n return routeId.replace(/\\/\\([^)]+\\)/g, \"\");\n}\n\n/**\n * Detect HTTP methods from endpoint file content.\n */\nexport function detectMethods(diff: FileDiff): string[] {\n const methods = new Set<string>();\n const content = getAdditions(diff).join(\"\\n\");\n\n let match;\n const pattern = new RegExp(METHOD_PATTERN.source, \"g\");\n while ((match = pattern.exec(content)) !== null) {\n methods.add(match[1]);\n }\n\n return Array.from(methods).sort();\n}\n\nexport const routeDetectorAnalyzer: Analyzer = {\n name: \"route-detector\",\n\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: Finding[] = [];\n const routeFiles = new Map<string, { diff?: FileDiff; status: FileStatus }>();\n\n // Collect route files from file changes\n for (const file of changeSet.files) {\n if (isRouteFile(file.path)) {\n routeFiles.set(file.path, { status: file.status });\n }\n }\n\n // Add diff data\n for (const diff of changeSet.diffs) {\n if (isRouteFile(diff.path)) {\n const existing = routeFiles.get(diff.path);\n if (existing) {\n existing.diff = diff;\n } else {\n routeFiles.set(diff.path, { diff, status: diff.status });\n }\n }\n }\n\n // Generate findings\n for (const [path, { diff, status }] of routeFiles) {\n const routeId = pathToRouteId(path);\n const routeType = getRouteType(path);\n\n // Extract evidence\n const evidence = [];\n if (diff && diff.hunks.length > 0) {\n const additions = getAdditions(diff);\n if (additions.length > 0) {\n const excerpt = extractRepresentativeExcerpt(additions);\n if (excerpt) {\n evidence.push(createEvidence(path, excerpt));\n }\n }\n }\n\n const finding: RouteChangeFinding = {\n type: \"route-change\",\n kind: \"route-change\",\n category: \"routes\",\n confidence: \"high\",\n evidence,\n routeId,\n file: path,\n change: status,\n routeType,\n };\n\n // Detect methods for endpoints\n if (routeType === \"endpoint\" && diff) {\n const methods = detectMethods(diff);\n if (methods.length > 0) {\n finding.methods = methods;\n // Add method export as evidence if available\n const methodsExcerpt = methods.map(m => `export const ${m}`).join(\", \");\n if (!evidence.length) {\n evidence.push(createEvidence(path, methodsExcerpt));\n }\n }\n }\n\n findings.push(finding);\n }\n\n return findings;\n },\n};\n\n",
|
|
15
|
-
"/**\n * Supabase migration detector with dangerous SQL scanning.\n */\n\nimport { getAdditions } from \"../git/parser.js\";\nimport { createEvidence } from \"../core/evidence.js\";\nimport type {\n Analyzer,\n ChangeSet,\n DbMigrationFinding,\n Finding,\n MigrationRisk,\n RiskFlagFinding,\n} from \"../core/types.js\";\n\n// Migration file pattern\nconst MIGRATION_PATTERN = /^supabase\\/migrations\\/.*\\.sql$/;\n\n// Seed/config patterns (lower risk)\nconst SEED_PATTERN = /^supabase\\/(seed|config)/;\n\n// Destructive SQL patterns\nconst DESTRUCTIVE_PATTERNS: Array<{ pattern: RegExp; description: string }> = [\n { pattern: /DROP\\s+TABLE/i, description: \"DROP TABLE\" },\n { pattern: /DROP\\s+COLUMN/i, description: \"DROP COLUMN\" },\n { pattern: /TRUNCATE/i, description: \"TRUNCATE\" },\n { pattern: /ALTER\\s+COLUMN/i, description: \"ALTER COLUMN\" },\n { pattern: /ALTER\\s+TABLE\\s+\\w+\\s+.*\\s+TYPE/i, description: \"ALTER TYPE\" },\n {\n pattern: /DELETE\\s+FROM\\s+\\w+\\s*(?:;|$)/i,\n description: \"DELETE without WHERE\",\n },\n];\n\n/**\n * Check if a path is a Supabase migration file.\n */\nexport function isMigrationFile(path: string): boolean {\n return MIGRATION_PATTERN.test(path);\n}\n\n/**\n * Check if a path is a seed or config file.\n */\nexport function isSeedOrConfig(path: string): boolean {\n return SEED_PATTERN.test(path);\n}\n\n/**\n * Scan SQL content for destructive patterns.\n */\nexport function scanForDestructivePatterns(\n content: string\n): Array<{ pattern: string; description: string }> {\n const matches: Array<{ pattern: string; description: string }> = [];\n\n for (const { pattern, description } of DESTRUCTIVE_PATTERNS) {\n if (pattern.test(content)) {\n matches.push({ pattern: pattern.source, description });\n }\n }\n\n return matches;\n}\n\n/**\n * Determine migration risk level based on content.\n * Returns risk level, reasons, and evidence.\n */\nexport function determineMigrationRisk(\n files: string[],\n changeSet: ChangeSet\n): {\n risk: MigrationRisk;\n reasons: string[];\n evidence: Array<{ file: string; excerpt: string }>;\n} {\n const reasons: string[] = [];\n const evidence: Array<{ file: string; excerpt: string }> = [];\n let hasDestructive = false;\n\n for (const file of files) {\n const diff = changeSet.diffs.find((d) => d.path === file);\n if (!diff) continue;\n\n const additions = getAdditions(diff);\n const additionsText = additions.join(\"\\n\");\n const destructive = scanForDestructivePatterns(additionsText);\n\n for (const { description } of destructive) {\n hasDestructive = true;\n reasons.push(`${description} detected in ${file}`);\n \n // Find the line with the destructive pattern\n const lineWithPattern = additions.find((line) =>\n DESTRUCTIVE_PATTERNS.some((p) => p.pattern.test(line))\n );\n if (lineWithPattern) {\n evidence.push({\n file,\n excerpt: lineWithPattern.trim(),\n });\n }\n }\n }\n\n if (hasDestructive) {\n return { risk: \"high\", reasons, evidence };\n }\n\n // Check if only seeds/config\n const onlySeedsOrConfig = files.every((f) => isSeedOrConfig(f));\n if (onlySeedsOrConfig) {\n return {\n risk: \"low\",\n reasons: [\"Only seed/config files changed\"],\n evidence,\n };\n }\n\n return {\n risk: \"medium\",\n reasons: [\"Migration files changed\"],\n evidence,\n };\n}\n\nexport const supabaseAnalyzer: Analyzer = {\n name: \"supabase\",\n\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: Finding[] = [];\n const migrationFiles: string[] = [];\n const supabaseFiles: string[] = [];\n\n // Collect migration and Supabase files\n for (const file of changeSet.files) {\n if (file.path.startsWith(\"supabase/\")) {\n supabaseFiles.push(file.path);\n if (isMigrationFile(file.path)) {\n migrationFiles.push(file.path);\n }\n }\n }\n\n // If no Supabase files, skip\n if (supabaseFiles.length === 0) {\n return [];\n }\n\n // Determine risk\n const { risk, reasons, evidence: evidenceData } = determineMigrationRisk(\n migrationFiles.length > 0 ? migrationFiles : supabaseFiles,\n changeSet\n );\n\n // Convert evidence data to Evidence type\n const evidence = evidenceData.map((e) =>\n createEvidence(e.file, e.excerpt)\n );\n\n const migrationFinding: DbMigrationFinding = {\n type: \"db-migration\",\n kind: \"db-migration\",\n category: \"database\",\n confidence: \"high\",\n evidence,\n tool: \"supabase\",\n files: migrationFiles.length > 0 ? migrationFiles : supabaseFiles,\n risk,\n reasons,\n };\n\n findings.push(migrationFinding);\n\n // Add risk flag for high risk\n if (risk === \"high\") {\n const riskFinding: RiskFlagFinding = {\n type: \"risk-flag\",\n kind: \"risk-flag\",\n category: \"database\",\n confidence: \"high\",\n evidence,\n risk: \"high\",\n evidenceText: `Destructive SQL detected: ${reasons.join(\", \")}`,\n };\n findings.push(riskFinding);\n }\n\n return findings;\n },\n};\n\n",
|
|
16
|
-
"/**\n * Environment variable detector.\n */\n\nimport { shouldExcludeFile } from \"../core/filters.js\";\nimport { createEvidence, extractRepresentativeExcerpt } from \"../core/evidence.js\";\nimport type {\n Analyzer,\n ChangeSet,\n EnvVarFinding,\n Finding,\n} from \"../core/types.js\";\nimport { getAdditions } from \"../git/parser.js\";\n\n// File extensions that should be scanned for env vars (actual code files)\nconst CODE_FILE_EXTENSIONS = new Set([\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \".mjs\",\n \".cjs\",\n \".svelte\",\n \".vue\",\n \".astro\",\n]);\n\n// Config files that might contain env var references\nconst CONFIG_FILE_PATTERNS = [\n /\\.env(\\..+)?$/, // .env, .env.local, .env.production\n /vite\\.config\\.(ts|js|mjs)$/,\n /svelte\\.config\\.(ts|js|mjs)$/,\n /next\\.config\\.(ts|js|mjs)$/,\n /nuxt\\.config\\.(ts|js|mjs)$/,\n /astro\\.config\\.(ts|js|mjs)$/,\n];\n\n/**\n * Check if a file should be scanned for env vars.\n * Only scan actual code files and config files, not documentation or tests.\n */\nfunction shouldScanForEnvVars(path: string): boolean {\n // Skip documentation\n if (path.endsWith(\".md\") || path.startsWith(\"docs/\")) {\n return false;\n }\n\n // Skip test files (they often contain example env vars)\n if (\n path.includes(\"/tests/\") ||\n path.includes(\"/__tests__/\") ||\n path.includes(\".test.\") ||\n path.includes(\".spec.\") ||\n path.startsWith(\"tests/\")\n ) {\n return false;\n }\n\n // Skip fixture files\n if (path.includes(\"/fixtures/\") || path.includes(\"/__fixtures__/\")) {\n return false;\n }\n\n // Check if it's a config file\n for (const pattern of CONFIG_FILE_PATTERNS) {\n if (pattern.test(path)) {\n return true;\n }\n }\n\n // Check if it has a code file extension\n const ext = path.substring(path.lastIndexOf(\".\"));\n return CODE_FILE_EXTENSIONS.has(ext);\n}\n\n// Patterns for env var detection\nconst ENV_PATTERNS = {\n // process.env.VAR_NAME (including REACT_APP_ and NEXT_PUBLIC_ prefixes)\n processEnv: /process\\.env\\.([A-Z_][A-Z0-9_]*)/g,\n\n // import.meta.env.VITE_VAR_NAME (Vite)\n viteEnv: /import\\.meta\\.env\\.VITE_([A-Z0-9_]+)/g,\n\n // PUBLIC_VAR (SvelteKit public env vars)\n publicVar: /\\bPUBLIC_([A-Z0-9_]+)/g,\n\n // $env/static/public imports\n envStaticPublic:\n /import\\s*\\{([^}]+)\\}\\s*from\\s*[\"']\\$env\\/static\\/public[\"']/g,\n\n // $env/static/private imports\n envStaticPrivate:\n /import\\s*\\{([^}]+)\\}\\s*from\\s*[\"']\\$env\\/static\\/private[\"']/g,\n\n // $env/dynamic/public imports\n envDynamicPublic:\n /import\\s*\\{([^}]+)\\}\\s*from\\s*[\"']\\$env\\/dynamic\\/public[\"']/g,\n\n // $env/dynamic/private imports\n envDynamicPrivate:\n /import\\s*\\{([^}]+)\\}\\s*from\\s*[\"']\\$env\\/dynamic\\/private[\"']/g,\n};\n\n/**\n * Extract variable names from an import statement's destructured list.\n */\nexport function extractImportedVars(importList: string): string[] {\n return importList\n .split(\",\")\n .map((v) => v.trim())\n .filter((v) => v.length > 0)\n .map((v) => {\n // Handle \"VAR as alias\" syntax\n const parts = v.split(/\\s+as\\s+/);\n return parts[0].trim();\n });\n}\n\n/**\n * Extract environment variable names from content.\n */\nexport function extractEnvVars(content: string): Set<string> {\n const vars = new Set<string>();\n\n // process.env.VAR\n // Reset lastIndex to ensure consistent results since we're reusing global Regexps\n ENV_PATTERNS.processEnv.lastIndex = 0;\n let match;\n while ((match = ENV_PATTERNS.processEnv.exec(content)) !== null) {\n vars.add(match[1]);\n }\n\n // import.meta.env.VITE_VAR (Vite)\n ENV_PATTERNS.viteEnv.lastIndex = 0;\n while ((match = ENV_PATTERNS.viteEnv.exec(content)) !== null) {\n vars.add(`VITE_${match[1]}`);\n }\n\n // PUBLIC_VAR\n ENV_PATTERNS.publicVar.lastIndex = 0;\n while ((match = ENV_PATTERNS.publicVar.exec(content)) !== null) {\n vars.add(`PUBLIC_${match[1]}`);\n }\n\n // $env imports (all types)\n const importPatterns = [\n ENV_PATTERNS.envStaticPublic,\n ENV_PATTERNS.envStaticPrivate,\n ENV_PATTERNS.envDynamicPublic,\n ENV_PATTERNS.envDynamicPrivate,\n ];\n\n for (const pattern of importPatterns) {\n pattern.lastIndex = 0;\n while ((match = pattern.exec(content)) !== null) {\n const importedVars = extractImportedVars(match[1]);\n for (const v of importedVars) {\n vars.add(v);\n }\n }\n }\n\n return vars;\n}\n\nexport const envVarAnalyzer: Analyzer = {\n name: \"env-var\",\n\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: Finding[] = [];\n const varToFilesAndExcerpts = new Map<\n string,\n Array<{ file: string; excerpt: string }>\n >();\n\n // Scan code files for env vars in additions\n for (const diff of changeSet.diffs) {\n // Skip build artifacts and generated files\n if (shouldExcludeFile(diff.path)) {\n continue;\n }\n\n // Only scan actual code files (not docs, tests, fixtures)\n if (!shouldScanForEnvVars(diff.path)) {\n continue;\n }\n\n const additions = getAdditions(diff);\n const additionsText = additions.join(\"\\n\");\n const vars = extractEnvVars(additionsText);\n\n for (const varName of vars) {\n if (!varToFilesAndExcerpts.has(varName)) {\n varToFilesAndExcerpts.set(varName, []);\n }\n \n // Find line with this var\n const lineWithVar = additions.find(line => \n line.includes(varName)\n );\n const excerpt = lineWithVar \n ? lineWithVar.trim()\n : extractRepresentativeExcerpt(additions);\n \n varToFilesAndExcerpts.get(varName)!.push({\n file: diff.path,\n excerpt,\n });\n }\n }\n\n // Create findings\n for (const [name, fileExcerpts] of varToFilesAndExcerpts) {\n const files = Array.from(\n new Set(fileExcerpts.map((fe) => fe.file))\n );\n \n // Create evidence (up to 3 excerpts)\n const evidence = fileExcerpts\n .slice(0, 3)\n .map((fe) => createEvidence(fe.file, fe.excerpt));\n\n const finding: EnvVarFinding = {\n type: \"env-var\",\n kind: \"env-var\",\n category: \"config_env\",\n confidence: \"high\",\n evidence,\n name,\n change: \"added\", // MVP heuristic: if in additions, treat as added\n evidenceFiles: files,\n };\n findings.push(finding);\n }\n\n return findings;\n },\n};\n",
|
|
17
|
-
"/**\n * Cloudflare change detector.\n */\n\nimport { getAdditions } from \"../git/parser.js\";\nimport { createEvidence, extractRepresentativeExcerpt } from \"../core/evidence.js\";\nimport type {\n Analyzer,\n ChangeSet,\n CloudflareArea,\n CloudflareChangeFinding,\n Finding,\n} from \"../core/types.js\";\n\n// Wrangler config patterns\nconst WRANGLER_PATTERNS = [/^wrangler\\.toml$/, /^wrangler\\.json$/];\n\n// GitHub workflow patterns\nconst WORKFLOW_PATTERN = /^\\.github\\/workflows\\/.*\\.(yml|yaml)$/;\n\n// Cloudflare keywords in CI\nconst CLOUDFLARE_CI_KEYWORDS = /\\b(wrangler|cloudflare|workers|pages)\\b/i;\n\n/**\n * Check if a file is a wrangler config.\n */\nexport function isWranglerConfig(path: string): boolean {\n return WRANGLER_PATTERNS.some((pattern) => pattern.test(path));\n}\n\n/**\n * Check if a file is a GitHub workflow.\n */\nexport function isGitHubWorkflow(path: string): boolean {\n return WORKFLOW_PATTERN.test(path);\n}\n\n/**\n * Check if workflow content mentions Cloudflare.\n */\nexport function workflowMentionsCloudflare(content: string): boolean {\n return CLOUDFLARE_CI_KEYWORDS.test(content);\n}\n\nexport const cloudflareAnalyzer: Analyzer = {\n name: \"cloudflare\",\n\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: Finding[] = [];\n const areaFilesAndEvidence = new Map<\n CloudflareArea,\n Array<{ file: string; excerpt: string }>\n >();\n\n // Check for wrangler config changes\n for (const file of changeSet.files) {\n if (isWranglerConfig(file.path)) {\n if (!areaFilesAndEvidence.has(\"wrangler\")) {\n areaFilesAndEvidence.set(\"wrangler\", []);\n }\n // Try to get excerpt from diff\n const diff = changeSet.diffs.find((d) => d.path === file.path);\n const excerpt = diff\n ? extractRepresentativeExcerpt(getAdditions(diff))\n : file.path;\n areaFilesAndEvidence.get(\"wrangler\")!.push({\n file: file.path,\n excerpt,\n });\n }\n }\n\n // Check for CI changes that mention Cloudflare\n for (const diff of changeSet.diffs) {\n if (isGitHubWorkflow(diff.path)) {\n const additions = getAdditions(diff);\n const additionsText = additions.join(\"\\n\");\n if (workflowMentionsCloudflare(additionsText)) {\n if (!areaFilesAndEvidence.has(\"ci\")) {\n areaFilesAndEvidence.set(\"ci\", []);\n }\n const excerpt = extractRepresentativeExcerpt(additions);\n areaFilesAndEvidence.get(\"ci\")!.push({\n file: diff.path,\n excerpt,\n });\n }\n }\n }\n\n // Create findings\n for (const [area, fileExcerpts] of areaFilesAndEvidence) {\n const files = fileExcerpts.map((fe) => fe.file);\n const evidence = fileExcerpts\n .slice(0, 3)\n .map((fe) => createEvidence(fe.file, fe.excerpt));\n\n const finding: CloudflareChangeFinding = {\n type: \"cloudflare-change\",\n kind: \"cloudflare-change\",\n category: \"cloudflare\",\n confidence: \"high\",\n evidence,\n area,\n files,\n };\n findings.push(finding);\n }\n\n return findings;\n },\n};\n\n",
|
|
18
|
-
"/**\n * Vitest test change detector.\n */\n\nimport { createEvidence } from \"../core/evidence.js\";\nimport type {\n Analyzer,\n ChangeSet,\n Finding,\n TestChangeFinding,\n} from \"../core/types.js\";\n\n// Test file patterns\nconst TEST_PATTERNS = [\n /\\.test\\.ts$/,\n /\\.spec\\.ts$/,\n /\\.test\\.js$/,\n /\\.spec\\.js$/,\n /^tests?\\//,\n];\n\n// Vitest config patterns (matches vitest.config.ts, vitest.config.e2e.ts, etc.)\nconst VITEST_CONFIG_PATTERNS = [\n /^vitest\\.config(\\.[a-z0-9]+)?\\.(ts|js|mts|mjs)$/,\n /^vite\\.config(\\.[a-z0-9]+)?\\.(ts|js|mts|mjs)$/, // Vite config might include vitest\n];\n\n/**\n * Check if a file is a test file.\n */\nexport function isTestFile(path: string): boolean {\n return TEST_PATTERNS.some((pattern) => pattern.test(path));\n}\n\n/**\n * Check if a file is a vitest config.\n */\nexport function isVitestConfig(path: string): boolean {\n return VITEST_CONFIG_PATTERNS.some((pattern) => pattern.test(path));\n}\n\nexport const vitestAnalyzer: Analyzer = {\n name: \"vitest\",\n\n analyze(changeSet: ChangeSet): Finding[] {\n const testFiles: string[] = [];\n\n // Collect test files\n for (const file of changeSet.files) {\n if (isTestFile(file.path) || isVitestConfig(file.path)) {\n testFiles.push(file.path);\n }\n }\n\n // Only emit if there are test changes\n if (testFiles.length === 0) {\n return [];\n }\n\n // Create evidence from file list\n const evidence = testFiles\n .slice(0, 3)\n .map((file) => createEvidence(file, `Test file ${file}`));\n\n const finding: TestChangeFinding = {\n type: \"test-change\",\n kind: \"test-change\",\n category: \"tests\",\n confidence: \"high\",\n evidence,\n framework: \"vitest\",\n files: testFiles,\n };\n\n return [finding];\n },\n};\n\n",
|
|
19
|
-
"/**\n * Dependency change analyzer.\n */\n\nimport * as semver from \"semver\";\nimport { createEvidence } from \"../core/evidence.js\";\nimport type {\n Analyzer,\n ChangeSet,\n DependencyChangeFinding,\n Finding,\n RiskFlagFinding,\n} from \"../core/types.js\";\n\ntype DependencySection = \"dependencies\" | \"devDependencies\";\n\ninterface PackageDeps {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\n// Critical packages that warrant a risk flag on major bump\nconst CRITICAL_PACKAGES = [\"@sveltejs/kit\", \"svelte\", \"vite\"];\n\n// Risky package categories\ntype RiskyCategory = \"auth\" | \"database\" | \"native\" | \"payment\";\n\n/**\n * Pre-built Map for O(1) risky package category lookup.\n * Built at module load time for maximum performance.\n */\nconst RISKY_PACKAGE_MAP: Map<string, RiskyCategory> = new Map([\n // auth packages\n ...[\"passport\", \"jsonwebtoken\", \"bcrypt\", \"bcryptjs\", \"oauth\", \"auth0\",\n \"@auth0/auth0-spa-js\", \"clerk\", \"@clerk/clerk-sdk-node\", \"@clerk/nextjs\",\n \"next-auth\", \"@auth/core\", \"@auth/sveltekit\", \"lucia\", \"lucia-auth\",\n \"arctic\", \"oslo\", \"express-session\", \"cookie-session\", \"passport-local\",\n \"passport-jwt\", \"passport-oauth2\", \"jose\", \"jwks-rsa\", \"supertokens-node\",\n \"@supabase/auth-helpers-sveltekit\", \"@supabase/ssr\"\n ].map(pkg => [pkg, \"auth\" as RiskyCategory] as const),\n\n // database packages\n ...[\"prisma\", \"@prisma/client\", \"drizzle-orm\", \"typeorm\", \"sequelize\",\n \"knex\", \"mongoose\", \"pg\", \"mysql\", \"mysql2\", \"sqlite3\", \"better-sqlite3\",\n \"mongodb\", \"redis\", \"ioredis\", \"@neondatabase/serverless\",\n \"@planetscale/database\", \"@libsql/client\", \"kysely\"\n ].map(pkg => [pkg, \"database\" as RiskyCategory] as const),\n\n // native packages (note: bcrypt appears in both auth and native)\n ...[\"sharp\", \"canvas\", \"node-gyp\", \"node-pre-gyp\", \"node-addon-api\",\n \"nan\", \"ffi-napi\", \"ref-napi\", \"argon2\", \"libsodium-wrappers\",\n \"sodium-native\", \"cpu-features\", \"usb\", \"serialport\"\n ].map(pkg => [pkg, \"native\" as RiskyCategory] as const),\n\n // payment packages\n ...[\"stripe\", \"@stripe/stripe-js\", \"paypal-rest-sdk\",\n \"@paypal/checkout-server-sdk\", \"braintree\", \"square\", \"@square/web-sdk\",\n \"adyen-api-library\", \"razorpay\", \"mollie-api-node\", \"lemon-squeezy\",\n \"@polar-sh/sdk\", \"polar-sdk\"\n ].map(pkg => [pkg, \"payment\" as RiskyCategory] as const),\n]);\n\n/**\n * Check if a package is in a risky category.\n * Uses Map lookup for O(1) performance.\n */\nfunction getRiskyCategory(packageName: string): RiskyCategory | undefined {\n return RISKY_PACKAGE_MAP.get(packageName);\n}\n\n/**\n * Pre-compiled regex for version string cleaning.\n * Compiled once at module load time for performance.\n */\nconst VERSION_PREFIX_REGEX = /^[\\^~>=<]+/;\n\n/**\n * Clean version string for semver parsing.\n */\nfunction cleanVersion(version: string): string {\n // Remove common prefixes: ^, ~, >=, etc.\n return version.replace(VERSION_PREFIX_REGEX, \"\").trim();\n}\n\n/**\n * Determine version impact.\n */\nexport function determineImpact(\n from: string | undefined,\n to: string | undefined\n): \"major\" | \"minor\" | \"patch\" | \"unknown\" {\n if (!from || !to) {\n return \"unknown\";\n }\n\n const cleanFrom = cleanVersion(from);\n const cleanTo = cleanVersion(to);\n\n const parsedFrom = semver.parse(cleanFrom);\n const parsedTo = semver.parse(cleanTo);\n\n if (!parsedFrom || !parsedTo) {\n return \"unknown\";\n }\n\n if (parsedTo.major > parsedFrom.major) {\n return \"major\";\n }\n if (parsedTo.minor > parsedFrom.minor) {\n return \"minor\";\n }\n if (parsedTo.patch > parsedFrom.patch) {\n return \"patch\";\n }\n\n return \"unknown\";\n}\n\n/**\n * Compare dependencies between two package.json versions.\n */\nexport function compareDependencies(\n basePkg: PackageDeps | undefined,\n headPkg: PackageDeps | undefined\n): DependencyChangeFinding[] {\n const findings: DependencyChangeFinding[] = [];\n\n const sections: DependencySection[] = [\"dependencies\", \"devDependencies\"];\n\n for (const section of sections) {\n const baseDeps = basePkg?.[section] ?? {};\n const headDeps = headPkg?.[section] ?? {};\n\n const allPackages = new Set([\n ...Object.keys(baseDeps),\n ...Object.keys(headDeps),\n ]);\n\n for (const name of allPackages) {\n const from = baseDeps[name];\n const to = headDeps[name];\n\n if (from === to) {\n continue; // No change\n }\n\n const riskCategory = getRiskyCategory(name);\n\n if (!from && to) {\n // Added\n const excerpt = `\"${name}\": \"${to}\"`;\n findings.push({\n type: \"dependency-change\",\n kind: \"dependency-change\",\n category: \"dependencies\",\n confidence: \"high\",\n evidence: [createEvidence(\"package.json\", excerpt)],\n name,\n section,\n to,\n impact: \"new\",\n riskCategory,\n });\n } else if (from && !to) {\n // Removed\n const excerpt = `\"${name}\": \"${from}\" (removed)`;\n findings.push({\n type: \"dependency-change\",\n kind: \"dependency-change\",\n category: \"dependencies\",\n confidence: \"high\",\n evidence: [createEvidence(\"package.json\", excerpt)],\n name,\n section,\n from,\n impact: \"removed\",\n riskCategory,\n });\n } else {\n // Changed\n const impact = determineImpact(from, to);\n const excerpt = `\"${name}\": \"${from}\" → \"${to}\"`;\n findings.push({\n type: \"dependency-change\",\n kind: \"dependency-change\",\n category: \"dependencies\",\n confidence: \"high\",\n evidence: [createEvidence(\"package.json\", excerpt)],\n name,\n section,\n from,\n to,\n impact,\n riskCategory,\n });\n }\n }\n }\n\n return findings;\n}\n\nexport const dependencyAnalyzer: Analyzer = {\n name: \"dependencies\",\n\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: Finding[] = [];\n\n const depFindings = compareDependencies(\n changeSet.basePackageJson as PackageDeps | undefined,\n changeSet.headPackageJson as PackageDeps | undefined\n );\n\n findings.push(...depFindings);\n\n // Check for critical package major bumps\n for (const depFinding of depFindings) {\n if (\n CRITICAL_PACKAGES.includes(depFinding.name) &&\n depFinding.impact === \"major\" &&\n depFinding.from &&\n depFinding.to\n ) {\n const excerpt = `${depFinding.name}: ${depFinding.from} → ${depFinding.to}`;\n const riskFinding: RiskFlagFinding = {\n type: \"risk-flag\",\n kind: \"risk-flag\",\n category: \"dependencies\",\n confidence: \"high\",\n evidence: [createEvidence(\"package.json\", excerpt)],\n risk: \"high\",\n evidenceText: `Major version bump: ${depFinding.name} ${depFinding.from} → ${depFinding.to}`,\n };\n findings.push(riskFinding);\n }\n\n // Flag risky packages\n if (depFinding.riskCategory && depFinding.impact === \"new\") {\n const categoryLabels: Record<RiskyCategory, string> = {\n auth: \"Authentication/Security\",\n database: \"Database/ORM\",\n native: \"Native Module\",\n payment: \"Payment Processing\",\n };\n const excerpt = `${depFinding.name}: ${depFinding.to}`;\n const riskFinding: RiskFlagFinding = {\n type: \"risk-flag\",\n kind: \"risk-flag\",\n category: \"dependencies\",\n confidence: \"medium\",\n evidence: [createEvidence(\"package.json\", excerpt)],\n risk: \"medium\",\n evidenceText: `New ${categoryLabels[depFinding.riskCategory]} package: ${depFinding.name}`,\n };\n findings.push(riskFinding);\n }\n }\n\n return findings;\n },\n};\n\n",
|
|
20
|
-
"/**\n * Security-sensitive file change detector.\n */\n\nimport { createEvidence } from \"../core/evidence.js\";\nimport type {\n Analyzer,\n ChangeSet,\n Finding,\n RiskFlagFinding,\n SecurityFileFinding,\n SecurityFileReason,\n} from \"../core/types.js\";\n\n// Patterns for security-sensitive paths\nconst SECURITY_PATH_PATTERNS: Array<{\n pattern: RegExp;\n reason: SecurityFileReason;\n}> = [\n // Auth-related paths\n { pattern: /\\bauth\\b/i, reason: \"auth-path\" },\n { pattern: /\\blogin\\b/i, reason: \"auth-path\" },\n { pattern: /\\blogout\\b/i, reason: \"auth-path\" },\n { pattern: /\\bsignin\\b/i, reason: \"auth-path\" },\n { pattern: /\\bsignout\\b/i, reason: \"auth-path\" },\n { pattern: /\\bsignup\\b/i, reason: \"auth-path\" },\n { pattern: /\\bregister\\b/i, reason: \"auth-path\" },\n\n // Session-related\n { pattern: /\\bsession\\b/i, reason: \"session-path\" },\n { pattern: /\\bjwt\\b/i, reason: \"session-path\" },\n { pattern: /\\btoken\\b/i, reason: \"session-path\" },\n { pattern: /\\bcookie\\b/i, reason: \"session-path\" },\n { pattern: /\\boauth\\b/i, reason: \"session-path\" },\n\n // Permission-related\n { pattern: /\\bpermission\\b/i, reason: \"permission-path\" },\n { pattern: /\\brbac\\b/i, reason: \"permission-path\" },\n { pattern: /\\bacl\\b/i, reason: \"permission-path\" },\n { pattern: /\\brole\\b/i, reason: \"permission-path\" },\n { pattern: /\\bauthoriz/i, reason: \"permission-path\" }, // authorize, authorization\n\n // Middleware (common in auth flows)\n { pattern: /middleware\\.[jt]sx?$/i, reason: \"middleware\" },\n { pattern: /\\/middleware\\//, reason: \"middleware\" },\n\n // Guards (route protection)\n { pattern: /guard\\.[jt]sx?$/i, reason: \"guard\" },\n { pattern: /\\/guards?\\//, reason: \"guard\" },\n\n // Policies\n { pattern: /policy\\.[jt]sx?$/i, reason: \"policy\" },\n { pattern: /\\/policies\\//, reason: \"policy\" },\n];\n\n/**\n * Check if a file path is security-sensitive.\n */\nexport function isSecurityFile(path: string): SecurityFileReason | null {\n for (const { pattern, reason } of SECURITY_PATH_PATTERNS) {\n if (pattern.test(path)) {\n return reason;\n }\n }\n return null;\n}\n\n/**\n * Get a human-readable label for a security reason.\n */\nexport function getSecurityReasonLabel(reason: SecurityFileReason): string {\n const labels: Record<SecurityFileReason, string> = {\n \"auth-path\": \"Authentication\",\n \"session-path\": \"Session/Token\",\n \"permission-path\": \"Permissions/RBAC\",\n middleware: \"Middleware\",\n guard: \"Route Guard\",\n policy: \"Policy\",\n };\n return labels[reason];\n}\n\nexport const securityFilesAnalyzer: Analyzer = {\n name: \"security-files\",\n\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: Finding[] = [];\n const securityFiles: string[] = [];\n const reasons = new Set<SecurityFileReason>();\n\n // Check all changed files\n for (const file of changeSet.files) {\n const reason = isSecurityFile(file.path);\n if (reason) {\n securityFiles.push(file.path);\n reasons.add(reason);\n }\n }\n\n // Only emit if there are security-sensitive files\n if (securityFiles.length === 0) {\n return [];\n }\n\n // Create evidence from file paths\n const evidence = securityFiles\n .slice(0, 3)\n .map((file) => createEvidence(file, `Security file: ${file}`));\n\n const securityFinding: SecurityFileFinding = {\n type: \"security-file\",\n kind: \"security-file\",\n category: \"infra\",\n confidence: \"medium\",\n evidence,\n files: securityFiles,\n reasons: Array.from(reasons),\n };\n findings.push(securityFinding);\n\n // Add risk flag for security file changes\n const reasonLabels = Array.from(reasons)\n .map(getSecurityReasonLabel)\n .join(\", \");\n const riskFinding: RiskFlagFinding = {\n type: \"risk-flag\",\n kind: \"risk-flag\",\n category: \"infra\",\n confidence: \"medium\",\n evidence,\n risk: \"medium\",\n evidenceText: `Security-sensitive files changed (${reasonLabels}): ${securityFiles.length} file(s)`,\n };\n findings.push(riskFinding);\n\n return findings;\n },\n};\n\n",
|
|
21
|
-
"/**\n * Batch git operations.\n */\n\nimport { execa as execaDefault } from \"execa\";\n\n/**\n * Fetch content for multiple file:ref pairs using git cat-file --batch.\n * @param items Array of { ref, path }\n * @param cwd Working directory\n * @returns Map of \"ref:path\" -> content\n */\nexport async function batchGetFileContent(\n items: Array<{ ref: string; path: string }>,\n cwd: string = process.cwd(),\n exec: typeof execaDefault = execaDefault\n): Promise<Map<string, string>> {\n if (items.length === 0) return new Map();\n\n const resultMap = new Map<string, string>();\n\n // Format input for git cat-file --batch: \"ref:path\"\n const inputs = items.map(item => `${item.ref}:${item.path}`);\n // IMPORTANT: git cat-file --batch expects a newline after the last item to process it\n const inputString = inputs.join(\"\\n\") + \"\\n\";\n\n try {\n const subprocess = exec(\"git\", [\"cat-file\", \"--batch\"], {\n cwd,\n input: inputString,\n // NOTE: We intentionally do NOT use execa's `encoding: \"buffer\"` here.\n // In Bun, execa's buffer mode can throw (attempting to write to readonly streams).\n // We parse using byte offsets by converting the UTF-8 string output to a Buffer.\n });\n\n const { stdout: stdoutRaw } = await subprocess;\n const stdout = Buffer.isBuffer(stdoutRaw)\n ? stdoutRaw\n : Buffer.from(String(stdoutRaw), \"utf-8\");\n\n let currentIndex = 0;\n for (const inputKey of inputs) {\n if (currentIndex >= stdout.length) break;\n\n // Find the header line (ends with newline)\n const newlineIndex = stdout.indexOf(\"\\n\", currentIndex);\n if (newlineIndex === -1) break;\n\n const headerBuffer = stdout.subarray(currentIndex, newlineIndex);\n const headerString = headerBuffer.toString(\"utf-8\");\n\n const [sha1, type, sizeStr] = headerString.split(\" \");\n\n if (!sha1 || !type || !sizeStr) {\n // Should not happen on standard success output\n currentIndex = newlineIndex + 1;\n continue;\n }\n\n if (type === \"missing\") {\n // \"<object> missing\"\n currentIndex = newlineIndex + 1;\n continue;\n }\n\n const size = parseInt(sizeStr, 10);\n const contentStart = newlineIndex + 1;\n const contentEnd = contentStart + size;\n\n // Extract content based on byte offsets\n const contentBuffer = stdout.subarray(contentStart, contentEnd);\n resultMap.set(inputKey, contentBuffer.toString(\"utf-8\"));\n\n // Advance index: content + newline\n currentIndex = contentEnd + 1;\n }\n\n } catch (error) {\n console.warn(\"Failed to batch fetch files:\", error);\n }\n\n return resultMap;\n}\n",
|
|
22
|
-
"/**\n * React Router route detector - detects changes in React Router routes.\n * Supports both JSX routes (<Route>) and data routers (createBrowserRouter).\n */\n\nimport { parse } from \"@babel/parser\";\nimport traverse from \"@babel/traverse\";\nimport * as t from \"@babel/types\";\nimport type {\n Analyzer,\n ChangeSet,\n Finding,\n RouteChangeFinding,\n} from \"../core/types.js\";\nimport { createEvidence } from \"../core/evidence.js\";\nimport { batchGetFileContent as defaultBatchGetFileContent } from \"../git/batch.js\";\n\n// Allow injection for testing\nexport const dependencies = {\n batchGetFileContent: defaultBatchGetFileContent,\n};\n\n// ============================================================================\n// Route Extraction\n// ============================================================================\n\ninterface ExtractedRoute {\n path: string;\n file: string;\n}\n\nfunction isCandidateFile(path: string): boolean {\n // Check extension\n const validExtensions = [\".ts\", \".tsx\", \".js\", \".jsx\"];\n if (!validExtensions.some((ext) => path.endsWith(ext))) {\n return false;\n }\n\n // We previously checked diffContent for react-router keywords,\n // but that causes us to miss modifications where imports aren't touched.\n // We accept the cost of checking all JS/TS files in exchange for correctness.\n return true;\n}\n\n/**\n * Normalize route path.\n * - Collapse multiple slashes\n * - Remove trailing slash unless path is exactly \"/\"\n */\nexport function normalizePath(path: string): string {\n // Collapse multiple slashes\n let normalized = path.replace(/\\/+/g, \"/\");\n\n // Remove trailing slash unless it's the root path\n if (normalized !== \"/\" && normalized.endsWith(\"/\")) {\n normalized = normalized.slice(0, -1);\n }\n\n return normalized;\n}\n\n/**\n * Join parent and child paths.\n */\nexport function joinPaths(parent: string, child: string): string {\n // If child starts with \"/\", treat as absolute\n if (child.startsWith(\"/\")) {\n return normalizePath(child);\n }\n\n // Join with \"/\"\n const joined = parent === \"/\" ? `/${child}` : `${parent}/${child}`;\n return normalizePath(joined);\n}\n\n/**\n * Extract routes from JSX <Route> elements.\n */\nexport function extractJsxRoutes(\n ast: t.File,\n filePath: string,\n parentPath = \"/\"\n): ExtractedRoute[] {\n const routes: ExtractedRoute[] = [];\n\n traverse(ast, {\n JSXElement(path) {\n const openingElement = path.node.openingElement;\n const name = openingElement.name;\n\n // Check if this is a <Route> element\n if (t.isJSXIdentifier(name) && name.name === \"Route\") {\n let routePath: string | null = null;\n let isIndex = false;\n let children: t.JSXElement[] = [];\n\n // Extract path attribute\n for (const attr of openingElement.attributes) {\n if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name)) {\n if (attr.name.name === \"path\" && attr.value) {\n if (t.isStringLiteral(attr.value)) {\n routePath = attr.value.value;\n } else if (\n t.isJSXExpressionContainer(attr.value) &&\n t.isStringLiteral(attr.value.expression)\n ) {\n routePath = attr.value.expression.value;\n }\n } else if (attr.name.name === \"index\") {\n isIndex = true;\n }\n }\n }\n\n // Handle index routes\n if (isIndex) {\n routes.push({\n path: normalizePath(parentPath),\n file: filePath,\n });\n } else if (routePath) {\n const fullPath = joinPaths(parentPath, routePath);\n routes.push({\n path: fullPath,\n file: filePath,\n });\n\n // Extract nested routes\n for (const child of path.node.children) {\n if (t.isJSXElement(child)) {\n children.push(child);\n }\n }\n\n // Process children with current route as parent\n for (const child of children) {\n const childAst: t.File = t.file(t.program([t.expressionStatement(child)]));\n const childRoutes = extractJsxRoutes(childAst, filePath, fullPath);\n routes.push(...childRoutes);\n }\n }\n\n // We've manually processed this Route's children; avoid traversing them again\n path.skip();\n }\n },\n });\n\n return routes;\n}\n\n/**\n * Extract routes from data router configuration.\n */\nexport function extractDataRoutes(\n ast: t.File,\n filePath: string,\n parentPath = \"/\"\n): ExtractedRoute[] {\n const routes: ExtractedRoute[] = [];\n const routeConfigs = new Map<string, t.Expression>();\n\n // First pass: collect route config variables\n traverse(ast, {\n VariableDeclarator(path) {\n if (\n t.isIdentifier(path.node.id) &&\n (t.isArrayExpression(path.node.init) ||\n t.isObjectExpression(path.node.init))\n ) {\n routeConfigs.set(path.node.id.name, path.node.init);\n }\n },\n });\n\n // Second pass: find createBrowserRouter/createHashRouter/createMemoryRouter calls\n traverse(ast, {\n CallExpression(path) {\n const callee = path.node.callee;\n if (\n t.isIdentifier(callee) &&\n (callee.name === \"createBrowserRouter\" ||\n callee.name === \"createHashRouter\" ||\n callee.name === \"createMemoryRouter\")\n ) {\n const firstArg = path.node.arguments[0];\n let routesArray: t.ArrayExpression | null = null;\n\n // Check if first argument is an array literal\n if (t.isArrayExpression(firstArg)) {\n routesArray = firstArg;\n }\n // Check if first argument is an identifier referencing a routes variable\n else if (t.isIdentifier(firstArg)) {\n const config = routeConfigs.get(firstArg.name);\n if (config && t.isArrayExpression(config)) {\n routesArray = config;\n }\n }\n\n if (routesArray) {\n const extracted = extractRoutesFromArray(\n routesArray,\n filePath,\n parentPath\n );\n routes.push(...extracted);\n }\n }\n },\n });\n\n return routes;\n}\n\n/**\n * Extract routes from route configuration array.\n */\nfunction extractRoutesFromArray(\n array: t.ArrayExpression,\n filePath: string,\n parentPath = \"/\"\n): ExtractedRoute[] {\n const routes: ExtractedRoute[] = [];\n\n for (const element of array.elements) {\n if (t.isObjectExpression(element)) {\n const routeConfig = extractRouteConfig(element);\n \n if (routeConfig.index) {\n routes.push({\n path: normalizePath(parentPath),\n file: filePath,\n });\n } else if (routeConfig.path) {\n const fullPath = joinPaths(parentPath, routeConfig.path);\n routes.push({\n path: fullPath,\n file: filePath,\n });\n\n // Process children\n if (routeConfig.children) {\n const childRoutes = extractRoutesFromArray(\n routeConfig.children,\n filePath,\n fullPath\n );\n routes.push(...childRoutes);\n }\n }\n }\n }\n\n return routes;\n}\n\n/**\n * Extract route configuration from an object expression.\n */\nfunction extractRouteConfig(obj: t.ObjectExpression): {\n path?: string;\n index?: boolean;\n children?: t.ArrayExpression;\n} {\n const config: {\n path?: string;\n index?: boolean;\n children?: t.ArrayExpression;\n } = {};\n\n for (const prop of obj.properties) {\n if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {\n if (prop.key.name === \"path\" && t.isStringLiteral(prop.value)) {\n config.path = prop.value.value;\n } else if (prop.key.name === \"index\") {\n if (t.isBooleanLiteral(prop.value) && prop.value.value) {\n config.index = true;\n }\n } else if (prop.key.name === \"children\" && t.isArrayExpression(prop.value)) {\n config.children = prop.value;\n }\n }\n }\n\n return config;\n}\n\n/**\n * Extract all routes from file content.\n */\nexport function extractRoutesFromContent(\n content: string,\n filePath: string\n): ExtractedRoute[] {\n try {\n const ast = parse(content, {\n sourceType: \"module\",\n plugins: [\"typescript\", \"jsx\"],\n });\n\n const jsxRoutes = extractJsxRoutes(ast, filePath);\n const dataRoutes = extractDataRoutes(ast, filePath);\n\n return [...jsxRoutes, ...dataRoutes];\n } catch (error) {\n // Parsing failed, skip silently\n return [];\n }\n}\n\n// ============================================================================\n// Analyzer\n// ============================================================================\n\nexport const reactRouterRoutesAnalyzer: Analyzer = {\n name: \"react-router-routes\",\n\n async analyze(changeSet: ChangeSet): Promise<Finding[]> {\n const findings: Finding[] = [];\n\n // Select candidate files\n const candidateFiles = changeSet.files.filter((file) => {\n // We assume isCandidateFile logic is correct\n return isCandidateFile(file.path);\n });\n\n if (candidateFiles.length === 0) return [];\n\n // Prepare batch request\n const batchRequest: Array<{ ref: string; path: string }> = [];\n for (const file of candidateFiles) {\n batchRequest.push({ ref: changeSet.base, path: file.path });\n batchRequest.push({ ref: changeSet.head, path: file.path });\n }\n\n // Determine CWD (implicitly handled if batchGetFileContent uses process.cwd(),\n // but ideally ChangeSet should provide it. Since we don't have it in ChangeSet,\n // we assume process.cwd() is correct as per other analyzers).\n // Note: In benchmarks we chdir to the repo.\n const contentMap = await dependencies.batchGetFileContent(batchRequest);\n\n // Extract routes from base and head for each file\n for (const file of candidateFiles) {\n const baseKey = `${changeSet.base}:${file.path}`;\n const headKey = `${changeSet.head}:${file.path}`;\n\n const baseContent = contentMap.get(baseKey);\n const headContent = contentMap.get(headKey);\n\n // Heuristic: If content doesn't contain \"react-router\", \"Route\", etc., skip AST parsing\n // This saves time on files that are .tsx but not routes.\n const hasRouterKeywords = (content: string) =>\n content.includes(\"react-router\") ||\n content.includes(\"<Route\") ||\n content.includes(\"createBrowserRouter\") ||\n content.includes(\"createHashRouter\") ||\n content.includes(\"createMemoryRouter\");\n\n if (baseContent && !hasRouterKeywords(baseContent) && headContent && !hasRouterKeywords(headContent)) {\n continue;\n }\n\n const baseRoutes = baseContent\n ? extractRoutesFromContent(baseContent, file.path)\n : [];\n const headRoutes = headContent\n ? extractRoutesFromContent(headContent, file.path)\n : [];\n\n // Create sets for comparison\n const basePaths = new Set(baseRoutes.map((r) => r.path));\n const headPaths = new Set(headRoutes.map((r) => r.path));\n\n // Find added routes\n for (const route of headRoutes) {\n if (!basePaths.has(route.path)) {\n const finding: RouteChangeFinding = {\n type: \"route-change\",\n kind: \"route-change\",\n category: \"routes\",\n confidence: \"high\",\n evidence: [createEvidence(file.path, `Route: ${route.path}`)],\n routeId: route.path,\n file: file.path,\n change: \"added\",\n routeType: \"page\",\n };\n findings.push(finding);\n }\n }\n\n // Find deleted routes\n for (const route of baseRoutes) {\n if (!headPaths.has(route.path)) {\n const finding: RouteChangeFinding = {\n type: \"route-change\",\n kind: \"route-change\",\n category: \"routes\",\n confidence: \"high\",\n evidence: [createEvidence(file.path, `Route: ${route.path}`)],\n routeId: route.path,\n file: file.path,\n change: \"deleted\",\n routeType: \"page\",\n };\n findings.push(finding);\n }\n }\n }\n\n // Deduplicate findings by routeId + change + file\n const uniqueFindings = Array.from(\n new Map(\n findings.map((f) => {\n const key = `${(f as RouteChangeFinding).routeId}-${\n (f as RouteChangeFinding).change\n }-${(f as RouteChangeFinding).file}`;\n return [key, f];\n })\n ).values()\n );\n\n // Sort by routeId for deterministic output\n return uniqueFindings.sort((a, b) => {\n const aRoute = (a as RouteChangeFinding).routeId;\n const bRoute = (b as RouteChangeFinding).routeId;\n return aRoute.localeCompare(bRoute);\n });\n },\n};\n",
|
|
23
|
-
"/**\n * Test Parity Analyzer.\n * Checks if modified source files have corresponding test files.\n *\n * This analyzer is opt-in only - it must be explicitly enabled via CLI flag\n * as it requires git file system operations which can be resource-intensive.\n */\n\nimport path from \"node:path\";\nimport { execa as execaDefault } from \"execa\";\nimport { createEvidence } from \"../core/evidence.js\";\nimport type {\n Analyzer,\n ChangeSet,\n Confidence,\n Finding,\n TestParityConfig,\n TestParityViolationFinding,\n} from \"../core/types.js\";\nimport { isTestFile } from \"./vitest.js\";\n\n// ============================================================================\n// Default Configuration\n// ============================================================================\n\n/** Default patterns for files to exclude from parity check */\nconst DEFAULT_EXCLUDED_PATTERNS: RegExp[] = [\n /\\.d\\.ts$/, // Type definitions\n /\\.config\\.(ts|js|mts|mjs|cjs)$/, // Config files\n /index\\.(ts|js|tsx|jsx)$/, // Barrel files (often don't need direct tests)\n /^docs\\//, // Documentation\n /^tests\\//, // Tests themselves\n /^test\\//, // Alternative test directory\n /^__tests__\\//, // Jest-style test directory\n /^scripts\\//, // Build scripts\n /^dist\\//, // Build artifacts\n /^build\\//, // Build artifacts\n /^\\./, // Dotfiles and directories\n /types?\\.(ts|js)$/, // Type-only files\n /constants?\\.(ts|js)$/, // Constants files (often just exports)\n];\n\n/** Default test file extensions to search for */\nconst DEFAULT_TEST_PATTERNS = [\".test.ts\", \".spec.ts\", \".test.js\", \".spec.js\", \".test.tsx\", \".spec.tsx\"];\n\n/** Default test directories */\nconst DEFAULT_TEST_DIRECTORIES = [\"tests\", \"test\", \"__tests__\", \"spec\"];\n\n/** Default source directories */\nconst DEFAULT_SOURCE_DIRECTORIES = [\"src\", \"lib\", \"app\"];\n\n// ============================================================================\n// Cache Management\n// ============================================================================\n\n/** Cache for files per directory (more granular than entire repo) */\nconst directoryFileCache = new Map<string, Set<string>>();\n\n/** Full file list cache (fallback) */\nlet cachedFullFileList: Set<string> | null = null;\n\n/**\n * Reset all caches - for testing purposes.\n */\nexport function _resetCacheForTesting(): void {\n directoryFileCache.clear();\n cachedFullFileList = null;\n}\n\n// ============================================================================\n// File Discovery (Optimized)\n// ============================================================================\n\n/**\n * Get files in specific directories using git ls-files.\n * More efficient than loading entire repo for targeted lookups.\n */\nasync function getFilesInDirectories(\n directories: string[],\n exec: typeof execaDefault\n): Promise<Set<string>> {\n // Check cache first\n const cachedResults = new Set<string>();\n const uncachedDirs: string[] = [];\n\n for (const dir of directories) {\n const cached = directoryFileCache.get(dir);\n if (cached) {\n for (const file of cached) {\n cachedResults.add(file);\n }\n } else {\n uncachedDirs.push(dir);\n }\n }\n\n // If all directories are cached, return combined results\n if (uncachedDirs.length === 0) {\n return cachedResults;\n }\n\n try {\n // Query git for uncached directories\n const { stdout } = await exec(\n \"git\",\n [\"ls-files\", \"--cached\", \"--others\", \"--exclude-standard\", \"--\", ...uncachedDirs],\n { reject: false }\n );\n\n const files = stdout.split(\"\\n\").filter(Boolean);\n\n // Cache per directory\n for (const dir of uncachedDirs) {\n const dirFiles = new Set<string>();\n for (const file of files) {\n if (file.startsWith(dir + \"/\") || file.startsWith(dir + path.sep)) {\n dirFiles.add(file);\n cachedResults.add(file);\n }\n }\n directoryFileCache.set(dir, dirFiles);\n }\n\n // Also add root-level files if querying root\n for (const file of files) {\n if (!file.includes(\"/\") && !file.includes(path.sep)) {\n cachedResults.add(file);\n }\n }\n\n return cachedResults;\n } catch {\n // Fallback to full file list if targeted query fails\n return getAllFiles(exec);\n }\n}\n\n/**\n * Get all files in the project using git ls-files.\n * Returns a Set for O(1) lookups.\n * This is the fallback when targeted queries aren't possible.\n */\nasync function getAllFiles(exec: typeof execaDefault): Promise<Set<string>> {\n if (cachedFullFileList) return cachedFullFileList;\n\n try {\n const { stdout } = await exec(\n \"git\",\n [\"ls-files\", \"--cached\", \"--others\", \"--exclude-standard\"],\n { reject: false }\n );\n cachedFullFileList = new Set(stdout.split(\"\\n\").filter(Boolean));\n return cachedFullFileList;\n } catch {\n return new Set();\n }\n}\n\n// ============================================================================\n// Analysis Helpers\n// ============================================================================\n\n/**\n * Merge user config with defaults.\n */\nfunction mergeConfig(config?: TestParityConfig): Required<Omit<TestParityConfig, \"excludePatterns\">> & { excludePatterns: RegExp[] } {\n return {\n testPatterns: config?.testPatterns ?? DEFAULT_TEST_PATTERNS,\n excludePatterns: [...DEFAULT_EXCLUDED_PATTERNS, ...(config?.excludePatterns ?? [])],\n testDirectories: config?.testDirectories ?? DEFAULT_TEST_DIRECTORIES,\n sourceDirectories: config?.sourceDirectories ?? DEFAULT_SOURCE_DIRECTORIES,\n };\n}\n\n/**\n * Check if a file should be checked for test parity.\n */\nfunction shouldCheckParity(filePath: string, excludePatterns: RegExp[]): boolean {\n if (isTestFile(filePath)) return false;\n if (excludePatterns.some((p) => p.test(filePath))) return false;\n // Only check typescript/javascript source files\n return /\\.(ts|js|tsx|jsx|mts|mjs)$/.test(filePath);\n}\n\n/**\n * Compute confidence based on file characteristics.\n */\nfunction computeConfidence(filePath: string, diff?: { additions: number; deletions: number }): Confidence {\n // Lower confidence for utility/helper files\n if (/utils?|helpers?|lib|shared/i.test(filePath)) {\n return \"medium\";\n }\n\n // Lower confidence for small files (if we have diff info)\n if (diff && diff.additions + diff.deletions < 10) {\n return \"low\";\n }\n\n // Higher confidence for core business logic\n if (/services?|controllers?|handlers?|api|routes|commands?|analyzers?/i.test(filePath)) {\n return \"high\";\n }\n\n // Default to medium for most cases\n return \"medium\";\n}\n\n/**\n * Generate all potential test file locations for a source file.\n */\nfunction generateTestLocations(\n sourcePath: string,\n testPatterns: string[],\n testDirectories: string[],\n sourceDirectories: string[]\n): string[] {\n const locations: string[] = [];\n const ext = path.extname(sourcePath);\n const baseName = path.basename(sourcePath, ext);\n const dirName = path.dirname(sourcePath);\n\n // 1. Colocation: src/foo.ts -> src/foo.test.ts\n for (const testExt of testPatterns) {\n locations.push(path.join(dirName, `${baseName}${testExt}`));\n }\n\n // 2. Test directory mappings\n let relativePath = sourcePath;\n for (const srcDir of sourceDirectories) {\n if (sourcePath.startsWith(`${srcDir}/`)) {\n relativePath = sourcePath.slice(srcDir.length + 1);\n break;\n }\n }\n\n for (const testDir of testDirectories) {\n for (const testExt of testPatterns) {\n // Mirror: src/utils/math.ts -> tests/utils/math.test.ts\n locations.push(path.join(testDir, path.dirname(relativePath), `${baseName}${testExt}`));\n\n // Flat: src/utils/math.ts -> tests/math.test.ts\n locations.push(path.join(testDir, `${baseName}${testExt}`));\n\n // Mirror with source dir: src/utils/math.ts -> tests/src/utils/math.test.ts\n locations.push(path.join(testDir, dirName, `${baseName}${testExt}`));\n }\n }\n\n // 3. Hyphenated patterns: various naming conventions\n const pathParts = relativePath.split(path.sep);\n if (pathParts.length > 1) {\n const parentDir = pathParts[pathParts.length - 2];\n // Pattern A: parent-basename (e.g., src/commands/facts/builder.ts -> tests/facts-builder.test.ts)\n const hyphenatedA = `${parentDir}-${baseName}`;\n // Pattern B: basename-parent (e.g., src/render/markdown.ts -> tests/markdown-render.test.ts)\n const hyphenatedB = `${baseName}-${parentDir}`;\n \n for (const testDir of testDirectories) {\n for (const testExt of testPatterns) {\n locations.push(path.join(testDir, `${hyphenatedA}${testExt}`));\n locations.push(path.join(testDir, `${hyphenatedB}${testExt}`));\n }\n }\n }\n\n // Deduplicate and normalize\n return [...new Set(locations.map((loc) => path.normalize(loc)))];\n}\n\n/**\n * Find an existing test file for a source file.\n */\nasync function findTestFile(\n sourcePath: string,\n testPatterns: string[],\n testDirectories: string[],\n sourceDirectories: string[],\n allFiles: Set<string>\n): Promise<string | null> {\n const locations = generateTestLocations(sourcePath, testPatterns, testDirectories, sourceDirectories);\n\n for (const location of locations) {\n if (allFiles.has(location)) {\n return location;\n }\n }\n\n return null;\n}\n\n/**\n * Check if a test file for the source is being added in the current changeset.\n */\nfunction hasNewTestInChangeset(sourcePath: string, changeSet: ChangeSet): boolean {\n const baseName = path.basename(sourcePath, path.extname(sourcePath));\n\n return changeSet.files.some(\n (f) => isTestFile(f.path) && f.path.includes(baseName) && f.status !== \"deleted\"\n );\n}\n\n// ============================================================================\n// Analyzer Factory\n// ============================================================================\n\n/**\n * Create a test parity analyzer with optional configuration.\n */\nexport function createTestParityAnalyzer(\n config?: TestParityConfig,\n options?: { exec?: typeof execaDefault }\n): Analyzer {\n const mergedConfig = mergeConfig(config);\n const exec = options?.exec ?? execaDefault;\n\n return {\n name: \"test-parity\",\n\n async analyze(changeSet: ChangeSet): Promise<Finding[]> {\n const findings: TestParityViolationFinding[] = [];\n\n // Collect directories we need to check\n const dirsToCheck = new Set<string>();\n for (const file of changeSet.files) {\n if (file.status === \"deleted\") continue;\n if (!shouldCheckParity(file.path, mergedConfig.excludePatterns)) continue;\n\n // Add source directory\n const dirName = path.dirname(file.path);\n if (dirName && dirName !== \".\") {\n dirsToCheck.add(dirName.split(path.sep)[0]); // Top-level dir\n }\n }\n\n // Add test directories to check\n for (const testDir of mergedConfig.testDirectories) {\n dirsToCheck.add(testDir);\n }\n\n // Get files from relevant directories only (optimized)\n const allFiles = await getFilesInDirectories([...dirsToCheck], exec);\n\n // Also ensure we have changeset files in our set (they may not be committed yet)\n for (const file of changeSet.files) {\n if (file.status !== \"deleted\") {\n allFiles.add(file.path);\n }\n }\n\n // Analyze each file\n for (const file of changeSet.files) {\n if (file.status === \"deleted\") continue;\n if (!shouldCheckParity(file.path, mergedConfig.excludePatterns)) continue;\n\n // Check for existing test file\n const testFile = await findTestFile(\n file.path,\n mergedConfig.testPatterns,\n mergedConfig.testDirectories,\n mergedConfig.sourceDirectories,\n allFiles\n );\n\n if (testFile) {\n // Test exists, no violation\n continue;\n }\n\n // Check if a new test is being added in the changeset\n if (hasNewTestInChangeset(file.path, changeSet)) {\n continue;\n }\n\n // Get diff info for confidence scoring\n const fileDiff = changeSet.diffs.find((d) => d.path === file.path);\n const diffInfo = fileDiff\n ? {\n additions: fileDiff.hunks.reduce((sum, h) => sum + h.additions.length, 0),\n deletions: fileDiff.hunks.reduce((sum, h) => sum + h.deletions.length, 0),\n }\n : undefined;\n\n const confidence = computeConfidence(file.path, diffInfo);\n const expectedLocations = generateTestLocations(\n file.path,\n mergedConfig.testPatterns,\n mergedConfig.testDirectories,\n mergedConfig.sourceDirectories\n ).slice(0, 5); // Limit to top 5 for readability\n\n const finding: TestParityViolationFinding = {\n type: \"test-parity-violation\",\n kind: \"test-parity-violation\",\n category: \"tests\",\n confidence,\n evidence: [\n createEvidence(file.path, `Source file modified without corresponding test: ${file.path}`),\n ],\n sourceFile: file.path,\n expectedTestLocations: expectedLocations,\n };\n\n findings.push(finding);\n }\n\n return findings;\n },\n };\n}\n\n/**\n * Default test parity analyzer instance (with default config).\n * Note: This analyzer is NOT included in any profile by default.\n * It must be explicitly enabled via CLI flags.\n */\nexport const testParityAnalyzer: Analyzer = createTestParityAnalyzer();\n",
|
|
24
|
-
"/**\n * Impact Analyzer.\n * Finds files that import the modified files (blast radius).\n */\n\nimport path from \"node:path\";\nimport fs from \"node:fs/promises\";\nimport { execa as execaDefault } from \"execa\";\nimport { createEvidence } from \"../core/evidence.js\";\nimport type {\n Analyzer,\n ChangeSet,\n Finding,\n ImpactAnalysisFinding,\n} from \"../core/types.js\";\n\n// Files to exclude from impact scanning (both as source and target)\nconst EXCLUDE_PATTERNS = [\n /node_modules/,\n /\\.d\\.ts$/,\n /^dist\\//,\n /^build\\//,\n /^\\.git\\//,\n];\n\n// File extensions that support import analysis (code files only)\n// Excludes docs, config, and other non-importable files\nconst ANALYZABLE_EXTENSIONS = new Set([\n \".js\",\n \".jsx\",\n \".ts\",\n \".tsx\",\n \".mjs\",\n \".cjs\",\n \".mts\",\n \".cts\",\n \".vue\",\n \".svelte\",\n]);\n\n// Pattern to match code files (for filtering dependents)\n// Only these files can have actual imports, excludes docs/config/lockfiles\nconst CODE_FILE_PATTERN = /\\.(js|jsx|ts|tsx|mjs|cjs|mts|cts|vue|svelte)$/i;\n\n/**\n * Batch search for dependents using git grep.\n */\nasync function findDependentsBatch(\n targets: Array<{ path: string; baseName: string }>,\n cwd: string = process.cwd(),\n exec: typeof execaDefault = execaDefault\n): Promise<Map<string, string[]>> {\n const results = new Map<string, string[]>();\n targets.forEach((t) => results.set(t.path, []));\n\n if (targets.length === 0) return results;\n\n // Group paths by basename to avoid duplicate searches\n const baseNameToPaths = new Map<string, string[]>();\n for (const t of targets) {\n if (!baseNameToPaths.has(t.baseName)) {\n baseNameToPaths.set(t.baseName, []);\n }\n baseNameToPaths.get(t.baseName)!.push(t.path);\n }\n\n const uniqueBaseNames = Array.from(baseNameToPaths.keys());\n\n // Chunking to avoid ARG_MAX issues\n const CHUNK_SIZE = 50;\n for (let i = 0; i < uniqueBaseNames.length; i += CHUNK_SIZE) {\n const chunk = uniqueBaseNames.slice(i, i + CHUNK_SIZE);\n\n // git grep -I -F --null -e name1 -e name2 ...\n // -I: ignore binary files\n // -F: fixed strings\n // --null: output \\0 after filename\n const args = [\"grep\", \"-I\", \"-F\", \"--null\"];\n for (const name of chunk) {\n args.push(\"-e\");\n args.push(name);\n }\n\n try {\n const { stdout } = await exec(\"git\", args, {\n cwd,\n maxBuffer: 1024 * 1024 * 20, // Increase buffer for large outputs\n reject: false // git grep returns 1 if no matches found\n });\n\n if (!stdout) continue;\n\n const lines = stdout.split(\"\\n\");\n for (const line of lines) {\n if (!line) continue;\n\n // Parse: filename\\0content\n const nullIndex = line.indexOf(\"\\0\");\n if (nullIndex === -1) continue;\n\n const file = line.slice(0, nullIndex);\n const content = line.slice(nullIndex + 1);\n\n // Skip excluded files\n if (EXCLUDE_PATTERNS.some(p => p.test(file))) continue;\n \n // Skip non-code files (docs, config, lockfiles, etc.)\n // These may contain filename text but aren't actual imports\n if (!CODE_FILE_PATTERN.test(file)) continue;\n\n // Check which basename(s) matched in this line\n for (const baseName of chunk) {\n if (content.includes(baseName)) {\n const sourcePaths = baseNameToPaths.get(baseName) || [];\n for (const sourcePath of sourcePaths) {\n // Avoid self-reference\n if (sourcePath !== file) {\n const deps = results.get(sourcePath)!;\n if (!deps.includes(file)) {\n deps.push(file);\n }\n }\n }\n }\n }\n }\n } catch (e) {\n // Should ignore errors\n }\n }\n\n return results;\n}\n\n/**\n * Analyze a dependent file to extract detailed usage information.\n */\nasync function analyzeDependency(\n dependentPath: string,\n sourcePath: string,\n cwd: string = process.cwd(),\n readFile: typeof fs.readFile = fs.readFile\n): Promise<{ importedSymbols: string[]; usageContext: string } | null> {\n try {\n const content = await readFile(path.join(cwd, dependentPath), \"utf-8\");\n const sourceBaseName = path.basename(sourcePath, path.extname(sourcePath));\n const lines = content.split(\"\\n\");\n\n const importedSymbols: string[] = [];\n let usageContext = \"\";\n\n // Regex to find import statement\n // Matches: import { A, B } from './source' or import X from './source'\n // This is heuristic and won't cover 100% of cases (e.g. multiline imports might need smarter parsing)\n // But we iterate lines to find the one containing the source name.\n\n for (const line of lines) {\n if (line.includes(sourceBaseName) && (line.trim().startsWith(\"import\") || line.trim().startsWith(\"export\"))) {\n usageContext = usageContext ? `${usageContext}\\n${line.trim()}` : line.trim();\n\n // Try to extract symbols\n // Case 1: Named imports: import { A, B } ...\n const namedMatch = line.match(/\\{([^}]+)\\}/);\n if (namedMatch) {\n const symbols = namedMatch[1].split(\",\").map(s => {\n const part = s.trim().split(\" as \")[0].trim(); // Handle 'as' aliases\n return part.replace(/^type\\s+/, \"\"); // Handle 'type' keyword\n });\n importedSymbols.push(...symbols);\n }\n\n // Case 2: Default or namespace import: import X ... / import * as X ...\n // Simplistic check: if no curly braces and follows 'import'\n if (!namedMatch && line.trim().startsWith(\"import\")) {\n const parts = line.split(\"from\");\n if (parts.length > 1) {\n const preFrom = parts[0].replace(\"import\", \"\").trim();\n if (preFrom) {\n // Handle namespace imports: import * as Utils from \"./utils\"\n const namespaceMatch = preFrom.match(/\\*\\s+as\\s+([A-Za-z0-9_$]+)/);\n if (namespaceMatch) {\n importedSymbols.push(namespaceMatch[1].trim());\n } else if (!preFrom.includes(\"{\") && !preFrom.includes(\"*\")) {\n // Handle default imports: import X from \"./x\"\n importedSymbols.push(preFrom.split(\" as \")[0].trim());\n }\n }\n } else {\n // Note: lines like `import \"./utils\";` or `import \"./styles.css\";` are side-effect-only imports.\n // In these cases (and if we otherwise fail to parse), we intentionally leave `importedSymbols` empty\n // to distinguish \"no named symbols, just side effects\" from the presence of explicit imported identifiers.\n }\n }\n\n // Removed break to capture multiple imports\n }\n }\n\n // Note: We intentionally don't fall back to any matching line.\n // If no import/export statement was found, usageContext stays empty.\n // This avoids showing garbage like random doc text or config values.\n\n return {\n importedSymbols,\n usageContext,\n };\n\n } catch (error) {\n // If file read fails (e.g. deleted), return null\n return null;\n }\n}\n\nexport function createImpactAnalyzer(options?: {\n cwd?: string;\n exec?: typeof execaDefault;\n readFile?: typeof fs.readFile;\n}): Analyzer {\n const cwd = options?.cwd ?? process.cwd();\n const exec = options?.exec ?? execaDefault;\n const readFile = options?.readFile ?? fs.readFile;\n\n return {\n name: \"impact\",\n\n async analyze(changeSet: ChangeSet): Promise<Finding[]> {\n const findings: Finding[] = [];\n\n // Filter relevant source files - only code files that can be imported\n const sourceFiles = changeSet.files.filter(f => {\n // Only modified or renamed files\n if (f.status !== \"modified\" && f.status !== \"renamed\") return false;\n // Skip excluded paths\n if (EXCLUDE_PATTERNS.some(p => p.test(f.path))) return false;\n // Only analyze files with importable extensions (skip docs, config, etc.)\n const ext = path.extname(f.path).toLowerCase();\n return ANALYZABLE_EXTENSIONS.has(ext);\n });\n\n if (sourceFiles.length === 0) return [];\n\n // Prepare targets for batch search\n const targets = sourceFiles.map(source => {\n const ext = path.extname(source.path);\n const baseName = path.basename(source.path, ext);\n return { path: source.path, baseName };\n });\n\n // Run batch search\n const dependentsMap = await findDependentsBatch(targets, cwd, exec);\n\n for (const source of sourceFiles) {\n const dependents = dependentsMap.get(source.path) || [];\n\n if (dependents.length > 0) {\n // Detailed analysis for each dependent\n const impactedFilesInfo: Array<{ file: string; details: any }> = [];\n\n for (const dep of dependents) {\n // We analyze only the first few dependents deeply to avoid perf hit on massive impact\n // Or maybe we analyze all? Let's analyze all for now, assuming typical impact < 100 files.\n // If massive, we might want to limit.\n if (impactedFilesInfo.length < 20) {\n const details = await analyzeDependency(dep, source.path, cwd, readFile);\n if (details) {\n impactedFilesInfo.push({ file: dep, details });\n } else {\n impactedFilesInfo.push({ file: dep, details: { importedSymbols: [], usageContext: \"\" } });\n }\n } else {\n impactedFilesInfo.push({ file: dep, details: { importedSymbols: [], usageContext: \"\" } });\n }\n }\n\n // Determine blast radius label for more informative evidence\n const blastLabel = dependents.length > 10 ? \"High\" : dependents.length > 3 ? \"Medium\" : \"Low\";\n \n const evidence = [\n createEvidence(source.path, `${blastLabel} blast radius: ${dependents.length} file(s) depend on this module`),\n ...impactedFilesInfo.slice(0, 5).map(info => {\n // More descriptive evidence showing what symbols are imported\n const text = info.details.importedSymbols?.length > 0\n ? `Imports: ${info.details.importedSymbols.slice(0, 3).join(\", \")}${info.details.importedSymbols.length > 3 ? ` (+${info.details.importedSymbols.length - 3} more)` : \"\"}`\n : `Imports module`;\n return createEvidence(info.file, text);\n })\n ];\n\n // Collect all symbols for the finding summary\n const allSymbols = new Set<string>();\n impactedFilesInfo.forEach(i => i.details.importedSymbols?.forEach((s: string) => allSymbols.add(s)));\n\n findings.push({\n type: \"impact-analysis\",\n kind: \"impact-analysis\",\n category: \"impact\",\n confidence: \"medium\",\n evidence: evidence,\n sourceFile: source.path,\n affectedFiles: dependents,\n importedSymbols: Array.from(allSymbols),\n usageContext: impactedFilesInfo[0]?.details.usageContext, // Example context from first file\n blastRadius: dependents.length > 10 ? \"high\" : dependents.length > 3 ? \"medium\" : \"low\",\n tags: [\"impact\", \"dependency\"]\n } as ImpactAnalysisFinding);\n }\n }\n\n return findings;\n },\n };\n}\n\nexport const impactAnalyzer: Analyzer = createImpactAnalyzer();\n",
|
|
25
|
-
"/**\n * Large diff (churn) analyzer.\n */\n\nimport type {\n Analyzer,\n ChangeSet,\n Finding,\n LargeDiffFinding,\n} from \"../core/types.js\";\n\n/**\n * Analyze large diffs to detect high churn.\n */\nexport const analyzeLargeDiff: Analyzer = {\n name: \"large-diff\",\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: LargeDiffFinding[] = [];\n\n const filesChanged = changeSet.files.length;\n let linesChanged = 0;\n\n for (const diff of changeSet.diffs) {\n for (const hunk of diff.hunks) {\n linesChanged += hunk.additions.length + hunk.deletions.length;\n }\n }\n\n // Trigger if more than 30 files or 1000 lines changed\n if (filesChanged > 30 || linesChanged > 1000) {\n findings.push({\n type: \"large-diff\",\n kind: \"large-diff\",\n category: \"unknown\", // No specific category for churn/quality metrics\n confidence: \"high\",\n evidence: [],\n filesChanged,\n linesChanged,\n });\n }\n\n return findings;\n },\n};\n",
|
|
26
|
-
"/**\n * Lockfile analyzer - detects lockfile/manifest mismatches.\n */\n\nimport type {\n Analyzer,\n ChangeSet,\n Finding,\n LockfileFinding,\n} from \"../core/types.js\";\n\n/**\n * Check if a file is package.json.\n */\nfunction isPackageJson(path: string): boolean {\n return path === \"package.json\";\n}\n\n/**\n * Check if a file is a lockfile.\n */\nfunction isLockfile(path: string): boolean {\n return (\n path === \"package-lock.json\" ||\n path === \"yarn.lock\" ||\n path === \"pnpm-lock.yaml\" ||\n path === \"bun.lockb\" ||\n path === \"bun.lock\"\n );\n}\n\n/**\n * Analyze lockfile changes.\n */\nexport const analyzeLockfiles: Analyzer = {\n name: \"lockfiles\",\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: LockfileFinding[] = [];\n\n const manifestChanged = changeSet.files.some(f => isPackageJson(f.path));\n const lockfileChanged = changeSet.files.some(f => isLockfile(f.path));\n\n // Flag if lockfile changed without manifest or vice versa\n if ((manifestChanged && !lockfileChanged) || (!manifestChanged && lockfileChanged)) {\n findings.push({\n type: \"lockfile-mismatch\",\n kind: \"lockfile-mismatch\",\n category: \"dependencies\",\n confidence: \"high\",\n evidence: [],\n manifestChanged,\n lockfileChanged,\n });\n }\n\n return findings;\n },\n};\n",
|
|
27
|
-
"/**\n * Test gap analyzer - detects when prod code changes without test changes.\n */\n\nimport { createEvidence } from \"../core/evidence.js\";\nimport type {\n Analyzer,\n ChangeSet,\n Finding,\n TestGapFinding,\n} from \"../core/types.js\";\n\n/**\n * Check if a file is a test file.\n */\nfunction isTestFile(path: string): boolean {\n return (\n path.includes(\"/tests/\") ||\n path.includes(\"/__tests__/\") ||\n path.includes(\".test.\") ||\n path.includes(\".spec.\") ||\n path.startsWith(\"tests/\")\n );\n}\n\n/**\n * Check if a file is a documentation file.\n */\nfunction isDocFile(path: string): boolean {\n return path.endsWith(\".md\") || path.startsWith(\"docs/\");\n}\n\n/**\n * Check if a file is a config/meta file.\n */\nfunction isConfigFile(path: string): boolean {\n const filename = path.split(\"/\").pop() || \"\";\n return (\n // Package manager files\n filename === \"package.json\" ||\n filename === \"package-lock.json\" ||\n filename === \"yarn.lock\" ||\n filename === \"pnpm-lock.yaml\" ||\n filename === \"bun.lockb\" ||\n // Config files in root\n filename.endsWith(\".config.js\") ||\n filename.endsWith(\".config.ts\") ||\n filename.endsWith(\".config.mjs\") ||\n filename.endsWith(\".config.cjs\") ||\n // TOML configs\n filename.endsWith(\".toml\") ||\n // Dotfiles in root (but not directories like .github)\n (path.split(\"/\").length === 1 && filename.startsWith(\".\"))\n );\n}\n\n/**\n * Analyze test coverage gaps.\n */\nexport const analyzeTestGaps: Analyzer = {\n name: \"test-gaps\",\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: TestGapFinding[] = [];\n\n let prodFilesChanged = 0;\n let testFilesChanged = 0;\n const prodFiles: string[] = [];\n\n for (const file of changeSet.files) {\n // Skip docs and config\n if (isDocFile(file.path) || isConfigFile(file.path)) {\n continue;\n }\n\n if (isTestFile(file.path)) {\n testFilesChanged++;\n } else {\n prodFilesChanged++;\n prodFiles.push(file.path);\n }\n }\n\n // Flag if production code changed significantly without tests\n if (prodFilesChanged >= 3 && testFilesChanged === 0) {\n // Create evidence showing the prod files that changed without tests\n // Use first file as the \"main\" evidence with the summary, rest as supporting\n const evidence = prodFiles.slice(0, 5).map((file, index) =>\n createEvidence(\n file,\n index === 0\n ? `${prodFilesChanged} production file(s) changed with no test updates`\n : \"No corresponding test changes\"\n )\n );\n\n findings.push({\n type: \"test-gap\",\n kind: \"test-gap\",\n category: \"quality\",\n confidence: \"medium\",\n evidence,\n prodFilesChanged,\n testFilesChanged,\n });\n }\n\n return findings;\n },\n};\n",
|
|
28
|
-
"/**\n * SQL risk analyzer - detects risky SQL patterns in migrations.\n */\n\nimport type {\n Analyzer,\n ChangeSet,\n Finding,\n SQLRiskFinding,\n} from \"../core/types.js\";\nimport { createEvidence, extractRepresentativeExcerpt } from \"../core/evidence.js\";\n\n/**\n * Check if a file is a migration or SQL file.\n */\nfunction isMigrationFile(path: string): boolean {\n return (\n path.includes(\"/migrations/\") ||\n path.includes(\"/migrate/\") ||\n path.endsWith(\".sql\")\n );\n}\n\n/**\n * Analyze SQL files for risky patterns.\n */\nexport const analyzeSQLRisks: Analyzer = {\n name: \"sql-risks\",\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: SQLRiskFinding[] = [];\n\n for (const diff of changeSet.diffs) {\n if (!isMigrationFile(diff.path)) continue;\n\n for (const hunk of diff.hunks) {\n const addedLines = hunk.additions.join(\"\\n\");\n\n // Check for destructive SQL\n const destructivePatterns = /\\b(DROP\\s+TABLE|DROP\\s+COLUMN|TRUNCATE)\\b/gi;\n if (destructivePatterns.test(addedLines)) {\n const excerpt = extractRepresentativeExcerpt(hunk.additions, 200);\n findings.push({\n type: \"sql-risk\",\n kind: \"sql-risk\",\n category: \"database\",\n confidence: \"high\",\n evidence: [\n createEvidence(diff.path, excerpt, { hunk }),\n ],\n file: diff.path,\n riskType: \"destructive\",\n details: \"Contains DROP TABLE/COLUMN or TRUNCATE\",\n });\n continue; // One finding per hunk\n }\n\n // Check for risky schema changes\n const riskySchemaPatterns = /ALTER\\s+TABLE[^;]+\\b(ALTER\\s+COLUMN|TYPE)\\b/gi;\n if (riskySchemaPatterns.test(addedLines)) {\n const excerpt = extractRepresentativeExcerpt(hunk.additions, 200);\n findings.push({\n type: \"sql-risk\",\n kind: \"sql-risk\",\n category: \"database\",\n confidence: \"high\",\n evidence: [\n createEvidence(diff.path, excerpt, { hunk }),\n ],\n file: diff.path,\n riskType: \"schema_change\",\n details: \"Contains ALTER COLUMN or TYPE change\",\n });\n continue;\n }\n\n // Check for unscoped data modification\n const unscopedPatterns = /(UPDATE|DELETE)\\s+(?![^;\\n]*\\bWHERE\\b)/gi;\n if (unscopedPatterns.test(addedLines)) {\n const excerpt = extractRepresentativeExcerpt(hunk.additions, 200);\n findings.push({\n type: \"sql-risk\",\n kind: \"sql-risk\",\n category: \"database\",\n confidence: \"medium\",\n evidence: [\n createEvidence(diff.path, excerpt, { hunk }),\n ],\n file: diff.path,\n riskType: \"unscoped_modification\",\n details: \"Contains UPDATE/DELETE without WHERE clause\",\n });\n }\n }\n }\n\n return findings;\n },\n};\n",
|
|
29
|
-
"/**\n * CI workflow analyzer - detects risky CI/CD patterns.\n */\n\nimport type {\n Analyzer,\n ChangeSet,\n CIWorkflowFinding,\n Finding,\n} from \"../core/types.js\";\nimport { createEvidence, extractRepresentativeExcerpt } from \"../core/evidence.js\";\n\n/**\n * Check if a file is a CI workflow file.\n */\nfunction isCIFile(path: string): boolean {\n return (\n (path.includes(\".github/workflows/\") && (path.endsWith(\".yml\") || path.endsWith(\".yaml\"))) ||\n path === \".gitlab-ci.yml\" ||\n path === \"Jenkinsfile\" ||\n path === \"azure-pipelines.yml\"\n );\n}\n\n/**\n * Analyze CI workflows for risky patterns.\n */\nexport const analyzeCIWorkflows: Analyzer = {\n name: \"ci-workflows\",\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: CIWorkflowFinding[] = [];\n const seenFiles = new Set<string>();\n\n for (const diff of changeSet.diffs) {\n if (!isCIFile(diff.path)) continue;\n\n let hasPermissions = false;\n let hasPullRequestTarget = false;\n let hasRemoteScript = false;\n\n for (const hunk of diff.hunks) {\n const addedLines = hunk.additions.join(\"\\n\");\n\n // Check for broadened permissions (supports inline and multi-line YAML)\n const writePermissions = /permissions:[\\s\\S]{0,500}?\\b(contents|id-token|actions|packages|deployments|security-events)\\b\\s*:\\s*write/gi;\n if (!hasPermissions && writePermissions.test(addedLines)) {\n hasPermissions = true;\n const excerpt = extractRepresentativeExcerpt(hunk.additions, 200);\n findings.push({\n type: \"ci-workflow\",\n kind: \"ci-workflow\",\n category: \"ci\",\n confidence: \"high\",\n evidence: [\n createEvidence(diff.path, excerpt, { hunk }),\n ],\n file: diff.path,\n riskType: \"permissions_broadened\",\n details: \"Workflow has broadened permissions (write access)\",\n });\n }\n\n // Check for pull_request_target\n const prTargetPattern = /pull_request_target/i;\n if (!hasPullRequestTarget && prTargetPattern.test(addedLines)) {\n hasPullRequestTarget = true;\n const excerpt = extractRepresentativeExcerpt(hunk.additions, 200);\n findings.push({\n type: \"ci-workflow\",\n kind: \"ci-workflow\",\n category: \"ci\",\n confidence: \"high\",\n evidence: [\n createEvidence(diff.path, excerpt, { hunk }),\n ],\n file: diff.path,\n riskType: \"pull_request_target\",\n details: \"Workflow uses pull_request_target event (can expose secrets)\",\n });\n }\n\n // Check for remote script download\n const downloadPattern = /(curl|wget)\\s+[^\\s]+\\s*\\|\\s*(sh|bash)/gi;\n if (!hasRemoteScript && downloadPattern.test(addedLines)) {\n hasRemoteScript = true;\n const excerpt = extractRepresentativeExcerpt(hunk.additions, 200);\n findings.push({\n type: \"ci-workflow\",\n kind: \"ci-workflow\",\n category: \"ci\",\n confidence: \"high\",\n evidence: [\n createEvidence(diff.path, excerpt, { hunk }),\n ],\n file: diff.path,\n riskType: \"remote_script_download\",\n details: \"Workflow downloads and pipes to shell (supply chain risk)\",\n });\n }\n }\n\n // General pipeline change (one per file)\n if (!seenFiles.has(diff.path) && diff.hunks.length > 0) {\n seenFiles.add(diff.path);\n const excerpt = extractRepresentativeExcerpt(diff.hunks[0].additions, 150);\n findings.push({\n type: \"ci-workflow\",\n kind: \"ci-workflow\",\n category: \"ci\",\n confidence: \"medium\",\n evidence: [\n createEvidence(diff.path, excerpt),\n ],\n file: diff.path,\n riskType: \"pipeline_changed\",\n details: \"CI/CD pipeline configuration modified\",\n });\n }\n }\n\n return findings;\n },\n};\n",
|
|
30
|
-
"/**\n * Infrastructure analyzer - detects infrastructure changes.\n */\n\nimport type {\n Analyzer,\n ChangeSet,\n Finding,\n InfraChangeFinding,\n} from \"../core/types.js\";\n\n/**\n * Analyze infrastructure file changes.\n */\nexport const analyzeInfra: Analyzer = {\n name: \"infra\",\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: InfraChangeFinding[] = [];\n\n // Group files by type\n const dockerfiles: string[] = [];\n const terraformFiles: string[] = [];\n const k8sFiles: string[] = [];\n\n for (const file of changeSet.files) {\n if (file.path.toLowerCase().includes(\"dockerfile\")) {\n dockerfiles.push(file.path);\n } else if (file.path.endsWith(\".tf\") || file.path.endsWith(\".tfvars\")) {\n terraformFiles.push(file.path);\n } else if (\n file.path.includes(\"kubernetes/\") ||\n file.path.includes(\"k8s/\") ||\n (file.path.endsWith(\".yaml\") && (\n file.path.includes(\"deployment\") ||\n file.path.includes(\"service\") ||\n file.path.includes(\"ingress\")\n ))\n ) {\n k8sFiles.push(file.path);\n }\n }\n\n if (dockerfiles.length > 0) {\n findings.push({\n type: \"infra-change\",\n kind: \"infra-change\",\n category: \"infra\",\n confidence: \"high\",\n evidence: [],\n infraType: \"dockerfile\",\n files: dockerfiles,\n });\n }\n\n if (terraformFiles.length > 0) {\n findings.push({\n type: \"infra-change\",\n kind: \"infra-change\",\n category: \"infra\",\n confidence: \"high\",\n evidence: [],\n infraType: \"terraform\",\n files: terraformFiles,\n });\n }\n\n if (k8sFiles.length > 0) {\n findings.push({\n type: \"infra-change\",\n kind: \"infra-change\",\n category: \"infra\",\n confidence: \"high\",\n evidence: [],\n infraType: \"k8s\",\n files: k8sFiles,\n });\n }\n\n return findings;\n },\n};\n",
|
|
31
|
-
"/**\n * API contract analyzer - detects API contract changes.\n */\n\nimport type {\n Analyzer,\n ChangeSet,\n Finding,\n APIContractChangeFinding,\n} from \"../core/types.js\";\n\n/**\n * Check if a file is an API contract file.\n */\nfunction isAPIContractFile(path: string): boolean {\n return (\n path.includes(\"openapi\") ||\n path.includes(\"swagger\") ||\n path.endsWith(\".proto\") ||\n (path.includes(\"/api/\") && (path.endsWith(\".yaml\") || path.endsWith(\".yml\") || path.endsWith(\".json\")))\n );\n}\n\n/**\n * Analyze API contract changes.\n */\nexport const analyzeAPIContracts: Analyzer = {\n name: \"api-contracts\",\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: APIContractChangeFinding[] = [];\n\n const contractFiles = changeSet.files\n .filter(f => isAPIContractFile(f.path))\n .map(f => f.path);\n\n if (contractFiles.length > 0) {\n findings.push({\n type: \"api-contract-change\",\n kind: \"api-contract-change\",\n category: \"api\",\n confidence: \"high\",\n evidence: [],\n files: contractFiles,\n });\n }\n\n return findings;\n },\n};\n",
|
|
32
|
-
"/**\n * Stencil analyzer - detects changes in StencilJS components.\n * Uses AST parsing to extract component metadata, props, events, methods, and slots.\n */\n\nimport { parse } from \"@babel/parser\";\nimport traverse from \"@babel/traverse\";\nimport * as t from \"@babel/types\";\nimport type {\n Analyzer,\n ChangeSet,\n Finding,\n StencilComponentChangeFinding,\n StencilPropChangeFinding,\n StencilEventChangeFinding,\n StencilMethodChangeFinding,\n StencilSlotChangeFinding,\n} from \"../core/types.js\";\nimport { createEvidence } from \"../core/evidence.js\";\nimport { batchGetFileContent as defaultBatchGetFileContent } from \"../git/batch.js\";\n\n// Allow injection for testing\nexport const dependencies = {\n batchGetFileContent: defaultBatchGetFileContent,\n};\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface StencilProp {\n name: string;\n typeText?: string;\n attribute?: string;\n reflect?: boolean;\n mutable?: boolean;\n line: number;\n}\n\ninterface StencilEvent {\n name: string; // Public event name (from option or member name)\n memberName: string;\n bubbles?: boolean;\n composed?: boolean;\n cancelable?: boolean;\n line: number;\n}\n\ninterface StencilMethod {\n name: string;\n signature?: string;\n line: number;\n}\n\ninterface StencilComponent {\n tag: string;\n shadow: boolean;\n file: string;\n line: number;\n props: Map<string, StencilProp>;\n events: Map<string, StencilEvent>;\n methods: Map<string, StencilMethod>;\n slots: Set<string>; // Only names for simple diffing\n}\n\n// ============================================================================\n// Extraction Logic\n// ============================================================================\n\nfunction isCandidateFile(path: string): boolean {\n return path.endsWith(\".tsx\") || path.endsWith(\".ts\");\n}\n\n/**\n * Format slot evidence string based on slot name type.\n */\nfunction formatSlotEvidence(slotName: string): string {\n if (slotName === \"default\") {\n return \"<slot />\";\n } else if (slotName === \"boolean\") {\n return \"<slot name />\";\n } else if (slotName === \"dynamic\") {\n return \"<slot name={...} />\";\n } else {\n return `<slot name=\"${slotName}\" />`;\n }\n}\n\n/**\n * Extract Stencil component information from file content.\n */\nexport function extractStencilComponents(\n content: string,\n filePath: string\n): StencilComponent[] {\n const components: StencilComponent[] = [];\n\n try {\n const ast = parse(content, {\n sourceType: \"module\",\n plugins: [\"typescript\", \"jsx\", \"decorators-legacy\"],\n });\n\n traverse(ast, {\n ClassDeclaration(path) {\n // Check for @Component decorator\n const decorators = path.node.decorators || [];\n const componentDecorator = decorators.find(\n (d) =>\n t.isCallExpression(d.expression) &&\n t.isIdentifier(d.expression.callee) &&\n d.expression.callee.name === \"Component\"\n );\n\n if (!componentDecorator) return;\n\n // Extract component metadata\n let tag = \"\";\n let shadow = false; // Default to false if not specified (though Stencil often recommends true)\n\n // Use default line 1 if loc is missing (rare)\n const componentLine = path.node.loc?.start.line ?? 1;\n\n if (t.isCallExpression(componentDecorator.expression)) {\n const arg = componentDecorator.expression.arguments[0];\n if (t.isObjectExpression(arg)) {\n for (const prop of arg.properties) {\n if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {\n if (prop.key.name === \"tag\") {\n if (t.isStringLiteral(prop.value)) {\n tag = prop.value.value;\n }\n } else if (prop.key.name === \"shadow\") {\n if (t.isBooleanLiteral(prop.value)) {\n shadow = prop.value.value;\n }\n }\n }\n }\n }\n }\n\n if (!tag) return; // Tag is required\n\n const props = new Map<string, StencilProp>();\n const events = new Map<string, StencilEvent>();\n const methods = new Map<string, StencilMethod>();\n const slots = new Set<string>();\n\n // Traverse class body for members\n for (const bodyNode of path.node.body.body) {\n // Props\n if (t.isClassProperty(bodyNode) || t.isClassMethod(bodyNode)) {\n const memberDecorators = bodyNode.decorators || [];\n\n // @Prop\n const propDec = memberDecorators.find(\n (d) =>\n (t.isCallExpression(d.expression) &&\n t.isIdentifier(d.expression.callee) &&\n d.expression.callee.name === \"Prop\") ||\n (t.isIdentifier(d.expression) && d.expression.name === \"Prop\")\n );\n\n if (propDec && t.isIdentifier(bodyNode.key)) {\n const name = bodyNode.key.name;\n const line = bodyNode.loc?.start.line ?? 1;\n\n let attribute: string | undefined;\n let reflect = false;\n let mutable = false;\n let typeText: string | undefined; // We can't easily get full type text from AST without printing, so skipping for now or simple extraction\n\n if (t.isClassProperty(bodyNode) && bodyNode.typeAnnotation && t.isTSTypeAnnotation(bodyNode.typeAnnotation)) {\n // Best effort type extraction - skipping complex types for now\n // In a real implementation we might print the type node\n }\n\n if (t.isCallExpression(propDec.expression)) {\n const arg = propDec.expression.arguments[0];\n if (t.isObjectExpression(arg)) {\n for (const p of arg.properties) {\n if (t.isObjectProperty(p) && t.isIdentifier(p.key)) {\n if (p.key.name === \"attribute\" && t.isStringLiteral(p.value)) attribute = p.value.value;\n if (p.key.name === \"reflect\" && t.isBooleanLiteral(p.value)) reflect = p.value.value;\n if (p.key.name === \"mutable\" && t.isBooleanLiteral(p.value)) mutable = p.value.value;\n }\n }\n }\n }\n\n props.set(name, { name, attribute, reflect, mutable, typeText, line });\n }\n\n // @Event\n const eventDec = memberDecorators.find(\n (d) =>\n (t.isCallExpression(d.expression) &&\n t.isIdentifier(d.expression.callee) &&\n d.expression.callee.name === \"Event\") ||\n (t.isIdentifier(d.expression) && d.expression.name === \"Event\")\n );\n\n if (eventDec && t.isIdentifier(bodyNode.key)) {\n const memberName = bodyNode.key.name;\n let eventName = memberName;\n const line = bodyNode.loc?.start.line ?? 1;\n\n let bubbles = true; // Default true\n let composed = true; // Default true\n let cancelable = true; // Default true\n\n if (t.isCallExpression(eventDec.expression)) {\n const arg = eventDec.expression.arguments[0];\n if (t.isObjectExpression(arg)) {\n for (const p of arg.properties) {\n if (t.isObjectProperty(p) && t.isIdentifier(p.key)) {\n if (p.key.name === \"eventName\" && t.isStringLiteral(p.value)) eventName = p.value.value;\n if (p.key.name === \"bubbles\" && t.isBooleanLiteral(p.value)) bubbles = p.value.value;\n if (p.key.name === \"composed\" && t.isBooleanLiteral(p.value)) composed = p.value.value;\n if (p.key.name === \"cancelable\" && t.isBooleanLiteral(p.value)) cancelable = p.value.value;\n }\n }\n }\n }\n\n events.set(eventName, { name: eventName, memberName, bubbles, composed, cancelable, line });\n }\n\n // @Method\n const methodDec = memberDecorators.find(\n (d) =>\n (t.isCallExpression(d.expression) &&\n t.isIdentifier(d.expression.callee) &&\n d.expression.callee.name === \"Method\") ||\n (t.isIdentifier(d.expression) && d.expression.name === \"Method\")\n );\n\n if (methodDec && t.isIdentifier(bodyNode.key)) {\n const name = bodyNode.key.name;\n const line = bodyNode.loc?.start.line ?? 1;\n // Extract signature if needed, for now just name\n methods.set(name, { name, line });\n }\n }\n\n // render() for slots\n if (t.isClassMethod(bodyNode) && t.isIdentifier(bodyNode.key) && bodyNode.key.name === \"render\") {\n // Traverse render method body for JSX slots\n traverse(bodyNode, {\n JSXElement(innerPath) {\n const opening = innerPath.node.openingElement;\n if (t.isJSXIdentifier(opening.name) && opening.name.name === \"slot\") {\n let slotName = \"default\";\n for (const attr of opening.attributes) {\n if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name) && attr.name.name === \"name\") {\n if (t.isStringLiteral(attr.value)) {\n slotName = attr.value.value;\n } else if (attr.value === null) {\n // Boolean \"name\" attribute: <slot name />\n slotName = \"boolean\";\n } else {\n // Dynamic or non-literal slot name, e.g. <slot name={expr} />\n slotName = \"dynamic\";\n }\n }\n }\n slots.add(slotName);\n }\n },\n // Also handle self-closing <slot /> (JSXElement handles both usually if parsed correctly, but just in case)\n }, path.scope, path);\n }\n }\n\n components.push({\n tag,\n shadow,\n file: filePath,\n line: componentLine,\n props,\n events,\n methods,\n slots,\n });\n },\n });\n } catch (error) {\n // Parsing error, skip\n }\n\n return components;\n}\n\n// ============================================================================\n// Analyzer\n// ============================================================================\n\nexport const stencilAnalyzer: Analyzer = {\n name: \"stencil\",\n\n async analyze(changeSet: ChangeSet): Promise<Finding[]> {\n const findings: Finding[] = [];\n\n // Select candidate files\n const candidateFiles = changeSet.files.filter((file) =>\n isCandidateFile(file.path)\n );\n\n if (candidateFiles.length === 0) return [];\n\n // Batch fetch content\n const batchRequest: Array<{ ref: string; path: string }> = [];\n for (const file of candidateFiles) {\n batchRequest.push({ ref: changeSet.base, path: file.path });\n batchRequest.push({ ref: changeSet.head, path: file.path });\n }\n\n const contentMap = await dependencies.batchGetFileContent(batchRequest);\n\n for (const file of candidateFiles) {\n const baseKey = `${changeSet.base}:${file.path}`;\n const headKey = `${changeSet.head}:${file.path}`;\n\n const baseContent = contentMap.get(baseKey);\n const headContent = contentMap.get(headKey);\n\n // Skip if neither has content (shouldn't happen for candidate files)\n if (!baseContent && !headContent) continue;\n\n const baseComponents = baseContent\n ? extractStencilComponents(baseContent, file.path)\n : [];\n const headComponents = headContent\n ? extractStencilComponents(headContent, file.path)\n : [];\n\n // Map by tag\n const baseMap = new Map(baseComponents.map((c) => [c.tag, c]));\n const headMap = new Map(headComponents.map((c) => [c.tag, c]));\n\n const allTags = new Set([...baseMap.keys(), ...headMap.keys()]);\n\n for (const tag of allTags) {\n const baseComp = baseMap.get(tag);\n const headComp = headMap.get(tag);\n\n if (baseComp && !headComp) {\n // Component removed\n findings.push({\n type: \"stencil-component-change\",\n kind: \"stencil-component-change\",\n category: \"api\",\n confidence: \"high\",\n evidence: [createEvidence(file.path, `@Component({ tag: \"${tag}\" })`, { line: baseComp.line })],\n tag,\n change: \"removed\",\n file: file.path,\n } as StencilComponentChangeFinding);\n } else if (!baseComp && headComp) {\n // Component added\n findings.push({\n type: \"stencil-component-change\",\n kind: \"stencil-component-change\",\n category: \"api\",\n confidence: \"high\",\n evidence: [createEvidence(file.path, `@Component({ tag: \"${tag}\" })`, { line: headComp.line })],\n tag,\n change: \"added\",\n file: file.path,\n } as StencilComponentChangeFinding);\n } else if (baseComp && headComp) {\n // Component modified - check details\n\n // Shadow DOM changed\n if (baseComp.shadow !== headComp.shadow) {\n findings.push({\n type: \"stencil-component-change\",\n kind: \"stencil-component-change\",\n category: \"api\",\n confidence: \"high\",\n evidence: [createEvidence(file.path, `@Component({ tag: \"${tag}\", shadow: ${headComp.shadow} })`, { line: headComp.line })],\n tag,\n change: \"shadow-changed\",\n file: file.path,\n fromShadow: baseComp.shadow,\n toShadow: headComp.shadow,\n } as StencilComponentChangeFinding);\n }\n\n // Props\n const allProps = new Set([...baseComp.props.keys(), ...headComp.props.keys()]);\n for (const propName of allProps) {\n const baseProp = baseComp.props.get(propName);\n const headProp = headComp.props.get(propName);\n\n if (baseProp && !headProp) {\n findings.push({\n type: \"stencil-prop-change\",\n kind: \"stencil-prop-change\",\n category: \"api\",\n confidence: \"high\",\n evidence: [createEvidence(file.path, `@Prop() ${propName}`, { line: baseProp.line })],\n tag,\n propName,\n change: \"removed\",\n file: file.path,\n } as StencilPropChangeFinding);\n } else if (!baseProp && headProp) {\n findings.push({\n type: \"stencil-prop-change\",\n kind: \"stencil-prop-change\",\n category: \"api\",\n confidence: \"high\",\n evidence: [createEvidence(file.path, `@Prop() ${propName}`, { line: headProp.line })],\n tag,\n propName,\n change: \"added\",\n file: file.path,\n details: {\n attribute: headProp.attribute,\n reflect: headProp.reflect,\n mutable: headProp.mutable,\n }\n } as StencilPropChangeFinding);\n } else if (baseProp && headProp) {\n // Check for changes\n if (\n baseProp.attribute !== headProp.attribute ||\n baseProp.reflect !== headProp.reflect ||\n baseProp.mutable !== headProp.mutable\n ) {\n findings.push({\n type: \"stencil-prop-change\",\n kind: \"stencil-prop-change\",\n category: \"api\",\n confidence: \"high\",\n evidence: [createEvidence(file.path, `@Prop() ${propName}`, { line: headProp.line })],\n tag,\n propName,\n change: \"changed\",\n file: file.path,\n details: {\n attribute: headProp.attribute,\n reflect: headProp.reflect,\n mutable: headProp.mutable,\n }\n } as StencilPropChangeFinding);\n }\n }\n }\n\n // Events\n const allEvents = new Set([...baseComp.events.keys(), ...headComp.events.keys()]);\n for (const eventName of allEvents) {\n const baseEvent = baseComp.events.get(eventName);\n const headEvent = headComp.events.get(eventName);\n\n if (baseEvent && !headEvent) {\n findings.push({\n type: \"stencil-event-change\",\n kind: \"stencil-event-change\",\n category: \"api\",\n confidence: \"high\",\n evidence: [createEvidence(file.path, `@Event() ${baseEvent.memberName}`, { line: baseEvent.line })],\n tag,\n eventName,\n change: \"removed\",\n file: file.path,\n } as StencilEventChangeFinding);\n } else if (!baseEvent && headEvent) {\n findings.push({\n type: \"stencil-event-change\",\n kind: \"stencil-event-change\",\n category: \"api\",\n confidence: \"high\",\n evidence: [createEvidence(file.path, `@Event() ${headEvent.memberName}`, { line: headEvent.line })],\n tag,\n eventName,\n change: \"added\",\n file: file.path,\n details: {\n bubbles: headEvent.bubbles,\n composed: headEvent.composed,\n cancelable: headEvent.cancelable\n }\n } as StencilEventChangeFinding);\n } else if (baseEvent && headEvent) {\n // Check for option changes\n if (\n baseEvent.bubbles !== headEvent.bubbles ||\n baseEvent.composed !== headEvent.composed ||\n baseEvent.cancelable !== headEvent.cancelable\n ) {\n findings.push({\n type: \"stencil-event-change\",\n kind: \"stencil-event-change\",\n category: \"api\",\n confidence: \"high\",\n evidence: [createEvidence(file.path, `@Event() ${headEvent.memberName}`, { line: headEvent.line })],\n tag,\n eventName,\n change: \"changed\",\n file: file.path,\n details: {\n bubbles: headEvent.bubbles,\n composed: headEvent.composed,\n cancelable: headEvent.cancelable\n }\n } as StencilEventChangeFinding);\n }\n }\n }\n\n // Methods\n const allMethods = new Set([...baseComp.methods.keys(), ...headComp.methods.keys()]);\n for (const methodName of allMethods) {\n const baseMethod = baseComp.methods.get(methodName);\n const headMethod = headComp.methods.get(methodName);\n\n if (baseMethod && !headMethod) {\n findings.push({\n type: \"stencil-method-change\",\n kind: \"stencil-method-change\",\n category: \"api\",\n confidence: \"high\",\n evidence: [createEvidence(file.path, `@Method() ${methodName}`, { line: baseMethod.line })],\n tag,\n methodName,\n change: \"removed\",\n file: file.path,\n } as StencilMethodChangeFinding);\n } else if (!baseMethod && headMethod) {\n findings.push({\n type: \"stencil-method-change\",\n kind: \"stencil-method-change\",\n category: \"api\",\n confidence: \"high\",\n evidence: [createEvidence(file.path, `@Method() ${methodName}`, { line: headMethod.line })],\n tag,\n methodName,\n change: \"added\",\n file: file.path,\n } as StencilMethodChangeFinding);\n }\n // Signature change check omitted for now (needs more complex AST analysis)\n }\n\n // Slots\n const allSlots = new Set([...baseComp.slots, ...headComp.slots]);\n for (const slotName of allSlots) {\n const baseHas = baseComp.slots.has(slotName);\n const headHas = headComp.slots.has(slotName);\n\n if (baseHas && !headHas) {\n findings.push({\n type: \"stencil-slot-change\",\n kind: \"stencil-slot-change\",\n category: \"api\",\n confidence: \"high\",\n evidence: [createEvidence(file.path, formatSlotEvidence(slotName), { line: baseComp.line })], // Approximate line\n tag,\n slotName,\n change: \"removed\",\n file: file.path,\n } as StencilSlotChangeFinding);\n } else if (!baseHas && headHas) {\n findings.push({\n type: \"stencil-slot-change\",\n kind: \"stencil-slot-change\",\n category: \"api\",\n confidence: \"high\",\n evidence: [createEvidence(file.path, formatSlotEvidence(slotName), { line: headComp.line })],\n tag,\n slotName,\n change: \"added\",\n file: file.path,\n } as StencilSlotChangeFinding);\n }\n }\n }\n }\n }\n\n return findings;\n },\n};\n",
|
|
33
|
-
"/**\n * Next.js App Router route detector - detects changes under app/ directory.\n *\n * Supports Next.js 13+ App Router conventions:\n * - page.tsx/ts/jsx/js - Page components\n * - layout.tsx/ts - Layout components\n * - loading.tsx/ts - Loading UI\n * - error.tsx/ts - Error boundaries\n * - not-found.tsx/ts - 404 pages\n * - route.ts/tsx - API route handlers\n */\n\nimport { getAdditions } from \"../git/parser.js\";\nimport { createEvidence, extractRepresentativeExcerpt } from \"../core/evidence.js\";\nimport type {\n Analyzer,\n ChangeSet,\n FileDiff,\n FileStatus,\n Finding,\n RouteChangeFinding,\n RouteType,\n SecurityFileFinding,\n} from \"../core/types.js\";\n\n// Route file patterns (App Router)\nconst ROUTE_FILE_PATTERNS: Record<string, RouteType> = {\n \"page.tsx\": \"page\",\n \"page.ts\": \"page\",\n \"page.jsx\": \"page\",\n \"page.js\": \"page\",\n \"layout.tsx\": \"layout\",\n \"layout.ts\": \"layout\",\n \"layout.jsx\": \"layout\",\n \"layout.js\": \"layout\",\n \"loading.tsx\": \"page\",\n \"loading.ts\": \"page\",\n \"loading.jsx\": \"page\",\n \"loading.js\": \"page\",\n \"error.tsx\": \"error\",\n \"error.ts\": \"error\",\n \"error.jsx\": \"error\",\n \"error.js\": \"error\",\n \"not-found.tsx\": \"error\",\n \"not-found.ts\": \"error\",\n \"not-found.jsx\": \"error\",\n \"not-found.js\": \"error\",\n \"route.ts\": \"endpoint\",\n \"route.tsx\": \"endpoint\",\n \"route.js\": \"endpoint\",\n \"route.jsx\": \"endpoint\",\n};\n\n// Middleware file patterns\nconst MIDDLEWARE_FILES = [\n \"middleware.ts\",\n \"middleware.js\",\n \"middleware.tsx\",\n \"middleware.jsx\",\n \"src/middleware.ts\",\n \"src/middleware.js\",\n \"src/middleware.tsx\",\n \"src/middleware.jsx\",\n];\n\n// Next.js config file patterns\nconst CONFIG_FILES = [\n \"next.config.js\",\n \"next.config.mjs\",\n \"next.config.ts\",\n];\n\n// HTTP method detection pattern for route handlers\nconst METHOD_PATTERN = /export\\s+(?:async\\s+)?function\\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\s*\\(/g;\n\n/**\n * Check if a path is a Next.js App Router route file.\n */\nexport function isNextRouteFile(path: string): boolean {\n // Must be under app/ directory (or src/app/)\n if (!path.startsWith(\"app/\") && !path.startsWith(\"src/app/\")) {\n return false;\n }\n return hasRouteFilePattern(path);\n}\n\n/**\n * Check if path ends with a route file pattern.\n */\nfunction hasRouteFilePattern(path: string): boolean {\n const fileName = path.split(\"/\").pop() ?? \"\";\n return Object.keys(ROUTE_FILE_PATTERNS).includes(fileName);\n}\n\n/**\n * Get the route type from a file path.\n */\nexport function getRouteType(path: string): RouteType {\n const fileName = path.split(\"/\").pop() ?? \"\";\n return ROUTE_FILE_PATTERNS[fileName] ?? \"unknown\";\n}\n\n/**\n * Convert a file path to a Next.js route ID.\n *\n * Rules:\n * - Strip `app/` or `src/app/` prefix\n * - Remove route groups `(name)` from URL\n * - Keep param notation: [slug], [[...catchAll]]\n * - Remove file name (the route is the directory)\n */\nexport function pathToRouteId(path: string): string {\n // Remove app/ or src/app/ prefix\n let routeId = path\n .replace(/^src\\/app/, \"\")\n .replace(/^app/, \"\");\n\n // Remove the file name\n const parts = routeId.split(\"/\");\n parts.pop(); // Remove file name\n\n routeId = parts.join(\"/\");\n\n // Remove route groups: (name)\n routeId = routeId.replace(/\\/\\([^)]+\\)/g, \"\");\n\n // If empty, it's the root route\n if (routeId === \"\" || routeId === \"/\") {\n return \"/\";\n }\n\n // Ensure leading slash\n if (!routeId.startsWith(\"/\")) {\n routeId = \"/\" + routeId;\n }\n\n // Remove trailing slash (except for root)\n if (routeId.length > 1 && routeId.endsWith(\"/\")) {\n routeId = routeId.slice(0, -1);\n }\n\n return routeId;\n}\n\n/**\n * Detect HTTP methods from route handler file content.\n */\nexport function detectMethods(diff: FileDiff): string[] {\n const methods = new Set<string>();\n const content = getAdditions(diff).join(\"\\n\");\n\n let match;\n const pattern = new RegExp(METHOD_PATTERN.source, \"g\");\n while ((match = pattern.exec(content)) !== null) {\n methods.add(match[1]);\n }\n\n return Array.from(methods).sort();\n}\n\n/**\n * Check if a path is a Next.js middleware file.\n */\nexport function isMiddlewareFile(path: string): boolean {\n return MIDDLEWARE_FILES.includes(path);\n}\n\n/**\n * Check if a path is a Next.js config file.\n */\nexport function isNextConfigFile(path: string): boolean {\n return CONFIG_FILES.includes(path);\n}\n\nexport const nextRoutesAnalyzer: Analyzer = {\n name: \"next-routes\",\n\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: Finding[] = [];\n const routeFiles = new Map<string, { diff?: FileDiff; status: FileStatus }>();\n\n // Collect route files from file changes\n for (const file of changeSet.files) {\n if (isNextRouteFile(file.path)) {\n routeFiles.set(file.path, { status: file.status });\n }\n\n // Check for middleware changes\n if (isMiddlewareFile(file.path)) {\n const diff = changeSet.diffs.find(d => d.path === file.path);\n const evidence = [];\n if (diff && diff.hunks.length > 0) {\n const additions = getAdditions(diff);\n if (additions.length > 0) {\n const excerpt = extractRepresentativeExcerpt(additions);\n if (excerpt) {\n evidence.push(createEvidence(file.path, excerpt));\n }\n }\n }\n\n const middlewareFinding: SecurityFileFinding = {\n type: \"security-file\",\n kind: \"security-file\",\n category: \"routes\",\n confidence: \"high\",\n evidence,\n files: [file.path],\n reasons: [\"middleware\"],\n };\n findings.push(middlewareFinding);\n }\n }\n\n // Add diff data for route files\n for (const diff of changeSet.diffs) {\n if (isNextRouteFile(diff.path)) {\n const existing = routeFiles.get(diff.path);\n if (existing) {\n existing.diff = diff;\n } else {\n routeFiles.set(diff.path, { diff, status: diff.status });\n }\n }\n }\n\n // Generate route findings\n for (const [path, { diff, status }] of routeFiles) {\n const routeId = pathToRouteId(path);\n const routeType = getRouteType(path);\n\n // Extract evidence\n const evidence = [];\n if (diff && diff.hunks.length > 0) {\n const additions = getAdditions(diff);\n if (additions.length > 0) {\n const excerpt = extractRepresentativeExcerpt(additions);\n if (excerpt) {\n evidence.push(createEvidence(path, excerpt));\n }\n }\n }\n\n const finding: RouteChangeFinding = {\n type: \"route-change\",\n kind: \"route-change\",\n category: \"routes\",\n confidence: \"high\",\n evidence,\n routeId,\n file: path,\n change: status,\n routeType,\n };\n\n // Detect methods for API route handlers\n if (routeType === \"endpoint\" && diff) {\n const methods = detectMethods(diff);\n if (methods.length > 0) {\n finding.methods = methods;\n // Add method export as evidence if available\n const methodsExcerpt = methods.map(m => `export function ${m}`).join(\", \");\n if (!evidence.length) {\n evidence.push(createEvidence(path, methodsExcerpt));\n }\n }\n }\n\n findings.push(finding);\n }\n\n return findings;\n },\n};\n",
|
|
34
|
-
"/**\n * GraphQL schema change detector.\n *\n * Detects changes to GraphQL schema files (.graphql, .gql) and identifies\n * potentially breaking changes such as removed types, fields, or arguments.\n */\n\nimport { getAdditions, getDeletions } from \"../git/parser.js\";\nimport { createEvidence, extractRepresentativeExcerpt } from \"../core/evidence.js\";\nimport type {\n Analyzer,\n ChangeSet,\n Finding,\n GraphQLChangeFinding,\n Confidence,\n} from \"../core/types.js\";\n\n// GraphQL schema file patterns\nconst GRAPHQL_PATTERNS = [\n /\\.graphql$/,\n /\\.gql$/,\n /schema\\.graphqls$/,\n /schema\\.sdl$/,\n];\n\n/**\n * Check if a file is a GraphQL schema file.\n */\nexport function isGraphQLSchema(path: string): boolean {\n return GRAPHQL_PATTERNS.some((pattern) => pattern.test(path));\n}\n\n/**\n * Analyze deletions for breaking changes.\n */\nfunction analyzeBreakingChanges(deletions: string[]): string[] {\n const breakingChanges: string[] = [];\n const deletedContent = deletions.join(\"\\n\");\n\n // Check for removed types\n const typeMatches = deletedContent.match(/type\\s+(\\w+)\\s*[{@]/g);\n if (typeMatches) {\n for (const match of typeMatches) {\n const typeName = match.match(/type\\s+(\\w+)/)?.[1];\n if (typeName) {\n breakingChanges.push(`Removed type: ${typeName}`);\n }\n }\n }\n\n // Check for removed enums\n const enumMatches = deletedContent.match(/enum\\s+(\\w+)\\s*{/g);\n if (enumMatches) {\n for (const match of enumMatches) {\n const enumName = match.match(/enum\\s+(\\w+)/)?.[1];\n if (enumName) {\n breakingChanges.push(`Removed enum: ${enumName}`);\n }\n }\n }\n\n // Check for removed interfaces\n const interfaceMatches = deletedContent.match(/interface\\s+(\\w+)\\s*[{@]/g);\n if (interfaceMatches) {\n for (const match of interfaceMatches) {\n const interfaceName = match.match(/interface\\s+(\\w+)/)?.[1];\n if (interfaceName) {\n breakingChanges.push(`Removed interface: ${interfaceName}`);\n }\n }\n }\n\n // Check for removed input types\n const inputMatches = deletedContent.match(/input\\s+(\\w+)\\s*{/g);\n if (inputMatches) {\n for (const match of inputMatches) {\n const inputName = match.match(/input\\s+(\\w+)/)?.[1];\n if (inputName) {\n breakingChanges.push(`Removed input type: ${inputName}`);\n }\n }\n }\n\n return breakingChanges;\n}\n\n/**\n * Analyze additions for new schema elements.\n */\nfunction analyzeAdditions(additions: string[]): string[] {\n const addedElements: string[] = [];\n const addedContent = additions.join(\"\\n\");\n\n // Check for added types\n const typeMatches = addedContent.match(/type\\s+(\\w+)\\s*[{@]/g);\n if (typeMatches) {\n for (const match of typeMatches) {\n const typeName = match.match(/type\\s+(\\w+)/)?.[1];\n if (typeName && ![\"Query\", \"Mutation\", \"Subscription\"].includes(typeName)) {\n addedElements.push(`Added type: ${typeName}`);\n }\n }\n }\n\n // Check for added enums\n const enumMatches = addedContent.match(/enum\\s+(\\w+)\\s*{/g);\n if (enumMatches) {\n for (const match of enumMatches) {\n const enumName = match.match(/enum\\s+(\\w+)/)?.[1];\n if (enumName) {\n addedElements.push(`Added enum: ${enumName}`);\n }\n }\n }\n\n return addedElements;\n}\n\nexport const graphqlAnalyzer: Analyzer = {\n name: \"graphql\",\n\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: Finding[] = [];\n\n for (const diff of changeSet.diffs) {\n if (!isGraphQLSchema(diff.path)) {\n continue;\n }\n\n const additions = getAdditions(diff);\n const deletions = getDeletions(diff);\n\n const breakingChanges = analyzeBreakingChanges(deletions);\n const addedElements = analyzeAdditions(additions);\n\n // Determine if this is a breaking change\n const isBreaking = breakingChanges.length > 0;\n const hasAdditions = addedElements.length > 0;\n const hasDeletions = deletions.length > 0;\n\n // Create evidence\n const excerpt = isBreaking\n ? extractRepresentativeExcerpt(deletions)\n : extractRepresentativeExcerpt(additions);\n\n let confidence: Confidence = \"medium\";\n if (isBreaking) {\n confidence = \"high\";\n } else if (hasAdditions && !hasDeletions) {\n confidence = \"low\";\n }\n\n const finding: GraphQLChangeFinding = {\n type: \"graphql-change\",\n kind: \"graphql-change\",\n category: \"api\",\n confidence,\n evidence: [createEvidence(diff.path, excerpt)],\n file: diff.path,\n status: diff.status,\n isBreaking,\n breakingChanges: breakingChanges.slice(0, 5),\n addedElements: addedElements.slice(0, 5),\n };\n\n findings.push(finding);\n }\n\n return findings;\n },\n};\n",
|
|
35
|
-
"/**\n * TypeScript configuration change detector.\n *\n * Detects changes to tsconfig.json files and identifies potentially\n * build-breaking or behavior-changing modifications.\n */\n\nimport { getAdditions, getDeletions } from \"../git/parser.js\";\nimport { createEvidence, extractRepresentativeExcerpt } from \"../core/evidence.js\";\nimport type {\n Analyzer,\n ChangeSet,\n Finding,\n TypeScriptConfigFinding,\n Confidence,\n} from \"../core/types.js\";\n\n// TypeScript config file patterns\nconst TSCONFIG_PATTERNS = [\n /^tsconfig\\.json$/,\n /^tsconfig\\.\\w+\\.json$/,\n /\\/tsconfig\\.json$/,\n /\\/tsconfig\\.\\w+\\.json$/,\n];\n\n// Critical compiler options that can break builds or change behavior\nconst CRITICAL_OPTIONS = new Set([\n \"strict\",\n \"strictNullChecks\",\n \"strictFunctionTypes\",\n \"strictBindCallApply\",\n \"strictPropertyInitialization\",\n \"noImplicitAny\",\n \"noImplicitThis\",\n \"noImplicitReturns\",\n \"noUncheckedIndexedAccess\",\n \"target\",\n \"module\",\n \"moduleResolution\",\n \"lib\",\n \"jsx\",\n \"esModuleInterop\",\n \"allowSyntheticDefaultImports\",\n \"skipLibCheck\",\n \"isolatedModules\",\n \"verbatimModuleSyntax\",\n \"baseUrl\",\n \"paths\",\n \"outDir\",\n \"rootDir\",\n \"declaration\",\n \"declarationMap\",\n \"sourceMap\",\n \"composite\",\n \"incremental\",\n \"emitDecoratorMetadata\",\n \"experimentalDecorators\",\n]);\n\n// Options that affect type checking strictness\nconst STRICTNESS_OPTIONS = new Set([\n \"strict\",\n \"strictNullChecks\",\n \"strictFunctionTypes\",\n \"strictBindCallApply\",\n \"strictPropertyInitialization\",\n \"noImplicitAny\",\n \"noImplicitThis\",\n \"noImplicitReturns\",\n \"noUncheckedIndexedAccess\",\n \"noUnusedLocals\",\n \"noUnusedParameters\",\n \"exactOptionalPropertyTypes\",\n]);\n\n/**\n * Check if a file is a TypeScript config file.\n */\nexport function isTsConfig(path: string): boolean {\n return TSCONFIG_PATTERNS.some((pattern) => pattern.test(path));\n}\n\n/**\n * Extract changed options from diff content.\n */\nfunction extractChangedOptions(\n additions: string[],\n deletions: string[]\n): { added: string[]; removed: string[]; modified: string[] } {\n const added: string[] = [];\n const removed: string[] = [];\n const modified: string[] = [];\n\n // Regex to match JSON property assignments\n const optionPattern = /\"(\\w+)\":\\s*/;\n\n const addedOptions = new Set<string>();\n const removedOptions = new Set<string>();\n\n for (const line of additions) {\n const match = line.match(optionPattern);\n if (match) {\n addedOptions.add(match[1]);\n }\n }\n\n for (const line of deletions) {\n const match = line.match(optionPattern);\n if (match) {\n removedOptions.add(match[1]);\n }\n }\n\n // Categorize: added, removed, or modified\n for (const opt of addedOptions) {\n if (removedOptions.has(opt)) {\n modified.push(opt);\n } else {\n added.push(opt);\n }\n }\n\n for (const opt of removedOptions) {\n if (!addedOptions.has(opt)) {\n removed.push(opt);\n }\n }\n\n return { added, removed, modified };\n}\n\n/**\n * Determine if changes are breaking.\n */\nfunction isBreakingChange(\n added: string[],\n removed: string[],\n modified: string[]\n): boolean {\n // Removing strictness options can silently break type safety\n // Adding strictness options can cause build failures\n for (const opt of [...added, ...removed, ...modified]) {\n if (CRITICAL_OPTIONS.has(opt)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Identify strictness-related changes.\n */\nfunction getStrictnessChanges(\n added: string[],\n removed: string[],\n modified: string[]\n): string[] {\n const changes: string[] = [];\n const allChanges = [...added, ...removed, ...modified];\n\n for (const opt of allChanges) {\n if (STRICTNESS_OPTIONS.has(opt)) {\n if (added.includes(opt)) {\n changes.push(`Added ${opt}`);\n } else if (removed.includes(opt)) {\n changes.push(`Removed ${opt}`);\n } else {\n changes.push(`Modified ${opt}`);\n }\n }\n }\n\n return changes;\n}\n\nexport const typescriptConfigAnalyzer: Analyzer = {\n name: \"typescript-config\",\n\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: Finding[] = [];\n\n for (const diff of changeSet.diffs) {\n if (!isTsConfig(diff.path)) {\n continue;\n }\n\n const additions = getAdditions(diff);\n const deletions = getDeletions(diff);\n\n const { added, removed, modified } = extractChangedOptions(\n additions,\n deletions\n );\n\n // Skip if no meaningful changes detected\n if (added.length === 0 && removed.length === 0 && modified.length === 0) {\n // Still report the file changed if there were additions/deletions\n if (additions.length > 0 || deletions.length > 0) {\n const finding: TypeScriptConfigFinding = {\n type: \"typescript-config\",\n kind: \"typescript-config\",\n category: \"config_env\",\n confidence: \"low\",\n evidence: [\n createEvidence(\n diff.path,\n extractRepresentativeExcerpt(additions.length > 0 ? additions : deletions)\n ),\n ],\n file: diff.path,\n status: diff.status,\n isBreaking: false,\n changedOptions: {\n added: [],\n removed: [],\n modified: [],\n },\n strictnessChanges: [],\n };\n findings.push(finding);\n }\n continue;\n }\n\n const isBreaking = isBreakingChange(added, removed, modified);\n const strictnessChanges = getStrictnessChanges(added, removed, modified);\n\n const confidence: Confidence = isBreaking ? \"high\" : \"medium\";\n\n const excerpt = extractRepresentativeExcerpt(\n additions.length > 0 ? additions : deletions\n );\n\n const finding: TypeScriptConfigFinding = {\n type: \"typescript-config\",\n kind: \"typescript-config\",\n category: \"config_env\",\n confidence,\n evidence: [createEvidence(diff.path, excerpt)],\n file: diff.path,\n status: diff.status,\n isBreaking,\n changedOptions: {\n added,\n removed,\n modified,\n },\n strictnessChanges,\n };\n\n findings.push(finding);\n }\n\n return findings;\n },\n};\n",
|
|
36
|
-
"/**\n * Tailwind CSS configuration change detector.\n *\n * Detects changes to Tailwind CSS configuration files and identifies\n * potentially breaking changes to themes, plugins, or content paths.\n */\n\nimport { getAdditions, getDeletions } from \"../git/parser.js\";\nimport { createEvidence, extractRepresentativeExcerpt } from \"../core/evidence.js\";\nimport type {\n Analyzer,\n ChangeSet,\n Finding,\n TailwindConfigFinding,\n Confidence,\n} from \"../core/types.js\";\n\n// Tailwind config file patterns\nconst TAILWIND_PATTERNS = [\n /^tailwind\\.config\\.(js|cjs|mjs|ts)$/,\n /\\/tailwind\\.config\\.(js|cjs|mjs|ts)$/,\n];\n\n// PostCSS config (often related to Tailwind)\nconst POSTCSS_PATTERNS = [\n /^postcss\\.config\\.(js|cjs|mjs)$/,\n /\\/postcss\\.config\\.(js|cjs|mjs)$/,\n];\n\n// Critical configuration sections\nconst CRITICAL_SECTIONS = [\n \"theme\",\n \"content\",\n \"plugins\",\n \"presets\",\n \"prefix\",\n \"important\",\n \"darkMode\",\n \"safelist\",\n];\n\n// Theme subsections that affect styling\nconst THEME_SECTIONS = [\n \"colors\",\n \"spacing\",\n \"screens\",\n \"fontFamily\",\n \"fontSize\",\n \"fontWeight\",\n \"extend\",\n \"borderRadius\",\n \"boxShadow\",\n \"animation\",\n \"keyframes\",\n];\n\n/**\n * Check if a file is a Tailwind config file.\n */\nexport function isTailwindConfig(path: string): boolean {\n return TAILWIND_PATTERNS.some((pattern) => pattern.test(path));\n}\n\n/**\n * Check if a file is a PostCSS config file.\n */\nexport function isPostCSSConfig(path: string): boolean {\n return POSTCSS_PATTERNS.some((pattern) => pattern.test(path));\n}\n\n/**\n * Extract affected sections from diff content.\n */\nfunction extractAffectedSections(content: string[]): string[] {\n const sections = new Set<string>();\n const fullContent = content.join(\"\\n\");\n\n // Check for critical section changes\n for (const section of CRITICAL_SECTIONS) {\n const pattern = new RegExp(`\\\\b${section}\\\\s*[:{]`, \"i\");\n if (pattern.test(fullContent)) {\n sections.add(section);\n }\n }\n\n // Check for theme subsection changes\n for (const section of THEME_SECTIONS) {\n const pattern = new RegExp(`\\\\b${section}\\\\s*[:{]`, \"i\");\n if (pattern.test(fullContent)) {\n sections.add(`theme.${section}`);\n }\n }\n\n return Array.from(sections);\n}\n\n/**\n * Check for potentially breaking changes.\n */\nfunction detectBreakingChanges(\n additions: string[],\n deletions: string[]\n): { isBreaking: boolean; reasons: string[] } {\n const reasons: string[] = [];\n const addedContent = additions.join(\"\\n\");\n const deletedContent = deletions.join(\"\\n\");\n\n // Content paths changed (can break purging)\n if (/\\bcontent\\s*[:{]/.test(deletedContent) || /\\bcontent\\s*[:{]/.test(addedContent)) {\n if (deletions.length > 0) {\n reasons.push(\"Content paths modified (may affect CSS purging)\");\n }\n }\n\n // Prefix changed (breaks all existing class usage)\n if (/\\bprefix\\s*[:{]/.test(deletedContent) && /\\bprefix\\s*[:{]/.test(addedContent)) {\n reasons.push(\"Class prefix changed (requires updating all class names)\");\n }\n\n // Theme colors removed\n if (/colors\\s*[:{]/.test(deletedContent)) {\n reasons.push(\"Theme colors modified (may break existing color classes)\");\n }\n\n // Screen breakpoints changed\n if (/screens\\s*[:{]/.test(deletedContent)) {\n reasons.push(\"Screen breakpoints modified (may affect responsive design)\");\n }\n\n // Plugins removed\n if (/plugins\\s*[:{]/.test(deletedContent) && deletions.some((l) => l.includes(\"require(\"))) {\n reasons.push(\"Plugins removed (may remove utility classes)\");\n }\n\n // Dark mode strategy changed\n if (/darkMode\\s*[:{]/.test(deletedContent) || /darkMode\\s*[:{]/.test(addedContent)) {\n reasons.push(\"Dark mode configuration changed\");\n }\n\n return {\n isBreaking: reasons.length > 0,\n reasons,\n };\n}\n\nexport const tailwindAnalyzer: Analyzer = {\n name: \"tailwind\",\n\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: Finding[] = [];\n\n for (const diff of changeSet.diffs) {\n const isTailwind = isTailwindConfig(diff.path);\n const isPostCSS = isPostCSSConfig(diff.path);\n\n if (!isTailwind && !isPostCSS) {\n continue;\n }\n\n const additions = getAdditions(diff);\n const deletions = getDeletions(diff);\n\n const affectedSections = extractAffectedSections([...additions, ...deletions]);\n const { isBreaking, reasons } = detectBreakingChanges(additions, deletions);\n\n const confidence: Confidence = isBreaking ? \"high\" : affectedSections.length > 0 ? \"medium\" : \"low\";\n\n const excerpt = extractRepresentativeExcerpt(\n additions.length > 0 ? additions : deletions\n );\n\n const finding: TailwindConfigFinding = {\n type: \"tailwind-config\",\n kind: \"tailwind-config\",\n category: \"config_env\",\n confidence,\n evidence: [createEvidence(diff.path, excerpt)],\n file: diff.path,\n status: diff.status,\n configType: isTailwind ? \"tailwind\" : \"postcss\",\n isBreaking,\n affectedSections,\n breakingReasons: reasons,\n };\n\n findings.push(finding);\n }\n\n return findings;\n },\n};\n",
|
|
37
|
-
"/**\n * Monorepo configuration change detector.\n *\n * Detects changes to monorepo configuration files (Turborepo, pnpm workspaces,\n * Lerna, Nx, Yarn workspaces) and identifies potentially impactful modifications.\n */\n\nimport { getAdditions, getDeletions } from \"../git/parser.js\";\nimport { createEvidence, extractRepresentativeExcerpt } from \"../core/evidence.js\";\nimport type {\n Analyzer,\n ChangeSet,\n Finding,\n MonorepoConfigFinding,\n MonorepoTool,\n Confidence,\n} from \"../core/types.js\";\n\n// Monorepo config patterns by tool\nconst CONFIG_PATTERNS: Record<MonorepoTool, RegExp[]> = {\n turborepo: [/^turbo\\.json$/],\n pnpm: [/^pnpm-workspace\\.yaml$/, /^pnpm-workspace\\.yml$/],\n lerna: [/^lerna\\.json$/],\n nx: [/^nx\\.json$/, /^project\\.json$/],\n yarn: [/^\\.yarnrc\\.yml$/, /^\\.yarnrc$/],\n npm: [/^package\\.json$/], // For workspaces field only\n changesets: [/^\\.changeset\\/config\\.json$/],\n};\n\n// Critical configuration fields by tool\nconst CRITICAL_FIELDS: Record<MonorepoTool, string[]> = {\n turborepo: [\"pipeline\", \"globalDependencies\", \"globalEnv\", \"tasks\"],\n pnpm: [\"packages\"],\n lerna: [\"packages\", \"version\", \"npmClient\", \"useWorkspaces\"],\n nx: [\"targetDefaults\", \"namedInputs\", \"plugins\", \"defaultProject\"],\n yarn: [\"nodeLinker\", \"enableGlobalCache\", \"nmMode\"],\n npm: [\"workspaces\"],\n changesets: [\"baseBranch\", \"access\", \"changelog\"],\n};\n\n/**\n * Detect which monorepo tool a file belongs to.\n */\nexport function detectMonorepoTool(path: string): MonorepoTool | null {\n for (const [tool, patterns] of Object.entries(CONFIG_PATTERNS)) {\n if (patterns.some((pattern) => pattern.test(path))) {\n // Special case: package.json only counts if it has workspaces\n if (tool === \"npm\" && !path.endsWith(\"package.json\")) {\n continue;\n }\n return tool as MonorepoTool;\n }\n }\n return null;\n}\n\n/**\n * Check if package.json has workspace changes.\n */\nfunction hasWorkspaceChanges(additions: string[], deletions: string[]): boolean {\n const allContent = [...additions, ...deletions].join(\"\\n\");\n return /[\"']workspaces[\"']/.test(allContent);\n}\n\n/**\n * Extract affected fields from diff content.\n */\nfunction extractAffectedFields(content: string[], tool: MonorepoTool): string[] {\n const criticalFields = CRITICAL_FIELDS[tool] || [];\n const affected: string[] = [];\n const fullContent = content.join(\"\\n\");\n\n for (const field of criticalFields) {\n const pattern = new RegExp(`[\"']?${field}[\"']?\\\\s*[:{[]`, \"i\");\n if (pattern.test(fullContent)) {\n affected.push(field);\n }\n }\n\n return affected;\n}\n\n/**\n * Detect potentially impactful changes.\n */\nfunction detectImpactfulChanges(\n tool: MonorepoTool,\n additions: string[],\n deletions: string[]\n): string[] {\n const impacts: string[] = [];\n const addedContent = additions.join(\"\\n\");\n const deletedContent = deletions.join(\"\\n\");\n\n switch (tool) {\n case \"turborepo\":\n if (/pipeline|tasks/.test(deletedContent)) {\n impacts.push(\"Build pipeline configuration changed\");\n }\n if (/cache\\s*[:=]\\s*false/.test(addedContent)) {\n impacts.push(\"Caching disabled for tasks\");\n }\n if (/globalDependencies/.test(addedContent) || /globalDependencies/.test(deletedContent)) {\n impacts.push(\"Global dependencies changed (affects cache invalidation)\");\n }\n break;\n\n case \"pnpm\":\n if (/packages/.test(deletedContent)) {\n impacts.push(\"Workspace packages configuration changed\");\n }\n break;\n\n case \"lerna\":\n if (/version/.test(addedContent) && /independent/.test(addedContent)) {\n impacts.push(\"Switching to independent versioning\");\n }\n if (/npmClient/.test(addedContent) || /npmClient/.test(deletedContent)) {\n impacts.push(\"npm client configuration changed\");\n }\n break;\n\n case \"nx\":\n if (/targetDefaults/.test(deletedContent)) {\n impacts.push(\"Default target configuration changed\");\n }\n if (/plugins/.test(addedContent) || /plugins/.test(deletedContent)) {\n impacts.push(\"Nx plugins configuration changed\");\n }\n break;\n\n case \"yarn\":\n if (/nodeLinker/.test(addedContent) || /nodeLinker/.test(deletedContent)) {\n impacts.push(\"Node linker strategy changed (affects dependency resolution)\");\n }\n break;\n\n case \"npm\":\n if (/workspaces/.test(deletedContent)) {\n impacts.push(\"Workspace packages configuration changed\");\n }\n break;\n\n case \"changesets\":\n if (/baseBranch/.test(addedContent) || /baseBranch/.test(deletedContent)) {\n impacts.push(\"Base branch for changesets modified\");\n }\n if (/access/.test(addedContent)) {\n impacts.push(\"Package publish access level changed\");\n }\n break;\n }\n\n return impacts;\n}\n\nexport const monorepoAnalyzer: Analyzer = {\n name: \"monorepo\",\n\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: Finding[] = [];\n\n for (const diff of changeSet.diffs) {\n const tool = detectMonorepoTool(diff.path);\n\n if (!tool) {\n continue;\n }\n\n const additions = getAdditions(diff);\n const deletions = getDeletions(diff);\n\n // For package.json, only report if workspaces field is affected\n if (tool === \"npm\" && !hasWorkspaceChanges(additions, deletions)) {\n continue;\n }\n\n const affectedFields = extractAffectedFields([...additions, ...deletions], tool);\n const impacts = detectImpactfulChanges(tool, additions, deletions);\n\n // Skip if no meaningful changes detected\n if (affectedFields.length === 0 && impacts.length === 0) {\n continue;\n }\n\n const isBreaking = impacts.length > 0;\n const confidence: Confidence = isBreaking ? \"high\" : \"medium\";\n\n const excerpt = extractRepresentativeExcerpt(\n additions.length > 0 ? additions : deletions\n );\n\n const finding: MonorepoConfigFinding = {\n type: \"monorepo-config\",\n kind: \"monorepo-config\",\n category: \"config_env\",\n confidence,\n evidence: [createEvidence(diff.path, excerpt)],\n file: diff.path,\n status: diff.status,\n tool,\n affectedFields,\n impacts,\n };\n\n findings.push(finding);\n }\n\n return findings;\n },\n};\n",
|
|
38
|
-
"/**\n * Package exports change detector.\n *\n * Detects changes to package.json exports field which is critical for\n * library consumers. Changes to exports can be breaking changes.\n */\n\nimport { createEvidence } from \"../core/evidence.js\";\nimport type {\n Analyzer,\n ChangeSet,\n Finding,\n PackageExportsFinding,\n Confidence,\n} from \"../core/types.js\";\n\ntype ExportsField = string | Record<string, unknown> | null;\n\n/**\n * Flatten exports field into a list of export paths.\n */\nfunction flattenExports(\n exports: ExportsField,\n prefix: string = \"\"\n): string[] {\n if (!exports) {\n return [];\n }\n\n if (typeof exports === \"string\") {\n return [prefix || \".\"];\n }\n\n if (typeof exports === \"object\") {\n const paths: string[] = [];\n\n for (const [key, value] of Object.entries(exports)) {\n // Conditional exports (e.g., \"import\", \"require\", \"types\")\n if (key.startsWith(\".\")) {\n paths.push(...flattenExports(value as ExportsField, key));\n } else {\n // This is a condition, not a subpath\n if (typeof value === \"string\" || typeof value === \"object\") {\n paths.push(...flattenExports(value as ExportsField, prefix));\n }\n }\n }\n\n // Remove duplicates\n return [...new Set(paths)];\n }\n\n return [];\n}\n\n/**\n * Compare exports between base and head package.json.\n */\nfunction compareExports(\n baseExports: ExportsField,\n headExports: ExportsField\n): {\n added: string[];\n removed: string[];\n hasExportsField: { base: boolean; head: boolean };\n} {\n const basePaths = flattenExports(baseExports);\n const headPaths = flattenExports(headExports);\n\n const baseSet = new Set(basePaths);\n const headSet = new Set(headPaths);\n\n const added = headPaths.filter((p) => !baseSet.has(p));\n const removed = basePaths.filter((p) => !headSet.has(p));\n\n return {\n added,\n removed,\n hasExportsField: {\n base: baseExports !== undefined && baseExports !== null,\n head: headExports !== undefined && headExports !== null,\n },\n };\n}\n\n/**\n * Check for main/module/types field changes (legacy entry points).\n */\nfunction compareLegacyFields(\n base: Record<string, unknown> | undefined,\n head: Record<string, unknown> | undefined\n): { field: string; from?: string; to?: string }[] {\n const fields = [\"main\", \"module\", \"types\", \"typings\", \"browser\"];\n const changes: { field: string; from?: string; to?: string }[] = [];\n\n for (const field of fields) {\n const baseValue = base?.[field] as string | undefined;\n const headValue = head?.[field] as string | undefined;\n\n if (baseValue !== headValue) {\n changes.push({\n field,\n from: baseValue,\n to: headValue,\n });\n }\n }\n\n return changes;\n}\n\n/**\n * Check for bin field changes.\n */\nfunction compareBinField(\n base: Record<string, unknown> | undefined,\n head: Record<string, unknown> | undefined\n): { added: string[]; removed: string[] } {\n const baseBin = base?.bin;\n const headBin = head?.bin;\n\n const getNames = (bin: unknown): string[] => {\n if (typeof bin === \"string\") {\n return [\"(default)\"];\n }\n if (typeof bin === \"object\" && bin !== null) {\n return Object.keys(bin);\n }\n return [];\n };\n\n const baseNames = new Set(getNames(baseBin));\n const headNames = new Set(getNames(headBin));\n\n return {\n added: [...headNames].filter((n) => !baseNames.has(n)),\n removed: [...baseNames].filter((n) => !headNames.has(n)),\n };\n}\n\nexport const packageExportsAnalyzer: Analyzer = {\n name: \"package-exports\",\n\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: Finding[] = [];\n\n const base = changeSet.basePackageJson;\n const head = changeSet.headPackageJson;\n\n // Skip if neither version has a package.json\n if (!base && !head) {\n return findings;\n }\n\n // Compare exports field\n const baseExports = base?.exports as ExportsField | undefined;\n const headExports = head?.exports as ExportsField | undefined;\n\n const exportsComparison = compareExports(\n baseExports ?? null,\n headExports ?? null\n );\n\n // Compare legacy entry point fields\n const legacyChanges = compareLegacyFields(base, head);\n\n // Compare bin field\n const binChanges = compareBinField(base, head);\n\n // Determine if there are breaking changes\n const hasRemovedExports = exportsComparison.removed.length > 0;\n const hasRemovedBins = binChanges.removed.length > 0;\n const hasRemovedLegacy = legacyChanges.some(\n (c) => c.from !== undefined && c.to === undefined\n );\n const isBreaking = hasRemovedExports || hasRemovedBins || hasRemovedLegacy;\n\n // Skip if no changes to exports/entry points\n const hasExportsChanges =\n exportsComparison.added.length > 0 ||\n exportsComparison.removed.length > 0;\n const hasLegacyChanges = legacyChanges.length > 0;\n const hasBinChanges =\n binChanges.added.length > 0 || binChanges.removed.length > 0;\n\n if (!hasExportsChanges && !hasLegacyChanges && !hasBinChanges) {\n return findings;\n }\n\n // Determine confidence\n let confidence: Confidence = \"medium\";\n if (isBreaking) {\n confidence = \"high\";\n } else if (\n exportsComparison.added.length > 0 ||\n binChanges.added.length > 0\n ) {\n confidence = \"low\";\n }\n\n // Create excerpt summarizing changes\n const excerptParts: string[] = [];\n if (exportsComparison.removed.length > 0) {\n excerptParts.push(\n `Removed exports: ${exportsComparison.removed.slice(0, 3).join(\", \")}`\n );\n }\n if (exportsComparison.added.length > 0) {\n excerptParts.push(\n `Added exports: ${exportsComparison.added.slice(0, 3).join(\", \")}`\n );\n }\n if (legacyChanges.length > 0) {\n excerptParts.push(\n `Changed fields: ${legacyChanges.map((c) => c.field).join(\", \")}`\n );\n }\n if (binChanges.removed.length > 0) {\n excerptParts.push(`Removed bins: ${binChanges.removed.join(\", \")}`);\n }\n if (binChanges.added.length > 0) {\n excerptParts.push(`Added bins: ${binChanges.added.join(\", \")}`);\n }\n\n const finding: PackageExportsFinding = {\n type: \"package-exports\",\n kind: \"package-exports\",\n category: \"api\",\n confidence,\n evidence: [createEvidence(\"package.json\", excerptParts.join(\"; \"))],\n isBreaking,\n addedExports: exportsComparison.added,\n removedExports: exportsComparison.removed,\n legacyFieldChanges: legacyChanges,\n binChanges: {\n added: binChanges.added,\n removed: binChanges.removed,\n },\n };\n\n findings.push(finding);\n\n return findings;\n },\n};\n",
|
|
39
|
-
"/**\n * Vue.js and Nuxt route change detector.\n *\n * Detects changes to Vue Router and Nuxt file-based routes.\n */\n\nimport { getAdditions } from \"../git/parser.js\";\nimport { createEvidence, extractRepresentativeExcerpt } from \"../core/evidence.js\";\nimport type {\n Analyzer,\n ChangeSet,\n Evidence,\n Finding,\n RouteChangeFinding,\n RouteType,\n} from \"../core/types.js\";\n\n// Nuxt 3 pages directory pattern\nconst NUXT_PAGES_PATTERN = /^(pages|src\\/pages)\\/(.+)\\.(vue|ts|tsx|js|jsx)$/;\n\n// Nuxt 3 server routes pattern\nconst NUXT_SERVER_PATTERN = /^server\\/(api|routes|middleware)\\/(.+)\\.(ts|js)$/;\n\n// Nuxt layouts pattern\nconst NUXT_LAYOUTS_PATTERN = /^(layouts|src\\/layouts)\\/(.+)\\.vue$/;\n\n// Vue Router config patterns\nconst VUE_ROUTER_PATTERNS = [\n /router\\.(ts|js)$/,\n /routes\\.(ts|js)$/,\n /router\\/index\\.(ts|js)$/,\n];\n\n/**\n * Check if file is a Nuxt page route.\n */\nexport function isNuxtPage(path: string): boolean {\n return NUXT_PAGES_PATTERN.test(path);\n}\n\n/**\n * Check if file is a Nuxt server route.\n */\nexport function isNuxtServerRoute(path: string): boolean {\n return NUXT_SERVER_PATTERN.test(path);\n}\n\n/**\n * Check if file is a Nuxt layout.\n */\nexport function isNuxtLayout(path: string): boolean {\n return NUXT_LAYOUTS_PATTERN.test(path);\n}\n\n/**\n * Check if file is Vue Router configuration.\n */\nexport function isVueRouterConfig(path: string): boolean {\n return VUE_ROUTER_PATTERNS.some((pattern) => pattern.test(path));\n}\n\n/**\n * Convert Nuxt file path to route path.\n * Examples:\n * - pages/index.vue -> /\n * - pages/about.vue -> /about\n * - pages/users/[id].vue -> /users/:id\n * - pages/[...slug].vue -> /:slug*\n */\nexport function nuxtFileToRoute(filePath: string): string {\n const match = filePath.match(NUXT_PAGES_PATTERN);\n if (!match) return filePath;\n\n let routePath = match[2];\n\n // Remove file extension part if it's like .get, .post, etc.\n routePath = routePath.replace(/\\.(get|post|put|delete|patch)$/i, \"\");\n\n // Convert to route path\n routePath = routePath\n // index -> /\n .replace(/\\/index$/, \"\")\n .replace(/^index$/, \"\")\n // [...slug] -> :slug*\n .replace(/\\[\\.\\.\\.(\\w+)\\]/g, \":$1*\")\n // [id] -> :id\n .replace(/\\[(\\w+)\\]/g, \":$1\");\n\n return \"/\" + routePath;\n}\n\n/**\n * Detect HTTP method from Nuxt server route filename.\n */\nfunction detectNuxtServerMethod(filePath: string): string[] {\n const methods: string[] = [];\n\n // Method can be in filename: route.get.ts, route.post.ts\n const methodMatch = filePath.match(/\\.(\\w+)\\.(ts|js)$/);\n if (methodMatch) {\n const method = methodMatch[1].toUpperCase();\n if ([\"GET\", \"POST\", \"PUT\", \"DELETE\", \"PATCH\", \"HEAD\", \"OPTIONS\"].includes(method)) {\n methods.push(method);\n }\n }\n\n // Default to all methods if no specific method detected\n if (methods.length === 0) {\n methods.push(\"*\");\n }\n\n return methods;\n}\n\n/**\n * Determine route type from file path.\n */\nfunction getRouteType(filePath: string): RouteType {\n if (isNuxtServerRoute(filePath)) {\n return \"endpoint\";\n }\n if (isNuxtLayout(filePath)) {\n return \"layout\";\n }\n if (\n filePath.includes(\"error.vue\") ||\n filePath.includes(\"404.vue\") ||\n filePath.includes(\"500.vue\")\n ) {\n return \"error\";\n }\n return \"page\";\n}\n\nexport const vueRoutesAnalyzer: Analyzer = {\n name: \"vue-routes\",\n\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: Finding[] = [];\n\n for (const file of changeSet.files) {\n const isPage = isNuxtPage(file.path);\n const isServer = isNuxtServerRoute(file.path);\n const isLayout = isNuxtLayout(file.path);\n const isRouterConfig = isVueRouterConfig(file.path);\n\n if (!isPage && !isServer && !isLayout && !isRouterConfig) {\n continue;\n }\n\n // For router config files, just report the change\n if (isRouterConfig) {\n const diff = changeSet.diffs.find((d) => d.path === file.path);\n const additions = diff ? getAdditions(diff) : [];\n const excerpt = extractRepresentativeExcerpt(additions);\n\n const finding: RouteChangeFinding = {\n type: \"route-change\",\n kind: \"route-change\",\n category: \"routes\",\n confidence: \"medium\",\n evidence: [createEvidence(file.path, excerpt || \"Vue Router config changed\")],\n routeId: \"vue-router-config\",\n file: file.path,\n change: file.status,\n routeType: \"unknown\",\n };\n findings.push(finding);\n continue;\n }\n\n // Get route details\n const routeId = isPage ? nuxtFileToRoute(file.path) : file.path;\n const routeType = getRouteType(file.path);\n const methods = isServer ? detectNuxtServerMethod(file.path) : undefined;\n\n // Get evidence from diff\n const diff = changeSet.diffs.find((d) => d.path === file.path);\n const additions = diff ? getAdditions(diff) : [];\n const excerpt = extractRepresentativeExcerpt(additions);\n\n const evidence: Evidence[] = [];\n if (excerpt) {\n evidence.push(createEvidence(file.path, excerpt));\n }\n\n const finding: RouteChangeFinding = {\n type: \"route-change\",\n kind: \"route-change\",\n category: \"routes\",\n confidence: \"high\",\n evidence,\n routeId,\n file: file.path,\n change: file.status,\n routeType,\n methods,\n };\n\n findings.push(finding);\n }\n\n return findings;\n },\n};\n",
|
|
40
|
-
"/**\n * Astro route and page change detector.\n *\n * Detects changes to Astro pages, API routes, and layouts.\n */\n\nimport { getAdditions } from \"../git/parser.js\";\nimport { createEvidence, extractRepresentativeExcerpt } from \"../core/evidence.js\";\nimport type {\n Analyzer,\n ChangeSet,\n Evidence,\n Finding,\n RouteChangeFinding,\n RouteType,\n} from \"../core/types.js\";\n\n// Astro pages directory pattern\nconst ASTRO_PAGES_PATTERN = /^src\\/pages\\/(.+)\\.(astro|md|mdx|html|ts|js)$/;\n\n// Astro layouts pattern\nconst ASTRO_LAYOUTS_PATTERN = /^src\\/layouts\\/(.+)\\.astro$/;\n\n// Astro content collections pattern\nconst ASTRO_CONTENT_PATTERN = /^src\\/content\\/(.+)\\.(md|mdx|json|yaml|yml)$/;\n\n// Astro config pattern\nconst ASTRO_CONFIG_PATTERN = /^astro\\.config\\.(mjs|ts|js)$/;\n\n/**\n * Check if file is an Astro page.\n */\nexport function isAstroPage(path: string): boolean {\n return ASTRO_PAGES_PATTERN.test(path);\n}\n\n/**\n * Check if file is an Astro API endpoint.\n */\nexport function isAstroEndpoint(path: string): boolean {\n return ASTRO_PAGES_PATTERN.test(path) && /\\.(ts|js)$/.test(path);\n}\n\n/**\n * Check if file is an Astro layout.\n */\nexport function isAstroLayout(path: string): boolean {\n return ASTRO_LAYOUTS_PATTERN.test(path);\n}\n\n/**\n * Check if file is Astro content.\n */\nexport function isAstroContent(path: string): boolean {\n return ASTRO_CONTENT_PATTERN.test(path);\n}\n\n/**\n * Check if file is Astro config.\n */\nexport function isAstroConfig(path: string): boolean {\n return ASTRO_CONFIG_PATTERN.test(path);\n}\n\n/**\n * Convert Astro file path to route path.\n * Examples:\n * - src/pages/index.astro -> /\n * - src/pages/about.astro -> /about\n * - src/pages/blog/[slug].astro -> /blog/:slug\n * - src/pages/[...slug].astro -> /:slug*\n */\nexport function astroFileToRoute(filePath: string): string {\n const match = filePath.match(ASTRO_PAGES_PATTERN);\n if (!match) return filePath;\n\n let routePath = match[1];\n\n // Remove file extension\n routePath = routePath.replace(/\\.(astro|md|mdx|html|ts|js)$/, \"\");\n\n // Convert to route path\n routePath = routePath\n // index -> /\n .replace(/\\/index$/, \"\")\n .replace(/^index$/, \"\")\n // [...slug] -> :slug*\n .replace(/\\[\\.\\.\\.(\\w+)\\]/g, \":$1*\")\n // [id] -> :id\n .replace(/\\[(\\w+)\\]/g, \":$1\");\n\n return \"/\" + routePath;\n}\n\n/**\n * Detect HTTP methods from Astro endpoint content.\n */\nfunction detectAstroEndpointMethods(additions: string[]): string[] {\n const methods: string[] = [];\n const content = additions.join(\"\\n\");\n\n // Astro exports functions for each HTTP method\n const methodPatterns = [\n { pattern: /export\\s+(const|function|async function)\\s+GET\\b/, method: \"GET\" },\n { pattern: /export\\s+(const|function|async function)\\s+POST\\b/, method: \"POST\" },\n { pattern: /export\\s+(const|function|async function)\\s+PUT\\b/, method: \"PUT\" },\n { pattern: /export\\s+(const|function|async function)\\s+DELETE\\b/, method: \"DELETE\" },\n { pattern: /export\\s+(const|function|async function)\\s+PATCH\\b/, method: \"PATCH\" },\n { pattern: /export\\s+(const|function|async function)\\s+ALL\\b/, method: \"*\" },\n ];\n\n for (const { pattern, method } of methodPatterns) {\n if (pattern.test(content)) {\n methods.push(method);\n }\n }\n\n return methods;\n}\n\n/**\n * Determine route type from file path and content.\n */\nfunction getRouteType(filePath: string): RouteType {\n if (isAstroLayout(filePath)) {\n return \"layout\";\n }\n if (isAstroEndpoint(filePath)) {\n return \"endpoint\";\n }\n if (filePath.includes(\"404.\") || filePath.includes(\"500.\")) {\n return \"error\";\n }\n return \"page\";\n}\n\nexport const astroRoutesAnalyzer: Analyzer = {\n name: \"astro-routes\",\n\n analyze(changeSet: ChangeSet): Finding[] {\n const findings: Finding[] = [];\n\n for (const file of changeSet.files) {\n const isPage = isAstroPage(file.path);\n const isLayout = isAstroLayout(file.path);\n const isContent = isAstroContent(file.path);\n const isConfig = isAstroConfig(file.path);\n\n if (!isPage && !isLayout && !isContent && !isConfig) {\n continue;\n }\n\n // Get evidence from diff\n const diff = changeSet.diffs.find((d) => d.path === file.path);\n const additions = diff ? getAdditions(diff) : [];\n const excerpt = extractRepresentativeExcerpt(additions);\n\n // For config files, just report the change\n if (isConfig) {\n const finding: RouteChangeFinding = {\n type: \"route-change\",\n kind: \"route-change\",\n category: \"routes\",\n confidence: \"medium\",\n evidence: [createEvidence(file.path, excerpt || \"Astro config changed\")],\n routeId: \"astro-config\",\n file: file.path,\n change: file.status,\n routeType: \"unknown\",\n };\n findings.push(finding);\n continue;\n }\n\n // For content files, report as content change\n if (isContent) {\n const finding: RouteChangeFinding = {\n type: \"route-change\",\n kind: \"route-change\",\n category: \"routes\",\n confidence: \"high\",\n evidence: excerpt ? [createEvidence(file.path, excerpt)] : [],\n routeId: file.path.replace(/^src\\/content\\//, \"/content/\"),\n file: file.path,\n change: file.status,\n routeType: \"page\",\n tags: [\"content-collection\"],\n };\n findings.push(finding);\n continue;\n }\n\n // Get route details for pages and layouts\n const routeId = isPage ? astroFileToRoute(file.path) : file.path;\n const routeType = getRouteType(file.path);\n const endpointMethods = isAstroEndpoint(file.path)\n ? detectAstroEndpointMethods(additions)\n : [];\n const methods = endpointMethods.length > 0 ? endpointMethods : undefined;\n\n const evidence: Evidence[] = [];\n if (excerpt) {\n evidence.push(createEvidence(file.path, excerpt));\n }\n\n const finding: RouteChangeFinding = {\n type: \"route-change\",\n kind: \"route-change\",\n category: \"routes\",\n confidence: \"high\",\n evidence,\n routeId,\n file: file.path,\n change: file.status,\n routeType,\n methods,\n };\n\n findings.push(finding);\n }\n\n return findings;\n },\n};\n",
|
|
41
|
-
"/**\n * Analyzer module exports.\n */\n\nexport * from \"./file-summary.js\";\nexport * from \"./file-category.js\";\nexport * from \"./route-detector.js\";\nexport * from \"./supabase.js\";\nexport * from \"./env-var.js\";\nexport * from \"./cloudflare.js\";\nexport * from \"./vitest.js\";\nexport * from \"./dependencies.js\";\nexport * from \"./security-files.js\";\nexport { reactRouterRoutesAnalyzer } from \"./reactRouterRoutes.js\";\nexport * from \"./test-parity.js\";\nexport * from \"./impact.js\";\nexport * from \"./large-diff.js\";\nexport * from \"./lockfiles.js\";\nexport * from \"./test-gaps.js\";\nexport * from \"./sql-risks.js\";\nexport * from \"./ci-workflows.js\";\nexport * from \"./infra.js\";\nexport * from \"./api-contracts.js\";\nexport { stencilAnalyzer } from \"./stencil.js\";\nexport { nextRoutesAnalyzer } from \"./next-routes.js\";\nexport { graphqlAnalyzer } from \"./graphql.js\";\nexport { typescriptConfigAnalyzer } from \"./typescript-config.js\";\nexport { tailwindAnalyzer } from \"./tailwind.js\";\nexport { monorepoAnalyzer } from \"./monorepo.js\";\nexport { packageExportsAnalyzer } from \"./package-exports.js\";\nexport { vueRoutesAnalyzer } from \"./vue-routes.js\";\nexport { astroRoutesAnalyzer } from \"./astro-routes.js\";\n\n",
|
|
42
|
-
"/**\n * Default profile - generic analyzers for any project.\n */\n\nimport type { Profile } from \"../core/types.js\";\nimport {\n cloudflareAnalyzer,\n dependencyAnalyzer,\n envVarAnalyzer,\n fileCategoryAnalyzer,\n fileSummaryAnalyzer,\n securityFilesAnalyzer,\n vitestAnalyzer,\n impactAnalyzer,\n analyzeLargeDiff,\n analyzeLockfiles,\n analyzeTestGaps,\n analyzeSQLRisks,\n analyzeCIWorkflows,\n analyzeInfra,\n analyzeAPIContracts,\n graphqlAnalyzer,\n} from \"../analyzers/index.js\";\n\n/**\n * Default profile with generic analyzers (no SvelteKit-specific ones).\n */\nexport const defaultProfile: Profile = {\n name: \"auto\", // Will be resolved to actual profile name\n analyzers: [\n fileSummaryAnalyzer,\n fileCategoryAnalyzer,\n envVarAnalyzer,\n cloudflareAnalyzer,\n vitestAnalyzer,\n dependencyAnalyzer,\n securityFilesAnalyzer,\n impactAnalyzer,\n graphqlAnalyzer,\n analyzeLargeDiff,\n analyzeLockfiles,\n analyzeTestGaps,\n analyzeSQLRisks,\n analyzeCIWorkflows,\n analyzeInfra,\n analyzeAPIContracts,\n ],\n};\n",
|
|
43
|
-
"/**\n * SvelteKit profile - composes analyzers for SvelteKit projects.\n */\n\nimport type { Profile } from \"../core/types.js\";\nimport {\n cloudflareAnalyzer,\n dependencyAnalyzer,\n envVarAnalyzer,\n fileCategoryAnalyzer,\n fileSummaryAnalyzer,\n routeDetectorAnalyzer,\n securityFilesAnalyzer,\n supabaseAnalyzer,\n vitestAnalyzer,\n impactAnalyzer,\n analyzeLargeDiff,\n analyzeLockfiles,\n analyzeTestGaps,\n analyzeSQLRisks,\n analyzeCIWorkflows,\n analyzeInfra,\n analyzeAPIContracts,\n} from \"../analyzers/index.js\";\nimport { tailwindAnalyzer } from \"../analyzers/tailwind.js\";\n\n/**\n * SvelteKit profile with all relevant analyzers.\n */\nexport const sveltekitProfile: Profile = {\n name: \"sveltekit\",\n analyzers: [\n fileSummaryAnalyzer,\n fileCategoryAnalyzer,\n routeDetectorAnalyzer,\n supabaseAnalyzer,\n envVarAnalyzer,\n cloudflareAnalyzer,\n vitestAnalyzer,\n dependencyAnalyzer,\n securityFilesAnalyzer,\n impactAnalyzer,\n tailwindAnalyzer,\n analyzeLargeDiff,\n analyzeLockfiles,\n analyzeTestGaps,\n analyzeSQLRisks,\n analyzeCIWorkflows,\n analyzeInfra,\n analyzeAPIContracts,\n ],\n};\n",
|
|
44
|
-
"/**\n * React profile - composes analyzers for React projects.\n */\n\nimport type { Profile } from \"../core/types.js\";\nimport {\n cloudflareAnalyzer,\n dependencyAnalyzer,\n envVarAnalyzer,\n fileCategoryAnalyzer,\n fileSummaryAnalyzer,\n reactRouterRoutesAnalyzer,\n securityFilesAnalyzer,\n vitestAnalyzer,\n impactAnalyzer,\n analyzeLargeDiff,\n analyzeLockfiles,\n analyzeTestGaps,\n analyzeSQLRisks,\n analyzeCIWorkflows,\n analyzeInfra,\n analyzeAPIContracts,\n} from \"../analyzers/index.js\";\nimport { tailwindAnalyzer } from \"../analyzers/tailwind.js\";\nimport { typescriptConfigAnalyzer } from \"../analyzers/typescript-config.js\";\n\n/**\n * React profile with all relevant analyzers.\n */\nexport const reactProfile: Profile = {\n name: \"react\",\n analyzers: [\n fileSummaryAnalyzer,\n fileCategoryAnalyzer,\n reactRouterRoutesAnalyzer,\n envVarAnalyzer,\n cloudflareAnalyzer,\n vitestAnalyzer,\n dependencyAnalyzer,\n securityFilesAnalyzer,\n impactAnalyzer,\n tailwindAnalyzer,\n typescriptConfigAnalyzer,\n analyzeLargeDiff,\n analyzeLockfiles,\n analyzeTestGaps,\n analyzeSQLRisks,\n analyzeCIWorkflows,\n analyzeInfra,\n analyzeAPIContracts,\n ],\n};\n",
|
|
45
|
-
"/**\n * Stencil profile definition.\n */\n\nimport type { Profile } from \"../core/types.js\";\nimport {\n fileSummaryAnalyzer,\n fileCategoryAnalyzer,\n dependencyAnalyzer,\n impactAnalyzer,\n stencilAnalyzer,\n envVarAnalyzer,\n cloudflareAnalyzer,\n vitestAnalyzer,\n securityFilesAnalyzer,\n analyzeLargeDiff,\n analyzeLockfiles,\n analyzeTestGaps,\n analyzeSQLRisks,\n analyzeCIWorkflows,\n analyzeInfra,\n analyzeAPIContracts,\n} from \"../analyzers/index.js\";\nimport { typescriptConfigAnalyzer } from \"../analyzers/typescript-config.js\";\n\nexport const stencilProfile: Profile = {\n name: \"stencil\",\n analyzers: [\n fileSummaryAnalyzer,\n fileCategoryAnalyzer,\n stencilAnalyzer,\n envVarAnalyzer,\n cloudflareAnalyzer,\n vitestAnalyzer,\n dependencyAnalyzer,\n securityFilesAnalyzer,\n impactAnalyzer,\n typescriptConfigAnalyzer,\n analyzeLargeDiff,\n analyzeLockfiles,\n analyzeTestGaps,\n analyzeSQLRisks,\n analyzeCIWorkflows,\n analyzeInfra,\n analyzeAPIContracts,\n ],\n};\n",
|
|
46
|
-
"/**\n * Next.js profile - composes analyzers for Next.js App Router projects.\n */\n\nimport type { Profile } from \"../core/types.js\";\nimport {\n analyzeLargeDiff,\n analyzeLockfiles,\n analyzeTestGaps,\n analyzeSQLRisks,\n analyzeCIWorkflows,\n analyzeInfra,\n analyzeAPIContracts,\n cloudflareAnalyzer,\n dependencyAnalyzer,\n envVarAnalyzer,\n fileCategoryAnalyzer,\n fileSummaryAnalyzer,\n securityFilesAnalyzer,\n vitestAnalyzer,\n impactAnalyzer,\n} from \"../analyzers/index.js\";\nimport { nextRoutesAnalyzer } from \"../analyzers/next-routes.js\";\nimport { tailwindAnalyzer } from \"../analyzers/tailwind.js\";\n\n/**\n * Next.js profile with all relevant analyzers for App Router projects.\n */\nexport const nextProfile: Profile = {\n name: \"next\",\n analyzers: [\n fileSummaryAnalyzer,\n fileCategoryAnalyzer,\n nextRoutesAnalyzer,\n envVarAnalyzer,\n cloudflareAnalyzer,\n vitestAnalyzer,\n dependencyAnalyzer,\n securityFilesAnalyzer,\n impactAnalyzer,\n tailwindAnalyzer,\n analyzeLargeDiff,\n analyzeLockfiles,\n analyzeTestGaps,\n analyzeSQLRisks,\n analyzeCIWorkflows,\n analyzeInfra,\n analyzeAPIContracts,\n ],\n};\n",
|
|
47
|
-
"/**\n * Vue.js / Nuxt profile - analyzers for Vue and Nuxt projects.\n */\n\nimport type { Profile } from \"../core/types.js\";\nimport {\n cloudflareAnalyzer,\n dependencyAnalyzer,\n envVarAnalyzer,\n fileCategoryAnalyzer,\n fileSummaryAnalyzer,\n securityFilesAnalyzer,\n vitestAnalyzer,\n impactAnalyzer,\n analyzeLargeDiff,\n analyzeLockfiles,\n analyzeTestGaps,\n analyzeSQLRisks,\n analyzeCIWorkflows,\n analyzeInfra,\n analyzeAPIContracts,\n} from \"../analyzers/index.js\";\nimport { vueRoutesAnalyzer } from \"../analyzers/vue-routes.js\";\nimport { tailwindAnalyzer } from \"../analyzers/tailwind.js\";\nimport { typescriptConfigAnalyzer } from \"../analyzers/typescript-config.js\";\n\n/**\n * Vue/Nuxt profile with Vue-specific analyzers.\n */\nexport const vueProfile: Profile = {\n name: \"vue\",\n analyzers: [\n fileSummaryAnalyzer,\n fileCategoryAnalyzer,\n vueRoutesAnalyzer,\n envVarAnalyzer,\n cloudflareAnalyzer,\n vitestAnalyzer,\n dependencyAnalyzer,\n securityFilesAnalyzer,\n impactAnalyzer,\n tailwindAnalyzer,\n typescriptConfigAnalyzer,\n analyzeLargeDiff,\n analyzeLockfiles,\n analyzeTestGaps,\n analyzeSQLRisks,\n analyzeCIWorkflows,\n analyzeInfra,\n analyzeAPIContracts,\n ],\n};\n",
|
|
48
|
-
"/**\n * Astro profile - analyzers for Astro projects.\n */\n\nimport type { Profile } from \"../core/types.js\";\nimport {\n cloudflareAnalyzer,\n dependencyAnalyzer,\n envVarAnalyzer,\n fileCategoryAnalyzer,\n fileSummaryAnalyzer,\n securityFilesAnalyzer,\n vitestAnalyzer,\n impactAnalyzer,\n analyzeLargeDiff,\n analyzeLockfiles,\n analyzeTestGaps,\n analyzeSQLRisks,\n analyzeCIWorkflows,\n analyzeInfra,\n analyzeAPIContracts,\n} from \"../analyzers/index.js\";\nimport { astroRoutesAnalyzer } from \"../analyzers/astro-routes.js\";\nimport { tailwindAnalyzer } from \"../analyzers/tailwind.js\";\nimport { typescriptConfigAnalyzer } from \"../analyzers/typescript-config.js\";\n\n/**\n * Astro profile with Astro-specific analyzers.\n */\nexport const astroProfile: Profile = {\n name: \"astro\",\n analyzers: [\n fileSummaryAnalyzer,\n fileCategoryAnalyzer,\n astroRoutesAnalyzer,\n envVarAnalyzer,\n cloudflareAnalyzer,\n vitestAnalyzer,\n dependencyAnalyzer,\n securityFilesAnalyzer,\n impactAnalyzer,\n tailwindAnalyzer,\n typescriptConfigAnalyzer,\n analyzeLargeDiff,\n analyzeLockfiles,\n analyzeTestGaps,\n analyzeSQLRisks,\n analyzeCIWorkflows,\n analyzeInfra,\n analyzeAPIContracts,\n ],\n};\n",
|
|
49
|
-
"/**\n * Library profile - analyzers for npm package/library development.\n *\n * This profile focuses on API surface changes, breaking changes detection,\n * and package metadata that matters for library consumers.\n */\n\nimport type { Profile } from \"../core/types.js\";\nimport {\n dependencyAnalyzer,\n fileCategoryAnalyzer,\n fileSummaryAnalyzer,\n vitestAnalyzer,\n impactAnalyzer,\n analyzeLargeDiff,\n analyzeLockfiles,\n analyzeTestGaps,\n analyzeCIWorkflows,\n analyzeAPIContracts,\n} from \"../analyzers/index.js\";\nimport { packageExportsAnalyzer } from \"../analyzers/package-exports.js\";\nimport { typescriptConfigAnalyzer } from \"../analyzers/typescript-config.js\";\nimport { monorepoAnalyzer } from \"../analyzers/monorepo.js\";\n\n/**\n * Library/Package profile with analyzers focused on API surface and breaking changes.\n */\nexport const libraryProfile: Profile = {\n name: \"library\",\n analyzers: [\n fileSummaryAnalyzer,\n fileCategoryAnalyzer,\n packageExportsAnalyzer,\n typescriptConfigAnalyzer,\n dependencyAnalyzer,\n vitestAnalyzer,\n impactAnalyzer,\n monorepoAnalyzer,\n analyzeLargeDiff,\n analyzeLockfiles,\n analyzeTestGaps,\n analyzeCIWorkflows,\n analyzeAPIContracts,\n ],\n};\n",
|
|
50
|
-
"/**\n * Profile detection and management.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { ChangeSet, Profile, ProfileName } from \"../core/types.js\";\nimport { defaultProfile } from \"./default.js\";\nimport { sveltekitProfile } from \"./sveltekit.js\";\nimport { reactProfile } from \"./react.js\";\nimport { stencilProfile } from \"./stencil.js\";\nimport { nextProfile } from \"./next.js\";\nimport { vueProfile } from \"./vue.js\";\nimport { astroProfile } from \"./astro.js\";\nimport { libraryProfile } from \"./library.js\";\n\n/**\n * Result of profile detection with reasons.\n */\nexport interface ProfileDetectionResult {\n profile: ProfileName;\n confidence: \"high\" | \"medium\" | \"low\";\n reasons: string[];\n}\n\n/**\n * Check if a project is a SvelteKit project.\n */\nexport function isSvelteKitProject(cwd: string = process.cwd()): boolean {\n // Check for src/routes directory\n if (existsSync(join(cwd, \"src\", \"routes\"))) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Check if package.json contains @sveltejs/kit.\n */\nexport function hasSvelteKitDependency(\n packageJson: Record<string, unknown> | undefined\n): boolean {\n if (!packageJson) return false;\n\n const deps = packageJson.dependencies as Record<string, string> | undefined;\n const devDeps = packageJson.devDependencies as\n | Record<string, string>\n | undefined;\n\n return Boolean(\n deps?.[\"@sveltejs/kit\"] || devDeps?.[\"@sveltejs/kit\"]\n );\n}\n\n/**\n * Check if package.json contains React dependencies.\n */\nexport function hasReactDependency(\n packageJson: Record<string, unknown> | undefined\n): boolean {\n if (!packageJson) return false;\n\n const deps = packageJson.dependencies as Record<string, string> | undefined;\n const devDeps = packageJson.devDependencies as\n | Record<string, string>\n | undefined;\n\n return Boolean(\n (deps?.[\"react\"] && deps?.[\"react-dom\"]) ||\n (devDeps?.[\"react\"] && devDeps?.[\"react-dom\"])\n );\n}\n\n/**\n * Check if package.json contains React Router dependencies.\n */\nexport function hasReactRouterDependency(\n packageJson: Record<string, unknown> | undefined\n): boolean {\n if (!packageJson) return false;\n\n const deps = packageJson.dependencies as Record<string, string> | undefined;\n const devDeps = packageJson.devDependencies as\n | Record<string, string>\n | undefined;\n\n return Boolean(\n deps?.[\"react-router\"] ||\n deps?.[\"react-router-dom\"] ||\n devDeps?.[\"react-router\"] ||\n devDeps?.[\"react-router-dom\"]\n );\n}\n\n/**\n * Check if package.json contains Next.js dependency.\n */\nexport function hasNextDependency(\n packageJson: Record<string, unknown> | undefined\n): boolean {\n if (!packageJson) return false;\n\n const deps = packageJson.dependencies as Record<string, string> | undefined;\n const devDeps = packageJson.devDependencies as\n | Record<string, string>\n | undefined;\n\n return Boolean(deps?.[\"next\"] || devDeps?.[\"next\"]);\n}\n\n/**\n * Check if package.json contains Stencil dependency.\n */\nexport function hasStencilDependency(\n packageJson: Record<string, unknown> | undefined\n): boolean {\n if (!packageJson) return false;\n\n const deps = packageJson.dependencies as Record<string, string> | undefined;\n const devDeps = packageJson.devDependencies as\n | Record<string, string>\n | undefined;\n\n return Boolean(deps?.[\"@stencil/core\"] || devDeps?.[\"@stencil/core\"]);\n}\n\n/**\n * Check if Stencil config exists.\n */\nexport function hasStencilConfig(cwd: string = process.cwd()): boolean {\n return existsSync(join(cwd, \"stencil.config.ts\")) || existsSync(join(cwd, \"stencil.config.js\"));\n}\n\n/**\n * Check if a project has Next.js App Router directory.\n */\nexport function isNextAppDir(cwd: string = process.cwd()): boolean {\n // Check for app/ directory (Next.js 13+ App Router)\n if (existsSync(join(cwd, \"app\"))) {\n return true;\n }\n // Check for src/app/ directory\n if (existsSync(join(cwd, \"src\", \"app\"))) {\n return true;\n }\n return false;\n}\n\n/**\n * Check if package.json contains Vue.js dependencies.\n */\nexport function hasVueDependency(\n packageJson: Record<string, unknown> | undefined\n): boolean {\n if (!packageJson) return false;\n\n const deps = packageJson.dependencies as Record<string, string> | undefined;\n const devDeps = packageJson.devDependencies as\n | Record<string, string>\n | undefined;\n\n return Boolean(deps?.[\"vue\"] || devDeps?.[\"vue\"]);\n}\n\n/**\n * Check if package.json contains Nuxt dependency.\n */\nexport function hasNuxtDependency(\n packageJson: Record<string, unknown> | undefined\n): boolean {\n if (!packageJson) return false;\n\n const deps = packageJson.dependencies as Record<string, string> | undefined;\n const devDeps = packageJson.devDependencies as\n | Record<string, string>\n | undefined;\n\n return Boolean(deps?.[\"nuxt\"] || devDeps?.[\"nuxt\"]);\n}\n\n/**\n * Check if project has Nuxt pages directory.\n */\nexport function isNuxtProject(cwd: string = process.cwd()): boolean {\n return existsSync(join(cwd, \"pages\")) || existsSync(join(cwd, \"src\", \"pages\"));\n}\n\n/**\n * Check if package.json contains Astro dependency.\n */\nexport function hasAstroDependency(\n packageJson: Record<string, unknown> | undefined\n): boolean {\n if (!packageJson) return false;\n\n const deps = packageJson.dependencies as Record<string, string> | undefined;\n const devDeps = packageJson.devDependencies as\n | Record<string, string>\n | undefined;\n\n return Boolean(deps?.[\"astro\"] || devDeps?.[\"astro\"]);\n}\n\n/**\n * Check if project has Astro config.\n */\nexport function hasAstroConfig(cwd: string = process.cwd()): boolean {\n return (\n existsSync(join(cwd, \"astro.config.mjs\")) ||\n existsSync(join(cwd, \"astro.config.ts\")) ||\n existsSync(join(cwd, \"astro.config.js\"))\n );\n}\n\n/**\n * Check if project is a library/package (has exports or publishConfig).\n */\nexport function isLibraryProject(\n packageJson: Record<string, unknown> | undefined\n): boolean {\n if (!packageJson) return false;\n\n // Has exports field (modern package entry points)\n if (packageJson.exports) return true;\n\n // Has publishConfig (intended for publishing)\n if (packageJson.publishConfig) return true;\n\n // Has private: false (explicitly public)\n if (packageJson.private === false) return true;\n\n // Has bin field (CLI tool)\n if (packageJson.bin) return true;\n\n return false;\n}\n\n/**\n * Detect the appropriate profile for a project with reasons.\n */\nexport function detectProfileWithReasons(\n changeSet: ChangeSet,\n cwd: string = process.cwd()\n): ProfileDetectionResult {\n const reasons: string[] = [];\n\n // Check for SvelteKit\n const hasSvelteRoutes = isSvelteKitProject(cwd);\n const hasSvelteDep = hasSvelteKitDependency(changeSet.headPackageJson);\n\n if (hasSvelteRoutes || hasSvelteDep) {\n if (hasSvelteRoutes) {\n reasons.push(\"Found src/routes/ directory (SvelteKit file-based routing)\");\n }\n if (hasSvelteDep) {\n reasons.push(\"Found @sveltejs/kit in package.json dependencies\");\n }\n return {\n profile: \"sveltekit\",\n confidence: hasSvelteRoutes && hasSvelteDep ? \"high\" : \"high\",\n reasons,\n };\n }\n\n // Check for Stencil\n const hasStencilDep = hasStencilDependency(changeSet.headPackageJson);\n const hasStencilConf = hasStencilConfig(cwd);\n\n if (hasStencilDep || hasStencilConf) {\n if (hasStencilDep) {\n reasons.push(\"Found @stencil/core in package.json dependencies\");\n }\n if (hasStencilConf) {\n reasons.push(\"Found stencil.config.ts or stencil.config.js\");\n }\n return {\n profile: \"stencil\",\n confidence: hasStencilDep && hasStencilConf ? \"high\" : \"high\",\n reasons,\n };\n }\n\n // Check for Next.js with App Router\n const hasNext = hasNextDependency(changeSet.headPackageJson);\n const hasAppDir = isNextAppDir(cwd);\n\n if (hasNext && hasAppDir) {\n reasons.push(\"Found next in package.json dependencies\");\n reasons.push(\"Found app/ directory (Next.js App Router)\");\n return {\n profile: \"next\",\n confidence: \"high\",\n reasons,\n };\n }\n\n if (hasNext) {\n reasons.push(\"Found next in package.json dependencies\");\n return {\n profile: \"next\",\n confidence: \"medium\",\n reasons,\n };\n }\n\n // Check for React with React Router (only if not Next.js)\n const hasReact = hasReactDependency(changeSet.headPackageJson);\n const hasRouter = hasReactRouterDependency(changeSet.headPackageJson);\n\n if (hasReact && hasRouter) {\n reasons.push(\"Found react and react-dom in package.json dependencies\");\n reasons.push(\"Found react-router or react-router-dom in package.json dependencies\");\n return {\n profile: \"react\",\n confidence: \"high\",\n reasons,\n };\n }\n\n // Check for Vue/Nuxt\n const hasVue = hasVueDependency(changeSet.headPackageJson);\n const hasNuxt = hasNuxtDependency(changeSet.headPackageJson);\n const isNuxt = isNuxtProject(cwd);\n\n if (hasNuxt || (hasVue && isNuxt)) {\n if (hasNuxt) {\n reasons.push(\"Found nuxt in package.json dependencies\");\n }\n if (hasVue) {\n reasons.push(\"Found vue in package.json dependencies\");\n }\n if (isNuxt) {\n reasons.push(\"Found pages/ directory (Nuxt file-based routing)\");\n }\n return {\n profile: \"vue\",\n confidence: \"high\",\n reasons,\n };\n }\n\n if (hasVue) {\n reasons.push(\"Found vue in package.json dependencies\");\n return {\n profile: \"vue\",\n confidence: \"medium\",\n reasons,\n };\n }\n\n // Check for Astro\n const hasAstro = hasAstroDependency(changeSet.headPackageJson);\n const hasAstroConf = hasAstroConfig(cwd);\n\n if (hasAstro || hasAstroConf) {\n if (hasAstro) {\n reasons.push(\"Found astro in package.json dependencies\");\n }\n if (hasAstroConf) {\n reasons.push(\"Found astro.config.{mjs,ts,js}\");\n }\n return {\n profile: \"astro\",\n confidence: hasAstro && hasAstroConf ? \"high\" : \"medium\",\n reasons,\n };\n }\n\n // Check for Library project (should be last before default)\n const isLibrary = isLibraryProject(changeSet.headPackageJson);\n\n if (isLibrary) {\n if (changeSet.headPackageJson?.exports) {\n reasons.push(\"Found exports field in package.json\");\n }\n if (changeSet.headPackageJson?.publishConfig) {\n reasons.push(\"Found publishConfig in package.json\");\n }\n if (changeSet.headPackageJson?.bin) {\n reasons.push(\"Found bin field in package.json (CLI tool)\");\n }\n if (changeSet.headPackageJson?.private === false) {\n reasons.push(\"Package marked as public (private: false)\");\n }\n return {\n profile: \"library\",\n confidence: \"medium\",\n reasons,\n };\n }\n\n // Default profile\n reasons.push(\"No framework-specific markers detected, using default analyzers\");\n return {\n profile: \"auto\",\n confidence: \"medium\",\n reasons,\n };\n}\n\n/**\n * Detect the appropriate profile for a project.\n * @deprecated Use detectProfileWithReasons for more detailed information.\n */\nexport function detectProfile(\n changeSet: ChangeSet,\n cwd: string = process.cwd()\n): ProfileName {\n return detectProfileWithReasons(changeSet, cwd).profile;\n}\n\n/**\n * Get profile by name.\n */\nexport function getProfile(name: ProfileName): Profile {\n switch (name) {\n case \"sveltekit\":\n return sveltekitProfile;\n case \"react\":\n return reactProfile;\n case \"stencil\":\n return stencilProfile;\n case \"next\":\n return nextProfile;\n case \"vue\":\n return vueProfile;\n case \"astro\":\n return astroProfile;\n case \"library\":\n return libraryProfile;\n case \"auto\":\n return defaultProfile;\n default:\n return defaultProfile;\n }\n}\n\n/**\n * Resolve profile name (handle 'auto').\n */\nexport function resolveProfileName(\n name: ProfileName,\n changeSet: ChangeSet,\n cwd: string = process.cwd()\n): ProfileName {\n if (name === \"auto\") {\n return detectProfile(changeSet, cwd);\n }\n return name;\n}\n\nexport { defaultProfile, sveltekitProfile, reactProfile, stencilProfile, nextProfile, vueProfile, astroProfile, libraryProfile };\n\n",
|
|
51
|
-
"/**\n * Risk score computation.\n */\n\nimport type {\n ConventionViolationFinding,\n FileCategory,\n FileCategoryFinding,\n FileSummaryFinding,\n Finding,\n LargeDiffFinding,\n RiskLevel,\n RiskScore,\n RiskFactor,\n} from \"../core/types.js\";\n\n/**\n * Check if changes are only in low-risk categories.\n */\nfunction checkLowRiskOnlyChanges(\n findings: Finding[]\n): { isLowRisk: boolean; category: string | null } {\n const categoryFinding = findings.find(\n (f) => f.type === \"file-category\"\n ) as FileCategoryFinding | undefined;\n\n if (!categoryFinding) {\n return { isLowRisk: false, category: null };\n }\n\n const { categories } = categoryFinding;\n const highRiskCategories: FileCategory[] = [\n \"product\",\n \"infra\",\n \"ci\",\n \"dependencies\",\n ];\n\n // Check if any high-risk category has files\n const hasHighRiskChanges = highRiskCategories.some(\n (cat) => categories[cat].length > 0\n );\n\n if (hasHighRiskChanges) {\n return { isLowRisk: false, category: null };\n }\n\n // Determine which low-risk category dominates\n if (categories.docs.length > 0 && categories.tests.length === 0) {\n return { isLowRisk: true, category: \"docs\" };\n }\n if (categories.tests.length > 0 && categories.docs.length === 0) {\n return { isLowRisk: true, category: \"tests\" };\n }\n if (\n categories.config.length > 0 &&\n categories.docs.length === 0 &&\n categories.tests.length === 0\n ) {\n return { isLowRisk: true, category: \"config\" };\n }\n if (\n categories.docs.length > 0 ||\n categories.tests.length > 0 ||\n categories.config.length > 0\n ) {\n return { isLowRisk: true, category: \"docs/tests/config\" };\n }\n\n return { isLowRisk: false, category: null };\n}\n\n/**\n * Compute aggregate risk score from findings.\n */\nexport function computeRiskScore(findings: Finding[]): RiskScore {\n let score = 0;\n const evidenceBullets: string[] = [];\n const factors: RiskFactor[] = [];\n\n // Check for low-risk only changes first\n const { isLowRisk, category } = checkLowRiskOnlyChanges(findings);\n if (isLowRisk && category) {\n const reductions: Record<string, number> = {\n docs: -15,\n tests: -10,\n config: -5,\n \"docs/tests/config\": -10,\n };\n const weight = reductions[category] ?? 0;\n score += weight;\n evidenceBullets.push(\n `✅ Changes are only in ${category} (lower risk)`\n );\n factors.push({\n kind: \"low-risk-category\",\n weight,\n explanation: `Changes are only in ${category} (lower risk)`,\n evidence: [],\n });\n }\n\n for (const finding of findings) {\n switch (finding.type) {\n case \"risk-flag\":\n {\n const weight = finding.risk === \"high\" \n ? 40 \n : finding.risk === \"medium\" \n ? 20 \n : 5;\n score += weight;\n const emoji = finding.risk === \"high\" \n ? \"⚠️\" \n : finding.risk === \"medium\" \n ? \"⚡\" \n : \"ℹ️\";\n evidenceBullets.push(`${emoji} ${finding.evidenceText}`);\n factors.push({\n kind: `risk-${finding.risk}`,\n weight,\n explanation: finding.evidenceText,\n evidence: finding.evidence,\n });\n }\n break;\n\n case \"db-migration\":\n {\n const weight = finding.risk === \"high\" \n ? 30 \n : finding.risk === \"medium\" \n ? 15 \n : 0;\n if (weight > 0) {\n score += weight;\n const explanation = finding.risk === \"high\"\n ? `High-risk database migration: ${finding.reasons.join(\", \")}`\n : `Database migration detected: ${finding.files.join(\", \")}`;\n evidenceBullets.push(\n finding.risk === \"high\" ? `⚠️ ${explanation}` : `⚡ ${explanation}`\n );\n factors.push({\n kind: \"db-migration\",\n weight,\n explanation,\n evidence: finding.evidence,\n });\n }\n }\n break;\n\n case \"route-change\":\n if (finding.change === \"added\") {\n score += 5;\n factors.push({\n kind: \"route-added\",\n weight: 5,\n explanation: `Route added: ${finding.routeId}`,\n evidence: finding.evidence,\n });\n } else if (finding.change === \"deleted\") {\n score += 10;\n evidenceBullets.push(`ℹ️ Route deleted: ${finding.routeId}`);\n factors.push({\n kind: \"route-deleted\",\n weight: 10,\n explanation: `Route deleted: ${finding.routeId}`,\n evidence: finding.evidence,\n });\n }\n break;\n\n case \"dependency-change\":\n {\n let weight = 0;\n if (finding.impact === \"major\") {\n weight = 15;\n } else if (finding.impact === \"minor\") {\n weight = 5;\n }\n // Risky packages get additional points (already flagged via risk-flag)\n if (finding.riskCategory && finding.impact === \"new\") {\n weight += 10;\n }\n if (weight > 0) {\n score += weight;\n factors.push({\n kind: `dependency-${finding.impact}`,\n weight,\n explanation: `${finding.name}: ${finding.from ?? \"new\"} → ${finding.to ?? \"removed\"}`,\n evidence: finding.evidence,\n });\n }\n }\n break;\n\n case \"env-var\":\n if (finding.change === \"added\") {\n score += 5;\n evidenceBullets.push(`ℹ️ New env var: ${finding.name}`);\n factors.push({\n kind: \"env-var-added\",\n weight: 5,\n explanation: `New env var: ${finding.name}`,\n evidence: finding.evidence,\n });\n }\n break;\n\n case \"security-file\":\n // Additional points for security files (already adds risk-flag)\n score += 15;\n factors.push({\n kind: \"security-file\",\n weight: 15,\n explanation: `Security-sensitive files changed: ${finding.files.length} file(s)`,\n evidence: finding.evidence,\n });\n break;\n\n case \"convention-violation\":\n {\n const violationFinding = finding as ConventionViolationFinding;\n const fileCount = violationFinding.files.length;\n // Only add risk if significant number of files lack tests\n if (fileCount > 5) {\n const weight = 10;\n score += weight;\n evidenceBullets.push(`⚡ ${fileCount} source files lack test coverage`);\n factors.push({\n kind: \"test-coverage-gap\",\n weight,\n explanation: `${fileCount} source files lack test coverage`,\n evidence: violationFinding.evidence.slice(0, 3),\n });\n }\n }\n break;\n\n case \"large-diff\":\n {\n const largeDiffFinding = finding as LargeDiffFinding;\n const weight = largeDiffFinding.linesChanged > 1000 \n ? 15 \n : largeDiffFinding.linesChanged > 500 \n ? 10 \n : 5;\n score += weight;\n evidenceBullets.push(\n `ℹ️ Large diff: ${largeDiffFinding.filesChanged} files, ${largeDiffFinding.linesChanged} lines`\n );\n factors.push({\n kind: \"large-diff\",\n weight,\n explanation: `Large diff: ${largeDiffFinding.filesChanged} files, ${largeDiffFinding.linesChanged} lines`,\n evidence: largeDiffFinding.evidence,\n });\n }\n break;\n }\n }\n\n // Check for core module changes (types.ts, index.ts in core directories)\n const coreFilePatterns = [/\\/types\\.ts$/, /\\/core\\/.*\\.ts$/, /\\/index\\.ts$/];\n const fileSummary = findings.find(f => f.type === \"file-summary\") as FileSummaryFinding | undefined;\n if (fileSummary) {\n const coreFilesModified = fileSummary.modified.filter(file => \n coreFilePatterns.some(p => p.test(file))\n );\n if (coreFilesModified.length > 0) {\n const weight = 10;\n score += weight;\n evidenceBullets.push(`⚡ Core module files modified: ${coreFilesModified.join(\", \")}`);\n factors.push({\n kind: \"core-module-change\",\n weight,\n explanation: `Core module files modified (types.ts, index.ts): ${coreFilesModified.length} file(s)`,\n evidence: [],\n });\n }\n }\n\n // Ensure score stays within bounds\n score = Math.max(0, Math.min(score, 100));\n\n // Determine level\n let level: RiskLevel;\n if (score >= 50) {\n level = \"high\";\n } else if (score >= 20) {\n level = \"medium\";\n } else {\n level = \"low\";\n }\n\n return { score, level, factors, evidenceBullets };\n}\n",
|
|
52
|
-
"/**\n * branch-narrator library exports.\n *\n * This module exports the core types and functions for programmatic use.\n */\n\n// Core types and utilities\nexport * from \"./core/types.js\";\nexport * from \"./core/change-set.js\";\nexport * from \"./core/errors.js\";\n\n// Export logger and sorting explicitly to avoid conflicts\nexport {\n configureLogger,\n getLoggerState,\n resetLogger,\n warn,\n info,\n debug,\n error,\n} from \"./core/logger.js\";\n\nexport {\n normalizePath,\n comparePaths,\n sortRiskFlags,\n sortFindings,\n sortEvidence,\n sortRiskFlagEvidence,\n sortFilePaths,\n createSortedObject,\n} from \"./core/sorting.js\";\n\n// Git utilities\nexport { collectChangeSet, isGitRepo, refExists } from \"./git/collector.js\";\nexport * from \"./git/parser.js\";\n\n// Analyzers\nexport * from \"./analyzers/index.js\";\n\n// Profiles\nexport {\n detectProfile,\n detectProfileWithReasons,\n getProfile,\n hasSvelteKitDependency,\n isSvelteKitProject,\n resolveProfileName,\n sveltekitProfile,\n} from \"./profiles/index.js\";\nexport type { ProfileDetectionResult } from \"./profiles/index.js\";\n\n// Renderers\nexport { renderMarkdown } from \"./render/markdown.js\";\nexport { renderJson } from \"./render/json.js\";\nexport { computeRiskScore } from \"./render/risk-score.js\";\n\n",
|
|
53
|
-
"/**\n * Global logger module for CLI diagnostics and warnings.\n * \n * Ensures clean stdout/stderr separation:\n * - All diagnostic output goes to stderr\n * - Honors --quiet and --debug flags\n * - No output pollution in JSON mode\n */\n\n/**\n * Logger state.\n */\ninterface LoggerState {\n quiet: boolean;\n debug: boolean;\n}\n\nconst state: LoggerState = {\n quiet: false,\n debug: false,\n};\n\n/**\n * Configure logger with global flags.\n */\nexport function configureLogger(options: { quiet?: boolean; debug?: boolean }): void {\n // --quiet overrides --debug\n if (options.quiet) {\n state.quiet = true;\n state.debug = false;\n } else {\n state.quiet = false;\n state.debug = options.debug ?? false;\n }\n}\n\n/**\n * Get current logger configuration.\n */\nexport function getLoggerState(): Readonly<LoggerState> {\n return { ...state };\n}\n\n/**\n * Reset logger to default state (for testing).\n */\nexport function resetLogger(): void {\n state.quiet = false;\n state.debug = false;\n}\n\n/**\n * Log a warning message to stderr.\n * Suppressed by --quiet.\n */\nexport function warn(message: string): void {\n if (!state.quiet) {\n console.error(message);\n }\n}\n\n/**\n * Log an info message to stderr.\n * Suppressed by --quiet.\n */\nexport function info(message: string): void {\n if (!state.quiet) {\n console.error(message);\n }\n}\n\n/**\n * Log a debug message to stderr.\n * Only shown when --debug is enabled.\n * Suppressed by --quiet.\n */\nexport function debug(message: string): void {\n if (!state.quiet && state.debug) {\n console.error(`[DEBUG] ${message}`);\n }\n}\n\n/**\n * Log an error message to stderr.\n * Never suppressed (even with --quiet).\n */\nexport function error(message: string): void {\n console.error(message);\n}\n",
|
|
54
|
-
"/**\n * Markdown PR body renderer.\n */\n\nimport type {\n APIContractChangeFinding,\n CIWorkflowFinding,\n CloudflareChangeFinding,\n ConventionViolationFinding,\n DbMigrationFinding,\n DependencyChangeFinding,\n EnvVarFinding,\n FileCategoryFinding,\n FileSummaryFinding,\n Finding,\n GraphQLChangeFinding,\n ImpactAnalysisFinding,\n InfraChangeFinding,\n LargeDiffFinding,\n LockfileFinding,\n MonorepoConfigFinding,\n PackageExportsFinding,\n RenderContext,\n RouteChangeFinding,\n SecurityFileFinding,\n SQLRiskFinding,\n StencilComponentChangeFinding,\n StencilEventChangeFinding,\n StencilMethodChangeFinding,\n StencilPropChangeFinding,\n StencilSlotChangeFinding,\n TailwindConfigFinding,\n TestChangeFinding,\n TestGapFinding,\n TestParityViolationFinding,\n TypeScriptConfigFinding,\n} from \"../core/types.js\";\nimport { routeIdToUrlPath } from \"../analyzers/route-detector.js\";\nimport { getCategoryLabel } from \"../analyzers/file-category.js\";\n\n/**\n * Group findings by type.\n */\nfunction groupFindings(findings: Finding[]): Map<string, Finding[]> {\n const groups = new Map<string, Finding[]>();\n for (const finding of findings) {\n if (!groups.has(finding.type)) {\n groups.set(finding.type, []);\n }\n groups.get(finding.type)!.push(finding);\n }\n return groups;\n}\n\n/**\n * Render the Context section (interactive mode only).\n */\nfunction renderContext(context: RenderContext): string {\n if (!context.interactive?.context) {\n return \"\";\n }\n return `## Context\\n\\n${context.interactive.context}\\n\\n`;\n}\n\n/**\n * Render the Summary section.\n */\nfunction renderSummary(groups: Map<string, Finding[]>): string {\n const bullets: string[] = [];\n\n const fileSummary = groups.get(\"file-summary\")?.[0] as\n | FileSummaryFinding\n | undefined;\n if (fileSummary) {\n const total =\n fileSummary.added.length +\n fileSummary.modified.length +\n fileSummary.deleted.length +\n fileSummary.renamed.length;\n bullets.push(`${total} file(s) changed`);\n\n if (fileSummary.added.length > 0) {\n bullets.push(`${fileSummary.added.length} file(s) added`);\n }\n if (fileSummary.deleted.length > 0) {\n bullets.push(`${fileSummary.deleted.length} file(s) deleted`);\n }\n }\n\n const routeChanges = groups.get(\"route-change\") as\n | RouteChangeFinding[]\n | undefined;\n if (routeChanges && routeChanges.length > 0) {\n const newRoutes = routeChanges.filter((r) => r.change === \"added\");\n if (newRoutes.length > 0) {\n bullets.push(`${newRoutes.length} new route(s)`);\n }\n }\n\n const migrations = groups.get(\"db-migration\") as\n | DbMigrationFinding[]\n | undefined;\n if (migrations && migrations.length > 0) {\n bullets.push(`Database migrations detected`);\n }\n\n const deps = groups.get(\"dependency-change\") as\n | DependencyChangeFinding[]\n | undefined;\n if (deps && deps.length > 0) {\n const majorBumps = deps.filter((d) => d.impact === \"major\");\n if (majorBumps.length > 0) {\n bullets.push(`${majorBumps.length} major dependency update(s)`);\n }\n }\n\n const securityFiles = groups.get(\"security-file\") as\n | SecurityFileFinding[]\n | undefined;\n if (securityFiles && securityFiles.length > 0) {\n const totalFiles = securityFiles.reduce(\n (acc, sf) => acc + sf.files.length,\n 0\n );\n bullets.push(`${totalFiles} security-sensitive file(s) changed`);\n }\n\n // GraphQL breaking changes\n const graphqlChanges = groups.get(\"graphql-change\") as\n | GraphQLChangeFinding[]\n | undefined;\n if (graphqlChanges && graphqlChanges.length > 0) {\n const breakingCount = graphqlChanges.filter((g) => g.isBreaking).length;\n if (breakingCount > 0) {\n bullets.push(`${breakingCount} GraphQL breaking change(s)`);\n }\n }\n\n // CI workflow risks\n const ciWorkflows = groups.get(\"ci-workflow\") as\n | CIWorkflowFinding[]\n | undefined;\n if (ciWorkflows && ciWorkflows.length > 0) {\n bullets.push(`${ciWorkflows.length} CI workflow change(s) detected`);\n }\n\n // Stencil component changes\n const stencilComponents = groups.get(\"stencil-component-change\") as\n | StencilComponentChangeFinding[]\n | undefined;\n if (stencilComponents && stencilComponents.length > 0) {\n bullets.push(`${stencilComponents.length} component API change(s)`);\n }\n\n // Package exports breaking changes\n const packageExports = groups.get(\"package-exports\") as\n | PackageExportsFinding[]\n | undefined;\n if (packageExports && packageExports.length > 0) {\n const breakingExports = packageExports.filter((p) => p.isBreaking);\n if (breakingExports.length > 0) {\n bullets.push(`Package API breaking changes detected`);\n }\n }\n\n if (bullets.length === 0) {\n bullets.push(\"Minor changes detected\");\n }\n\n // Limit to 6 bullets\n const limitedBullets = bullets.slice(0, 6);\n\n return (\n `## Summary\\n\\n` +\n limitedBullets.map((b) => `- ${b}`).join(\"\\n\") +\n \"\\n\\n\"\n );\n}\n\n/**\n * Render What Changed section (grouped by category).\n */\nfunction renderWhatChanged(\n categoryFinding: FileCategoryFinding | undefined,\n fileSummary: FileSummaryFinding | undefined\n): string {\n if (!categoryFinding || !fileSummary) {\n return \"\";\n }\n\n const { categories, summary } = categoryFinding;\n\n // Skip if no meaningful categorization\n if (summary.length <= 1) {\n return \"\";\n }\n\n let output = \"## What Changed\\n\\n\";\n\n // Order categories by count (descending)\n const orderedCategories = summary\n .filter((s) => s.count > 0)\n .sort((a, b) => b.count - a.count);\n\n for (const { category, count } of orderedCategories) {\n const label = getCategoryLabel(category);\n const files = categories[category];\n\n output += `### ${label} (${count})\\n\\n`;\n\n // Show up to 10 files per category\n const displayFiles = files.slice(0, 10);\n for (const file of displayFiles) {\n // Determine if added, modified, or deleted\n let status = \"\";\n if (fileSummary.added.includes(file)) {\n status = \" *(new)*\";\n } else if (fileSummary.deleted.includes(file)) {\n status = \" *(deleted)*\";\n }\n output += `- \\`${file}\\`${status}\\n`;\n }\n\n if (files.length > 10) {\n output += `- *...and ${files.length - 10} more*\\n`;\n }\n\n output += \"\\n\";\n }\n\n return output;\n}\n\n/**\n * Render Routes / API section.\n */\nfunction renderRoutes(routes: RouteChangeFinding[]): string {\n if (routes.length === 0) {\n return \"\";\n }\n\n let output = \"## Routes / API\\n\\n\";\n output += \"| Route | Type | Change | Methods |\\n\";\n output += \"|-------|------|--------|--------|\\n\";\n\n for (const route of routes) {\n const urlPath = routeIdToUrlPath(route.routeId);\n const methods = route.methods?.join(\", \") || \"-\";\n output += `| \\`${urlPath}\\` | ${route.routeType} | ${route.change} | ${methods} |\\n`;\n }\n\n return output + \"\\n\";\n}\n\n/**\n * Render API Contract changes.\n */\nfunction renderAPIContracts(contracts: APIContractChangeFinding[]): string {\n if (contracts.length === 0) {\n return \"\";\n }\n\n let output = \"## API Contracts\\n\\n\";\n output += \"The following API specification files have changed:\\n\\n\";\n\n for (const contract of contracts) {\n for (const file of contract.files) {\n output += `- \\`${file}\\`\\n`;\n }\n }\n output += \"\\n\";\n\n return output;\n}\n\n/**\n * Render Database (Supabase) section.\n */\nfunction renderDatabase(migrations: DbMigrationFinding[]): string {\n if (migrations.length === 0) {\n return \"\";\n }\n\n let output = \"## Database (Supabase)\\n\\n\";\n\n for (const migration of migrations) {\n const riskEmoji =\n migration.risk === \"high\"\n ? \"🔴\"\n : migration.risk === \"medium\"\n ? \"🟡\"\n : \"🟢\";\n output += `**Risk Level:** ${riskEmoji} ${migration.risk.toUpperCase()}\\n\\n`;\n output += \"**Files:**\\n\";\n for (const file of migration.files) {\n output += `- \\`${file}\\`\\n`;\n }\n output += \"\\n\";\n\n if (migration.reasons.length > 0) {\n output += \"**Detected patterns:**\\n\";\n for (const reason of migration.reasons) {\n output += `- ${reason}\\n`;\n }\n output += \"\\n\";\n }\n }\n\n return output;\n}\n\n/**\n * Render Config / Env section.\n */\nfunction renderEnvVars(envVars: EnvVarFinding[]): string {\n if (envVars.length === 0) {\n return \"\";\n }\n\n let output = \"## Config / Env\\n\\n\";\n output += \"| Variable | Status | Evidence |\\n\";\n output += \"|----------|--------|----------|\\n\";\n\n for (const envVar of envVars) {\n const files = envVar.evidenceFiles.slice(0, 2).join(\", \");\n output += `| \\`${envVar.name}\\` | ${envVar.change} | ${files} |\\n`;\n }\n\n return output + \"\\n\";\n}\n\n/**\n * Render Cloudflare section.\n */\nfunction renderCloudflare(changes: CloudflareChangeFinding[]): string {\n if (changes.length === 0) {\n return \"\";\n }\n\n let output = \"## Cloudflare\\n\\n\";\n\n for (const change of changes) {\n output += `**Area:** ${change.area}\\n`;\n output += \"**Files:**\\n\";\n for (const file of change.files) {\n output += `- \\`${file}\\`\\n`;\n }\n output += \"\\n\";\n }\n\n return output;\n}\n\n/**\n * Render Dependencies section.\n */\nfunction renderDependencies(deps: DependencyChangeFinding[]): string {\n if (deps.length === 0) {\n return \"\";\n }\n\n const prodDeps = deps.filter((d) => d.section === \"dependencies\");\n const devDeps = deps.filter((d) => d.section === \"devDependencies\");\n\n let output = \"## Dependencies\\n\\n\";\n\n if (prodDeps.length > 0) {\n output += \"### Production\\n\\n\";\n output += \"| Package | From | To | Impact |\\n\";\n output += \"|---------|------|-----|--------|\\n\";\n for (const dep of prodDeps) {\n output += `| \\`${dep.name}\\` | ${dep.from ?? \"-\"} | ${dep.to ?? \"-\"} | ${dep.impact ?? \"-\"} |\\n`;\n }\n output += \"\\n\";\n }\n\n if (devDeps.length > 0) {\n output += \"### Dev Dependencies\\n\\n\";\n output += \"| Package | From | To | Impact |\\n\";\n output += \"|---------|------|-----|--------|\\n\";\n for (const dep of devDeps) {\n output += `| \\`${dep.name}\\` | ${dep.from ?? \"-\"} | ${dep.to ?? \"-\"} | ${dep.impact ?? \"-\"} |\\n`;\n }\n output += \"\\n\";\n }\n\n return output;\n}\n\n/**\n * Render GraphQL Schema section.\n */\nfunction renderGraphQL(changes: GraphQLChangeFinding[]): string {\n if (changes.length === 0) {\n return \"\";\n }\n\n let output = \"## GraphQL Schema\\n\\n\";\n\n // Check for breaking changes\n const breakingChanges = changes.filter((c) => c.isBreaking);\n if (breakingChanges.length > 0) {\n output += \"### 🔴 Breaking Changes\\n\\n\";\n for (const change of breakingChanges) {\n output += `**File:** \\`${change.file}\\`\\n`;\n if (change.breakingChanges.length > 0) {\n for (const bc of change.breakingChanges) {\n output += `- ${bc}\\n`;\n }\n }\n output += \"\\n\";\n }\n }\n\n // Show added elements\n const withAdditions = changes.filter((c) => c.addedElements.length > 0);\n if (withAdditions.length > 0) {\n output += \"### Added Elements\\n\\n\";\n for (const change of withAdditions) {\n output += `**File:** \\`${change.file}\\`\\n`;\n for (const elem of change.addedElements.slice(0, 10)) {\n output += `- ${elem}\\n`;\n }\n if (change.addedElements.length > 10) {\n output += `- ...and ${change.addedElements.length - 10} more\\n`;\n }\n output += \"\\n\";\n }\n }\n\n // Summary table for all changes\n output += \"### All Schema Changes\\n\\n\";\n output += \"| File | Status | Breaking |\\n\";\n output += \"|------|--------|----------|\\n\";\n for (const change of changes) {\n const breakingEmoji = change.isBreaking ? \"🔴 Yes\" : \"🟢 No\";\n output += `| \\`${change.file}\\` | ${change.status} | ${breakingEmoji} |\\n`;\n }\n output += \"\\n\";\n\n return output;\n}\n\n/**\n * Render TypeScript Config section.\n */\nfunction renderTypeScriptConfig(configs: TypeScriptConfigFinding[]): string {\n if (configs.length === 0) {\n return \"\";\n }\n\n let output = \"### TypeScript Configuration\\n\\n\";\n\n for (const config of configs) {\n const breakingEmoji = config.isBreaking ? \"🔴\" : \"🟢\";\n output += `**File:** \\`${config.file}\\` ${breakingEmoji}\\n\\n`;\n\n // Strictness changes\n if (config.strictnessChanges.length > 0) {\n output += \"**Strictness Changes:**\\n\";\n for (const change of config.strictnessChanges) {\n output += `- ${change}\\n`;\n }\n output += \"\\n\";\n }\n\n // Changed options\n const { added, removed, modified } = config.changedOptions;\n if (added.length > 0) {\n output += `**Added:** ${added.map((o) => `\\`${o}\\``).join(\", \")}\\n`;\n }\n if (removed.length > 0) {\n output += `**Removed:** ${removed.map((o) => `\\`${o}\\``).join(\", \")}\\n`;\n }\n if (modified.length > 0) {\n output += `**Modified:** ${modified.map((o) => `\\`${o}\\``).join(\", \")}\\n`;\n }\n output += \"\\n\";\n }\n\n return output;\n}\n\n/**\n * Render Tailwind Config section.\n */\nfunction renderTailwindConfig(configs: TailwindConfigFinding[]): string {\n if (configs.length === 0) {\n return \"\";\n }\n\n let output = \"### Tailwind Configuration\\n\\n\";\n\n for (const config of configs) {\n const breakingEmoji = config.isBreaking ? \"🔴\" : \"🟢\";\n output += `**File:** \\`${config.file}\\` (${config.configType}) ${breakingEmoji}\\n\\n`;\n\n if (config.affectedSections.length > 0) {\n output += \"**Affected Sections:**\\n\";\n for (const section of config.affectedSections) {\n output += `- ${section}\\n`;\n }\n output += \"\\n\";\n }\n\n if (config.isBreaking && config.breakingReasons.length > 0) {\n output += \"**Breaking Changes:**\\n\";\n for (const reason of config.breakingReasons) {\n output += `- ${reason}\\n`;\n }\n output += \"\\n\";\n }\n }\n\n return output;\n}\n\n/**\n * Render Monorepo Config section.\n */\nfunction renderMonorepoConfig(configs: MonorepoConfigFinding[]): string {\n if (configs.length === 0) {\n return \"\";\n }\n\n let output = \"### Monorepo Configuration\\n\\n\";\n\n for (const config of configs) {\n output += `**Tool:** ${config.tool}\\n`;\n output += `**File:** \\`${config.file}\\`\\n\\n`;\n\n if (config.affectedFields.length > 0) {\n output += \"**Changed Fields:**\\n\";\n for (const field of config.affectedFields) {\n output += `- ${field}\\n`;\n }\n output += \"\\n\";\n }\n\n if (config.impacts.length > 0) {\n output += \"**Impacts:**\\n\";\n for (const impact of config.impacts) {\n output += `- ${impact}\\n`;\n }\n output += \"\\n\";\n }\n }\n\n return output;\n}\n\n/**\n * Render combined Configuration section.\n */\nfunction renderConfiguration(\n tsConfigs: TypeScriptConfigFinding[],\n tailwindConfigs: TailwindConfigFinding[],\n monorepoConfigs: MonorepoConfigFinding[]\n): string {\n const hasTsConfig = tsConfigs.length > 0;\n const hasTailwind = tailwindConfigs.length > 0;\n const hasMonorepo = monorepoConfigs.length > 0;\n\n if (!hasTsConfig && !hasTailwind && !hasMonorepo) {\n return \"\";\n }\n\n let output = \"## Configuration Changes\\n\\n\";\n\n if (hasTsConfig) {\n output += renderTypeScriptConfig(tsConfigs);\n }\n if (hasTailwind) {\n output += renderTailwindConfig(tailwindConfigs);\n }\n if (hasMonorepo) {\n output += renderMonorepoConfig(monorepoConfigs);\n }\n\n return output;\n}\n\n/**\n * Render Package Exports / API section.\n */\nfunction renderPackageExports(exports: PackageExportsFinding[]): string {\n if (exports.length === 0) {\n return \"\";\n }\n\n let output = \"## Package API\\n\\n\";\n\n for (const exp of exports) {\n const breakingEmoji = exp.isBreaking ? \"🔴 Breaking\" : \"🟢 Non-breaking\";\n output += `**Status:** ${breakingEmoji}\\n\\n`;\n\n // Removed exports (breaking)\n if (exp.removedExports.length > 0) {\n output += \"### Removed Exports\\n\\n\";\n for (const removed of exp.removedExports) {\n output += `- 🔴 \\`${removed}\\`\\n`;\n }\n output += \"\\n\";\n }\n\n // Added exports\n if (exp.addedExports.length > 0) {\n output += \"### Added Exports\\n\\n\";\n for (const added of exp.addedExports) {\n output += `- 🟢 \\`${added}\\`\\n`;\n }\n output += \"\\n\";\n }\n\n // Legacy field changes\n if (exp.legacyFieldChanges.length > 0) {\n output += \"### Entry Point Changes\\n\\n\";\n output += \"| Field | From | To |\\n\";\n output += \"|-------|------|----|\\n\";\n for (const change of exp.legacyFieldChanges) {\n output += `| \\`${change.field}\\` | ${change.from ?? \"-\"} | ${change.to ?? \"-\"} |\\n`;\n }\n output += \"\\n\";\n }\n\n // Bin changes\n if (exp.binChanges.added.length > 0 || exp.binChanges.removed.length > 0) {\n output += \"### Binary Commands\\n\\n\";\n if (exp.binChanges.added.length > 0) {\n output += `**Added:** ${exp.binChanges.added.map((b) => `\\`${b}\\``).join(\", \")}\\n`;\n }\n if (exp.binChanges.removed.length > 0) {\n output += `**Removed:** ${exp.binChanges.removed.map((b) => `\\`${b}\\``).join(\", \")}\\n`;\n }\n output += \"\\n\";\n }\n }\n\n return output;\n}\n\n/**\n * Render Stencil Component API changes.\n */\nfunction renderStencilChanges(groups: Map<string, Finding[]>): string {\n const componentChanges =\n (groups.get(\"stencil-component-change\") as StencilComponentChangeFinding[]) ?? [];\n const propChanges =\n (groups.get(\"stencil-prop-change\") as StencilPropChangeFinding[]) ?? [];\n const eventChanges =\n (groups.get(\"stencil-event-change\") as StencilEventChangeFinding[]) ?? [];\n const methodChanges =\n (groups.get(\"stencil-method-change\") as StencilMethodChangeFinding[]) ?? [];\n const slotChanges =\n (groups.get(\"stencil-slot-change\") as StencilSlotChangeFinding[]) ?? [];\n\n const hasChanges =\n componentChanges.length > 0 ||\n propChanges.length > 0 ||\n eventChanges.length > 0 ||\n methodChanges.length > 0 ||\n slotChanges.length > 0;\n\n if (!hasChanges) {\n return \"\";\n }\n\n let output = \"## Component API (Stencil)\\n\\n\";\n\n // Group all changes by component tag\n const byTag = new Map<string, {\n component?: StencilComponentChangeFinding;\n props: StencilPropChangeFinding[];\n events: StencilEventChangeFinding[];\n methods: StencilMethodChangeFinding[];\n slots: StencilSlotChangeFinding[];\n }>();\n\n // Initialize groups for all tags\n const initTag = (tag: string) => {\n if (!byTag.has(tag)) {\n byTag.set(tag, { props: [], events: [], methods: [], slots: [] });\n }\n };\n\n for (const c of componentChanges) {\n initTag(c.tag);\n byTag.get(c.tag)!.component = c;\n }\n for (const p of propChanges) {\n initTag(p.tag);\n byTag.get(p.tag)!.props.push(p);\n }\n for (const e of eventChanges) {\n initTag(e.tag);\n byTag.get(e.tag)!.events.push(e);\n }\n for (const m of methodChanges) {\n initTag(m.tag);\n byTag.get(m.tag)!.methods.push(m);\n }\n for (const s of slotChanges) {\n initTag(s.tag);\n byTag.get(s.tag)!.slots.push(s);\n }\n\n // Render each component\n for (const [tag, changes] of byTag) {\n output += `### \\`<${tag}>\\`\\n\\n`;\n\n // Component-level changes\n if (changes.component) {\n const c = changes.component;\n const changeEmoji = c.change === \"removed\" ? \"🔴\" : c.change === \"added\" ? \"🟢\" : \"🟡\";\n output += `**Component:** ${changeEmoji} ${c.change}`;\n if (c.change === \"tag-changed\") {\n output += ` (${c.fromTag} → ${c.toTag})`;\n }\n if (c.change === \"shadow-changed\") {\n output += ` (shadow: ${c.fromShadow} → ${c.toShadow})`;\n }\n output += `\\n`;\n output += `**File:** \\`${c.file}\\`\\n\\n`;\n }\n\n // Props\n if (changes.props.length > 0) {\n output += \"**Props:**\\n\";\n for (const p of changes.props) {\n const emoji = p.change === \"removed\" ? \"🔴\" : p.change === \"added\" ? \"🟢\" : \"🟡\";\n let detail = \"\";\n if (p.details?.typeText) {\n detail = `: ${p.details.typeText}`;\n }\n output += `- ${emoji} \\`${p.propName}\\`${detail} (${p.change})\\n`;\n }\n output += \"\\n\";\n }\n\n // Events\n if (changes.events.length > 0) {\n output += \"**Events:**\\n\";\n for (const e of changes.events) {\n const emoji = e.change === \"removed\" ? \"🔴\" : e.change === \"added\" ? \"🟢\" : \"🟡\";\n output += `- ${emoji} \\`${e.eventName}\\` (${e.change})\\n`;\n }\n output += \"\\n\";\n }\n\n // Methods\n if (changes.methods.length > 0) {\n output += \"**Methods:**\\n\";\n for (const m of changes.methods) {\n const emoji = m.change === \"removed\" ? \"🔴\" : m.change === \"added\" ? \"🟢\" : \"🟡\";\n const sig = m.signature ? `: ${m.signature}` : \"\";\n output += `- ${emoji} \\`${m.methodName}\\`${sig} (${m.change})\\n`;\n }\n output += \"\\n\";\n }\n\n // Slots\n if (changes.slots.length > 0) {\n output += \"**Slots:**\\n\";\n for (const s of changes.slots) {\n const emoji = s.change === \"removed\" ? \"🔴\" : \"🟢\";\n const slotName = s.slotName === \"default\" ? \"(default)\" : `\"${s.slotName}\"`;\n output += `- ${emoji} ${slotName} (${s.change})\\n`;\n }\n output += \"\\n\";\n }\n }\n\n return output;\n}\n\n/**\n * Render CI Workflow findings.\n */\nfunction renderCIWorkflow(findings: CIWorkflowFinding[]): string {\n if (findings.length === 0) {\n return \"\";\n }\n\n let output = \"### CI Workflows\\n\\n\";\n\n for (const finding of findings) {\n const riskEmoji =\n finding.riskType === \"permissions_broadened\" ||\n finding.riskType === \"pull_request_target\" ||\n finding.riskType === \"remote_script_download\"\n ? \"🔴\"\n : \"🟡\";\n\n const riskLabel = finding.riskType.replace(/_/g, \" \");\n output += `${riskEmoji} **${riskLabel}**\\n`;\n output += `- File: \\`${finding.file}\\`\\n`;\n output += `- ${finding.details}\\n\\n`;\n }\n\n return output;\n}\n\n/**\n * Render SQL Risk findings.\n */\nfunction renderSQLRisk(findings: SQLRiskFinding[]): string {\n if (findings.length === 0) {\n return \"\";\n }\n\n let output = \"## SQL Risk\\n\\n\";\n\n for (const finding of findings) {\n const riskEmoji =\n finding.riskType === \"destructive\"\n ? \"🔴\"\n : finding.riskType === \"unscoped_modification\"\n ? \"🔴\"\n : \"🟡\";\n\n const riskLabel = finding.riskType.replace(/_/g, \" \");\n output += `${riskEmoji} **${riskLabel}**\\n`;\n output += `- File: \\`${finding.file}\\`\\n`;\n output += `- ${finding.details}\\n\\n`;\n }\n\n return output;\n}\n\n/**\n * Render Infrastructure changes.\n */\nfunction renderInfraChanges(findings: InfraChangeFinding[]): string {\n if (findings.length === 0) {\n return \"\";\n }\n\n let output = \"### Infrastructure\\n\\n\";\n\n // Group by infra type\n const byType = new Map<string, InfraChangeFinding[]>();\n for (const finding of findings) {\n if (!byType.has(finding.infraType)) {\n byType.set(finding.infraType, []);\n }\n byType.get(finding.infraType)!.push(finding);\n }\n\n for (const [infraType, typeFindings] of byType) {\n const label =\n infraType === \"dockerfile\"\n ? \"Docker\"\n : infraType === \"terraform\"\n ? \"Terraform\"\n : infraType === \"k8s\"\n ? \"Kubernetes\"\n : infraType;\n\n output += `**${label}:**\\n`;\n const allFiles = typeFindings.flatMap((f) => f.files);\n for (const file of allFiles) {\n output += `- \\`${file}\\`\\n`;\n }\n output += \"\\n\";\n }\n\n return output;\n}\n\n/**\n * Render combined CI / Infrastructure section.\n */\nfunction renderCIInfrastructure(\n ciFindings: CIWorkflowFinding[],\n infraFindings: InfraChangeFinding[]\n): string {\n if (ciFindings.length === 0 && infraFindings.length === 0) {\n return \"\";\n }\n\n let output = \"## CI / Infrastructure\\n\\n\";\n output += renderCIWorkflow(ciFindings);\n output += renderInfraChanges(infraFindings);\n\n return output;\n}\n\n/**\n * Render Warnings section (large-diff, lockfile-mismatch, test-gap).\n */\nfunction renderWarnings(groups: Map<string, Finding[]>): string {\n const largeDiff =\n (groups.get(\"large-diff\") as LargeDiffFinding[]) ?? [];\n const lockfileMismatch =\n (groups.get(\"lockfile-mismatch\") as LockfileFinding[]) ?? [];\n const testGap =\n (groups.get(\"test-gap\") as TestGapFinding[]) ?? [];\n\n const hasWarnings =\n largeDiff.length > 0 || lockfileMismatch.length > 0 || testGap.length > 0;\n\n if (!hasWarnings) {\n return \"\";\n }\n\n let output = \"## ⚠️ Warnings\\n\\n\";\n\n // Large diff warning\n for (const ld of largeDiff) {\n output += `- **Large diff detected:** ${ld.filesChanged} files changed, ${ld.linesChanged} lines modified\\n`;\n }\n\n // Lockfile mismatch warning\n for (const lm of lockfileMismatch) {\n if (lm.manifestChanged && !lm.lockfileChanged) {\n output += `- **Lockfile mismatch:** package.json changed but lockfile not updated\\n`;\n } else if (!lm.manifestChanged && lm.lockfileChanged) {\n output += `- **Lockfile mismatch:** lockfile changed but package.json not updated\\n`;\n }\n }\n\n // Test gap warning\n for (const tg of testGap) {\n output += `- **Test coverage gap:** ${tg.prodFilesChanged} production files changed, only ${tg.testFilesChanged} test files changed\\n`;\n }\n\n output += \"\\n\";\n return output;\n}\n\n/**\n * Render Suggested test plan section.\n */\nfunction renderTestPlan(\n context: RenderContext,\n groups: Map<string, Finding[]>\n): string {\n const bullets: string[] = [];\n\n // Check if vitest tests exist\n const testChanges = groups.get(\"test-change\") as\n | TestChangeFinding[]\n | undefined;\n if (testChanges && testChanges.length > 0) {\n bullets.push(\"`bun test` - Run test suite\");\n }\n\n // SvelteKit check\n if (context.profile === \"sveltekit\") {\n bullets.push(\"`bun run check` - Run SvelteKit type check\");\n }\n\n // Route exercise suggestions\n const routes = groups.get(\"route-change\") as RouteChangeFinding[] | undefined;\n if (routes) {\n const endpoints = routes.filter((r) => r.routeType === \"endpoint\");\n for (const endpoint of endpoints.slice(0, 3)) {\n const urlPath = routeIdToUrlPath(endpoint.routeId);\n const methods = endpoint.methods?.join(\"/\") || \"GET\";\n bullets.push(`Test \\`${methods} ${urlPath}\\` endpoint`);\n }\n\n const pages = routes.filter(\n (r) => r.routeType === \"page\" && r.change !== \"deleted\"\n );\n for (const page of pages.slice(0, 3)) {\n const urlPath = routeIdToUrlPath(page.routeId);\n bullets.push(`Verify \\`${urlPath}\\` page renders correctly`);\n }\n }\n\n // Interactive test notes\n if (context.interactive?.testNotes) {\n bullets.push(context.interactive.testNotes);\n }\n\n if (bullets.length === 0) {\n bullets.push(\"No specific test suggestions\");\n }\n\n let output = \"## Suggested Test Plan\\n\\n\";\n output += bullets.map((b) => `- [ ] ${b}`).join(\"\\n\") + \"\\n\\n\";\n\n return output;\n}\n\n/**\n * Render Risks / Notes section.\n */\nfunction renderRisks(context: RenderContext): string {\n const { riskScore } = context;\n\n const levelEmoji =\n riskScore.level === \"high\"\n ? \"🔴\"\n : riskScore.level === \"medium\"\n ? \"🟡\"\n : \"🟢\";\n\n let output = \"## Risks / Notes\\n\\n\";\n output += `**Overall Risk:** ${levelEmoji} ${riskScore.level.toUpperCase()} (score: ${riskScore.score}/100)\\n\\n`;\n\n const bullets = riskScore.evidenceBullets ?? [];\n if (bullets.length > 0) {\n for (const bullet of bullets) {\n output += `- ${bullet}\\n`;\n }\n output += \"\\n\";\n }\n\n return output;\n}\n\n/**\n * Render findings into a Markdown PR body.\n */\nexport function renderMarkdown(context: RenderContext): string {\n const groups = groupFindings(context.findings);\n\n let output = \"\";\n\n // Context (interactive only)\n output += renderContext(context);\n\n // Summary\n output += renderSummary(groups);\n\n // What Changed (grouped by category)\n const categoryFinding = groups.get(\"file-category\")?.[0] as\n | FileCategoryFinding\n | undefined;\n const fileSummary = groups.get(\"file-summary\")?.[0] as\n | FileSummaryFinding\n | undefined;\n output += renderWhatChanged(categoryFinding, fileSummary);\n\n // Routes / API\n const routes = (groups.get(\"route-change\") as RouteChangeFinding[]) ?? [];\n output += renderRoutes(routes);\n\n // API Contracts\n const apiContracts =\n (groups.get(\"api-contract-change\") as APIContractChangeFinding[]) ?? [];\n output += renderAPIContracts(apiContracts);\n\n // GraphQL Schema\n const graphqlChanges =\n (groups.get(\"graphql-change\") as GraphQLChangeFinding[]) ?? [];\n output += renderGraphQL(graphqlChanges);\n\n // Database (Supabase)\n const migrations =\n (groups.get(\"db-migration\") as DbMigrationFinding[]) ?? [];\n output += renderDatabase(migrations);\n\n // SQL Risk\n const sqlRisks = (groups.get(\"sql-risk\") as SQLRiskFinding[]) ?? [];\n output += renderSQLRisk(sqlRisks);\n\n // Config / Env\n const envVars = (groups.get(\"env-var\") as EnvVarFinding[]) ?? [];\n output += renderEnvVars(envVars);\n\n // Configuration Changes (TypeScript, Tailwind, Monorepo)\n const tsConfigs =\n (groups.get(\"typescript-config\") as TypeScriptConfigFinding[]) ?? [];\n const tailwindConfigs =\n (groups.get(\"tailwind-config\") as TailwindConfigFinding[]) ?? [];\n const monorepoConfigs =\n (groups.get(\"monorepo-config\") as MonorepoConfigFinding[]) ?? [];\n output += renderConfiguration(tsConfigs, tailwindConfigs, monorepoConfigs);\n\n // Cloudflare\n const cloudflare =\n (groups.get(\"cloudflare-change\") as CloudflareChangeFinding[]) ?? [];\n output += renderCloudflare(cloudflare);\n\n // Dependencies\n const deps =\n (groups.get(\"dependency-change\") as DependencyChangeFinding[]) ?? [];\n output += renderDependencies(deps);\n\n // Package API (exports)\n const packageExports =\n (groups.get(\"package-exports\") as PackageExportsFinding[]) ?? [];\n output += renderPackageExports(packageExports);\n\n // Component API (Stencil)\n output += renderStencilChanges(groups);\n\n // CI / Infrastructure\n const ciWorkflows =\n (groups.get(\"ci-workflow\") as CIWorkflowFinding[]) ?? [];\n const infraChanges =\n (groups.get(\"infra-change\") as InfraChangeFinding[]) ?? [];\n output += renderCIInfrastructure(ciWorkflows, infraChanges);\n\n // Convention Violations\n const violations =\n (groups.get(\"convention-violation\") as ConventionViolationFinding[]) ?? [];\n if (violations.length > 0) {\n output += \"## ⚠️ Conventions\\n\\n\";\n for (const v of violations) {\n output += `- **${v.message}**\\n`;\n for (const file of v.files.slice(0, 5)) {\n output += ` - \\`${file}\\`\\n`;\n }\n if (v.files.length > 5) {\n output += ` - ...and ${v.files.length - 5} more\\n`;\n }\n }\n output += \"\\n\";\n }\n\n // Test Parity Violations\n const testParityViolations =\n (groups.get(\"test-parity-violation\") as TestParityViolationFinding[]) ?? [];\n if (testParityViolations.length > 0) {\n output += \"## 🧪 Test Coverage Gaps\\n\\n\";\n output += `Found ${testParityViolations.length} source file(s) without corresponding tests:\\n\\n`;\n for (const v of testParityViolations.slice(0, 10)) {\n const confidenceLabel = v.confidence === \"high\" ? \"🔴\" : v.confidence === \"medium\" ? \"🟡\" : \"⚪\";\n output += `- ${confidenceLabel} \\`${v.sourceFile}\\`\\n`;\n }\n if (testParityViolations.length > 10) {\n output += `- ...and ${testParityViolations.length - 10} more\\n`;\n }\n output += \"\\n\";\n }\n\n // Impact Analysis\n const impacts =\n (groups.get(\"impact-analysis\") as ImpactAnalysisFinding[]) ?? [];\n if (impacts.length > 0) {\n output += \"## 🧨 Impact Analysis\\n\\n\";\n for (const impact of impacts) {\n const radiusEmoji = impact.blastRadius === \"high\" ? \"🔴\" : impact.blastRadius === \"medium\" ? \"🟡\" : \"🟢\";\n output += `### \\`${impact.sourceFile}\\` ${radiusEmoji}\\n\\n`;\n output += `**Blast Radius:** ${impact.blastRadius.toUpperCase()} (${impact.affectedFiles.length} files)\\n\\n`;\n output += \"Affected files:\\n\";\n for (const f of impact.affectedFiles.slice(0, 5)) {\n output += `- \\`${f}\\`\\n`;\n }\n if (impact.affectedFiles.length > 5) {\n output += `- ...and ${impact.affectedFiles.length - 5} more\\n`;\n }\n output += \"\\n\";\n }\n }\n\n // Warnings (large-diff, lockfile-mismatch, test-gap)\n output += renderWarnings(groups);\n\n // Suggested test plan\n output += renderTestPlan(context, groups);\n\n // Risks / Notes\n output += renderRisks(context);\n\n return output.trim() + \"\\n\";\n}\n\n",
|
|
55
|
-
"/**\n * JSON facts renderer.\n */\n\nimport type { Finding, RenderContext, RiskScore } from \"../core/types.js\";\n\nexport interface FactsOutput {\n profile: string;\n riskScore: RiskScore;\n findings: Finding[];\n}\n\n/**\n * Render findings as JSON output.\n */\nexport function renderJson(context: RenderContext): string {\n const output: FactsOutput = {\n profile: context.profile,\n riskScore: context.riskScore,\n findings: context.findings,\n };\n\n return JSON.stringify(output, null, 2);\n}\n\n"
|
|
56
|
-
],
|
|
57
|
-
"mappings": "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",
|
|
58
|
-
"debugId": "00C118A3568229BD64756E2164756E21",
|
|
59
|
-
"names": []
|
|
60
|
-
}
|