@titan-design/style-analyzer 0.1.3 → 0.1.4
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/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1071,7 +1071,7 @@ var FormattingExtractor = class {
|
|
|
1071
1071
|
}
|
|
1072
1072
|
detectTrailingCommas(source, filePath) {
|
|
1073
1073
|
const trailingCommaPattern = /,\s*[\n\r]\s*[}\]]/g;
|
|
1074
|
-
const noTrailingPattern = /[
|
|
1074
|
+
const noTrailingPattern = /[^,;{}\s]\s*[\n\r]\s*[}\]]/g;
|
|
1075
1075
|
const trailing = (source.match(trailingCommaPattern) || []).length;
|
|
1076
1076
|
const noTrailing = (source.match(noTrailingPattern) || []).length;
|
|
1077
1077
|
const total = trailing + noTrailing;
|
|
@@ -1126,7 +1126,8 @@ var FormattingExtractor = class {
|
|
|
1126
1126
|
let spaceCount = 0;
|
|
1127
1127
|
const spaceSizes = [];
|
|
1128
1128
|
for (const line of lines) {
|
|
1129
|
-
|
|
1129
|
+
const trimmed = line.trim();
|
|
1130
|
+
if (!trimmed || this.isComment(trimmed)) continue;
|
|
1130
1131
|
const leadingWhitespace = line.match(/^(\s+)/);
|
|
1131
1132
|
if (!leadingWhitespace) continue;
|
|
1132
1133
|
const ws = leadingWhitespace[1];
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/extractors/naming.ts","../src/extractors/structure.ts","../src/extractors/control-flow.ts","../src/extractors/documentation.ts","../src/extractors/error-handling.ts","../src/extractors/formatting.ts","../src/extractors/formatting-config.ts","../src/extractors/complexity.ts","../src/extractors/idioms.ts","../src/extractors/review-voice.ts","../src/extractors/factory.ts","../src/aggregator/confidence.ts","../src/aggregator/frequency.ts","../src/aggregator/stability.ts","../src/aggregator/aggregator.ts","../src/enricher/llm-runner.ts","../src/enricher/prompts.ts","../src/enricher/enricher.ts"],"sourcesContent":["export type {\n IngestConfig,\n CodeCorpus,\n CodeFile,\n ReviewComment,\n PullRequest,\n PullRequestFile,\n IngestMetadata,\n} from \"./ingest/types.js\";\nexport {\n shouldIncludeFile,\n getLanguageFromPath,\n parseFile,\n getSupportedLanguages,\n} from \"@titan-design/code-parser\";\n\nexport type {\n StyleExtractor,\n Extractor,\n Observation,\n ObservationCategory,\n ParsedFile,\n} from \"./extractors/types.js\";\nexport { NamingExtractor } from \"./extractors/naming.js\";\nexport { StructureExtractor } from \"./extractors/structure.js\";\nexport { ControlFlowExtractor } from \"./extractors/control-flow.js\";\nexport { DocumentationExtractor } from \"./extractors/documentation.js\";\nexport { ErrorHandlingExtractor } from \"./extractors/error-handling.js\";\nexport { FormattingExtractor } from \"./extractors/formatting.js\";\nexport { ComplexityExtractor } from \"./extractors/complexity.js\";\nexport { IdiomsExtractor } from \"./extractors/idioms.js\";\nexport { ReviewVoiceExtractor } from \"./extractors/review-voice.js\";\n\nexport { createStyleExtractors } from \"./extractors/factory.js\";\n\nexport {\n Aggregator,\n computeConfidence,\n mapSeverity,\n lookupStability,\n type AggregatedFeature,\n type AggregatorConfig,\n type AggregatorResult,\n type FrequencyDistribution,\n type Severity,\n type Stability,\n type StabilityWeights,\n type SeverityThresholds,\n} from \"./aggregator/aggregator.js\";\n\nexport {\n Enricher,\n needsAiEnrichment,\n AI_ENRICHED_FEATURES,\n type LlmProvider,\n type LlmMessage,\n type LlmResponse,\n type EnrichmentEntry,\n type EnrichmentError,\n type EnrichmentResult,\n type EnricherConfig,\n} from \"./enricher/enricher.js\";\n","import type { Node } from \"web-tree-sitter\";\nimport type { StyleExtractor, ParsedFile, Observation } from \"./types.js\";\n\nconst NAMING_PATTERNS: Record<string, RegExp> = {\n camelCase: /^[a-z][a-zA-Z0-9]*$/,\n PascalCase: /^[A-Z][a-zA-Z0-9]*$/,\n snake_case: /^[a-z][a-z0-9]*(_[a-z0-9]+)+$/,\n SCREAMING_SNAKE: /^[A-Z][A-Z0-9]*(_[A-Z0-9]+)+$/,\n \"kebab-case\": /^[a-z][a-z0-9]*(-[a-z0-9]+)+$/,\n};\n\nconst BOOLEAN_PREFIXES = /^(is|has|should|can|will|did|was)[A-Z_]/;\nconst PYTHON_BOOLEAN_PREFIXES = /^(is|has|should|can|will|did|was)_/;\n\nfunction detectConvention(name: string): string | null {\n for (const [convention, pattern] of Object.entries(NAMING_PATTERNS)) {\n if (pattern.test(name)) return convention;\n }\n if (/^[a-z][a-z0-9]*$/.test(name)) return \"camelCase\";\n return null;\n}\n\n// One capitalised word counts too; a single letter does not, because it is almost always a TypeVar or generic.\nconst SINGLE_WORD_CONSTANT = /^[A-Z][A-Z0-9]+$/;\n\nfunction isConstantName(name: string): boolean {\n return NAMING_PATTERNS.SCREAMING_SNAKE!.test(name) || SINGLE_WORD_CONSTANT.test(name);\n}\n\nfunction detectBooleanPrefix(name: string, language: string): string | null {\n const pattern = language === \"python\" ? PYTHON_BOOLEAN_PREFIXES : BOOLEAN_PREFIXES;\n const match = name.match(pattern);\n return match ? match[1]! : null;\n}\n\n// Blocks that do not open a new scope, so an assignment inside one still binds a module global.\nconst MODULE_SCOPE_BLOCKS = new Set([\n \"block\", \"if_statement\", \"elif_clause\", \"else_clause\",\n \"try_statement\", \"except_clause\", \"finally_clause\", \"with_statement\",\n]);\n\n// tree-sitter-python wraps an assignment in expression_statement; chained targets nest in assignment.\nfunction isModuleLevelAssignment(node: Node): boolean {\n let scope = node.parent;\n while (scope?.type === \"assignment\") scope = scope.parent;\n if (scope?.type !== \"expression_statement\") return false;\n scope = scope.parent;\n while (scope && MODULE_SCOPE_BLOCKS.has(scope.type)) scope = scope.parent;\n return scope?.type === \"module\";\n}\n\nexport class NamingExtractor implements StyleExtractor {\n readonly name = \"naming\";\n\n extract(file: ParsedFile): Observation[] {\n const observations: Observation[] = [];\n\n const visit = (node: Node): void => {\n this.processNode(node, file, observations);\n for (const child of node.children) {\n visit(child);\n }\n };\n\n visit(file.tree.rootNode);\n return observations;\n }\n\n private processNode(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n switch (file.language) {\n case \"typescript\":\n case \"tsx\":\n this.processTypeScriptNode(node, file, observations);\n break;\n case \"python\":\n this.processPythonNode(node, file, observations);\n break;\n }\n }\n\n private processTypeScriptNode(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n switch (node.type) {\n case \"variable_declarator\":\n this.processTypeScriptVariable(node, file, observations);\n break;\n case \"function_declaration\":\n this.observeDeclarationName(node, \"naming.function\", file, observations);\n break;\n case \"interface_declaration\":\n case \"type_alias_declaration\":\n this.observeDeclarationName(node, \"naming.type\", file, observations);\n break;\n case \"enum_declaration\":\n this.observeDeclarationName(node, \"naming.enum\", file, observations);\n break;\n case \"class_declaration\":\n if (this.observeDeclarationName(node, \"naming.type\", file, observations)) {\n this.detectPrivateMembers(node, file, observations);\n }\n break;\n case \"required_parameter\":\n case \"optional_parameter\":\n this.processTypeScriptParameter(node, file, observations);\n break;\n }\n }\n\n private processTypeScriptVariable(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const nameNode = node.childForFieldName(\"name\");\n if (!nameNode || nameNode.type !== \"identifier\") return;\n const name = nameNode.text;\n\n const declKind = node.parent?.type === \"lexical_declaration\"\n ? node.parent.children[0]?.text\n : null;\n\n if (declKind === \"const\" && isConstantName(name)) {\n this.addObservation(observations, \"naming.constant\", \"SCREAMING_SNAKE\", file, node);\n return;\n }\n\n this.observeVariable(name, node, file, observations);\n }\n\n private processTypeScriptParameter(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const nameNode = node.childForFieldName(\"pattern\") ?? node.childForFieldName(\"name\");\n if (!nameNode || nameNode.type !== \"identifier\") return;\n if (nameNode.text === \"this\") return;\n const convention = detectConvention(nameNode.text);\n if (convention) {\n this.addObservation(observations, \"naming.parameter\", convention, file, node);\n }\n }\n\n private processPythonNode(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n switch (node.type) {\n case \"assignment\":\n this.processPythonAssignment(node, file, observations);\n break;\n case \"function_definition\": {\n const nameNode = node.childForFieldName(\"name\");\n if (!nameNode) break;\n if (nameNode.text.startsWith(\"__\") && nameNode.text.endsWith(\"__\")) break;\n this.observeDeclarationName(node, \"naming.function\", file, observations);\n break;\n }\n case \"class_definition\":\n this.observeDeclarationName(node, \"naming.type\", file, observations);\n break;\n case \"parameters\":\n this.processPythonParameters(node, file, observations);\n break;\n }\n }\n\n private processPythonAssignment(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const left = node.childForFieldName(\"left\");\n if (!left || left.type !== \"identifier\") return;\n const name = left.text;\n\n if (\n isModuleLevelAssignment(node) &&\n isConstantName(name)\n ) {\n this.addObservation(observations, \"naming.constant\", \"SCREAMING_SNAKE\", file, node);\n return;\n }\n\n this.observeVariable(name, node, file, observations);\n }\n\n private processPythonParameters(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n for (const child of node.children) {\n if (child.type === \"identifier\" && child.text !== \"self\" && child.text !== \"cls\") {\n const convention = detectConvention(child.text);\n if (convention) {\n this.addObservation(observations, \"naming.parameter\", convention, file, child);\n }\n }\n if (child.type === \"typed_parameter\") {\n const paramName = child.childForFieldName(\"name\") ?? child.children[0];\n if (paramName && paramName.type === \"identifier\" && paramName.text !== \"self\") {\n const convention = detectConvention(paramName.text);\n if (convention) {\n this.addObservation(observations, \"naming.parameter\", convention, file, child);\n }\n }\n }\n }\n }\n\n private observeVariable(\n name: string,\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const prefix = detectBooleanPrefix(name, file.language);\n if (prefix) {\n this.addObservation(observations, \"naming.boolean\", prefix, file, node);\n }\n\n const convention = detectConvention(name);\n if (convention) {\n this.addObservation(observations, \"naming.variable\", convention, file, node);\n }\n }\n\n // Returns whether the node had a name, because a nameless class skips its private-member scan.\n private observeDeclarationName(\n node: Node,\n type: string,\n file: ParsedFile,\n observations: Observation[],\n ): boolean {\n const nameNode = node.childForFieldName(\"name\");\n if (!nameNode) return false;\n const convention = detectConvention(nameNode.text);\n if (convention) {\n this.addObservation(observations, type, convention, file, node);\n }\n return true;\n }\n\n private detectPrivateMembers(\n classNode: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const body = classNode.childForFieldName(\"body\");\n if (!body) return;\n\n for (const member of body.children) {\n if (member.type === \"public_field_definition\") {\n const nameNode = member.childForFieldName(\"name\");\n if (!nameNode) continue;\n const name = nameNode.text;\n\n if (name.startsWith(\"#\")) {\n this.addObservation(observations, \"naming.private-member\", \"hash-prefix\", file, member);\n } else if (name.startsWith(\"_\") && !name.startsWith(\"__\")) {\n this.addObservation(observations, \"naming.private-member\", \"underscore-prefix\", file, member);\n }\n }\n }\n }\n\n private addObservation(\n observations: Observation[],\n type: string,\n value: string | number | boolean,\n file: ParsedFile,\n node: Node,\n ): void {\n observations.push({\n type,\n category: \"naming\",\n value,\n file: file.filePath,\n line: node.startPosition.row + 1,\n });\n }\n}\n","import type { Node } from \"web-tree-sitter\";\nimport type { StyleExtractor, ParsedFile, Observation } from \"./types.js\";\n\nconst PYTHON_BUILTINS = new Set([\n \"os\", \"sys\", \"re\", \"json\", \"math\", \"time\", \"datetime\", \"pathlib\",\n \"collections\", \"itertools\", \"functools\", \"typing\", \"io\", \"abc\",\n \"dataclasses\", \"enum\", \"logging\", \"unittest\", \"hashlib\", \"subprocess\",\n \"argparse\", \"copy\", \"glob\", \"shutil\", \"tempfile\", \"textwrap\",\n \"contextlib\", \"operator\", \"string\", \"struct\", \"csv\", \"xml\",\n]);\n\nfunction classifyImportSource(source: string, language: string): string {\n if (language === \"python\") {\n if (source.startsWith(\".\")) return \"relative\";\n const topModule = source.split(\".\")[0]!;\n if (PYTHON_BUILTINS.has(topModule)) return \"builtin\";\n return \"external\";\n }\n\n if (source.startsWith(\"node:\")) return \"builtin\";\n if (source.startsWith(\".\") || source.startsWith(\"..\")) return \"relative\";\n if (source.startsWith(\"@\")) {\n const scope = source.split(\"/\")[0]!;\n if ([\"@app\", \"@lib\", \"@src\", \"@internal\", \"@modules\"].includes(scope)) {\n return \"internal\";\n }\n }\n return \"external\";\n}\n\nconst EXPORT_DECLARATION_TYPES = [\n \"function_declaration\",\n \"class_declaration\",\n \"lexical_declaration\",\n \"interface_declaration\",\n \"type_alias_declaration\",\n \"enum_declaration\",\n];\n\nfunction isBarrelFile(root: Node): boolean {\n let exportFromCount = 0;\n let otherStatements = 0;\n\n for (const child of root.children) {\n if (child.type === \"export_statement\") {\n const source = child.childForFieldName(\"source\");\n if (source) {\n exportFromCount++;\n } else {\n otherStatements++;\n }\n } else if (child.isNamed && child.type !== \"comment\") {\n otherStatements++;\n }\n }\n\n return exportFromCount > 0 && otherStatements <= 1;\n}\n\nexport class StructureExtractor implements StyleExtractor {\n readonly name = \"structure\";\n\n extract(file: ParsedFile): Observation[] {\n const observations: Observation[] = [];\n const root = file.tree.rootNode;\n\n this.extractImports(root, file, observations);\n this.extractExports(root, file, observations);\n this.detectBarrelFile(root, file, observations);\n\n return observations;\n }\n\n private extractImports(\n root: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const groupSequence: string[] = [];\n\n for (const child of root.children) {\n const source = this.importSource(child, file.language);\n\n if (source) {\n const group = classifyImportSource(source, file.language);\n groupSequence.push(group);\n observations.push({\n type: \"structure.import-group\",\n category: \"structure\",\n value: group,\n file: file.filePath,\n line: child.startPosition.row + 1,\n metadata: { source },\n });\n }\n }\n\n this.addImportOrder(groupSequence, file, observations);\n }\n\n private addImportOrder(\n groupSequence: string[],\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const uniqueOrder = [...new Set(groupSequence)];\n if (uniqueOrder.length > 0) {\n observations.push({\n type: \"structure.import-order\",\n category: \"structure\",\n value: JSON.stringify(uniqueOrder),\n file: file.filePath,\n line: 1,\n metadata: { groupCount: uniqueOrder.length },\n });\n }\n }\n\n private importSource(child: Node, language: string): string | null {\n let source: string | null = null;\n\n if (language === \"python\") {\n if (child.type === \"import_statement\") {\n const nameNode = child.childForFieldName(\"name\");\n source = nameNode?.text ?? null;\n } else if (child.type === \"import_from_statement\") {\n const moduleNode = child.childForFieldName(\"module_name\");\n const dots = child.children\n .filter((c) => c.type === \".\" || c.type === \"relative_import\")\n .map((c) => c.text)\n .join(\"\");\n source = dots + (moduleNode?.text ?? \"\");\n }\n } else {\n if (child.type === \"import_statement\") {\n const sourceNode = child.childForFieldName(\"source\");\n source = sourceNode?.text?.replace(/['\"]/g, \"\") ?? null;\n }\n }\n\n return source;\n }\n\n private extractExports(\n root: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (file.language === \"python\") return;\n\n for (const child of root.children) {\n if (child.type === \"export_statement\") {\n this.processExport(child, file, observations);\n }\n }\n }\n\n private processExport(\n child: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const isDefault = child.children.some((c) => c.type === \"default\");\n const style = isDefault ? \"default\" : \"named\";\n\n observations.push({\n type: \"structure.export-style\",\n category: \"structure\",\n value: style,\n file: file.filePath,\n line: child.startPosition.row + 1,\n });\n\n const proximity = this.exportProximity(child, isDefault);\n if (proximity) {\n observations.push({\n type: \"structure.export-proximity\",\n category: \"structure\",\n value: proximity,\n file: file.filePath,\n line: child.startPosition.row + 1,\n });\n }\n }\n\n private exportProximity(\n child: Node,\n isDefault: boolean,\n ): \"inline\" | \"trailing\" | null {\n const hasDeclaration = child.children.some((c) =>\n EXPORT_DECLARATION_TYPES.includes(c.type),\n );\n const isReExport = child.childForFieldName(\"source\") !== null;\n\n if (hasDeclaration || isDefault) return \"inline\";\n if (!isReExport) return \"trailing\";\n return null;\n }\n\n private detectBarrelFile(\n root: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (file.language === \"python\") return;\n\n if (isBarrelFile(root)) {\n observations.push({\n type: \"structure.barrel-file\",\n category: \"structure\",\n value: true,\n file: file.filePath,\n line: 1,\n });\n }\n }\n}\n","import type { Node } from \"web-tree-sitter\";\nimport type { StyleExtractor, ParsedFile, Observation } from \"./types.js\";\n\nconst ARRAY_METHODS = new Set([\n \"map\", \"filter\", \"reduce\", \"forEach\", \"find\", \"some\", \"every\", \"flatMap\",\n \"findIndex\",\n]);\n\nexport class ControlFlowExtractor implements StyleExtractor {\n readonly name = \"control-flow\";\n\n extract(file: ParsedFile): Observation[] {\n const observations: Observation[] = [];\n this.walk(file.tree.rootNode, file, observations);\n return observations;\n }\n\n private walk(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n this.processNode(node, file, observations);\n for (const child of node.children) {\n this.walk(child, file, observations);\n }\n }\n\n private processNode(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n this.processBranch(node, file, observations);\n this.processLoop(node, file, observations);\n this.processCall(node, file, observations);\n }\n\n private processBranch(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (\n node.type === \"ternary_expression\" ||\n node.type === \"conditional_expression\"\n ) {\n this.emit(observations, \"control-flow.ternary\", true, file, node);\n }\n\n if (node.type === \"if_statement\") {\n this.emit(observations, \"control-flow.if-else\", true, file, node);\n this.detectGuardClause(node, file, observations);\n this.detectElseAfterReturn(node, file, observations);\n }\n }\n\n private processLoop(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (node.type === \"for_statement\" && file.language !== \"python\") {\n this.emit(observations, \"control-flow.for-loop\", true, file, node);\n }\n\n if (node.type === \"for_in_statement\") {\n const isForOf = node.children.some((c) => c.type === \"of\");\n const loopType = isForOf ? \"control-flow.for-of\" : \"control-flow.for-in\";\n this.emit(observations, loopType, true, file, node);\n }\n\n if (node.type === \"for_statement\" && file.language === \"python\") {\n this.emit(observations, \"control-flow.for-loop\", true, file, node);\n }\n\n if (\n node.type === \"list_comprehension\" ||\n node.type === \"set_comprehension\" ||\n node.type === \"dictionary_comprehension\" ||\n node.type === \"generator_expression\"\n ) {\n this.emit(observations, \"control-flow.array-method\", true, file, node);\n }\n }\n\n private processCall(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (node.type === \"call_expression\") {\n const fn = node.childForFieldName(\"function\");\n if (fn?.type === \"member_expression\") {\n this.processMemberCall(fn, node, file, observations);\n }\n }\n\n if (node.type === \"await_expression\") {\n this.emit(observations, \"control-flow.async-await\", true, file, node);\n }\n }\n\n private processMemberCall(\n fn: Node,\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const property = fn.childForFieldName(\"property\");\n if (property) {\n const methodName = property.text;\n if (ARRAY_METHODS.has(methodName)) {\n this.emit(\n observations,\n \"control-flow.array-method\",\n methodName,\n file,\n node,\n );\n }\n if (methodName === \"then\") {\n this.emit(\n observations,\n \"control-flow.promise-then\",\n true,\n file,\n node,\n );\n }\n }\n }\n\n private detectGuardClause(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const parent = node.parent;\n if (!parent) return;\n\n if (!this.isFunctionBody(parent)) return;\n\n const siblings = parent.children.filter(\n (c) => c.type !== \"comment\" && c.type !== \"{\" && c.type !== \"}\",\n );\n const nodeIndex = siblings.indexOf(node);\n if (nodeIndex > 2) return;\n\n const consequent =\n node.childForFieldName(\"consequence\") ??\n node.childForFieldName(\"body\");\n if (!consequent) return;\n\n const hasReturn = this.containsReturn(consequent);\n const hasElse = node.childForFieldName(\"alternative\") !== null;\n\n if (hasReturn && !hasElse) {\n this.emit(observations, \"control-flow.guard-clause\", true, file, node);\n }\n }\n\n private isFunctionBody(parent: Node): boolean {\n const isFunctionBody =\n parent.type === \"statement_block\" &&\n (parent.parent?.type === \"function_declaration\" ||\n parent.parent?.type === \"method_definition\" ||\n parent.parent?.type === \"arrow_function\");\n\n const isPythonFunctionBody =\n parent.type === \"block\" &&\n parent.parent?.type === \"function_definition\";\n\n return isFunctionBody || isPythonFunctionBody;\n }\n\n private detectElseAfterReturn(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const consequent =\n node.childForFieldName(\"consequence\") ??\n node.childForFieldName(\"body\");\n const alternative = node.childForFieldName(\"alternative\");\n\n if (!consequent || !alternative) return;\n\n if (this.containsReturn(consequent)) {\n this.emit(\n observations,\n \"control-flow.else-after-return\",\n true,\n file,\n node,\n );\n }\n }\n\n private containsReturn(node: Node): boolean {\n if (node.type === \"return_statement\") return true;\n for (const child of node.children) {\n if (child.type === \"return_statement\") return true;\n }\n return false;\n }\n\n private emit(\n observations: Observation[],\n type: string,\n value: string | number | boolean,\n file: ParsedFile,\n node: Node,\n ): void {\n observations.push({\n type,\n category: \"control-flow\",\n value,\n file: file.filePath,\n line: node.startPosition.row + 1,\n });\n }\n}\n","import type { Node } from \"web-tree-sitter\";\nimport type { StyleExtractor, ParsedFile, Observation } from \"./types.js\";\n\nconst JSDOC_TAG_PATTERN = /@(param|returns?|throws?|example|deprecated|see|since|type|typedef|template|callback|async)\\b/g;\nconst PYTHON_DOC_TAG_PATTERN = /^[ \\t]*(Args|Returns?|Raises?|Yields?|Note|Notes|Example|Attributes|Todo|References):/gm;\n\nexport class DocumentationExtractor implements StyleExtractor {\n readonly name = \"documentation\";\n\n extract(file: ParsedFile): Observation[] {\n const observations: Observation[] = [];\n\n this.walkDeclarations(file.tree.rootNode, file, observations);\n this.walkForComments(file.tree.rootNode, file, observations);\n\n return observations;\n }\n\n private walkDeclarations(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n for (const child of node.children) {\n if (this.isDeclaration(child, file.language)) {\n this.processDeclaration(child, file, observations);\n }\n\n if (\n child.type === \"class_declaration\" ||\n child.type === \"class_definition\" ||\n child.type === \"class_body\" ||\n child.type === \"block\"\n ) {\n this.walkDeclarations(child, file, observations);\n }\n\n if (child.type === \"export_statement\") {\n this.walkDeclarations(child, file, observations);\n }\n }\n }\n\n private isDeclaration(node: Node, language: string): boolean {\n if (language === \"python\") {\n return (\n node.type === \"function_definition\" ||\n node.type === \"class_definition\"\n );\n }\n return (\n node.type === \"function_declaration\" ||\n node.type === \"method_definition\" ||\n node.type === \"class_declaration\" ||\n node.type === \"interface_declaration\" ||\n node.type === \"type_alias_declaration\"\n );\n }\n\n private processDeclaration(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const isExported = this.isExported(node, file.language);\n const hasDoc = this.hasLeadingDoc(node, file.language);\n\n this.emit(observations, \"documentation.jsdoc-presence\", hasDoc, file, node);\n\n const coverageType = isExported\n ? \"documentation.public-coverage\"\n : \"documentation.private-coverage\";\n this.emit(observations, coverageType, hasDoc, file, node);\n\n if (hasDoc) {\n this.extractTags(node, file, observations);\n }\n }\n\n private hasLeadingDoc(node: Node, language: string): boolean {\n if (language === \"python\") {\n return this.hasPythonDocstring(node);\n }\n return this.hasJSDoc(node);\n }\n\n private hasJSDoc(node: Node): boolean {\n const prev = node.previousSibling;\n if (prev?.type === \"comment\" && prev.text.startsWith(\"/**\")) {\n return true;\n }\n if (node.parent?.type === \"export_statement\") {\n const exportPrev = node.parent.previousSibling;\n if (exportPrev?.type === \"comment\" && exportPrev.text.startsWith(\"/**\")) {\n return true;\n }\n }\n return false;\n }\n\n private hasPythonDocstring(node: Node): boolean {\n const body = node.childForFieldName(\"body\");\n if (!body) return false;\n\n const firstStatement = body.children.find(\n (c) => c.type !== \"comment\" && c.type !== \"newline\",\n );\n if (!firstStatement) return false;\n\n if (firstStatement.type === \"expression_statement\") {\n const expr = firstStatement.children[0];\n return expr?.type === \"string\" || expr?.type === \"concatenated_string\";\n }\n return false;\n }\n\n private extractTags(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (file.language === \"python\") {\n this.extractPythonDocTags(node, file, observations);\n return;\n }\n\n const commentNode = this.getLeadingComment(node);\n if (!commentNode) return;\n\n const text = commentNode.text;\n const tagMatches = text.matchAll(JSDOC_TAG_PATTERN);\n const seenTags = new Set<string>();\n\n for (const match of tagMatches) {\n const tag = `@${match[1]}`;\n const normalized = tag\n .replace(/^@return$/, \"@returns\")\n .replace(/^@throw$/, \"@throws\");\n\n if (seenTags.has(normalized)) continue;\n seenTags.add(normalized);\n\n this.emit(observations, \"documentation.jsdoc-tag\", normalized, file, commentNode);\n }\n }\n\n private extractPythonDocTags(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const body = node.childForFieldName(\"body\");\n if (!body) return;\n\n const firstStatement = body.children.find(\n (c) => c.type === \"expression_statement\",\n );\n if (!firstStatement) return;\n\n const expr = firstStatement.children[0];\n if (!expr) return;\n\n const text = expr.text;\n const tagMatches = text.matchAll(PYTHON_DOC_TAG_PATTERN);\n const seenTags = new Set<string>();\n\n for (const match of tagMatches) {\n const tag = match[1]!;\n if (seenTags.has(tag)) continue;\n seenTags.add(tag);\n this.emit(observations, \"documentation.jsdoc-tag\", tag, file, expr);\n }\n }\n\n private walkForComments(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (node.type === \"comment\") {\n if (!node.text.startsWith(\"/**\")) {\n this.emit(observations, \"documentation.inline-comment\", true, file, node);\n\n const placement = this.getCommentPlacement(node);\n this.emit(observations, \"documentation.comment-placement\", placement, file, node);\n }\n }\n\n for (const child of node.children) {\n this.walkForComments(child, file, observations);\n }\n }\n\n private getCommentPlacement(node: Node): \"leading\" | \"trailing\" {\n const prev = node.previousSibling;\n if (prev && prev.endPosition.row === node.startPosition.row) {\n return \"trailing\";\n }\n return \"leading\";\n }\n\n private isExported(node: Node, language: string): boolean {\n if (language === \"python\") {\n const nameNode = node.childForFieldName(\"name\");\n return (\n node.parent?.type === \"module\" &&\n !!nameNode &&\n !nameNode.text.startsWith(\"_\")\n );\n }\n return node.parent?.type === \"export_statement\";\n }\n\n private getLeadingComment(node: Node): Node | null {\n const prev = node.previousSibling;\n if (prev?.type === \"comment\" && prev.text.startsWith(\"/**\")) {\n return prev;\n }\n if (node.parent?.type === \"export_statement\") {\n const exportPrev = node.parent.previousSibling;\n if (exportPrev?.type === \"comment\" && exportPrev.text.startsWith(\"/**\")) {\n return exportPrev;\n }\n }\n return null;\n }\n\n private emit(\n observations: Observation[],\n type: string,\n value: string | number | boolean,\n file: ParsedFile,\n node: Node,\n ): void {\n observations.push({\n type,\n category: \"documentation\",\n value,\n file: file.filePath,\n line: node.startPosition.row + 1,\n });\n }\n}\n","import type { Node } from \"web-tree-sitter\";\nimport type { StyleExtractor, ParsedFile, Observation } from \"./types.js\";\n\nconst RESULT_TYPE_NAMES = new Set([\n \"Result\", \"Either\", \"Ok\", \"Err\", \"Success\", \"Failure\",\n]);\n\nconst GENERIC_CATCH_TYPES = new Set([\n \"Error\", \"Exception\", \"unknown\",\n]);\n\nexport class ErrorHandlingExtractor implements StyleExtractor {\n readonly name = \"error-handling\";\n\n extract(file: ParsedFile): Observation[] {\n const observations: Observation[] = [];\n this.walk(file.tree.rootNode, file, observations);\n return observations;\n }\n\n private walk(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n this.processNode(node, file, observations);\n for (const child of node.children) {\n this.walk(child, file, observations);\n }\n }\n\n private processNode(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n this.processDeclaration(node, file, observations);\n this.processFunctionCheck(node, file, observations);\n }\n\n private processDeclaration(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (node.type === \"try_statement\") {\n this.emit(observations, \"error-handling.try-catch\", true, file, node);\n this.analyzeCatchClauses(node, file, observations);\n }\n\n if (\n node.type === \"class_declaration\" ||\n node.type === \"class_definition\"\n ) {\n this.detectCustomErrorClass(node, file, observations);\n }\n\n if (\n node.type === \"type_alias_declaration\" &&\n (file.language === \"typescript\" || file.language === \"tsx\")\n ) {\n this.detectResultType(node, file, observations);\n }\n }\n\n private processFunctionCheck(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (\n node.type === \"function_declaration\" ||\n node.type === \"method_definition\"\n ) {\n this.detectResultReturnType(node, file, observations);\n }\n\n if (node.type === \"function_declaration\") {\n this.detectAssertNever(node, file, observations);\n }\n\n if (node.type === \"switch_statement\") {\n this.detectExhaustiveSwitch(node, file, observations);\n }\n }\n\n private analyzeCatchClauses(\n tryNode: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n for (const child of tryNode.children) {\n if (child.type === \"catch_clause\") {\n const body = child.childForFieldName(\"body\");\n if (body && this.hasInstanceofCheck(body)) {\n this.emit(observations, \"error-handling.catch-specificity\", \"specific\", file, child);\n } else {\n this.emit(observations, \"error-handling.catch-specificity\", \"generic\", file, child);\n }\n }\n\n if (child.type === \"except_clause\") {\n const typeNode = child.children.find(\n (c) => c.type === \"identifier\" || c.type === \"attribute\",\n );\n\n if (typeNode && !GENERIC_CATCH_TYPES.has(typeNode.text)) {\n this.emit(observations, \"error-handling.catch-specificity\", \"specific\", file, child);\n } else {\n this.emit(observations, \"error-handling.catch-specificity\", \"generic\", file, child);\n }\n }\n }\n }\n\n private hasInstanceofCheck(body: Node): boolean {\n return body.text.includes(\"instanceof\");\n }\n\n private detectCustomErrorClass(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (file.language === \"python\") {\n const superclasses = node.childForFieldName(\"superclasses\");\n if (!superclasses) return;\n\n const bases = superclasses.text;\n if (bases.includes(\"Error\") || bases.includes(\"Exception\")) {\n this.emit(observations, \"error-handling.custom-error-class\", true, file, node);\n }\n return;\n }\n\n const heritage = node.children.find(\n (c) => c.type === \"class_heritage\",\n );\n if (!heritage) return;\n\n if (heritage.text.includes(\"Error\")) {\n this.emit(observations, \"error-handling.custom-error-class\", true, file, node);\n }\n }\n\n private detectResultType(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const nameNode = node.childForFieldName(\"name\");\n if (!nameNode) return;\n\n if (RESULT_TYPE_NAMES.has(nameNode.text)) {\n this.emit(observations, \"error-handling.result-type\", nameNode.text, file, node);\n }\n }\n\n private detectResultReturnType(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const returnType = node.childForFieldName(\"return_type\");\n if (!returnType) return;\n\n const text = returnType.text;\n for (const name of RESULT_TYPE_NAMES) {\n if (text.includes(name)) {\n this.emit(observations, \"error-handling.result-type\", name, file, node);\n break;\n }\n }\n }\n\n private detectAssertNever(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const nameNode = node.childForFieldName(\"name\");\n if (!nameNode) return;\n\n const name = nameNode.text;\n if (name !== \"assertNever\" && name !== \"absurd\") return;\n\n const params = node.childForFieldName(\"parameters\");\n const returnType = node.childForFieldName(\"return_type\");\n\n const hasNeverParam = params?.text.includes(\"never\") ?? false;\n const returnsNever = returnType?.text.includes(\"never\") ?? false;\n\n if (hasNeverParam || returnsNever) {\n this.emit(observations, \"error-handling.assert-never\", true, file, node);\n }\n }\n\n private detectExhaustiveSwitch(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const body = node.childForFieldName(\"body\");\n if (!body) return;\n\n let defaultCallsAssertNever = false;\n\n for (const child of body.children) {\n if (child.type === \"switch_default\") {\n const text = child.text;\n if (text.includes(\"assertNever\") || text.includes(\"absurd\")) {\n defaultCallsAssertNever = true;\n }\n }\n }\n\n this.emit(\n observations,\n \"error-handling.exhaustive-switch\",\n defaultCallsAssertNever,\n file,\n node,\n );\n }\n\n private emit(\n observations: Observation[],\n type: string,\n value: string | number | boolean,\n file: ParsedFile,\n node: Node,\n ): void {\n observations.push({\n type,\n category: \"error-handling\",\n value,\n file: file.filePath,\n line: node.startPosition.row + 1,\n });\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport type { StyleExtractor, ParsedFile, Observation } from \"./types.js\";\nimport {\n makeFormattingObs,\n parseEditorConfig,\n parsePrettierConfig,\n} from \"./formatting-config.js\";\n\nexport class FormattingExtractor implements StyleExtractor {\n readonly name = \"formatting\";\n\n extract(file: ParsedFile): Observation[] {\n return this.extractFromSource(file.content, file.filePath);\n }\n\n async extractFromConfig(configPath: string): Promise<Observation[]> {\n try {\n const raw = await readFile(configPath, \"utf-8\");\n\n if (configPath.endsWith(\".editorconfig\")) {\n return parseEditorConfig(raw, configPath);\n }\n\n if (\n configPath.includes(\".prettierrc\") ||\n configPath.includes(\"prettier.config\")\n ) {\n return parsePrettierConfig(raw, configPath);\n }\n\n return [];\n } catch {\n return [];\n }\n }\n\n extractFromSource(source: string, filePath: string): Observation[] {\n const observations: Observation[] = [];\n const lines = source.split(\"\\n\");\n\n observations.push(...this.detectSemicolons(lines, filePath));\n observations.push(...this.detectQuoteStyle(source, filePath));\n observations.push(...this.detectTrailingCommas(source, filePath));\n observations.push(...this.detectBraceStyle(source, filePath));\n observations.push(...this.detectIndentation(lines, filePath));\n\n return observations;\n }\n\n private detectSemicolons(\n lines: string[],\n filePath: string,\n ): Observation[] {\n let withSemi = 0;\n let withoutSemi = 0;\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || this.isComment(trimmed)) continue;\n if (this.isStructuralLine(trimmed)) continue;\n\n if (trimmed.endsWith(\";\")) {\n withSemi++;\n } else if (this.isStatementStart(trimmed)) {\n withoutSemi++;\n }\n }\n\n const total = withSemi + withoutSemi;\n if (total === 0) return [];\n\n return [makeFormattingObs(\n \"formatting.semicolons\",\n withSemi / total > 0.5,\n filePath, 1, \"frequency\",\n )];\n }\n\n private detectQuoteStyle(\n source: string,\n filePath: string,\n ): Observation[] {\n let singleQuotes = 0;\n let doubleQuotes = 0;\n\n const stringPattern = /(?<!=)(?<!\\\\)(['\"])((?:(?!\\1|\\\\).|\\\\.)*)\\1/g;\n let match: RegExpExecArray | null;\n\n while ((match = stringPattern.exec(source)) !== null) {\n if (match[1] === \"'\") {\n singleQuotes++;\n } else {\n doubleQuotes++;\n }\n }\n\n const total = singleQuotes + doubleQuotes;\n if (total === 0) return [];\n\n return [makeFormattingObs(\n \"formatting.quoteStyle\",\n singleQuotes > doubleQuotes ? \"single\" : \"double\",\n filePath, 1, \"frequency\",\n )];\n }\n\n private detectTrailingCommas(\n source: string,\n filePath: string,\n ): Observation[] {\n const trailingCommaPattern = /,\\s*[\\n\\r]\\s*[}\\]]/g;\n const noTrailingPattern = /[^,\\s]\\s*[\\n\\r]\\s*[}\\]]/g;\n\n const trailing = (source.match(trailingCommaPattern) || []).length;\n const noTrailing = (source.match(noTrailingPattern) || []).length;\n const total = trailing + noTrailing;\n\n if (total === 0) return [];\n\n return [makeFormattingObs(\n \"formatting.trailingCommas\",\n trailing / total > 0.5,\n filePath, 1, \"frequency\",\n )];\n }\n\n private detectBraceStyle(\n source: string,\n filePath: string,\n ): Observation[] {\n const sameLine = (source.match(/\\)[^\\S\\n]*\\{/g) || []).length;\n const nextLine = (source.match(/\\)\\s*\\n\\s*\\{/g) || []).length;\n\n const total = sameLine + nextLine;\n if (total === 0) return [];\n\n return [makeFormattingObs(\n \"formatting.braceStyle\",\n nextLine / total > 0.5 ? \"allman\" : \"1tbs\",\n filePath, 1, \"frequency\",\n )];\n }\n\n private detectIndentation(\n lines: string[],\n filePath: string,\n ): Observation[] {\n const { tabCount, spaceCount, spaceSizes } = this.countIndentation(lines);\n\n const observations: Observation[] = [];\n const total = tabCount + spaceCount;\n if (total === 0) return observations;\n\n observations.push(makeFormattingObs(\n \"formatting.indentStyle\",\n tabCount > spaceCount ? \"tab\" : \"space\",\n filePath, 1, \"frequency\",\n ));\n\n if (spaceCount > tabCount && spaceSizes.length > 0) {\n const gcd = this.findGcdOfArray(spaceSizes.filter((s) => s > 0));\n observations.push(makeFormattingObs(\n \"formatting.indentSize\", gcd, filePath, 1, \"frequency\",\n ));\n }\n\n return observations;\n }\n\n private countIndentation(lines: string[]): {\n tabCount: number;\n spaceCount: number;\n spaceSizes: number[];\n } {\n let tabCount = 0;\n let spaceCount = 0;\n const spaceSizes: number[] = [];\n\n for (const line of lines) {\n if (!line || line.trim() === \"\") continue;\n\n const leadingWhitespace = line.match(/^(\\s+)/);\n if (!leadingWhitespace) continue;\n\n const ws = leadingWhitespace[1]!;\n\n if (ws.includes(\"\\t\")) {\n tabCount++;\n } else if (ws.length > 0) {\n spaceCount++;\n spaceSizes.push(ws.length);\n }\n }\n\n return { tabCount, spaceCount, spaceSizes };\n }\n\n private isComment(trimmed: string): boolean {\n return (\n trimmed.startsWith(\"//\") ||\n trimmed.startsWith(\"/*\") ||\n trimmed.startsWith(\"*\")\n );\n }\n\n private isStructuralLine(trimmed: string): boolean {\n return (\n trimmed.endsWith(\"{\") ||\n trimmed.endsWith(\"}\") ||\n trimmed.endsWith(\"(\") ||\n trimmed.endsWith(\",\")\n );\n }\n\n private isStatementStart(trimmed: string): boolean {\n return (\n trimmed.startsWith(\"const \") ||\n trimmed.startsWith(\"let \") ||\n trimmed.startsWith(\"var \") ||\n trimmed.startsWith(\"return \") ||\n trimmed.startsWith(\"import \") ||\n trimmed.startsWith(\"export \")\n );\n }\n\n private findGcdOfArray(nums: number[]): number {\n if (nums.length === 0) return 2;\n return nums.reduce((a, b) => this.gcd(a, b));\n }\n\n private gcd(a: number, b: number): number {\n while (b) {\n [a, b] = [b, a % b];\n }\n return a;\n }\n}\n","import type { Observation } from \"./types.js\";\n\ninterface PrettierConfig {\n semi?: boolean;\n singleQuote?: boolean;\n trailingComma?: \"none\" | \"es5\" | \"all\";\n tabWidth?: number;\n useTabs?: boolean;\n}\n\ninterface EditorConfigSection {\n indent_style?: \"space\" | \"tab\";\n indent_size?: string;\n insert_final_newline?: string;\n}\n\nexport function parsePrettierConfig(\n raw: string,\n configPath: string,\n): Observation[] {\n const config: PrettierConfig = JSON.parse(raw);\n return [\n ...prettierSyntaxObservations(config, configPath),\n ...prettierIndentObservations(config, configPath),\n ];\n}\n\nfunction prettierSyntaxObservations(\n config: PrettierConfig,\n configPath: string,\n): Observation[] {\n const observations: Observation[] = [];\n\n if (config.semi !== undefined) {\n observations.push(makeFormattingObs(\n \"formatting.semicolons\", config.semi, configPath, 1, \"config\",\n ));\n }\n\n if (config.singleQuote !== undefined) {\n observations.push(makeFormattingObs(\n \"formatting.quoteStyle\",\n config.singleQuote ? \"single\" : \"double\",\n configPath, 1, \"config\",\n ));\n }\n\n if (config.trailingComma !== undefined) {\n observations.push(makeFormattingObs(\n \"formatting.trailingCommas\",\n config.trailingComma !== \"none\",\n configPath, 1, \"config\",\n ));\n }\n\n return observations;\n}\n\nfunction prettierIndentObservations(\n config: PrettierConfig,\n configPath: string,\n): Observation[] {\n const observations: Observation[] = [];\n\n if (config.tabWidth !== undefined) {\n observations.push(makeFormattingObs(\n \"formatting.indentSize\", config.tabWidth, configPath, 1, \"config\",\n ));\n }\n\n if (config.useTabs !== undefined) {\n observations.push(makeFormattingObs(\n \"formatting.indentStyle\",\n config.useTabs ? \"tab\" : \"space\",\n configPath, 1, \"config\",\n ));\n }\n\n return observations;\n}\n\nexport function parseEditorConfig(\n raw: string,\n configPath: string,\n): Observation[] {\n const observations: Observation[] = [];\n const section = parseEditorConfigGlobal(raw);\n\n if (section.indent_style) {\n observations.push(makeFormattingObs(\n \"formatting.indentStyle\", section.indent_style, configPath, 1, \"config\",\n ));\n }\n\n if (section.indent_size) {\n observations.push(makeFormattingObs(\n \"formatting.indentSize\",\n parseInt(section.indent_size, 10),\n configPath, 1, \"config\",\n ));\n }\n\n if (section.insert_final_newline) {\n observations.push(makeFormattingObs(\n \"formatting.trailingNewline\",\n section.insert_final_newline === \"true\",\n configPath, 1, \"config\",\n ));\n }\n\n return observations;\n}\n\nfunction parseEditorConfigGlobal(raw: string): EditorConfigSection {\n const result: EditorConfigSection = {};\n const lines = raw.split(\"\\n\");\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith(\"#\") || trimmed.startsWith(\"[\") || !trimmed) {\n continue;\n }\n const eqIndex = trimmed.indexOf(\"=\");\n if (eqIndex === -1) continue;\n const key = trimmed.substring(0, eqIndex).trim();\n const value = trimmed.substring(eqIndex + 1).trim();\n if (key && value) {\n (result as Record<string, string>)[key] = value;\n }\n }\n\n return result;\n}\n\nexport function makeFormattingObs(\n type: string,\n value: string | number | boolean,\n file: string,\n line: number,\n source: string,\n): Observation {\n return {\n type,\n category: \"formatting\",\n value,\n file,\n line,\n metadata: { source },\n };\n}\n","import type { Node } from \"web-tree-sitter\";\nimport type { StyleExtractor, ParsedFile, Observation } from \"./types.js\";\n\ninterface FunctionInfo {\n name: string;\n statementCount: number;\n maxNestingDepth: number;\n cyclomaticComplexity: number;\n line: number;\n}\n\nconst TS_FUNCTION_TYPES = new Set([\n \"function_declaration\",\n \"method_definition\",\n]);\n\nconst PY_FUNCTION_TYPES = new Set([\n \"function_definition\",\n]);\n\nconst TS_NESTING_TYPES = new Set([\n \"if_statement\",\n \"for_statement\",\n \"for_in_statement\",\n \"while_statement\",\n \"do_statement\",\n \"switch_statement\",\n \"try_statement\",\n]);\n\nconst PY_NESTING_TYPES = new Set([\n \"if_statement\",\n \"for_statement\",\n \"while_statement\",\n \"try_statement\",\n]);\n\nconst TS_BRANCH_TYPES = new Set([\n \"if_statement\",\n \"for_statement\",\n \"for_in_statement\",\n \"while_statement\",\n \"do_statement\",\n \"switch_case\",\n \"catch_clause\",\n \"ternary_expression\",\n]);\n\nconst PY_BRANCH_TYPES = new Set([\n \"if_statement\",\n \"elif_clause\",\n \"for_statement\",\n \"while_statement\",\n \"except_clause\",\n \"conditional_expression\",\n]);\n\nexport class ComplexityExtractor implements StyleExtractor {\n readonly name = \"complexity\";\n\n extract(file: ParsedFile): Observation[] {\n const observations: Observation[] = [];\n\n const lineCount = file.content\n .split(\"\\n\")\n .filter((l) => l.trim() !== \"\").length;\n\n observations.push({\n type: \"complexity.fileLength\",\n category: \"complexity\",\n value: lineCount,\n file: file.filePath,\n line: 1,\n });\n\n const functionTypes = this.getFunctionTypes(file.language);\n const functions = this.findFunctions(\n file.tree.rootNode, functionTypes, file.language,\n );\n\n for (const fn of functions) {\n observations.push(...this.functionObservations(fn, file.filePath));\n }\n\n return observations;\n }\n\n private functionObservations(fn: FunctionInfo, filePath: string): Observation[] {\n const metrics: Array<[string, number]> = [\n [\"complexity.functionLength\", fn.statementCount],\n [\"complexity.nestingDepth\", fn.maxNestingDepth],\n [\"complexity.cyclomatic\", fn.cyclomaticComplexity],\n ];\n return metrics.map(([type, value]) => ({\n type,\n category: \"complexity\",\n value,\n file: filePath,\n line: fn.line,\n metadata: { functionName: fn.name },\n }));\n }\n\n private getFunctionTypes(language: string): Set<string> {\n return language === \"python\" ? PY_FUNCTION_TYPES : TS_FUNCTION_TYPES;\n }\n\n private findFunctions(\n root: Node,\n functionTypes: Set<string>,\n language: string,\n ): FunctionInfo[] {\n const functions: FunctionInfo[] = [];\n\n const visit = (node: Node): void => {\n if (functionTypes.has(node.type)) {\n const info = this.analyzeFunctionNode(node, language);\n if (info) functions.push(info);\n }\n for (const child of node.children) {\n visit(child);\n }\n };\n\n visit(root);\n return functions;\n }\n\n private analyzeFunctionNode(\n node: Node,\n language: string,\n ): FunctionInfo | null {\n const nameNode = node.childForFieldName(\"name\");\n if (!nameNode) return null;\n const name = nameNode.text;\n\n const body = node.childForFieldName(\"body\");\n if (!body) return null;\n\n const statementCount = this.countStatements(body, language);\n const maxNestingDepth = this.measureNestingDepth(body, language, 0);\n const cyclomaticComplexity = this.measureCyclomaticComplexity(\n body, language,\n );\n\n return {\n name,\n statementCount,\n maxNestingDepth,\n cyclomaticComplexity,\n line: node.startPosition.row + 1,\n };\n }\n\n private countStatements(body: Node, language: string): number {\n let count = 0;\n for (const child of body.namedChildren) {\n if (this.isStatement(child, language)) {\n count++;\n }\n }\n return count;\n }\n\n private isStatement(node: Node, language: string): boolean {\n if (language === \"python\") {\n return this.isPythonStatement(node);\n }\n return this.isTypeScriptStatement(node);\n }\n\n private isTypeScriptStatement(node: Node): boolean {\n const statementTypes = new Set([\n \"lexical_declaration\",\n \"variable_declaration\",\n \"expression_statement\",\n \"return_statement\",\n \"if_statement\",\n \"for_statement\",\n \"for_in_statement\",\n \"while_statement\",\n \"do_statement\",\n \"switch_statement\",\n \"try_statement\",\n \"throw_statement\",\n \"break_statement\",\n \"continue_statement\",\n ]);\n return statementTypes.has(node.type);\n }\n\n private isPythonStatement(node: Node): boolean {\n const statementTypes = new Set([\n \"expression_statement\",\n \"return_statement\",\n \"if_statement\",\n \"for_statement\",\n \"while_statement\",\n \"try_statement\",\n \"raise_statement\",\n \"assert_statement\",\n \"pass_statement\",\n \"break_statement\",\n \"continue_statement\",\n \"assignment\",\n \"augmented_assignment\",\n ]);\n return statementTypes.has(node.type);\n }\n\n private measureNestingDepth(\n node: Node,\n language: string,\n depth: number,\n ): number {\n const nestingTypes = language === \"python\"\n ? PY_NESTING_TYPES\n : TS_NESTING_TYPES;\n\n let maxDepth = depth;\n\n for (const child of node.namedChildren) {\n if (nestingTypes.has(child.type)) {\n const childMax = this.measureNestingDepth(\n child, language, depth + 1,\n );\n if (childMax > maxDepth) maxDepth = childMax;\n } else {\n const childMax = this.measureNestingDepth(\n child, language, depth,\n );\n if (childMax > maxDepth) maxDepth = childMax;\n }\n }\n\n return maxDepth;\n }\n\n private measureCyclomaticComplexity(\n body: Node,\n language: string,\n ): number {\n let complexity = 1;\n const branchTypes = language === \"python\"\n ? PY_BRANCH_TYPES\n : TS_BRANCH_TYPES;\n\n const visit = (node: Node): void => {\n complexity += this.branchIncrement(node, language, branchTypes);\n\n for (const child of node.namedChildren) {\n visit(child);\n }\n };\n\n visit(body);\n return complexity;\n }\n\n private branchIncrement(\n node: Node,\n language: string,\n branchTypes: Set<string>,\n ): number {\n let increment = 0;\n if (branchTypes.has(node.type)) {\n increment++;\n }\n\n if (node.type === \"binary_expression\") {\n const operator = node.childForFieldName(\"operator\");\n if (operator) {\n const text = operator.text;\n if (text === \"&&\" || text === \"||\") {\n increment++;\n }\n }\n }\n\n if (\n language === \"python\" &&\n node.type === \"boolean_operator\"\n ) {\n increment++;\n }\n return increment;\n }\n}\n","import type { StyleExtractor, Observation, ParsedFile } from \"./types.js\";\nimport type {\n IClone,\n IMapFrame,\n IOptions,\n} from \"@jscpd/core\";\n\ninterface SourceFile {\n content: string;\n path: string;\n language: string;\n}\n\ninterface CloneInstance {\n sourceFile: string;\n startLine: number;\n endLine: number;\n fragment: string;\n}\n\ninterface CloneGroup {\n instances: CloneInstance[];\n linesCount: number;\n}\n\nexport class IdiomsExtractor implements StyleExtractor {\n readonly name = \"idioms\";\n\n private minLines: number;\n private minTokens: number;\n\n constructor(options?: { minLines?: number; minTokens?: number }) {\n this.minLines = options?.minLines ?? 3;\n this.minTokens = options?.minTokens ?? 25;\n }\n\n extract(_file: ParsedFile): Observation[] {\n return [];\n }\n\n async extractFromSources(sources: SourceFile[]): Promise<Observation[]> {\n const observations: Observation[] = [];\n\n const clones = await this.detectClones(sources);\n const groups = this.groupClones(clones);\n\n for (const group of groups.values()) {\n const frequency = group.instances.length;\n if (frequency < 2) continue;\n\n observations.push(this.cloneObservation(group));\n }\n\n return observations;\n }\n\n private cloneObservation(group: CloneGroup): Observation {\n const frequency = group.instances.length;\n const first = group.instances[0]!;\n\n return {\n type: \"idiom.clone\",\n category: \"idioms\",\n value: this.summarizeClone(first.fragment),\n file: first.sourceFile,\n line: first.startLine,\n metadata: {\n frequency,\n fragment: first.fragment,\n linesCount: group.linesCount,\n locations: group.instances.map((inst) => ({\n file: inst.sourceFile,\n startLine: inst.startLine,\n endLine: inst.endLine,\n })),\n },\n };\n }\n\n private async detectClones(\n sources: SourceFile[],\n ): Promise<CloneGroup[]> {\n const { allClones, sourceMap } = await this.runDetector(sources);\n return allClones.map((clone) => this.toCloneGroup(clone, sourceMap));\n }\n\n private async runDetector(\n sources: SourceFile[],\n ): Promise<{ allClones: IClone[]; sourceMap: Map<string, string> }> {\n const { Detector, MemoryStore } = await import(\"@jscpd/core\");\n const { Tokenizer } = await import(\"@jscpd/tokenizer\");\n\n const options: IOptions = {\n minLines: this.minLines,\n minTokens: this.minTokens,\n };\n\n const store = new MemoryStore<IMapFrame>();\n const tokenizer = new Tokenizer();\n const detector = new Detector(tokenizer, store, [], options);\n\n const allClones: IClone[] = [];\n const sourceMap = new Map<string, string>();\n\n for (const source of sources) {\n sourceMap.set(source.path, source.content);\n const format = this.languageToFormat(source.language);\n const detected = await detector.detect(\n source.path,\n source.content,\n format,\n );\n allClones.push(...detected);\n }\n\n return { allClones, sourceMap };\n }\n\n private toCloneGroup(\n clone: IClone,\n sourceMap: Map<string, string>,\n ): CloneGroup {\n return {\n instances: [\n this.toInstance(clone.duplicationA, sourceMap),\n this.toInstance(clone.duplicationB, sourceMap),\n ],\n linesCount:\n clone.duplicationA.end.line - clone.duplicationA.start.line + 1,\n };\n }\n\n private toInstance(\n duplication: IClone[\"duplicationA\"],\n sourceMap: Map<string, string>,\n ): CloneInstance {\n const content = sourceMap.get(duplication.sourceId) ?? \"\";\n return {\n sourceFile: duplication.sourceId,\n startLine: duplication.start.line,\n endLine: duplication.end.line,\n fragment: this.extractFragment(\n content,\n duplication.start.line,\n duplication.end.line,\n ),\n };\n }\n\n private extractFragment(\n content: string,\n startLine: number,\n endLine: number,\n ): string {\n const lines = content.split(\"\\n\");\n return lines.slice(startLine - 1, endLine).join(\"\\n\");\n }\n\n private languageToFormat(language: string): string {\n const mapping: Record<string, string> = {\n typescript: \"typescript\",\n javascript: \"javascript\",\n python: \"python\",\n tsx: \"tsx\",\n jsx: \"jsx\",\n };\n return mapping[language] ?? language;\n }\n\n private groupClones(\n clones: CloneGroup[],\n ): Map<string, CloneGroup> {\n const groups = new Map<string, CloneGroup>();\n\n for (const clone of clones) {\n const key = this.normalizeFragment(clone.instances[0]?.fragment ?? \"\");\n\n const existing = groups.get(key);\n if (existing) {\n this.mergeInstances(existing, clone);\n } else {\n groups.set(key, {\n instances: [...clone.instances],\n linesCount: clone.linesCount,\n });\n }\n }\n\n return groups;\n }\n\n private mergeInstances(existing: CloneGroup, clone: CloneGroup): void {\n for (const inst of clone.instances) {\n const alreadyTracked = existing.instances.some(\n (e) =>\n e.sourceFile === inst.sourceFile &&\n e.startLine === inst.startLine,\n );\n if (!alreadyTracked) {\n existing.instances.push(inst);\n }\n }\n }\n\n private normalizeFragment(fragment: string): string {\n return fragment.replace(/\\s+/g, \" \").trim().substring(0, 200);\n }\n\n private summarizeClone(fragment: string): string {\n const firstLine = fragment.split(\"\\n\")[0]?.trim() ?? \"\";\n if (firstLine.length > 80) {\n return firstLine.substring(0, 77) + \"...\";\n }\n return firstLine;\n }\n}\n","import type { StyleExtractor, Observation, ParsedFile } from \"./types.js\";\n\ninterface ReviewComment {\n body: string;\n file?: string;\n}\n\ntype ReviewTopic =\n | \"naming\"\n | \"error-handling\"\n | \"complexity\"\n | \"style\"\n | \"performance\"\n | \"documentation\"\n | \"testing\"\n | \"security\"\n | \"readability\"\n | \"structure\";\n\ninterface TopicPattern {\n topic: ReviewTopic;\n patterns: RegExp[];\n}\n\nconst TOPIC_PATTERNS: TopicPattern[] = [\n {\n topic: \"naming\",\n patterns: [\n /\\bnam(?:e|ing)\\b/i,\n /\\brenam(?:e|ing)\\b/i,\n /\\bcamelCase\\b/i,\n /\\bsnake_case\\b/i,\n /\\bdescriptive\\b/i,\n /\\bconfusing\\b/i,\n /\\bprefer\\s+\\S+\\s+over\\b/i,\n ],\n },\n {\n topic: \"error-handling\",\n patterns: [\n /\\berror\\s*handl/i,\n /\\bmissing\\s+error/i,\n /\\btry\\s*\\/?\\s*catch\\b/i,\n /\\bwhat\\s+happens\\s+if\\b/i,\n /\\bedge\\s*case/i,\n /\\bnull\\b/i,\n /\\bfails?\\b/i,\n ],\n },\n {\n topic: \"complexity\",\n patterns: [\n /\\bcomplex\\b/i,\n /\\btoo\\s+long\\b/i,\n /\\bsplit\\b.*\\bup\\b/i,\n /\\bextract\\b.*\\bfunction/i,\n /\\bsmaller\\s+functions?\\b/i,\n /\\bsimplif/i,\n /\\bnesting\\b/i,\n ],\n },\n {\n topic: \"style\",\n patterns: [\n /\\bstyle\\b/i,\n /\\bformat/i,\n /\\bconsistenc/i,\n /\\bnit\\b/i,\n /\\bquotes?\\b/i,\n /\\bsemicolon/i,\n /\\bindent/i,\n /\\bwhitespace\\b/i,\n ],\n },\n {\n topic: \"performance\",\n patterns: [\n /\\bperforman/i,\n /\\bmemoiz/i,\n /\\bre-?render/i,\n /\\boptimiz/i,\n /\\bexpensive\\b/i,\n /\\befficien/i,\n /\\bcach/i,\n ],\n },\n {\n topic: \"documentation\",\n patterns: [\n /\\bdocument/i,\n /\\bjsdoc\\b/i,\n ],\n },\n {\n topic: \"testing\",\n patterns: [\n /\\btest/i,\n /\\bcover(?:age)?\\b/i,\n /\\bassert/i,\n /\\bmock/i,\n /\\bspec\\b/i,\n ],\n },\n {\n topic: \"security\",\n patterns: [\n /\\bsecur/i,\n /\\bvulnerab/i,\n /\\bsaniti[zs]/i,\n /\\binject/i,\n /\\bescap/i,\n /\\bxss\\b/i,\n ],\n },\n {\n topic: \"readability\",\n patterns: [\n /\\breadab/i,\n /\\bearly\\s+return/i,\n /\\bguard\\s+clause/i,\n ],\n },\n {\n topic: \"structure\",\n patterns: [\n /\\bstructur/i,\n /\\barchitect/i,\n /\\borganiz/i,\n /\\bseparati/i,\n ],\n },\n];\n\nconst KEYWORD_PATTERNS: Array<{ keyword: string; pattern: RegExp }> = [\n { keyword: \"early-return\", pattern: /\\bearly\\s+return\\b/i },\n { keyword: \"guard-clause\", pattern: /\\bguard\\s+clause\\b/i },\n {\n keyword: \"single-responsibility\",\n pattern: /\\bsingle\\s+responsib/i,\n },\n { keyword: \"dry\", pattern: /\\b(?:DRY|don'?t\\s+repeat)\\b/i },\n { keyword: \"immutability\", pattern: /\\bimmutab/i },\n { keyword: \"type-safety\", pattern: /\\btype[\\s-]*safe/i },\n { keyword: \"null-check\", pattern: /\\bnull\\s+check/i },\n { keyword: \"magic-number\", pattern: /\\bmagic\\s+number/i },\n];\n\nexport class ReviewVoiceExtractor implements StyleExtractor {\n readonly name = \"reviewVoice\";\n\n extract(_file: ParsedFile): Observation[] {\n return [];\n }\n\n extractFromComments(comments: ReviewComment[]): Observation[] {\n if (comments.length === 0) return [];\n\n const observations: Observation[] = [];\n\n observations.push(...this.categorizeTopics(comments));\n observations.push(...this.extractKeywords(comments));\n\n return observations;\n }\n\n private categorizeTopics(comments: ReviewComment[]): Observation[] {\n const { topicCounts, topicExamples } = this.countTopics(comments);\n\n const observations: Observation[] = [];\n\n for (const [topic, count] of topicCounts) {\n observations.push({\n type: \"reviewVoice.topicFrequency\",\n category: \"reviewVoice\",\n value: topic,\n file: \"_reviews\",\n line: 0,\n metadata: {\n count,\n total: comments.length,\n ratio: count / comments.length,\n examples: topicExamples.get(topic) ?? [],\n },\n });\n }\n\n observations.sort(\n (a, b) =>\n ((b.metadata?.count as number) ?? 0) -\n ((a.metadata?.count as number) ?? 0),\n );\n\n return observations;\n }\n\n private countTopics(comments: ReviewComment[]): {\n topicCounts: Map<ReviewTopic, number>;\n topicExamples: Map<ReviewTopic, string[]>;\n } {\n const topicCounts = new Map<ReviewTopic, number>();\n const topicExamples = new Map<ReviewTopic, string[]>();\n\n for (const comment of comments) {\n for (const topic of this.matchTopics(comment.body)) {\n topicCounts.set(topic, (topicCounts.get(topic) ?? 0) + 1);\n\n const examples = topicExamples.get(topic) ?? [];\n if (examples.length < 3) {\n examples.push(comment.body);\n topicExamples.set(topic, examples);\n }\n }\n }\n\n return { topicCounts, topicExamples };\n }\n\n private matchTopics(body: string): Set<ReviewTopic> {\n const matchedTopics = new Set<ReviewTopic>();\n\n for (const { topic, patterns } of TOPIC_PATTERNS) {\n for (const pattern of patterns) {\n if (pattern.test(body)) {\n matchedTopics.add(topic);\n break;\n }\n }\n }\n\n return matchedTopics;\n }\n\n private extractKeywords(comments: ReviewComment[]): Observation[] {\n const keywordCounts = new Map<string, number>();\n\n for (const comment of comments) {\n for (const { keyword, pattern } of KEYWORD_PATTERNS) {\n if (pattern.test(comment.body)) {\n keywordCounts.set(keyword, (keywordCounts.get(keyword) ?? 0) + 1);\n }\n }\n }\n\n const observations: Observation[] = [];\n\n for (const [keyword, count] of keywordCounts) {\n observations.push({\n type: \"reviewVoice.keyword\",\n category: \"reviewVoice\",\n value: keyword,\n file: \"_reviews\",\n line: 0,\n metadata: {\n count,\n total: comments.length,\n },\n });\n }\n\n return observations;\n }\n}\n","import type { StyleExtractor } from \"./types.js\";\nimport { NamingExtractor } from \"./naming.js\";\nimport { StructureExtractor } from \"./structure.js\";\nimport { ControlFlowExtractor } from \"./control-flow.js\";\nimport { DocumentationExtractor } from \"./documentation.js\";\nimport { ErrorHandlingExtractor } from \"./error-handling.js\";\nimport { FormattingExtractor } from \"./formatting.js\";\nimport { ComplexityExtractor } from \"./complexity.js\";\nimport { IdiomsExtractor } from \"./idioms.js\";\nimport { ReviewVoiceExtractor } from \"./review-voice.js\";\n\n/**\n * Canonical set of style extractors. Single source of truth — CLI commands,\n * scripts, and tests should import this rather than reconstructing the list.\n */\nexport function createStyleExtractors(): StyleExtractor[] {\n return [\n new NamingExtractor(),\n new StructureExtractor(),\n new ControlFlowExtractor(),\n new DocumentationExtractor(),\n new ErrorHandlingExtractor(),\n new FormattingExtractor(),\n new ComplexityExtractor(),\n new IdiomsExtractor(),\n new ReviewVoiceExtractor(),\n ];\n}\n","import type { Severity, SeverityThresholds } from \"@titan-design/style-profile\";\nimport { DEFAULT_SEVERITY_THRESHOLDS, severityForConfidence } from \"@titan-design/style-profile\";\nimport type { Stability } from \"./stability.js\";\n\nexport type { Severity, SeverityThresholds };\nexport { DEFAULT_SEVERITY_THRESHOLDS };\n\nexport interface StabilityWeights {\n high: number;\n medium: number;\n low: number;\n}\n\nexport const DEFAULT_STABILITY_WEIGHTS: StabilityWeights = {\n high: 1.0,\n medium: 0.85,\n low: 0.7,\n};\n\nexport function computeConfidence(\n consistency: number,\n stability: Stability,\n weights: StabilityWeights = DEFAULT_STABILITY_WEIGHTS,\n): number {\n return Math.min(1.0, consistency * weights[stability]);\n}\n\nexport { severityForConfidence as mapSeverity };\n","import type { Observation } from \"../extractors/types.js\";\n\nexport interface FrequencyDistribution {\n values: Map<string | number | boolean, number>;\n total: number;\n dominant: string | number | boolean;\n consistency: number;\n}\n\nexport function groupByType(\n observations: Observation[],\n): Map<string, Observation[]> {\n const groups = new Map<string, Observation[]>();\n\n for (const obs of observations) {\n const existing = groups.get(obs.type) ?? [];\n existing.push(obs);\n groups.set(obs.type, existing);\n }\n\n return groups;\n}\n\nexport function computeDistribution(\n observations: Observation[],\n): FrequencyDistribution {\n const valueCounts = new Map<string | number | boolean, number>();\n\n for (const obs of observations) {\n const key = normalizeValue(obs.value);\n valueCounts.set(key, (valueCounts.get(key) ?? 0) + 1);\n }\n\n const total = observations.length;\n\n let dominant: string | number | boolean = \"\";\n let maxCount = 0;\n\n for (const [value, count] of valueCounts) {\n if (count > maxCount) {\n maxCount = count;\n dominant = value;\n }\n }\n\n return {\n values: valueCounts,\n total,\n dominant,\n consistency: total > 0 ? maxCount / total : 0,\n };\n}\n\nfunction normalizeValue(value: unknown): string | number | boolean {\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return value;\n }\n if (Array.isArray(value)) {\n return JSON.stringify(value);\n }\n return String(value);\n}\n\nexport function selectExamples(\n observations: Observation[],\n maxExamples: number,\n): Observation[] {\n if (observations.length <= maxExamples) {\n return [...observations];\n }\n\n const step = Math.floor(observations.length / maxExamples);\n const examples: Observation[] = [];\n\n for (\n let i = 0;\n i < observations.length && examples.length < maxExamples;\n i += step\n ) {\n examples.push(observations[i]!);\n }\n\n return examples;\n}\n","export type Stability = \"high\" | \"medium\" | \"low\";\n\n/**\n * Stability lookup table derived from RoPGen research and the unified\n * feature taxonomy (docs/research/07-unified-feature-taxonomy.md).\n *\n * Key: an observation type exactly as an extractor emits it (e.g., \"naming.variable\").\n * Value: stability rating.\n *\n * High = persists even when developer tries to write differently (weight 1.0)\n * Medium = consistent under normal conditions (weight 0.85)\n * Low = varies by project/language/intent (weight 0.7)\n *\n * stability.test.ts fails when an emitted type is neither keyed here nor listed\n * in UNRATED_TYPES, and when a key here names a type no extractor emits.\n */\nexport const STABILITY_MAP: Record<string, Stability> = {\n // Category 1: Naming Conventions\n \"naming.variable\": \"high\",\n \"naming.function\": \"high\",\n \"naming.type\": \"high\",\n \"naming.constant\": \"high\",\n \"naming.boolean\": \"medium\",\n \"naming.parameter\": \"medium\",\n \"naming.enum\": \"high\",\n \"naming.private-member\": \"high\",\n\n // Category 2: Code Structure\n \"structure.import-group\": \"high\",\n \"structure.import-order\": \"high\",\n \"structure.export-style\": \"high\",\n \"structure.barrel-file\": \"medium\",\n \"structure.export-proximity\": \"medium\",\n\n // Category 3: Control Flow Patterns\n \"control-flow.guard-clause\": \"high\",\n \"control-flow.ternary\": \"medium\",\n \"control-flow.array-method\": \"high\",\n \"control-flow.for-loop\": \"medium\",\n \"control-flow.for-of\": \"medium\",\n \"control-flow.for-in\": \"medium\",\n \"control-flow.async-await\": \"high\",\n\n // Category 4: Error Handling\n \"error-handling.try-catch\": \"high\",\n \"error-handling.catch-specificity\": \"medium\",\n \"error-handling.result-type\": \"high\",\n \"error-handling.custom-error-class\": \"medium\",\n \"error-handling.exhaustive-switch\": \"high\",\n \"error-handling.assert-never\": \"high\",\n\n // Category 5: Documentation\n \"documentation.jsdoc-presence\": \"high\",\n \"documentation.public-coverage\": \"medium\",\n \"documentation.private-coverage\": \"medium\",\n \"documentation.inline-comment\": \"medium\",\n \"documentation.comment-placement\": \"medium\",\n \"documentation.jsdoc-tag\": \"medium\",\n\n // Category 7: Formatting & Layout\n \"formatting.indentStyle\": \"high\",\n \"formatting.indentSize\": \"high\",\n \"formatting.semicolons\": \"high\",\n \"formatting.quoteStyle\": \"high\",\n \"formatting.trailingCommas\": \"high\",\n \"formatting.braceStyle\": \"high\",\n \"formatting.trailingNewline\": \"high\",\n\n // Category 9: Habitual Idioms\n \"idiom.clone\": \"high\",\n\n // Category 10: Review Voice\n \"reviewVoice.topicFrequency\": \"medium\",\n \"reviewVoice.keyword\": \"medium\",\n\n // Complexity (from task-07)\n \"complexity.functionLength\": \"high\",\n \"complexity.nestingDepth\": \"high\",\n \"complexity.cyclomatic\": \"high\",\n \"complexity.fileLength\": \"medium\",\n};\n\n/**\n * Emitted types the taxonomy gives no rating. They take the medium default on\n * purpose, and each is an open question for the profile's owner.\n */\nexport const UNRATED_TYPES: ReadonlySet<string> = new Set([\n \"control-flow.if-else\",\n \"control-flow.promise-then\",\n \"control-flow.else-after-return\",\n]);\n\nexport function lookupStability(type: string): Stability {\n if (STABILITY_MAP[type]) return STABILITY_MAP[type];\n\n const category = type.indexOf(\".\") > 0 ? type.substring(0, type.indexOf(\".\")) : type;\n if (STABILITY_MAP[category]) return STABILITY_MAP[category];\n\n return \"medium\";\n}\n","import type { Observation, ObservationCategory } from \"../extractors/types.js\";\nimport {\n computeConfidence,\n mapSeverity,\n DEFAULT_STABILITY_WEIGHTS,\n DEFAULT_SEVERITY_THRESHOLDS,\n type StabilityWeights,\n type SeverityThresholds,\n type Severity,\n} from \"./confidence.js\";\nimport {\n groupByType,\n computeDistribution,\n selectExamples,\n type FrequencyDistribution,\n} from \"./frequency.js\";\nimport { lookupStability, type Stability } from \"./stability.js\";\n\nexport { computeConfidence, mapSeverity } from \"./confidence.js\";\nexport { lookupStability, type Stability } from \"./stability.js\";\nexport type { FrequencyDistribution } from \"./frequency.js\";\nexport type { Severity } from \"@titan-design/style-profile\";\nexport type {\n StabilityWeights,\n SeverityThresholds,\n} from \"./confidence.js\";\n\nexport interface AggregatedFeature {\n type: string;\n category: ObservationCategory;\n convention: string | number | boolean | string[];\n distribution: FrequencyDistribution;\n confidence: number;\n stability: Stability;\n severity: Severity;\n needsReview: boolean;\n examples: Observation[];\n}\n\nexport interface AggregatorConfig {\n stabilityWeights?: StabilityWeights;\n severityThresholds?: SeverityThresholds;\n reviewThreshold?: number;\n maxExamples?: number;\n}\n\nexport interface AggregatorResult {\n features: Map<string, AggregatedFeature>;\n reviewQueue: AggregatedFeature[];\n summary: {\n totalObservations: number;\n totalFeatures: number;\n avgConfidence: number;\n featuresNeedingReview: number;\n };\n}\n\nexport class Aggregator {\n private stabilityWeights: StabilityWeights;\n private severityThresholds: SeverityThresholds;\n private reviewThreshold: number;\n private maxExamples: number;\n\n constructor(config?: AggregatorConfig) {\n this.stabilityWeights =\n config?.stabilityWeights ?? DEFAULT_STABILITY_WEIGHTS;\n this.severityThresholds =\n config?.severityThresholds ?? DEFAULT_SEVERITY_THRESHOLDS;\n this.reviewThreshold = config?.reviewThreshold ?? 0.6;\n this.maxExamples = config?.maxExamples ?? 5;\n }\n\n aggregate(observations: Observation[]): AggregatorResult {\n const grouped = groupByType(observations);\n const features = new Map<string, AggregatedFeature>();\n const reviewQueue: AggregatedFeature[] = [];\n\n for (const [type, typeObservations] of grouped) {\n const feature = this.buildFeature(type, typeObservations);\n\n features.set(type, feature);\n\n if (feature.needsReview) {\n reviewQueue.push(feature);\n }\n }\n\n reviewQueue.sort((a, b) => a.confidence - b.confidence);\n\n return {\n features,\n reviewQueue,\n summary: {\n totalObservations: observations.length,\n totalFeatures: features.size,\n avgConfidence: averageConfidence(features),\n featuresNeedingReview: reviewQueue.length,\n },\n };\n }\n\n private buildFeature(\n type: string,\n typeObservations: Observation[],\n ): AggregatedFeature {\n const distribution = computeDistribution(typeObservations);\n const stability = lookupStability(type);\n const confidence = computeConfidence(\n distribution.consistency,\n stability,\n this.stabilityWeights,\n );\n\n return {\n type,\n category: this.extractCategory(type),\n convention: distribution.dominant,\n distribution,\n confidence,\n stability,\n severity: mapSeverity(confidence, this.severityThresholds),\n needsReview: confidence < this.reviewThreshold,\n examples: selectExamples(typeObservations, this.maxExamples),\n };\n }\n\n private extractCategory(type: string): ObservationCategory {\n const dotIndex = type.indexOf(\".\");\n return (dotIndex > 0 ? type.substring(0, dotIndex) : type) as ObservationCategory;\n }\n}\n\nfunction averageConfidence(features: Map<string, AggregatedFeature>): number {\n const confidences = Array.from(features.values()).map((f) => f.confidence);\n return confidences.length > 0\n ? confidences.reduce((a, b) => a + b, 0) / confidences.length\n : 0;\n}\n","import type { LlmMessage, LlmProvider } from \"./llm.js\";\n\nexport interface LlmJob<TKey> {\n key: TKey;\n messages: LlmMessage[];\n maxTokens: number;\n}\n\nexport interface LlmJobSuccess<TKey> {\n key: TKey;\n content: string;\n tokensUsed: number;\n}\n\nexport interface LlmJobFailure<TKey> {\n key: TKey;\n error: string;\n}\n\nexport interface LlmRunResult<TKey> {\n results: LlmJobSuccess<TKey>[];\n errors: LlmJobFailure<TKey>[];\n totalTokensUsed: number;\n budgetExceeded: boolean;\n}\n\nexport interface LlmRunnerConfig {\n provider: LlmProvider;\n totalTokenBudget?: number;\n}\n\n/**\n * Runs a list of LLM jobs sequentially against a provider, halting when the\n * cumulative token budget is exceeded and capturing per-job errors instead\n * of throwing. Knows nothing about features, prompts, or domain shapes —\n * callers build jobs upstream.\n */\nexport class LlmRunner {\n private provider: LlmProvider;\n private totalTokenBudget: number;\n\n constructor(config: LlmRunnerConfig) {\n this.provider = config.provider;\n this.totalTokenBudget = config.totalTokenBudget ?? 20_000;\n }\n\n async run<TKey>(jobs: LlmJob<TKey>[]): Promise<LlmRunResult<TKey>> {\n const results: LlmJobSuccess<TKey>[] = [];\n const errors: LlmJobFailure<TKey>[] = [];\n let totalTokensUsed = 0;\n let budgetExceeded = false;\n\n for (const job of jobs) {\n if (totalTokensUsed >= this.totalTokenBudget) {\n budgetExceeded = true;\n break;\n }\n\n totalTokensUsed += await this.runJob(job, results, errors);\n }\n\n return { results, errors, totalTokensUsed, budgetExceeded };\n }\n\n // Returns the tokens the job consumed, which is zero when the provider throws.\n private async runJob<TKey>(\n job: LlmJob<TKey>,\n results: LlmJobSuccess<TKey>[],\n errors: LlmJobFailure<TKey>[],\n ): Promise<number> {\n try {\n const response = await this.provider.generate(job.messages, {\n maxTokens: job.maxTokens,\n });\n results.push({\n key: job.key,\n content: response.content,\n tokensUsed: response.tokensUsed,\n });\n return response.tokensUsed;\n } catch (error) {\n errors.push({\n key: job.key,\n error: error instanceof Error ? error.message : String(error),\n });\n return 0;\n }\n }\n}\n","export interface PromptInput {\n category: string;\n featureType: string;\n convention: string | number | boolean | string[];\n confidence: number;\n consistency: number;\n examples: string[];\n distribution?: Record<string, number>;\n}\n\nexport interface PromptTemplate {\n featureTypes: string[];\n system: string;\n buildUserMessage: (input: PromptInput) => string;\n maxTokens: number;\n}\n\nexport const DESCRIPTION_PROMPT: PromptTemplate = {\n featureTypes: [\n \"documentation.comment-placement\",\n \"documentation.inline-comment\",\n \"documentation.jsdoc-tag\",\n \"error-handling.catch-specificity\",\n \"structure.export-style\",\n ],\n system:\n \"You are a code style analyst. Given statistical observations about a developer's coding patterns, write a concise, actionable style rule description. Output ONLY the description text (1-3 sentences). Do not include markdown formatting or headers.\",\n buildUserMessage: (input: PromptInput) => {\n const lines = [\n `Feature: ${input.featureType}`,\n `Dominant pattern: ${JSON.stringify(input.convention)}`,\n `Confidence: ${(input.confidence * 100).toFixed(0)}%`,\n `Consistency: ${(input.consistency * 100).toFixed(0)}%`,\n ];\n\n if (input.distribution) {\n lines.push(\n `Distribution: ${JSON.stringify(input.distribution)}`,\n );\n }\n\n if (input.examples.length > 0) {\n lines.push(\"\", \"Representative code samples:\");\n for (const example of input.examples.slice(0, 5)) {\n lines.push(\"```\", example, \"```\");\n }\n }\n\n lines.push(\n \"\",\n \"Write a concise style rule description for this pattern.\",\n );\n\n return lines.join(\"\\n\");\n },\n maxTokens: 300,\n};\n\nexport const REVIEW_VOICE_PROMPT: PromptTemplate = {\n featureTypes: [\n \"reviewVoice.topicFrequency\",\n \"reviewVoice.keyword\",\n ],\n system:\n \"You are analyzing a developer's code review comments to understand their review voice and priorities. Given topic frequencies and example comments, synthesize a brief description of what this developer cares about in code reviews. Output ONLY the synthesis text (2-4 sentences). Do not include markdown formatting or headers.\",\n buildUserMessage: (input: PromptInput) => {\n const lines = [\n `Review topic: ${input.featureType}`,\n `Pattern: ${JSON.stringify(input.convention)}`,\n ];\n\n if (input.distribution) {\n lines.push(\n `Topic frequencies: ${JSON.stringify(input.distribution)}`,\n );\n }\n\n if (input.examples.length > 0) {\n lines.push(\"\", \"Example review comments:\");\n for (const example of input.examples.slice(0, 5)) {\n lines.push(`- \"${example}\"`);\n }\n }\n\n lines.push(\n \"\",\n \"Synthesize what this developer values in code reviews.\",\n );\n\n return lines.join(\"\\n\");\n },\n maxTokens: 400,\n};\n\nexport const AI_ENRICHED_FEATURES = [\n ...DESCRIPTION_PROMPT.featureTypes,\n ...REVIEW_VOICE_PROMPT.featureTypes,\n];\n\nexport function getPromptForFeature(\n featureType: string,\n): PromptTemplate | null {\n if (DESCRIPTION_PROMPT.featureTypes.includes(featureType)) {\n return DESCRIPTION_PROMPT;\n }\n if (REVIEW_VOICE_PROMPT.featureTypes.includes(featureType)) {\n return REVIEW_VOICE_PROMPT;\n }\n return null;\n}\n\nexport function needsAiEnrichment(featureType: string): boolean {\n return AI_ENRICHED_FEATURES.includes(featureType);\n}\n","import type { AggregatedFeature } from \"../aggregator/aggregator.js\";\nimport { LlmRunner, type LlmJob, type LlmRunResult } from \"./llm-runner.js\";\nimport type { LlmMessage, LlmProvider } from \"./llm.js\";\nimport {\n getPromptForFeature,\n needsAiEnrichment,\n type PromptInput,\n} from \"./prompts.js\";\n\nexport { needsAiEnrichment, AI_ENRICHED_FEATURES } from \"./prompts.js\";\nexport type { LlmProvider, LlmMessage, LlmResponse } from \"./llm.js\";\n\nexport type { AggregatedFeature } from \"../aggregator/aggregator.js\";\n\nexport interface EnrichmentEntry {\n featureType: string;\n description: string;\n tokensUsed: number;\n}\n\nexport interface EnrichmentError {\n featureType: string;\n error: string;\n}\n\nexport interface EnrichmentResult {\n enriched: Map<string, EnrichmentEntry>;\n errors: EnrichmentError[];\n totalTokensUsed: number;\n budgetExceeded: boolean;\n skipped: boolean;\n}\n\nexport interface EnricherConfig {\n provider: LlmProvider;\n enabled?: boolean;\n totalTokenBudget?: number;\n}\n\nexport class Enricher {\n private runner: LlmRunner;\n private enabled: boolean;\n\n constructor(config: EnricherConfig) {\n this.runner = new LlmRunner({\n provider: config.provider,\n totalTokenBudget: config.totalTokenBudget,\n });\n this.enabled = config.enabled ?? true;\n }\n\n async enrich(\n features: Map<string, AggregatedFeature>,\n ): Promise<EnrichmentResult> {\n if (!this.enabled) {\n return {\n enriched: new Map(),\n errors: [],\n totalTokensUsed: 0,\n budgetExceeded: false,\n skipped: true,\n };\n }\n\n const runResult = await this.runner.run(this.buildJobs(features));\n return toEnrichmentResult(runResult);\n }\n\n private buildJobs(\n features: Map<string, AggregatedFeature>,\n ): LlmJob<string>[] {\n const jobs: LlmJob<string>[] = [];\n for (const [type, feature] of features) {\n if (!needsAiEnrichment(type)) continue;\n const promptTemplate = getPromptForFeature(type);\n if (!promptTemplate) continue;\n\n const input = this.buildPromptInput(type, feature);\n const messages: LlmMessage[] = [\n { role: \"system\", content: promptTemplate.system },\n {\n role: \"user\",\n content: promptTemplate.buildUserMessage(input),\n },\n ];\n\n jobs.push({ key: type, messages, maxTokens: promptTemplate.maxTokens });\n }\n return jobs;\n }\n\n private buildPromptInput(\n type: string,\n feature: AggregatedFeature,\n ): PromptInput {\n const distributionRecord: Record<string, number> = {};\n for (const [key, count] of feature.distribution.values) {\n distributionRecord[String(key)] = count;\n }\n\n const exampleTexts = feature.examples.map((obs) => {\n if (typeof obs.value === \"string\") return obs.value;\n return JSON.stringify(obs.value);\n });\n\n return {\n category: feature.category,\n featureType: type,\n convention: feature.convention,\n confidence: feature.confidence,\n consistency: feature.distribution.consistency,\n examples: exampleTexts,\n distribution: distributionRecord,\n };\n }\n}\n\nfunction toEnrichmentResult(runResult: LlmRunResult<string>): EnrichmentResult {\n const enriched = new Map<string, EnrichmentEntry>();\n for (const r of runResult.results) {\n enriched.set(r.key, {\n featureType: r.key,\n description: r.content,\n tokensUsed: r.tokensUsed,\n });\n }\n\n return {\n enriched,\n errors: runResult.errors.map((e) => ({\n featureType: e.key,\n error: e.error,\n })),\n totalTokensUsed: runResult.totalTokensUsed,\n budgetExceeded: runResult.budgetExceeded,\n skipped: false,\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/extractors/naming.ts","../src/extractors/structure.ts","../src/extractors/control-flow.ts","../src/extractors/documentation.ts","../src/extractors/error-handling.ts","../src/extractors/formatting.ts","../src/extractors/formatting-config.ts","../src/extractors/complexity.ts","../src/extractors/idioms.ts","../src/extractors/review-voice.ts","../src/extractors/factory.ts","../src/aggregator/confidence.ts","../src/aggregator/frequency.ts","../src/aggregator/stability.ts","../src/aggregator/aggregator.ts","../src/enricher/llm-runner.ts","../src/enricher/prompts.ts","../src/enricher/enricher.ts"],"sourcesContent":["export type {\n IngestConfig,\n CodeCorpus,\n CodeFile,\n ReviewComment,\n PullRequest,\n PullRequestFile,\n IngestMetadata,\n} from \"./ingest/types.js\";\nexport {\n shouldIncludeFile,\n getLanguageFromPath,\n parseFile,\n getSupportedLanguages,\n} from \"@titan-design/code-parser\";\n\nexport type {\n StyleExtractor,\n Extractor,\n Observation,\n ObservationCategory,\n ParsedFile,\n} from \"./extractors/types.js\";\nexport { NamingExtractor } from \"./extractors/naming.js\";\nexport { StructureExtractor } from \"./extractors/structure.js\";\nexport { ControlFlowExtractor } from \"./extractors/control-flow.js\";\nexport { DocumentationExtractor } from \"./extractors/documentation.js\";\nexport { ErrorHandlingExtractor } from \"./extractors/error-handling.js\";\nexport { FormattingExtractor } from \"./extractors/formatting.js\";\nexport { ComplexityExtractor } from \"./extractors/complexity.js\";\nexport { IdiomsExtractor } from \"./extractors/idioms.js\";\nexport { ReviewVoiceExtractor } from \"./extractors/review-voice.js\";\n\nexport { createStyleExtractors } from \"./extractors/factory.js\";\n\nexport {\n Aggregator,\n computeConfidence,\n mapSeverity,\n lookupStability,\n type AggregatedFeature,\n type AggregatorConfig,\n type AggregatorResult,\n type FrequencyDistribution,\n type Severity,\n type Stability,\n type StabilityWeights,\n type SeverityThresholds,\n} from \"./aggregator/aggregator.js\";\n\nexport {\n Enricher,\n needsAiEnrichment,\n AI_ENRICHED_FEATURES,\n type LlmProvider,\n type LlmMessage,\n type LlmResponse,\n type EnrichmentEntry,\n type EnrichmentError,\n type EnrichmentResult,\n type EnricherConfig,\n} from \"./enricher/enricher.js\";\n","import type { Node } from \"web-tree-sitter\";\nimport type { StyleExtractor, ParsedFile, Observation } from \"./types.js\";\n\nconst NAMING_PATTERNS: Record<string, RegExp> = {\n camelCase: /^[a-z][a-zA-Z0-9]*$/,\n PascalCase: /^[A-Z][a-zA-Z0-9]*$/,\n snake_case: /^[a-z][a-z0-9]*(_[a-z0-9]+)+$/,\n SCREAMING_SNAKE: /^[A-Z][A-Z0-9]*(_[A-Z0-9]+)+$/,\n \"kebab-case\": /^[a-z][a-z0-9]*(-[a-z0-9]+)+$/,\n};\n\nconst BOOLEAN_PREFIXES = /^(is|has|should|can|will|did|was)[A-Z_]/;\nconst PYTHON_BOOLEAN_PREFIXES = /^(is|has|should|can|will|did|was)_/;\n\nfunction detectConvention(name: string): string | null {\n for (const [convention, pattern] of Object.entries(NAMING_PATTERNS)) {\n if (pattern.test(name)) return convention;\n }\n if (/^[a-z][a-z0-9]*$/.test(name)) return \"camelCase\";\n return null;\n}\n\n// One capitalised word counts too; a single letter does not, because it is almost always a TypeVar or generic.\nconst SINGLE_WORD_CONSTANT = /^[A-Z][A-Z0-9]+$/;\n\nfunction isConstantName(name: string): boolean {\n return NAMING_PATTERNS.SCREAMING_SNAKE!.test(name) || SINGLE_WORD_CONSTANT.test(name);\n}\n\nfunction detectBooleanPrefix(name: string, language: string): string | null {\n const pattern = language === \"python\" ? PYTHON_BOOLEAN_PREFIXES : BOOLEAN_PREFIXES;\n const match = name.match(pattern);\n return match ? match[1]! : null;\n}\n\n// Blocks that do not open a new scope, so an assignment inside one still binds a module global.\nconst MODULE_SCOPE_BLOCKS = new Set([\n \"block\", \"if_statement\", \"elif_clause\", \"else_clause\",\n \"try_statement\", \"except_clause\", \"finally_clause\", \"with_statement\",\n]);\n\n// tree-sitter-python wraps an assignment in expression_statement; chained targets nest in assignment.\nfunction isModuleLevelAssignment(node: Node): boolean {\n let scope = node.parent;\n while (scope?.type === \"assignment\") scope = scope.parent;\n if (scope?.type !== \"expression_statement\") return false;\n scope = scope.parent;\n while (scope && MODULE_SCOPE_BLOCKS.has(scope.type)) scope = scope.parent;\n return scope?.type === \"module\";\n}\n\nexport class NamingExtractor implements StyleExtractor {\n readonly name = \"naming\";\n\n extract(file: ParsedFile): Observation[] {\n const observations: Observation[] = [];\n\n const visit = (node: Node): void => {\n this.processNode(node, file, observations);\n for (const child of node.children) {\n visit(child);\n }\n };\n\n visit(file.tree.rootNode);\n return observations;\n }\n\n private processNode(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n switch (file.language) {\n case \"typescript\":\n case \"tsx\":\n this.processTypeScriptNode(node, file, observations);\n break;\n case \"python\":\n this.processPythonNode(node, file, observations);\n break;\n }\n }\n\n private processTypeScriptNode(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n switch (node.type) {\n case \"variable_declarator\":\n this.processTypeScriptVariable(node, file, observations);\n break;\n case \"function_declaration\":\n this.observeDeclarationName(node, \"naming.function\", file, observations);\n break;\n case \"interface_declaration\":\n case \"type_alias_declaration\":\n this.observeDeclarationName(node, \"naming.type\", file, observations);\n break;\n case \"enum_declaration\":\n this.observeDeclarationName(node, \"naming.enum\", file, observations);\n break;\n case \"class_declaration\":\n if (this.observeDeclarationName(node, \"naming.type\", file, observations)) {\n this.detectPrivateMembers(node, file, observations);\n }\n break;\n case \"required_parameter\":\n case \"optional_parameter\":\n this.processTypeScriptParameter(node, file, observations);\n break;\n }\n }\n\n private processTypeScriptVariable(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const nameNode = node.childForFieldName(\"name\");\n if (!nameNode || nameNode.type !== \"identifier\") return;\n const name = nameNode.text;\n\n const declKind = node.parent?.type === \"lexical_declaration\"\n ? node.parent.children[0]?.text\n : null;\n\n if (declKind === \"const\" && isConstantName(name)) {\n this.addObservation(observations, \"naming.constant\", \"SCREAMING_SNAKE\", file, node);\n return;\n }\n\n this.observeVariable(name, node, file, observations);\n }\n\n private processTypeScriptParameter(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const nameNode = node.childForFieldName(\"pattern\") ?? node.childForFieldName(\"name\");\n if (!nameNode || nameNode.type !== \"identifier\") return;\n if (nameNode.text === \"this\") return;\n const convention = detectConvention(nameNode.text);\n if (convention) {\n this.addObservation(observations, \"naming.parameter\", convention, file, node);\n }\n }\n\n private processPythonNode(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n switch (node.type) {\n case \"assignment\":\n this.processPythonAssignment(node, file, observations);\n break;\n case \"function_definition\": {\n const nameNode = node.childForFieldName(\"name\");\n if (!nameNode) break;\n if (nameNode.text.startsWith(\"__\") && nameNode.text.endsWith(\"__\")) break;\n this.observeDeclarationName(node, \"naming.function\", file, observations);\n break;\n }\n case \"class_definition\":\n this.observeDeclarationName(node, \"naming.type\", file, observations);\n break;\n case \"parameters\":\n this.processPythonParameters(node, file, observations);\n break;\n }\n }\n\n private processPythonAssignment(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const left = node.childForFieldName(\"left\");\n if (!left || left.type !== \"identifier\") return;\n const name = left.text;\n\n if (\n isModuleLevelAssignment(node) &&\n isConstantName(name)\n ) {\n this.addObservation(observations, \"naming.constant\", \"SCREAMING_SNAKE\", file, node);\n return;\n }\n\n this.observeVariable(name, node, file, observations);\n }\n\n private processPythonParameters(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n for (const child of node.children) {\n if (child.type === \"identifier\" && child.text !== \"self\" && child.text !== \"cls\") {\n const convention = detectConvention(child.text);\n if (convention) {\n this.addObservation(observations, \"naming.parameter\", convention, file, child);\n }\n }\n if (child.type === \"typed_parameter\") {\n const paramName = child.childForFieldName(\"name\") ?? child.children[0];\n if (paramName && paramName.type === \"identifier\" && paramName.text !== \"self\") {\n const convention = detectConvention(paramName.text);\n if (convention) {\n this.addObservation(observations, \"naming.parameter\", convention, file, child);\n }\n }\n }\n }\n }\n\n private observeVariable(\n name: string,\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const prefix = detectBooleanPrefix(name, file.language);\n if (prefix) {\n this.addObservation(observations, \"naming.boolean\", prefix, file, node);\n }\n\n const convention = detectConvention(name);\n if (convention) {\n this.addObservation(observations, \"naming.variable\", convention, file, node);\n }\n }\n\n // Returns whether the node had a name, because a nameless class skips its private-member scan.\n private observeDeclarationName(\n node: Node,\n type: string,\n file: ParsedFile,\n observations: Observation[],\n ): boolean {\n const nameNode = node.childForFieldName(\"name\");\n if (!nameNode) return false;\n const convention = detectConvention(nameNode.text);\n if (convention) {\n this.addObservation(observations, type, convention, file, node);\n }\n return true;\n }\n\n private detectPrivateMembers(\n classNode: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const body = classNode.childForFieldName(\"body\");\n if (!body) return;\n\n for (const member of body.children) {\n if (member.type === \"public_field_definition\") {\n const nameNode = member.childForFieldName(\"name\");\n if (!nameNode) continue;\n const name = nameNode.text;\n\n if (name.startsWith(\"#\")) {\n this.addObservation(observations, \"naming.private-member\", \"hash-prefix\", file, member);\n } else if (name.startsWith(\"_\") && !name.startsWith(\"__\")) {\n this.addObservation(observations, \"naming.private-member\", \"underscore-prefix\", file, member);\n }\n }\n }\n }\n\n private addObservation(\n observations: Observation[],\n type: string,\n value: string | number | boolean,\n file: ParsedFile,\n node: Node,\n ): void {\n observations.push({\n type,\n category: \"naming\",\n value,\n file: file.filePath,\n line: node.startPosition.row + 1,\n });\n }\n}\n","import type { Node } from \"web-tree-sitter\";\nimport type { StyleExtractor, ParsedFile, Observation } from \"./types.js\";\n\nconst PYTHON_BUILTINS = new Set([\n \"os\", \"sys\", \"re\", \"json\", \"math\", \"time\", \"datetime\", \"pathlib\",\n \"collections\", \"itertools\", \"functools\", \"typing\", \"io\", \"abc\",\n \"dataclasses\", \"enum\", \"logging\", \"unittest\", \"hashlib\", \"subprocess\",\n \"argparse\", \"copy\", \"glob\", \"shutil\", \"tempfile\", \"textwrap\",\n \"contextlib\", \"operator\", \"string\", \"struct\", \"csv\", \"xml\",\n]);\n\nfunction classifyImportSource(source: string, language: string): string {\n if (language === \"python\") {\n if (source.startsWith(\".\")) return \"relative\";\n const topModule = source.split(\".\")[0]!;\n if (PYTHON_BUILTINS.has(topModule)) return \"builtin\";\n return \"external\";\n }\n\n if (source.startsWith(\"node:\")) return \"builtin\";\n if (source.startsWith(\".\") || source.startsWith(\"..\")) return \"relative\";\n if (source.startsWith(\"@\")) {\n const scope = source.split(\"/\")[0]!;\n if ([\"@app\", \"@lib\", \"@src\", \"@internal\", \"@modules\"].includes(scope)) {\n return \"internal\";\n }\n }\n return \"external\";\n}\n\nconst EXPORT_DECLARATION_TYPES = [\n \"function_declaration\",\n \"class_declaration\",\n \"lexical_declaration\",\n \"interface_declaration\",\n \"type_alias_declaration\",\n \"enum_declaration\",\n];\n\nfunction isBarrelFile(root: Node): boolean {\n let exportFromCount = 0;\n let otherStatements = 0;\n\n for (const child of root.children) {\n if (child.type === \"export_statement\") {\n const source = child.childForFieldName(\"source\");\n if (source) {\n exportFromCount++;\n } else {\n otherStatements++;\n }\n } else if (child.isNamed && child.type !== \"comment\") {\n otherStatements++;\n }\n }\n\n return exportFromCount > 0 && otherStatements <= 1;\n}\n\nexport class StructureExtractor implements StyleExtractor {\n readonly name = \"structure\";\n\n extract(file: ParsedFile): Observation[] {\n const observations: Observation[] = [];\n const root = file.tree.rootNode;\n\n this.extractImports(root, file, observations);\n this.extractExports(root, file, observations);\n this.detectBarrelFile(root, file, observations);\n\n return observations;\n }\n\n private extractImports(\n root: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const groupSequence: string[] = [];\n\n for (const child of root.children) {\n const source = this.importSource(child, file.language);\n\n if (source) {\n const group = classifyImportSource(source, file.language);\n groupSequence.push(group);\n observations.push({\n type: \"structure.import-group\",\n category: \"structure\",\n value: group,\n file: file.filePath,\n line: child.startPosition.row + 1,\n metadata: { source },\n });\n }\n }\n\n this.addImportOrder(groupSequence, file, observations);\n }\n\n private addImportOrder(\n groupSequence: string[],\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const uniqueOrder = [...new Set(groupSequence)];\n if (uniqueOrder.length > 0) {\n observations.push({\n type: \"structure.import-order\",\n category: \"structure\",\n value: JSON.stringify(uniqueOrder),\n file: file.filePath,\n line: 1,\n metadata: { groupCount: uniqueOrder.length },\n });\n }\n }\n\n private importSource(child: Node, language: string): string | null {\n let source: string | null = null;\n\n if (language === \"python\") {\n if (child.type === \"import_statement\") {\n const nameNode = child.childForFieldName(\"name\");\n source = nameNode?.text ?? null;\n } else if (child.type === \"import_from_statement\") {\n const moduleNode = child.childForFieldName(\"module_name\");\n const dots = child.children\n .filter((c) => c.type === \".\" || c.type === \"relative_import\")\n .map((c) => c.text)\n .join(\"\");\n source = dots + (moduleNode?.text ?? \"\");\n }\n } else {\n if (child.type === \"import_statement\") {\n const sourceNode = child.childForFieldName(\"source\");\n source = sourceNode?.text?.replace(/['\"]/g, \"\") ?? null;\n }\n }\n\n return source;\n }\n\n private extractExports(\n root: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (file.language === \"python\") return;\n\n for (const child of root.children) {\n if (child.type === \"export_statement\") {\n this.processExport(child, file, observations);\n }\n }\n }\n\n private processExport(\n child: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const isDefault = child.children.some((c) => c.type === \"default\");\n const style = isDefault ? \"default\" : \"named\";\n\n observations.push({\n type: \"structure.export-style\",\n category: \"structure\",\n value: style,\n file: file.filePath,\n line: child.startPosition.row + 1,\n });\n\n const proximity = this.exportProximity(child, isDefault);\n if (proximity) {\n observations.push({\n type: \"structure.export-proximity\",\n category: \"structure\",\n value: proximity,\n file: file.filePath,\n line: child.startPosition.row + 1,\n });\n }\n }\n\n private exportProximity(\n child: Node,\n isDefault: boolean,\n ): \"inline\" | \"trailing\" | null {\n const hasDeclaration = child.children.some((c) =>\n EXPORT_DECLARATION_TYPES.includes(c.type),\n );\n const isReExport = child.childForFieldName(\"source\") !== null;\n\n if (hasDeclaration || isDefault) return \"inline\";\n if (!isReExport) return \"trailing\";\n return null;\n }\n\n private detectBarrelFile(\n root: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (file.language === \"python\") return;\n\n if (isBarrelFile(root)) {\n observations.push({\n type: \"structure.barrel-file\",\n category: \"structure\",\n value: true,\n file: file.filePath,\n line: 1,\n });\n }\n }\n}\n","import type { Node } from \"web-tree-sitter\";\nimport type { StyleExtractor, ParsedFile, Observation } from \"./types.js\";\n\nconst ARRAY_METHODS = new Set([\n \"map\", \"filter\", \"reduce\", \"forEach\", \"find\", \"some\", \"every\", \"flatMap\",\n \"findIndex\",\n]);\n\nexport class ControlFlowExtractor implements StyleExtractor {\n readonly name = \"control-flow\";\n\n extract(file: ParsedFile): Observation[] {\n const observations: Observation[] = [];\n this.walk(file.tree.rootNode, file, observations);\n return observations;\n }\n\n private walk(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n this.processNode(node, file, observations);\n for (const child of node.children) {\n this.walk(child, file, observations);\n }\n }\n\n private processNode(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n this.processBranch(node, file, observations);\n this.processLoop(node, file, observations);\n this.processCall(node, file, observations);\n }\n\n private processBranch(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (\n node.type === \"ternary_expression\" ||\n node.type === \"conditional_expression\"\n ) {\n this.emit(observations, \"control-flow.ternary\", true, file, node);\n }\n\n if (node.type === \"if_statement\") {\n this.emit(observations, \"control-flow.if-else\", true, file, node);\n this.detectGuardClause(node, file, observations);\n this.detectElseAfterReturn(node, file, observations);\n }\n }\n\n private processLoop(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (node.type === \"for_statement\" && file.language !== \"python\") {\n this.emit(observations, \"control-flow.for-loop\", true, file, node);\n }\n\n if (node.type === \"for_in_statement\") {\n const isForOf = node.children.some((c) => c.type === \"of\");\n const loopType = isForOf ? \"control-flow.for-of\" : \"control-flow.for-in\";\n this.emit(observations, loopType, true, file, node);\n }\n\n if (node.type === \"for_statement\" && file.language === \"python\") {\n this.emit(observations, \"control-flow.for-loop\", true, file, node);\n }\n\n if (\n node.type === \"list_comprehension\" ||\n node.type === \"set_comprehension\" ||\n node.type === \"dictionary_comprehension\" ||\n node.type === \"generator_expression\"\n ) {\n this.emit(observations, \"control-flow.array-method\", true, file, node);\n }\n }\n\n private processCall(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (node.type === \"call_expression\") {\n const fn = node.childForFieldName(\"function\");\n if (fn?.type === \"member_expression\") {\n this.processMemberCall(fn, node, file, observations);\n }\n }\n\n if (node.type === \"await_expression\") {\n this.emit(observations, \"control-flow.async-await\", true, file, node);\n }\n }\n\n private processMemberCall(\n fn: Node,\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const property = fn.childForFieldName(\"property\");\n if (property) {\n const methodName = property.text;\n if (ARRAY_METHODS.has(methodName)) {\n this.emit(\n observations,\n \"control-flow.array-method\",\n methodName,\n file,\n node,\n );\n }\n if (methodName === \"then\") {\n this.emit(\n observations,\n \"control-flow.promise-then\",\n true,\n file,\n node,\n );\n }\n }\n }\n\n private detectGuardClause(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const parent = node.parent;\n if (!parent) return;\n\n if (!this.isFunctionBody(parent)) return;\n\n const siblings = parent.children.filter(\n (c) => c.type !== \"comment\" && c.type !== \"{\" && c.type !== \"}\",\n );\n const nodeIndex = siblings.indexOf(node);\n if (nodeIndex > 2) return;\n\n const consequent =\n node.childForFieldName(\"consequence\") ??\n node.childForFieldName(\"body\");\n if (!consequent) return;\n\n const hasReturn = this.containsReturn(consequent);\n const hasElse = node.childForFieldName(\"alternative\") !== null;\n\n if (hasReturn && !hasElse) {\n this.emit(observations, \"control-flow.guard-clause\", true, file, node);\n }\n }\n\n private isFunctionBody(parent: Node): boolean {\n const isFunctionBody =\n parent.type === \"statement_block\" &&\n (parent.parent?.type === \"function_declaration\" ||\n parent.parent?.type === \"method_definition\" ||\n parent.parent?.type === \"arrow_function\");\n\n const isPythonFunctionBody =\n parent.type === \"block\" &&\n parent.parent?.type === \"function_definition\";\n\n return isFunctionBody || isPythonFunctionBody;\n }\n\n private detectElseAfterReturn(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const consequent =\n node.childForFieldName(\"consequence\") ??\n node.childForFieldName(\"body\");\n const alternative = node.childForFieldName(\"alternative\");\n\n if (!consequent || !alternative) return;\n\n if (this.containsReturn(consequent)) {\n this.emit(\n observations,\n \"control-flow.else-after-return\",\n true,\n file,\n node,\n );\n }\n }\n\n private containsReturn(node: Node): boolean {\n if (node.type === \"return_statement\") return true;\n for (const child of node.children) {\n if (child.type === \"return_statement\") return true;\n }\n return false;\n }\n\n private emit(\n observations: Observation[],\n type: string,\n value: string | number | boolean,\n file: ParsedFile,\n node: Node,\n ): void {\n observations.push({\n type,\n category: \"control-flow\",\n value,\n file: file.filePath,\n line: node.startPosition.row + 1,\n });\n }\n}\n","import type { Node } from \"web-tree-sitter\";\nimport type { StyleExtractor, ParsedFile, Observation } from \"./types.js\";\n\nconst JSDOC_TAG_PATTERN = /@(param|returns?|throws?|example|deprecated|see|since|type|typedef|template|callback|async)\\b/g;\nconst PYTHON_DOC_TAG_PATTERN = /^[ \\t]*(Args|Returns?|Raises?|Yields?|Note|Notes|Example|Attributes|Todo|References):/gm;\n\nexport class DocumentationExtractor implements StyleExtractor {\n readonly name = \"documentation\";\n\n extract(file: ParsedFile): Observation[] {\n const observations: Observation[] = [];\n\n this.walkDeclarations(file.tree.rootNode, file, observations);\n this.walkForComments(file.tree.rootNode, file, observations);\n\n return observations;\n }\n\n private walkDeclarations(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n for (const child of node.children) {\n if (this.isDeclaration(child, file.language)) {\n this.processDeclaration(child, file, observations);\n }\n\n if (\n child.type === \"class_declaration\" ||\n child.type === \"class_definition\" ||\n child.type === \"class_body\" ||\n child.type === \"block\"\n ) {\n this.walkDeclarations(child, file, observations);\n }\n\n if (child.type === \"export_statement\") {\n this.walkDeclarations(child, file, observations);\n }\n }\n }\n\n private isDeclaration(node: Node, language: string): boolean {\n if (language === \"python\") {\n return (\n node.type === \"function_definition\" ||\n node.type === \"class_definition\"\n );\n }\n return (\n node.type === \"function_declaration\" ||\n node.type === \"method_definition\" ||\n node.type === \"class_declaration\" ||\n node.type === \"interface_declaration\" ||\n node.type === \"type_alias_declaration\"\n );\n }\n\n private processDeclaration(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const isExported = this.isExported(node, file.language);\n const hasDoc = this.hasLeadingDoc(node, file.language);\n\n this.emit(observations, \"documentation.jsdoc-presence\", hasDoc, file, node);\n\n const coverageType = isExported\n ? \"documentation.public-coverage\"\n : \"documentation.private-coverage\";\n this.emit(observations, coverageType, hasDoc, file, node);\n\n if (hasDoc) {\n this.extractTags(node, file, observations);\n }\n }\n\n private hasLeadingDoc(node: Node, language: string): boolean {\n if (language === \"python\") {\n return this.hasPythonDocstring(node);\n }\n return this.hasJSDoc(node);\n }\n\n private hasJSDoc(node: Node): boolean {\n const prev = node.previousSibling;\n if (prev?.type === \"comment\" && prev.text.startsWith(\"/**\")) {\n return true;\n }\n if (node.parent?.type === \"export_statement\") {\n const exportPrev = node.parent.previousSibling;\n if (exportPrev?.type === \"comment\" && exportPrev.text.startsWith(\"/**\")) {\n return true;\n }\n }\n return false;\n }\n\n private hasPythonDocstring(node: Node): boolean {\n const body = node.childForFieldName(\"body\");\n if (!body) return false;\n\n const firstStatement = body.children.find(\n (c) => c.type !== \"comment\" && c.type !== \"newline\",\n );\n if (!firstStatement) return false;\n\n if (firstStatement.type === \"expression_statement\") {\n const expr = firstStatement.children[0];\n return expr?.type === \"string\" || expr?.type === \"concatenated_string\";\n }\n return false;\n }\n\n private extractTags(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (file.language === \"python\") {\n this.extractPythonDocTags(node, file, observations);\n return;\n }\n\n const commentNode = this.getLeadingComment(node);\n if (!commentNode) return;\n\n const text = commentNode.text;\n const tagMatches = text.matchAll(JSDOC_TAG_PATTERN);\n const seenTags = new Set<string>();\n\n for (const match of tagMatches) {\n const tag = `@${match[1]}`;\n const normalized = tag\n .replace(/^@return$/, \"@returns\")\n .replace(/^@throw$/, \"@throws\");\n\n if (seenTags.has(normalized)) continue;\n seenTags.add(normalized);\n\n this.emit(observations, \"documentation.jsdoc-tag\", normalized, file, commentNode);\n }\n }\n\n private extractPythonDocTags(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const body = node.childForFieldName(\"body\");\n if (!body) return;\n\n const firstStatement = body.children.find(\n (c) => c.type === \"expression_statement\",\n );\n if (!firstStatement) return;\n\n const expr = firstStatement.children[0];\n if (!expr) return;\n\n const text = expr.text;\n const tagMatches = text.matchAll(PYTHON_DOC_TAG_PATTERN);\n const seenTags = new Set<string>();\n\n for (const match of tagMatches) {\n const tag = match[1]!;\n if (seenTags.has(tag)) continue;\n seenTags.add(tag);\n this.emit(observations, \"documentation.jsdoc-tag\", tag, file, expr);\n }\n }\n\n private walkForComments(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (node.type === \"comment\") {\n if (!node.text.startsWith(\"/**\")) {\n this.emit(observations, \"documentation.inline-comment\", true, file, node);\n\n const placement = this.getCommentPlacement(node);\n this.emit(observations, \"documentation.comment-placement\", placement, file, node);\n }\n }\n\n for (const child of node.children) {\n this.walkForComments(child, file, observations);\n }\n }\n\n private getCommentPlacement(node: Node): \"leading\" | \"trailing\" {\n const prev = node.previousSibling;\n if (prev && prev.endPosition.row === node.startPosition.row) {\n return \"trailing\";\n }\n return \"leading\";\n }\n\n private isExported(node: Node, language: string): boolean {\n if (language === \"python\") {\n const nameNode = node.childForFieldName(\"name\");\n return (\n node.parent?.type === \"module\" &&\n !!nameNode &&\n !nameNode.text.startsWith(\"_\")\n );\n }\n return node.parent?.type === \"export_statement\";\n }\n\n private getLeadingComment(node: Node): Node | null {\n const prev = node.previousSibling;\n if (prev?.type === \"comment\" && prev.text.startsWith(\"/**\")) {\n return prev;\n }\n if (node.parent?.type === \"export_statement\") {\n const exportPrev = node.parent.previousSibling;\n if (exportPrev?.type === \"comment\" && exportPrev.text.startsWith(\"/**\")) {\n return exportPrev;\n }\n }\n return null;\n }\n\n private emit(\n observations: Observation[],\n type: string,\n value: string | number | boolean,\n file: ParsedFile,\n node: Node,\n ): void {\n observations.push({\n type,\n category: \"documentation\",\n value,\n file: file.filePath,\n line: node.startPosition.row + 1,\n });\n }\n}\n","import type { Node } from \"web-tree-sitter\";\nimport type { StyleExtractor, ParsedFile, Observation } from \"./types.js\";\n\nconst RESULT_TYPE_NAMES = new Set([\n \"Result\", \"Either\", \"Ok\", \"Err\", \"Success\", \"Failure\",\n]);\n\nconst GENERIC_CATCH_TYPES = new Set([\n \"Error\", \"Exception\", \"unknown\",\n]);\n\nexport class ErrorHandlingExtractor implements StyleExtractor {\n readonly name = \"error-handling\";\n\n extract(file: ParsedFile): Observation[] {\n const observations: Observation[] = [];\n this.walk(file.tree.rootNode, file, observations);\n return observations;\n }\n\n private walk(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n this.processNode(node, file, observations);\n for (const child of node.children) {\n this.walk(child, file, observations);\n }\n }\n\n private processNode(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n this.processDeclaration(node, file, observations);\n this.processFunctionCheck(node, file, observations);\n }\n\n private processDeclaration(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (node.type === \"try_statement\") {\n this.emit(observations, \"error-handling.try-catch\", true, file, node);\n this.analyzeCatchClauses(node, file, observations);\n }\n\n if (\n node.type === \"class_declaration\" ||\n node.type === \"class_definition\"\n ) {\n this.detectCustomErrorClass(node, file, observations);\n }\n\n if (\n node.type === \"type_alias_declaration\" &&\n (file.language === \"typescript\" || file.language === \"tsx\")\n ) {\n this.detectResultType(node, file, observations);\n }\n }\n\n private processFunctionCheck(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (\n node.type === \"function_declaration\" ||\n node.type === \"method_definition\"\n ) {\n this.detectResultReturnType(node, file, observations);\n }\n\n if (node.type === \"function_declaration\") {\n this.detectAssertNever(node, file, observations);\n }\n\n if (node.type === \"switch_statement\") {\n this.detectExhaustiveSwitch(node, file, observations);\n }\n }\n\n private analyzeCatchClauses(\n tryNode: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n for (const child of tryNode.children) {\n if (child.type === \"catch_clause\") {\n const body = child.childForFieldName(\"body\");\n if (body && this.hasInstanceofCheck(body)) {\n this.emit(observations, \"error-handling.catch-specificity\", \"specific\", file, child);\n } else {\n this.emit(observations, \"error-handling.catch-specificity\", \"generic\", file, child);\n }\n }\n\n if (child.type === \"except_clause\") {\n const typeNode = child.children.find(\n (c) => c.type === \"identifier\" || c.type === \"attribute\",\n );\n\n if (typeNode && !GENERIC_CATCH_TYPES.has(typeNode.text)) {\n this.emit(observations, \"error-handling.catch-specificity\", \"specific\", file, child);\n } else {\n this.emit(observations, \"error-handling.catch-specificity\", \"generic\", file, child);\n }\n }\n }\n }\n\n private hasInstanceofCheck(body: Node): boolean {\n return body.text.includes(\"instanceof\");\n }\n\n private detectCustomErrorClass(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n if (file.language === \"python\") {\n const superclasses = node.childForFieldName(\"superclasses\");\n if (!superclasses) return;\n\n const bases = superclasses.text;\n if (bases.includes(\"Error\") || bases.includes(\"Exception\")) {\n this.emit(observations, \"error-handling.custom-error-class\", true, file, node);\n }\n return;\n }\n\n const heritage = node.children.find(\n (c) => c.type === \"class_heritage\",\n );\n if (!heritage) return;\n\n if (heritage.text.includes(\"Error\")) {\n this.emit(observations, \"error-handling.custom-error-class\", true, file, node);\n }\n }\n\n private detectResultType(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const nameNode = node.childForFieldName(\"name\");\n if (!nameNode) return;\n\n if (RESULT_TYPE_NAMES.has(nameNode.text)) {\n this.emit(observations, \"error-handling.result-type\", nameNode.text, file, node);\n }\n }\n\n private detectResultReturnType(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const returnType = node.childForFieldName(\"return_type\");\n if (!returnType) return;\n\n const text = returnType.text;\n for (const name of RESULT_TYPE_NAMES) {\n if (text.includes(name)) {\n this.emit(observations, \"error-handling.result-type\", name, file, node);\n break;\n }\n }\n }\n\n private detectAssertNever(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const nameNode = node.childForFieldName(\"name\");\n if (!nameNode) return;\n\n const name = nameNode.text;\n if (name !== \"assertNever\" && name !== \"absurd\") return;\n\n const params = node.childForFieldName(\"parameters\");\n const returnType = node.childForFieldName(\"return_type\");\n\n const hasNeverParam = params?.text.includes(\"never\") ?? false;\n const returnsNever = returnType?.text.includes(\"never\") ?? false;\n\n if (hasNeverParam || returnsNever) {\n this.emit(observations, \"error-handling.assert-never\", true, file, node);\n }\n }\n\n private detectExhaustiveSwitch(\n node: Node,\n file: ParsedFile,\n observations: Observation[],\n ): void {\n const body = node.childForFieldName(\"body\");\n if (!body) return;\n\n let defaultCallsAssertNever = false;\n\n for (const child of body.children) {\n if (child.type === \"switch_default\") {\n const text = child.text;\n if (text.includes(\"assertNever\") || text.includes(\"absurd\")) {\n defaultCallsAssertNever = true;\n }\n }\n }\n\n this.emit(\n observations,\n \"error-handling.exhaustive-switch\",\n defaultCallsAssertNever,\n file,\n node,\n );\n }\n\n private emit(\n observations: Observation[],\n type: string,\n value: string | number | boolean,\n file: ParsedFile,\n node: Node,\n ): void {\n observations.push({\n type,\n category: \"error-handling\",\n value,\n file: file.filePath,\n line: node.startPosition.row + 1,\n });\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport type { StyleExtractor, ParsedFile, Observation } from \"./types.js\";\nimport {\n makeFormattingObs,\n parseEditorConfig,\n parsePrettierConfig,\n} from \"./formatting-config.js\";\n\nexport class FormattingExtractor implements StyleExtractor {\n readonly name = \"formatting\";\n\n extract(file: ParsedFile): Observation[] {\n return this.extractFromSource(file.content, file.filePath);\n }\n\n async extractFromConfig(configPath: string): Promise<Observation[]> {\n try {\n const raw = await readFile(configPath, \"utf-8\");\n\n if (configPath.endsWith(\".editorconfig\")) {\n return parseEditorConfig(raw, configPath);\n }\n\n if (\n configPath.includes(\".prettierrc\") ||\n configPath.includes(\"prettier.config\")\n ) {\n return parsePrettierConfig(raw, configPath);\n }\n\n return [];\n } catch {\n return [];\n }\n }\n\n extractFromSource(source: string, filePath: string): Observation[] {\n const observations: Observation[] = [];\n const lines = source.split(\"\\n\");\n\n observations.push(...this.detectSemicolons(lines, filePath));\n observations.push(...this.detectQuoteStyle(source, filePath));\n observations.push(...this.detectTrailingCommas(source, filePath));\n observations.push(...this.detectBraceStyle(source, filePath));\n observations.push(...this.detectIndentation(lines, filePath));\n\n return observations;\n }\n\n private detectSemicolons(\n lines: string[],\n filePath: string,\n ): Observation[] {\n let withSemi = 0;\n let withoutSemi = 0;\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || this.isComment(trimmed)) continue;\n if (this.isStructuralLine(trimmed)) continue;\n\n if (trimmed.endsWith(\";\")) {\n withSemi++;\n } else if (this.isStatementStart(trimmed)) {\n withoutSemi++;\n }\n }\n\n const total = withSemi + withoutSemi;\n if (total === 0) return [];\n\n return [makeFormattingObs(\n \"formatting.semicolons\",\n withSemi / total > 0.5,\n filePath, 1, \"frequency\",\n )];\n }\n\n private detectQuoteStyle(\n source: string,\n filePath: string,\n ): Observation[] {\n let singleQuotes = 0;\n let doubleQuotes = 0;\n\n const stringPattern = /(?<!=)(?<!\\\\)(['\"])((?:(?!\\1|\\\\).|\\\\.)*)\\1/g;\n let match: RegExpExecArray | null;\n\n while ((match = stringPattern.exec(source)) !== null) {\n if (match[1] === \"'\") {\n singleQuotes++;\n } else {\n doubleQuotes++;\n }\n }\n\n const total = singleQuotes + doubleQuotes;\n if (total === 0) return [];\n\n return [makeFormattingObs(\n \"formatting.quoteStyle\",\n singleQuotes > doubleQuotes ? \"single\" : \"double\",\n filePath, 1, \"frequency\",\n )];\n }\n\n private detectTrailingCommas(\n source: string,\n filePath: string,\n ): Observation[] {\n const trailingCommaPattern = /,\\s*[\\n\\r]\\s*[}\\]]/g;\n // `;`, `{` and `}` before a closer end a block body, not a list, so they\n // say nothing about trailing-comma style.\n const noTrailingPattern = /[^,;{}\\s]\\s*[\\n\\r]\\s*[}\\]]/g;\n\n const trailing = (source.match(trailingCommaPattern) || []).length;\n const noTrailing = (source.match(noTrailingPattern) || []).length;\n const total = trailing + noTrailing;\n\n if (total === 0) return [];\n\n return [makeFormattingObs(\n \"formatting.trailingCommas\",\n trailing / total > 0.5,\n filePath, 1, \"frequency\",\n )];\n }\n\n private detectBraceStyle(\n source: string,\n filePath: string,\n ): Observation[] {\n const sameLine = (source.match(/\\)[^\\S\\n]*\\{/g) || []).length;\n const nextLine = (source.match(/\\)\\s*\\n\\s*\\{/g) || []).length;\n\n const total = sameLine + nextLine;\n if (total === 0) return [];\n\n return [makeFormattingObs(\n \"formatting.braceStyle\",\n nextLine / total > 0.5 ? \"allman\" : \"1tbs\",\n filePath, 1, \"frequency\",\n )];\n }\n\n private detectIndentation(\n lines: string[],\n filePath: string,\n ): Observation[] {\n const { tabCount, spaceCount, spaceSizes } = this.countIndentation(lines);\n\n const observations: Observation[] = [];\n const total = tabCount + spaceCount;\n if (total === 0) return observations;\n\n observations.push(makeFormattingObs(\n \"formatting.indentStyle\",\n tabCount > spaceCount ? \"tab\" : \"space\",\n filePath, 1, \"frequency\",\n ));\n\n if (spaceCount > tabCount && spaceSizes.length > 0) {\n const gcd = this.findGcdOfArray(spaceSizes.filter((s) => s > 0));\n observations.push(makeFormattingObs(\n \"formatting.indentSize\", gcd, filePath, 1, \"frequency\",\n ));\n }\n\n return observations;\n }\n\n private countIndentation(lines: string[]): {\n tabCount: number;\n spaceCount: number;\n spaceSizes: number[];\n } {\n let tabCount = 0;\n let spaceCount = 0;\n const spaceSizes: number[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n // JSDoc continuation lines (` * text`) carry a 1-space offset that is\n // alignment, not indentation, and would drive the GCD to 1.\n if (!trimmed || this.isComment(trimmed)) continue;\n\n const leadingWhitespace = line.match(/^(\\s+)/);\n if (!leadingWhitespace) continue;\n\n const ws = leadingWhitespace[1]!;\n\n if (ws.includes(\"\\t\")) {\n tabCount++;\n } else if (ws.length > 0) {\n spaceCount++;\n spaceSizes.push(ws.length);\n }\n }\n\n return { tabCount, spaceCount, spaceSizes };\n }\n\n private isComment(trimmed: string): boolean {\n return (\n trimmed.startsWith(\"//\") ||\n trimmed.startsWith(\"/*\") ||\n trimmed.startsWith(\"*\")\n );\n }\n\n private isStructuralLine(trimmed: string): boolean {\n return (\n trimmed.endsWith(\"{\") ||\n trimmed.endsWith(\"}\") ||\n trimmed.endsWith(\"(\") ||\n trimmed.endsWith(\",\")\n );\n }\n\n private isStatementStart(trimmed: string): boolean {\n return (\n trimmed.startsWith(\"const \") ||\n trimmed.startsWith(\"let \") ||\n trimmed.startsWith(\"var \") ||\n trimmed.startsWith(\"return \") ||\n trimmed.startsWith(\"import \") ||\n trimmed.startsWith(\"export \")\n );\n }\n\n private findGcdOfArray(nums: number[]): number {\n if (nums.length === 0) return 2;\n return nums.reduce((a, b) => this.gcd(a, b));\n }\n\n private gcd(a: number, b: number): number {\n while (b) {\n [a, b] = [b, a % b];\n }\n return a;\n }\n}\n","import type { Observation } from \"./types.js\";\n\ninterface PrettierConfig {\n semi?: boolean;\n singleQuote?: boolean;\n trailingComma?: \"none\" | \"es5\" | \"all\";\n tabWidth?: number;\n useTabs?: boolean;\n}\n\ninterface EditorConfigSection {\n indent_style?: \"space\" | \"tab\";\n indent_size?: string;\n insert_final_newline?: string;\n}\n\nexport function parsePrettierConfig(\n raw: string,\n configPath: string,\n): Observation[] {\n const config: PrettierConfig = JSON.parse(raw);\n return [\n ...prettierSyntaxObservations(config, configPath),\n ...prettierIndentObservations(config, configPath),\n ];\n}\n\nfunction prettierSyntaxObservations(\n config: PrettierConfig,\n configPath: string,\n): Observation[] {\n const observations: Observation[] = [];\n\n if (config.semi !== undefined) {\n observations.push(makeFormattingObs(\n \"formatting.semicolons\", config.semi, configPath, 1, \"config\",\n ));\n }\n\n if (config.singleQuote !== undefined) {\n observations.push(makeFormattingObs(\n \"formatting.quoteStyle\",\n config.singleQuote ? \"single\" : \"double\",\n configPath, 1, \"config\",\n ));\n }\n\n if (config.trailingComma !== undefined) {\n observations.push(makeFormattingObs(\n \"formatting.trailingCommas\",\n config.trailingComma !== \"none\",\n configPath, 1, \"config\",\n ));\n }\n\n return observations;\n}\n\nfunction prettierIndentObservations(\n config: PrettierConfig,\n configPath: string,\n): Observation[] {\n const observations: Observation[] = [];\n\n if (config.tabWidth !== undefined) {\n observations.push(makeFormattingObs(\n \"formatting.indentSize\", config.tabWidth, configPath, 1, \"config\",\n ));\n }\n\n if (config.useTabs !== undefined) {\n observations.push(makeFormattingObs(\n \"formatting.indentStyle\",\n config.useTabs ? \"tab\" : \"space\",\n configPath, 1, \"config\",\n ));\n }\n\n return observations;\n}\n\nexport function parseEditorConfig(\n raw: string,\n configPath: string,\n): Observation[] {\n const observations: Observation[] = [];\n const section = parseEditorConfigGlobal(raw);\n\n if (section.indent_style) {\n observations.push(makeFormattingObs(\n \"formatting.indentStyle\", section.indent_style, configPath, 1, \"config\",\n ));\n }\n\n if (section.indent_size) {\n observations.push(makeFormattingObs(\n \"formatting.indentSize\",\n parseInt(section.indent_size, 10),\n configPath, 1, \"config\",\n ));\n }\n\n if (section.insert_final_newline) {\n observations.push(makeFormattingObs(\n \"formatting.trailingNewline\",\n section.insert_final_newline === \"true\",\n configPath, 1, \"config\",\n ));\n }\n\n return observations;\n}\n\nfunction parseEditorConfigGlobal(raw: string): EditorConfigSection {\n const result: EditorConfigSection = {};\n const lines = raw.split(\"\\n\");\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith(\"#\") || trimmed.startsWith(\"[\") || !trimmed) {\n continue;\n }\n const eqIndex = trimmed.indexOf(\"=\");\n if (eqIndex === -1) continue;\n const key = trimmed.substring(0, eqIndex).trim();\n const value = trimmed.substring(eqIndex + 1).trim();\n if (key && value) {\n (result as Record<string, string>)[key] = value;\n }\n }\n\n return result;\n}\n\nexport function makeFormattingObs(\n type: string,\n value: string | number | boolean,\n file: string,\n line: number,\n source: string,\n): Observation {\n return {\n type,\n category: \"formatting\",\n value,\n file,\n line,\n metadata: { source },\n };\n}\n","import type { Node } from \"web-tree-sitter\";\nimport type { StyleExtractor, ParsedFile, Observation } from \"./types.js\";\n\ninterface FunctionInfo {\n name: string;\n statementCount: number;\n maxNestingDepth: number;\n cyclomaticComplexity: number;\n line: number;\n}\n\nconst TS_FUNCTION_TYPES = new Set([\n \"function_declaration\",\n \"method_definition\",\n]);\n\nconst PY_FUNCTION_TYPES = new Set([\n \"function_definition\",\n]);\n\nconst TS_NESTING_TYPES = new Set([\n \"if_statement\",\n \"for_statement\",\n \"for_in_statement\",\n \"while_statement\",\n \"do_statement\",\n \"switch_statement\",\n \"try_statement\",\n]);\n\nconst PY_NESTING_TYPES = new Set([\n \"if_statement\",\n \"for_statement\",\n \"while_statement\",\n \"try_statement\",\n]);\n\nconst TS_BRANCH_TYPES = new Set([\n \"if_statement\",\n \"for_statement\",\n \"for_in_statement\",\n \"while_statement\",\n \"do_statement\",\n \"switch_case\",\n \"catch_clause\",\n \"ternary_expression\",\n]);\n\nconst PY_BRANCH_TYPES = new Set([\n \"if_statement\",\n \"elif_clause\",\n \"for_statement\",\n \"while_statement\",\n \"except_clause\",\n \"conditional_expression\",\n]);\n\nexport class ComplexityExtractor implements StyleExtractor {\n readonly name = \"complexity\";\n\n extract(file: ParsedFile): Observation[] {\n const observations: Observation[] = [];\n\n const lineCount = file.content\n .split(\"\\n\")\n .filter((l) => l.trim() !== \"\").length;\n\n observations.push({\n type: \"complexity.fileLength\",\n category: \"complexity\",\n value: lineCount,\n file: file.filePath,\n line: 1,\n });\n\n const functionTypes = this.getFunctionTypes(file.language);\n const functions = this.findFunctions(\n file.tree.rootNode, functionTypes, file.language,\n );\n\n for (const fn of functions) {\n observations.push(...this.functionObservations(fn, file.filePath));\n }\n\n return observations;\n }\n\n private functionObservations(fn: FunctionInfo, filePath: string): Observation[] {\n const metrics: Array<[string, number]> = [\n [\"complexity.functionLength\", fn.statementCount],\n [\"complexity.nestingDepth\", fn.maxNestingDepth],\n [\"complexity.cyclomatic\", fn.cyclomaticComplexity],\n ];\n return metrics.map(([type, value]) => ({\n type,\n category: \"complexity\",\n value,\n file: filePath,\n line: fn.line,\n metadata: { functionName: fn.name },\n }));\n }\n\n private getFunctionTypes(language: string): Set<string> {\n return language === \"python\" ? PY_FUNCTION_TYPES : TS_FUNCTION_TYPES;\n }\n\n private findFunctions(\n root: Node,\n functionTypes: Set<string>,\n language: string,\n ): FunctionInfo[] {\n const functions: FunctionInfo[] = [];\n\n const visit = (node: Node): void => {\n if (functionTypes.has(node.type)) {\n const info = this.analyzeFunctionNode(node, language);\n if (info) functions.push(info);\n }\n for (const child of node.children) {\n visit(child);\n }\n };\n\n visit(root);\n return functions;\n }\n\n private analyzeFunctionNode(\n node: Node,\n language: string,\n ): FunctionInfo | null {\n const nameNode = node.childForFieldName(\"name\");\n if (!nameNode) return null;\n const name = nameNode.text;\n\n const body = node.childForFieldName(\"body\");\n if (!body) return null;\n\n const statementCount = this.countStatements(body, language);\n const maxNestingDepth = this.measureNestingDepth(body, language, 0);\n const cyclomaticComplexity = this.measureCyclomaticComplexity(\n body, language,\n );\n\n return {\n name,\n statementCount,\n maxNestingDepth,\n cyclomaticComplexity,\n line: node.startPosition.row + 1,\n };\n }\n\n private countStatements(body: Node, language: string): number {\n let count = 0;\n for (const child of body.namedChildren) {\n if (this.isStatement(child, language)) {\n count++;\n }\n }\n return count;\n }\n\n private isStatement(node: Node, language: string): boolean {\n if (language === \"python\") {\n return this.isPythonStatement(node);\n }\n return this.isTypeScriptStatement(node);\n }\n\n private isTypeScriptStatement(node: Node): boolean {\n const statementTypes = new Set([\n \"lexical_declaration\",\n \"variable_declaration\",\n \"expression_statement\",\n \"return_statement\",\n \"if_statement\",\n \"for_statement\",\n \"for_in_statement\",\n \"while_statement\",\n \"do_statement\",\n \"switch_statement\",\n \"try_statement\",\n \"throw_statement\",\n \"break_statement\",\n \"continue_statement\",\n ]);\n return statementTypes.has(node.type);\n }\n\n private isPythonStatement(node: Node): boolean {\n const statementTypes = new Set([\n \"expression_statement\",\n \"return_statement\",\n \"if_statement\",\n \"for_statement\",\n \"while_statement\",\n \"try_statement\",\n \"raise_statement\",\n \"assert_statement\",\n \"pass_statement\",\n \"break_statement\",\n \"continue_statement\",\n \"assignment\",\n \"augmented_assignment\",\n ]);\n return statementTypes.has(node.type);\n }\n\n private measureNestingDepth(\n node: Node,\n language: string,\n depth: number,\n ): number {\n const nestingTypes = language === \"python\"\n ? PY_NESTING_TYPES\n : TS_NESTING_TYPES;\n\n let maxDepth = depth;\n\n for (const child of node.namedChildren) {\n if (nestingTypes.has(child.type)) {\n const childMax = this.measureNestingDepth(\n child, language, depth + 1,\n );\n if (childMax > maxDepth) maxDepth = childMax;\n } else {\n const childMax = this.measureNestingDepth(\n child, language, depth,\n );\n if (childMax > maxDepth) maxDepth = childMax;\n }\n }\n\n return maxDepth;\n }\n\n private measureCyclomaticComplexity(\n body: Node,\n language: string,\n ): number {\n let complexity = 1;\n const branchTypes = language === \"python\"\n ? PY_BRANCH_TYPES\n : TS_BRANCH_TYPES;\n\n const visit = (node: Node): void => {\n complexity += this.branchIncrement(node, language, branchTypes);\n\n for (const child of node.namedChildren) {\n visit(child);\n }\n };\n\n visit(body);\n return complexity;\n }\n\n private branchIncrement(\n node: Node,\n language: string,\n branchTypes: Set<string>,\n ): number {\n let increment = 0;\n if (branchTypes.has(node.type)) {\n increment++;\n }\n\n if (node.type === \"binary_expression\") {\n const operator = node.childForFieldName(\"operator\");\n if (operator) {\n const text = operator.text;\n if (text === \"&&\" || text === \"||\") {\n increment++;\n }\n }\n }\n\n if (\n language === \"python\" &&\n node.type === \"boolean_operator\"\n ) {\n increment++;\n }\n return increment;\n }\n}\n","import type { StyleExtractor, Observation, ParsedFile } from \"./types.js\";\nimport type {\n IClone,\n IMapFrame,\n IOptions,\n} from \"@jscpd/core\";\n\ninterface SourceFile {\n content: string;\n path: string;\n language: string;\n}\n\ninterface CloneInstance {\n sourceFile: string;\n startLine: number;\n endLine: number;\n fragment: string;\n}\n\ninterface CloneGroup {\n instances: CloneInstance[];\n linesCount: number;\n}\n\nexport class IdiomsExtractor implements StyleExtractor {\n readonly name = \"idioms\";\n\n private minLines: number;\n private minTokens: number;\n\n constructor(options?: { minLines?: number; minTokens?: number }) {\n this.minLines = options?.minLines ?? 3;\n this.minTokens = options?.minTokens ?? 25;\n }\n\n extract(_file: ParsedFile): Observation[] {\n return [];\n }\n\n async extractFromSources(sources: SourceFile[]): Promise<Observation[]> {\n const observations: Observation[] = [];\n\n const clones = await this.detectClones(sources);\n const groups = this.groupClones(clones);\n\n for (const group of groups.values()) {\n const frequency = group.instances.length;\n if (frequency < 2) continue;\n\n observations.push(this.cloneObservation(group));\n }\n\n return observations;\n }\n\n private cloneObservation(group: CloneGroup): Observation {\n const frequency = group.instances.length;\n const first = group.instances[0]!;\n\n return {\n type: \"idiom.clone\",\n category: \"idioms\",\n value: this.summarizeClone(first.fragment),\n file: first.sourceFile,\n line: first.startLine,\n metadata: {\n frequency,\n fragment: first.fragment,\n linesCount: group.linesCount,\n locations: group.instances.map((inst) => ({\n file: inst.sourceFile,\n startLine: inst.startLine,\n endLine: inst.endLine,\n })),\n },\n };\n }\n\n private async detectClones(\n sources: SourceFile[],\n ): Promise<CloneGroup[]> {\n const { allClones, sourceMap } = await this.runDetector(sources);\n return allClones.map((clone) => this.toCloneGroup(clone, sourceMap));\n }\n\n private async runDetector(\n sources: SourceFile[],\n ): Promise<{ allClones: IClone[]; sourceMap: Map<string, string> }> {\n const { Detector, MemoryStore } = await import(\"@jscpd/core\");\n const { Tokenizer } = await import(\"@jscpd/tokenizer\");\n\n const options: IOptions = {\n minLines: this.minLines,\n minTokens: this.minTokens,\n };\n\n const store = new MemoryStore<IMapFrame>();\n const tokenizer = new Tokenizer();\n const detector = new Detector(tokenizer, store, [], options);\n\n const allClones: IClone[] = [];\n const sourceMap = new Map<string, string>();\n\n for (const source of sources) {\n sourceMap.set(source.path, source.content);\n const format = this.languageToFormat(source.language);\n const detected = await detector.detect(\n source.path,\n source.content,\n format,\n );\n allClones.push(...detected);\n }\n\n return { allClones, sourceMap };\n }\n\n private toCloneGroup(\n clone: IClone,\n sourceMap: Map<string, string>,\n ): CloneGroup {\n return {\n instances: [\n this.toInstance(clone.duplicationA, sourceMap),\n this.toInstance(clone.duplicationB, sourceMap),\n ],\n linesCount:\n clone.duplicationA.end.line - clone.duplicationA.start.line + 1,\n };\n }\n\n private toInstance(\n duplication: IClone[\"duplicationA\"],\n sourceMap: Map<string, string>,\n ): CloneInstance {\n const content = sourceMap.get(duplication.sourceId) ?? \"\";\n return {\n sourceFile: duplication.sourceId,\n startLine: duplication.start.line,\n endLine: duplication.end.line,\n fragment: this.extractFragment(\n content,\n duplication.start.line,\n duplication.end.line,\n ),\n };\n }\n\n private extractFragment(\n content: string,\n startLine: number,\n endLine: number,\n ): string {\n const lines = content.split(\"\\n\");\n return lines.slice(startLine - 1, endLine).join(\"\\n\");\n }\n\n private languageToFormat(language: string): string {\n const mapping: Record<string, string> = {\n typescript: \"typescript\",\n javascript: \"javascript\",\n python: \"python\",\n tsx: \"tsx\",\n jsx: \"jsx\",\n };\n return mapping[language] ?? language;\n }\n\n private groupClones(\n clones: CloneGroup[],\n ): Map<string, CloneGroup> {\n const groups = new Map<string, CloneGroup>();\n\n for (const clone of clones) {\n const key = this.normalizeFragment(clone.instances[0]?.fragment ?? \"\");\n\n const existing = groups.get(key);\n if (existing) {\n this.mergeInstances(existing, clone);\n } else {\n groups.set(key, {\n instances: [...clone.instances],\n linesCount: clone.linesCount,\n });\n }\n }\n\n return groups;\n }\n\n private mergeInstances(existing: CloneGroup, clone: CloneGroup): void {\n for (const inst of clone.instances) {\n const alreadyTracked = existing.instances.some(\n (e) =>\n e.sourceFile === inst.sourceFile &&\n e.startLine === inst.startLine,\n );\n if (!alreadyTracked) {\n existing.instances.push(inst);\n }\n }\n }\n\n private normalizeFragment(fragment: string): string {\n return fragment.replace(/\\s+/g, \" \").trim().substring(0, 200);\n }\n\n private summarizeClone(fragment: string): string {\n const firstLine = fragment.split(\"\\n\")[0]?.trim() ?? \"\";\n if (firstLine.length > 80) {\n return firstLine.substring(0, 77) + \"...\";\n }\n return firstLine;\n }\n}\n","import type { StyleExtractor, Observation, ParsedFile } from \"./types.js\";\n\ninterface ReviewComment {\n body: string;\n file?: string;\n}\n\ntype ReviewTopic =\n | \"naming\"\n | \"error-handling\"\n | \"complexity\"\n | \"style\"\n | \"performance\"\n | \"documentation\"\n | \"testing\"\n | \"security\"\n | \"readability\"\n | \"structure\";\n\ninterface TopicPattern {\n topic: ReviewTopic;\n patterns: RegExp[];\n}\n\nconst TOPIC_PATTERNS: TopicPattern[] = [\n {\n topic: \"naming\",\n patterns: [\n /\\bnam(?:e|ing)\\b/i,\n /\\brenam(?:e|ing)\\b/i,\n /\\bcamelCase\\b/i,\n /\\bsnake_case\\b/i,\n /\\bdescriptive\\b/i,\n /\\bconfusing\\b/i,\n /\\bprefer\\s+\\S+\\s+over\\b/i,\n ],\n },\n {\n topic: \"error-handling\",\n patterns: [\n /\\berror\\s*handl/i,\n /\\bmissing\\s+error/i,\n /\\btry\\s*\\/?\\s*catch\\b/i,\n /\\bwhat\\s+happens\\s+if\\b/i,\n /\\bedge\\s*case/i,\n /\\bnull\\b/i,\n /\\bfails?\\b/i,\n ],\n },\n {\n topic: \"complexity\",\n patterns: [\n /\\bcomplex\\b/i,\n /\\btoo\\s+long\\b/i,\n /\\bsplit\\b.*\\bup\\b/i,\n /\\bextract\\b.*\\bfunction/i,\n /\\bsmaller\\s+functions?\\b/i,\n /\\bsimplif/i,\n /\\bnesting\\b/i,\n ],\n },\n {\n topic: \"style\",\n patterns: [\n /\\bstyle\\b/i,\n /\\bformat/i,\n /\\bconsistenc/i,\n /\\bnit\\b/i,\n /\\bquotes?\\b/i,\n /\\bsemicolon/i,\n /\\bindent/i,\n /\\bwhitespace\\b/i,\n ],\n },\n {\n topic: \"performance\",\n patterns: [\n /\\bperforman/i,\n /\\bmemoiz/i,\n /\\bre-?render/i,\n /\\boptimiz/i,\n /\\bexpensive\\b/i,\n /\\befficien/i,\n /\\bcach/i,\n ],\n },\n {\n topic: \"documentation\",\n patterns: [\n /\\bdocument/i,\n /\\bjsdoc\\b/i,\n ],\n },\n {\n topic: \"testing\",\n patterns: [\n /\\btest/i,\n /\\bcover(?:age)?\\b/i,\n /\\bassert/i,\n /\\bmock/i,\n /\\bspec\\b/i,\n ],\n },\n {\n topic: \"security\",\n patterns: [\n /\\bsecur/i,\n /\\bvulnerab/i,\n /\\bsaniti[zs]/i,\n /\\binject/i,\n /\\bescap/i,\n /\\bxss\\b/i,\n ],\n },\n {\n topic: \"readability\",\n patterns: [\n /\\breadab/i,\n /\\bearly\\s+return/i,\n /\\bguard\\s+clause/i,\n ],\n },\n {\n topic: \"structure\",\n patterns: [\n /\\bstructur/i,\n /\\barchitect/i,\n /\\borganiz/i,\n /\\bseparati/i,\n ],\n },\n];\n\nconst KEYWORD_PATTERNS: Array<{ keyword: string; pattern: RegExp }> = [\n { keyword: \"early-return\", pattern: /\\bearly\\s+return\\b/i },\n { keyword: \"guard-clause\", pattern: /\\bguard\\s+clause\\b/i },\n {\n keyword: \"single-responsibility\",\n pattern: /\\bsingle\\s+responsib/i,\n },\n { keyword: \"dry\", pattern: /\\b(?:DRY|don'?t\\s+repeat)\\b/i },\n { keyword: \"immutability\", pattern: /\\bimmutab/i },\n { keyword: \"type-safety\", pattern: /\\btype[\\s-]*safe/i },\n { keyword: \"null-check\", pattern: /\\bnull\\s+check/i },\n { keyword: \"magic-number\", pattern: /\\bmagic\\s+number/i },\n];\n\nexport class ReviewVoiceExtractor implements StyleExtractor {\n readonly name = \"reviewVoice\";\n\n extract(_file: ParsedFile): Observation[] {\n return [];\n }\n\n extractFromComments(comments: ReviewComment[]): Observation[] {\n if (comments.length === 0) return [];\n\n const observations: Observation[] = [];\n\n observations.push(...this.categorizeTopics(comments));\n observations.push(...this.extractKeywords(comments));\n\n return observations;\n }\n\n private categorizeTopics(comments: ReviewComment[]): Observation[] {\n const { topicCounts, topicExamples } = this.countTopics(comments);\n\n const observations: Observation[] = [];\n\n for (const [topic, count] of topicCounts) {\n observations.push({\n type: \"reviewVoice.topicFrequency\",\n category: \"reviewVoice\",\n value: topic,\n file: \"_reviews\",\n line: 0,\n metadata: {\n count,\n total: comments.length,\n ratio: count / comments.length,\n examples: topicExamples.get(topic) ?? [],\n },\n });\n }\n\n observations.sort(\n (a, b) =>\n ((b.metadata?.count as number) ?? 0) -\n ((a.metadata?.count as number) ?? 0),\n );\n\n return observations;\n }\n\n private countTopics(comments: ReviewComment[]): {\n topicCounts: Map<ReviewTopic, number>;\n topicExamples: Map<ReviewTopic, string[]>;\n } {\n const topicCounts = new Map<ReviewTopic, number>();\n const topicExamples = new Map<ReviewTopic, string[]>();\n\n for (const comment of comments) {\n for (const topic of this.matchTopics(comment.body)) {\n topicCounts.set(topic, (topicCounts.get(topic) ?? 0) + 1);\n\n const examples = topicExamples.get(topic) ?? [];\n if (examples.length < 3) {\n examples.push(comment.body);\n topicExamples.set(topic, examples);\n }\n }\n }\n\n return { topicCounts, topicExamples };\n }\n\n private matchTopics(body: string): Set<ReviewTopic> {\n const matchedTopics = new Set<ReviewTopic>();\n\n for (const { topic, patterns } of TOPIC_PATTERNS) {\n for (const pattern of patterns) {\n if (pattern.test(body)) {\n matchedTopics.add(topic);\n break;\n }\n }\n }\n\n return matchedTopics;\n }\n\n private extractKeywords(comments: ReviewComment[]): Observation[] {\n const keywordCounts = new Map<string, number>();\n\n for (const comment of comments) {\n for (const { keyword, pattern } of KEYWORD_PATTERNS) {\n if (pattern.test(comment.body)) {\n keywordCounts.set(keyword, (keywordCounts.get(keyword) ?? 0) + 1);\n }\n }\n }\n\n const observations: Observation[] = [];\n\n for (const [keyword, count] of keywordCounts) {\n observations.push({\n type: \"reviewVoice.keyword\",\n category: \"reviewVoice\",\n value: keyword,\n file: \"_reviews\",\n line: 0,\n metadata: {\n count,\n total: comments.length,\n },\n });\n }\n\n return observations;\n }\n}\n","import type { StyleExtractor } from \"./types.js\";\nimport { NamingExtractor } from \"./naming.js\";\nimport { StructureExtractor } from \"./structure.js\";\nimport { ControlFlowExtractor } from \"./control-flow.js\";\nimport { DocumentationExtractor } from \"./documentation.js\";\nimport { ErrorHandlingExtractor } from \"./error-handling.js\";\nimport { FormattingExtractor } from \"./formatting.js\";\nimport { ComplexityExtractor } from \"./complexity.js\";\nimport { IdiomsExtractor } from \"./idioms.js\";\nimport { ReviewVoiceExtractor } from \"./review-voice.js\";\n\n/**\n * Canonical set of style extractors. Single source of truth — CLI commands,\n * scripts, and tests should import this rather than reconstructing the list.\n */\nexport function createStyleExtractors(): StyleExtractor[] {\n return [\n new NamingExtractor(),\n new StructureExtractor(),\n new ControlFlowExtractor(),\n new DocumentationExtractor(),\n new ErrorHandlingExtractor(),\n new FormattingExtractor(),\n new ComplexityExtractor(),\n new IdiomsExtractor(),\n new ReviewVoiceExtractor(),\n ];\n}\n","import type { Severity, SeverityThresholds } from \"@titan-design/style-profile\";\nimport { DEFAULT_SEVERITY_THRESHOLDS, severityForConfidence } from \"@titan-design/style-profile\";\nimport type { Stability } from \"./stability.js\";\n\nexport type { Severity, SeverityThresholds };\nexport { DEFAULT_SEVERITY_THRESHOLDS };\n\nexport interface StabilityWeights {\n high: number;\n medium: number;\n low: number;\n}\n\nexport const DEFAULT_STABILITY_WEIGHTS: StabilityWeights = {\n high: 1.0,\n medium: 0.85,\n low: 0.7,\n};\n\nexport function computeConfidence(\n consistency: number,\n stability: Stability,\n weights: StabilityWeights = DEFAULT_STABILITY_WEIGHTS,\n): number {\n return Math.min(1.0, consistency * weights[stability]);\n}\n\nexport { severityForConfidence as mapSeverity };\n","import type { Observation } from \"../extractors/types.js\";\n\nexport interface FrequencyDistribution {\n values: Map<string | number | boolean, number>;\n total: number;\n dominant: string | number | boolean;\n consistency: number;\n}\n\nexport function groupByType(\n observations: Observation[],\n): Map<string, Observation[]> {\n const groups = new Map<string, Observation[]>();\n\n for (const obs of observations) {\n const existing = groups.get(obs.type) ?? [];\n existing.push(obs);\n groups.set(obs.type, existing);\n }\n\n return groups;\n}\n\nexport function computeDistribution(\n observations: Observation[],\n): FrequencyDistribution {\n const valueCounts = new Map<string | number | boolean, number>();\n\n for (const obs of observations) {\n const key = normalizeValue(obs.value);\n valueCounts.set(key, (valueCounts.get(key) ?? 0) + 1);\n }\n\n const total = observations.length;\n\n let dominant: string | number | boolean = \"\";\n let maxCount = 0;\n\n for (const [value, count] of valueCounts) {\n if (count > maxCount) {\n maxCount = count;\n dominant = value;\n }\n }\n\n return {\n values: valueCounts,\n total,\n dominant,\n consistency: total > 0 ? maxCount / total : 0,\n };\n}\n\nfunction normalizeValue(value: unknown): string | number | boolean {\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return value;\n }\n if (Array.isArray(value)) {\n return JSON.stringify(value);\n }\n return String(value);\n}\n\nexport function selectExamples(\n observations: Observation[],\n maxExamples: number,\n): Observation[] {\n if (observations.length <= maxExamples) {\n return [...observations];\n }\n\n const step = Math.floor(observations.length / maxExamples);\n const examples: Observation[] = [];\n\n for (\n let i = 0;\n i < observations.length && examples.length < maxExamples;\n i += step\n ) {\n examples.push(observations[i]!);\n }\n\n return examples;\n}\n","export type Stability = \"high\" | \"medium\" | \"low\";\n\n/**\n * Stability lookup table derived from RoPGen research and the unified\n * feature taxonomy (docs/research/07-unified-feature-taxonomy.md).\n *\n * Key: an observation type exactly as an extractor emits it (e.g., \"naming.variable\").\n * Value: stability rating.\n *\n * High = persists even when developer tries to write differently (weight 1.0)\n * Medium = consistent under normal conditions (weight 0.85)\n * Low = varies by project/language/intent (weight 0.7)\n *\n * stability.test.ts fails when an emitted type is neither keyed here nor listed\n * in UNRATED_TYPES, and when a key here names a type no extractor emits.\n */\nexport const STABILITY_MAP: Record<string, Stability> = {\n // Category 1: Naming Conventions\n \"naming.variable\": \"high\",\n \"naming.function\": \"high\",\n \"naming.type\": \"high\",\n \"naming.constant\": \"high\",\n \"naming.boolean\": \"medium\",\n \"naming.parameter\": \"medium\",\n \"naming.enum\": \"high\",\n \"naming.private-member\": \"high\",\n\n // Category 2: Code Structure\n \"structure.import-group\": \"high\",\n \"structure.import-order\": \"high\",\n \"structure.export-style\": \"high\",\n \"structure.barrel-file\": \"medium\",\n \"structure.export-proximity\": \"medium\",\n\n // Category 3: Control Flow Patterns\n \"control-flow.guard-clause\": \"high\",\n \"control-flow.ternary\": \"medium\",\n \"control-flow.array-method\": \"high\",\n \"control-flow.for-loop\": \"medium\",\n \"control-flow.for-of\": \"medium\",\n \"control-flow.for-in\": \"medium\",\n \"control-flow.async-await\": \"high\",\n\n // Category 4: Error Handling\n \"error-handling.try-catch\": \"high\",\n \"error-handling.catch-specificity\": \"medium\",\n \"error-handling.result-type\": \"high\",\n \"error-handling.custom-error-class\": \"medium\",\n \"error-handling.exhaustive-switch\": \"high\",\n \"error-handling.assert-never\": \"high\",\n\n // Category 5: Documentation\n \"documentation.jsdoc-presence\": \"high\",\n \"documentation.public-coverage\": \"medium\",\n \"documentation.private-coverage\": \"medium\",\n \"documentation.inline-comment\": \"medium\",\n \"documentation.comment-placement\": \"medium\",\n \"documentation.jsdoc-tag\": \"medium\",\n\n // Category 7: Formatting & Layout\n \"formatting.indentStyle\": \"high\",\n \"formatting.indentSize\": \"high\",\n \"formatting.semicolons\": \"high\",\n \"formatting.quoteStyle\": \"high\",\n \"formatting.trailingCommas\": \"high\",\n \"formatting.braceStyle\": \"high\",\n \"formatting.trailingNewline\": \"high\",\n\n // Category 9: Habitual Idioms\n \"idiom.clone\": \"high\",\n\n // Category 10: Review Voice\n \"reviewVoice.topicFrequency\": \"medium\",\n \"reviewVoice.keyword\": \"medium\",\n\n // Complexity (from task-07)\n \"complexity.functionLength\": \"high\",\n \"complexity.nestingDepth\": \"high\",\n \"complexity.cyclomatic\": \"high\",\n \"complexity.fileLength\": \"medium\",\n};\n\n/**\n * Emitted types the taxonomy gives no rating. They take the medium default on\n * purpose, and each is an open question for the profile's owner.\n */\nexport const UNRATED_TYPES: ReadonlySet<string> = new Set([\n \"control-flow.if-else\",\n \"control-flow.promise-then\",\n \"control-flow.else-after-return\",\n]);\n\nexport function lookupStability(type: string): Stability {\n if (STABILITY_MAP[type]) return STABILITY_MAP[type];\n\n const category = type.indexOf(\".\") > 0 ? type.substring(0, type.indexOf(\".\")) : type;\n if (STABILITY_MAP[category]) return STABILITY_MAP[category];\n\n return \"medium\";\n}\n","import type { Observation, ObservationCategory } from \"../extractors/types.js\";\nimport {\n computeConfidence,\n mapSeverity,\n DEFAULT_STABILITY_WEIGHTS,\n DEFAULT_SEVERITY_THRESHOLDS,\n type StabilityWeights,\n type SeverityThresholds,\n type Severity,\n} from \"./confidence.js\";\nimport {\n groupByType,\n computeDistribution,\n selectExamples,\n type FrequencyDistribution,\n} from \"./frequency.js\";\nimport { lookupStability, type Stability } from \"./stability.js\";\n\nexport { computeConfidence, mapSeverity } from \"./confidence.js\";\nexport { lookupStability, type Stability } from \"./stability.js\";\nexport type { FrequencyDistribution } from \"./frequency.js\";\nexport type { Severity } from \"@titan-design/style-profile\";\nexport type {\n StabilityWeights,\n SeverityThresholds,\n} from \"./confidence.js\";\n\nexport interface AggregatedFeature {\n type: string;\n category: ObservationCategory;\n convention: string | number | boolean | string[];\n distribution: FrequencyDistribution;\n confidence: number;\n stability: Stability;\n severity: Severity;\n needsReview: boolean;\n examples: Observation[];\n}\n\nexport interface AggregatorConfig {\n stabilityWeights?: StabilityWeights;\n severityThresholds?: SeverityThresholds;\n reviewThreshold?: number;\n maxExamples?: number;\n}\n\nexport interface AggregatorResult {\n features: Map<string, AggregatedFeature>;\n reviewQueue: AggregatedFeature[];\n summary: {\n totalObservations: number;\n totalFeatures: number;\n avgConfidence: number;\n featuresNeedingReview: number;\n };\n}\n\nexport class Aggregator {\n private stabilityWeights: StabilityWeights;\n private severityThresholds: SeverityThresholds;\n private reviewThreshold: number;\n private maxExamples: number;\n\n constructor(config?: AggregatorConfig) {\n this.stabilityWeights =\n config?.stabilityWeights ?? DEFAULT_STABILITY_WEIGHTS;\n this.severityThresholds =\n config?.severityThresholds ?? DEFAULT_SEVERITY_THRESHOLDS;\n this.reviewThreshold = config?.reviewThreshold ?? 0.6;\n this.maxExamples = config?.maxExamples ?? 5;\n }\n\n aggregate(observations: Observation[]): AggregatorResult {\n const grouped = groupByType(observations);\n const features = new Map<string, AggregatedFeature>();\n const reviewQueue: AggregatedFeature[] = [];\n\n for (const [type, typeObservations] of grouped) {\n const feature = this.buildFeature(type, typeObservations);\n\n features.set(type, feature);\n\n if (feature.needsReview) {\n reviewQueue.push(feature);\n }\n }\n\n reviewQueue.sort((a, b) => a.confidence - b.confidence);\n\n return {\n features,\n reviewQueue,\n summary: {\n totalObservations: observations.length,\n totalFeatures: features.size,\n avgConfidence: averageConfidence(features),\n featuresNeedingReview: reviewQueue.length,\n },\n };\n }\n\n private buildFeature(\n type: string,\n typeObservations: Observation[],\n ): AggregatedFeature {\n const distribution = computeDistribution(typeObservations);\n const stability = lookupStability(type);\n const confidence = computeConfidence(\n distribution.consistency,\n stability,\n this.stabilityWeights,\n );\n\n return {\n type,\n category: this.extractCategory(type),\n convention: distribution.dominant,\n distribution,\n confidence,\n stability,\n severity: mapSeverity(confidence, this.severityThresholds),\n needsReview: confidence < this.reviewThreshold,\n examples: selectExamples(typeObservations, this.maxExamples),\n };\n }\n\n private extractCategory(type: string): ObservationCategory {\n const dotIndex = type.indexOf(\".\");\n return (dotIndex > 0 ? type.substring(0, dotIndex) : type) as ObservationCategory;\n }\n}\n\nfunction averageConfidence(features: Map<string, AggregatedFeature>): number {\n const confidences = Array.from(features.values()).map((f) => f.confidence);\n return confidences.length > 0\n ? confidences.reduce((a, b) => a + b, 0) / confidences.length\n : 0;\n}\n","import type { LlmMessage, LlmProvider } from \"./llm.js\";\n\nexport interface LlmJob<TKey> {\n key: TKey;\n messages: LlmMessage[];\n maxTokens: number;\n}\n\nexport interface LlmJobSuccess<TKey> {\n key: TKey;\n content: string;\n tokensUsed: number;\n}\n\nexport interface LlmJobFailure<TKey> {\n key: TKey;\n error: string;\n}\n\nexport interface LlmRunResult<TKey> {\n results: LlmJobSuccess<TKey>[];\n errors: LlmJobFailure<TKey>[];\n totalTokensUsed: number;\n budgetExceeded: boolean;\n}\n\nexport interface LlmRunnerConfig {\n provider: LlmProvider;\n totalTokenBudget?: number;\n}\n\n/**\n * Runs a list of LLM jobs sequentially against a provider, halting when the\n * cumulative token budget is exceeded and capturing per-job errors instead\n * of throwing. Knows nothing about features, prompts, or domain shapes —\n * callers build jobs upstream.\n */\nexport class LlmRunner {\n private provider: LlmProvider;\n private totalTokenBudget: number;\n\n constructor(config: LlmRunnerConfig) {\n this.provider = config.provider;\n this.totalTokenBudget = config.totalTokenBudget ?? 20_000;\n }\n\n async run<TKey>(jobs: LlmJob<TKey>[]): Promise<LlmRunResult<TKey>> {\n const results: LlmJobSuccess<TKey>[] = [];\n const errors: LlmJobFailure<TKey>[] = [];\n let totalTokensUsed = 0;\n let budgetExceeded = false;\n\n for (const job of jobs) {\n if (totalTokensUsed >= this.totalTokenBudget) {\n budgetExceeded = true;\n break;\n }\n\n totalTokensUsed += await this.runJob(job, results, errors);\n }\n\n return { results, errors, totalTokensUsed, budgetExceeded };\n }\n\n // Returns the tokens the job consumed, which is zero when the provider throws.\n private async runJob<TKey>(\n job: LlmJob<TKey>,\n results: LlmJobSuccess<TKey>[],\n errors: LlmJobFailure<TKey>[],\n ): Promise<number> {\n try {\n const response = await this.provider.generate(job.messages, {\n maxTokens: job.maxTokens,\n });\n results.push({\n key: job.key,\n content: response.content,\n tokensUsed: response.tokensUsed,\n });\n return response.tokensUsed;\n } catch (error) {\n errors.push({\n key: job.key,\n error: error instanceof Error ? error.message : String(error),\n });\n return 0;\n }\n }\n}\n","export interface PromptInput {\n category: string;\n featureType: string;\n convention: string | number | boolean | string[];\n confidence: number;\n consistency: number;\n examples: string[];\n distribution?: Record<string, number>;\n}\n\nexport interface PromptTemplate {\n featureTypes: string[];\n system: string;\n buildUserMessage: (input: PromptInput) => string;\n maxTokens: number;\n}\n\nexport const DESCRIPTION_PROMPT: PromptTemplate = {\n featureTypes: [\n \"documentation.comment-placement\",\n \"documentation.inline-comment\",\n \"documentation.jsdoc-tag\",\n \"error-handling.catch-specificity\",\n \"structure.export-style\",\n ],\n system:\n \"You are a code style analyst. Given statistical observations about a developer's coding patterns, write a concise, actionable style rule description. Output ONLY the description text (1-3 sentences). Do not include markdown formatting or headers.\",\n buildUserMessage: (input: PromptInput) => {\n const lines = [\n `Feature: ${input.featureType}`,\n `Dominant pattern: ${JSON.stringify(input.convention)}`,\n `Confidence: ${(input.confidence * 100).toFixed(0)}%`,\n `Consistency: ${(input.consistency * 100).toFixed(0)}%`,\n ];\n\n if (input.distribution) {\n lines.push(\n `Distribution: ${JSON.stringify(input.distribution)}`,\n );\n }\n\n if (input.examples.length > 0) {\n lines.push(\"\", \"Representative code samples:\");\n for (const example of input.examples.slice(0, 5)) {\n lines.push(\"```\", example, \"```\");\n }\n }\n\n lines.push(\n \"\",\n \"Write a concise style rule description for this pattern.\",\n );\n\n return lines.join(\"\\n\");\n },\n maxTokens: 300,\n};\n\nexport const REVIEW_VOICE_PROMPT: PromptTemplate = {\n featureTypes: [\n \"reviewVoice.topicFrequency\",\n \"reviewVoice.keyword\",\n ],\n system:\n \"You are analyzing a developer's code review comments to understand their review voice and priorities. Given topic frequencies and example comments, synthesize a brief description of what this developer cares about in code reviews. Output ONLY the synthesis text (2-4 sentences). Do not include markdown formatting or headers.\",\n buildUserMessage: (input: PromptInput) => {\n const lines = [\n `Review topic: ${input.featureType}`,\n `Pattern: ${JSON.stringify(input.convention)}`,\n ];\n\n if (input.distribution) {\n lines.push(\n `Topic frequencies: ${JSON.stringify(input.distribution)}`,\n );\n }\n\n if (input.examples.length > 0) {\n lines.push(\"\", \"Example review comments:\");\n for (const example of input.examples.slice(0, 5)) {\n lines.push(`- \"${example}\"`);\n }\n }\n\n lines.push(\n \"\",\n \"Synthesize what this developer values in code reviews.\",\n );\n\n return lines.join(\"\\n\");\n },\n maxTokens: 400,\n};\n\nexport const AI_ENRICHED_FEATURES = [\n ...DESCRIPTION_PROMPT.featureTypes,\n ...REVIEW_VOICE_PROMPT.featureTypes,\n];\n\nexport function getPromptForFeature(\n featureType: string,\n): PromptTemplate | null {\n if (DESCRIPTION_PROMPT.featureTypes.includes(featureType)) {\n return DESCRIPTION_PROMPT;\n }\n if (REVIEW_VOICE_PROMPT.featureTypes.includes(featureType)) {\n return REVIEW_VOICE_PROMPT;\n }\n return null;\n}\n\nexport function needsAiEnrichment(featureType: string): boolean {\n return AI_ENRICHED_FEATURES.includes(featureType);\n}\n","import type { AggregatedFeature } from \"../aggregator/aggregator.js\";\nimport { LlmRunner, type LlmJob, type LlmRunResult } from \"./llm-runner.js\";\nimport type { LlmMessage, LlmProvider } from \"./llm.js\";\nimport {\n getPromptForFeature,\n needsAiEnrichment,\n type PromptInput,\n} from \"./prompts.js\";\n\nexport { needsAiEnrichment, AI_ENRICHED_FEATURES } from \"./prompts.js\";\nexport type { LlmProvider, LlmMessage, LlmResponse } from \"./llm.js\";\n\nexport type { AggregatedFeature } from \"../aggregator/aggregator.js\";\n\nexport interface EnrichmentEntry {\n featureType: string;\n description: string;\n tokensUsed: number;\n}\n\nexport interface EnrichmentError {\n featureType: string;\n error: string;\n}\n\nexport interface EnrichmentResult {\n enriched: Map<string, EnrichmentEntry>;\n errors: EnrichmentError[];\n totalTokensUsed: number;\n budgetExceeded: boolean;\n skipped: boolean;\n}\n\nexport interface EnricherConfig {\n provider: LlmProvider;\n enabled?: boolean;\n totalTokenBudget?: number;\n}\n\nexport class Enricher {\n private runner: LlmRunner;\n private enabled: boolean;\n\n constructor(config: EnricherConfig) {\n this.runner = new LlmRunner({\n provider: config.provider,\n totalTokenBudget: config.totalTokenBudget,\n });\n this.enabled = config.enabled ?? true;\n }\n\n async enrich(\n features: Map<string, AggregatedFeature>,\n ): Promise<EnrichmentResult> {\n if (!this.enabled) {\n return {\n enriched: new Map(),\n errors: [],\n totalTokensUsed: 0,\n budgetExceeded: false,\n skipped: true,\n };\n }\n\n const runResult = await this.runner.run(this.buildJobs(features));\n return toEnrichmentResult(runResult);\n }\n\n private buildJobs(\n features: Map<string, AggregatedFeature>,\n ): LlmJob<string>[] {\n const jobs: LlmJob<string>[] = [];\n for (const [type, feature] of features) {\n if (!needsAiEnrichment(type)) continue;\n const promptTemplate = getPromptForFeature(type);\n if (!promptTemplate) continue;\n\n const input = this.buildPromptInput(type, feature);\n const messages: LlmMessage[] = [\n { role: \"system\", content: promptTemplate.system },\n {\n role: \"user\",\n content: promptTemplate.buildUserMessage(input),\n },\n ];\n\n jobs.push({ key: type, messages, maxTokens: promptTemplate.maxTokens });\n }\n return jobs;\n }\n\n private buildPromptInput(\n type: string,\n feature: AggregatedFeature,\n ): PromptInput {\n const distributionRecord: Record<string, number> = {};\n for (const [key, count] of feature.distribution.values) {\n distributionRecord[String(key)] = count;\n }\n\n const exampleTexts = feature.examples.map((obs) => {\n if (typeof obs.value === \"string\") return obs.value;\n return JSON.stringify(obs.value);\n });\n\n return {\n category: feature.category,\n featureType: type,\n convention: feature.convention,\n confidence: feature.confidence,\n consistency: feature.distribution.consistency,\n examples: exampleTexts,\n distribution: distributionRecord,\n };\n }\n}\n\nfunction toEnrichmentResult(runResult: LlmRunResult<string>): EnrichmentResult {\n const enriched = new Map<string, EnrichmentEntry>();\n for (const r of runResult.results) {\n enriched.set(r.key, {\n featureType: r.key,\n description: r.content,\n tokensUsed: r.tokensUsed,\n });\n }\n\n return {\n enriched,\n errors: runResult.errors.map((e) => ({\n featureType: e.key,\n error: e.error,\n })),\n totalTokensUsed: runResult.totalTokensUsed,\n budgetExceeded: runResult.budgetExceeded,\n skipped: false,\n };\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@titan-design/style-analyzer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Tree-sitter style extractors that turn source files into observations, and the aggregator that turns observations into a style profile with confidence and stability",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|