@titan-design/style-analyzer 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,8 +9,8 @@ describe the features that numbers alone cannot capture.
9
9
 
10
10
  Tier 2 of the titan-platform DAG (TP-134). Depends on `@titan-design/code-parser` (tier 0)
11
11
  and `@titan-design/style-profile` (tier 2). `zod` v4 is a peer because style-profile
12
- needs it at runtime. Ported unchanged from codewatch's
13
- `@codewatch/analyzer`.
12
+ needs it at runtime. Ported from codewatch's `@codewatch/analyzer`, with two bug fixes
13
+ since: stability keys and Python constants (see Gotchas).
14
14
 
15
15
  ```sh
16
16
  npm install @titan-design/style-analyzer web-tree-sitter@^0.26.6 zod
@@ -116,9 +116,19 @@ at the original's versions.
116
116
  - `extractFromConfig` swallows every error, including a missing file or malformed JSON,
117
117
  and returns `[]`.
118
118
  - Review-voice observations use `file: "_reviews"` and `line: 0`.
119
- - `STABILITY_MAP` uses spellings the extractors do not emit. Examples are
120
- `naming.variables` against the emitted `naming.variable`, and `controlFlow.*` against
121
- `control-flow.*`. Those types fall back to `medium`. This is the original's behaviour.
119
+ - `STABILITY_MAP` keys are the exact emitted types, and `stability.test.ts` fails in both
120
+ directions when they drift. `UNRATED_TYPES` lists the three emitted types the taxonomy
121
+ never rated (`control-flow.if-else`, `.promise-then`, `.else-after-return`); they take
122
+ `medium` on purpose. The original codewatch map used taxonomy spellings that matched
123
+ none of 30 emitted types, so those types all fell back to `medium` (TP-172).
124
+ - A Python assignment counts as `naming.constant` only at module scope (TP-173). Module
125
+ scope means top level, or inside a module-level `if`, `elif`, `else`, `try`, `except`,
126
+ `finally` or `with` block. Annotated and chained forms count. Class, function and loop
127
+ bodies do not.
128
+ - In both languages, a constant name is `SCREAMING_SNAKE` or one capitalised word of two
129
+ or more characters (`DEBUG`, `VERSION`). A single letter such as `T = TypeVar("T")` or
130
+ `const K = 1` stays `naming.variable` `PascalCase`. A two-letter TypeVar such as
131
+ `KT = TypeVar("KT")` counts as a constant.
122
132
 
123
133
  The worked example and the full observation list are in the site reference page,
124
134
  `site/reference/style-analyzer.md`.
package/dist/index.js CHANGED
@@ -23,11 +23,33 @@ function detectConvention(name) {
23
23
  if (/^[a-z][a-z0-9]*$/.test(name)) return "camelCase";
24
24
  return null;
25
25
  }
26
+ var SINGLE_WORD_CONSTANT = /^[A-Z][A-Z0-9]+$/;
27
+ function isConstantName(name) {
28
+ return NAMING_PATTERNS.SCREAMING_SNAKE.test(name) || SINGLE_WORD_CONSTANT.test(name);
29
+ }
26
30
  function detectBooleanPrefix(name, language) {
27
31
  const pattern = language === "python" ? PYTHON_BOOLEAN_PREFIXES : BOOLEAN_PREFIXES;
28
32
  const match = name.match(pattern);
29
33
  return match ? match[1] : null;
30
34
  }
35
+ var MODULE_SCOPE_BLOCKS = /* @__PURE__ */ new Set([
36
+ "block",
37
+ "if_statement",
38
+ "elif_clause",
39
+ "else_clause",
40
+ "try_statement",
41
+ "except_clause",
42
+ "finally_clause",
43
+ "with_statement"
44
+ ]);
45
+ function isModuleLevelAssignment(node) {
46
+ let scope = node.parent;
47
+ while (scope?.type === "assignment") scope = scope.parent;
48
+ if (scope?.type !== "expression_statement") return false;
49
+ scope = scope.parent;
50
+ while (scope && MODULE_SCOPE_BLOCKS.has(scope.type)) scope = scope.parent;
51
+ return scope?.type === "module";
52
+ }
31
53
  var NamingExtractor = class {
32
54
  name = "naming";
33
55
  extract(file) {
@@ -83,7 +105,7 @@ var NamingExtractor = class {
83
105
  if (!nameNode || nameNode.type !== "identifier") return;
84
106
  const name = nameNode.text;
85
107
  const declKind = node.parent?.type === "lexical_declaration" ? node.parent.children[0]?.text : null;
86
- if (declKind === "const" && NAMING_PATTERNS.SCREAMING_SNAKE.test(name)) {
108
+ if (declKind === "const" && isConstantName(name)) {
87
109
  this.addObservation(observations, "naming.constant", "SCREAMING_SNAKE", file, node);
88
110
  return;
89
111
  }
@@ -122,7 +144,7 @@ var NamingExtractor = class {
122
144
  const left = node.childForFieldName("left");
123
145
  if (!left || left.type !== "identifier") return;
124
146
  const name = left.text;
125
- if (node.parent?.type === "module" && NAMING_PATTERNS.SCREAMING_SNAKE.test(name)) {
147
+ if (isModuleLevelAssignment(node) && isConstantName(name)) {
126
148
  this.addObservation(observations, "naming.constant", "SCREAMING_SNAKE", file, node);
127
149
  return;
128
150
  }
@@ -1806,70 +1828,42 @@ function selectExamples(observations, maxExamples) {
1806
1828
  // src/aggregator/stability.ts
1807
1829
  var STABILITY_MAP = {
1808
1830
  // Category 1: Naming Conventions
1809
- "naming.variables": "high",
1810
- "naming.functions": "high",
1811
- "naming.types": "high",
1812
- "naming.constants": "high",
1813
- "naming.files": "high",
1814
- "naming.booleans": "medium",
1815
- "naming.abbreviations": "medium",
1816
- "naming.parameters": "medium",
1817
- "naming.enums": "high",
1818
- "naming.privateMembers": "high",
1831
+ "naming.variable": "high",
1832
+ "naming.function": "high",
1833
+ "naming.type": "high",
1834
+ "naming.constant": "high",
1835
+ "naming.boolean": "medium",
1836
+ "naming.parameter": "medium",
1837
+ "naming.enum": "high",
1838
+ "naming.private-member": "high",
1819
1839
  // Category 2: Code Structure
1820
1840
  "structure.import-group": "high",
1821
1841
  "structure.import-order": "high",
1822
- "structure.importPathStyle": "medium",
1823
- "structure.typeImportSeparation": "medium",
1824
1842
  "structure.export-style": "high",
1825
1843
  "structure.barrel-file": "medium",
1826
1844
  "structure.export-proximity": "medium",
1827
- "structure.functionLength": "high",
1828
- "structure.nestingDepth": "high",
1829
- "structure.fileLength": "medium",
1830
- "structure.moduleTopology": "low",
1831
- "structure.fileOrganization": "low",
1832
1845
  // Category 3: Control Flow Patterns
1833
- "controlFlow.guardClauses": "high",
1834
- "controlFlow.earlyReturn": "high",
1835
- "controlFlow.ternaryPreference": "medium",
1836
- "controlFlow.arrayMethods": "high",
1837
- "controlFlow.forStyle": "medium",
1838
- "controlFlow.asyncAwait": "high",
1839
- "controlFlow.switchVsIf": "medium",
1840
- "controlFlow.optionalChaining": "medium",
1841
- "controlFlow.nullishCoalescing": "low",
1846
+ "control-flow.guard-clause": "high",
1847
+ "control-flow.ternary": "medium",
1848
+ "control-flow.array-method": "high",
1849
+ "control-flow.for-loop": "medium",
1850
+ "control-flow.for-of": "medium",
1851
+ "control-flow.for-in": "medium",
1852
+ "control-flow.async-await": "high",
1842
1853
  // Category 4: Error Handling
1843
- "errorHandling.tryCatchFrequency": "high",
1844
- "errorHandling.catchSpecificity": "medium",
1845
- "errorHandling.resultType": "high",
1846
- "errorHandling.errorReturnTuples": "medium",
1847
- "errorHandling.customErrorClasses": "medium",
1848
- "errorHandling.exhaustiveSwitch": "high",
1849
- "errorHandling.assertNever": "high",
1850
- "errorHandling.floatingPromises": "medium",
1851
- "errorHandling.errorBoundary": "low",
1854
+ "error-handling.try-catch": "high",
1855
+ "error-handling.catch-specificity": "medium",
1856
+ "error-handling.result-type": "high",
1857
+ "error-handling.custom-error-class": "medium",
1858
+ "error-handling.exhaustive-switch": "high",
1859
+ "error-handling.assert-never": "high",
1852
1860
  // Category 5: Documentation
1853
- "documentation.jsdocPresence": "high",
1854
- "documentation.publicPrivateCoverage": "medium",
1855
- "documentation.inlineCommentDensity": "medium",
1856
- "documentation.commentPlacement": "medium",
1857
- "documentation.sectionComments": "low",
1858
- "documentation.moduleHeaders": "medium",
1859
- "documentation.jsdocTags": "medium",
1860
- "documentation.voice": "low",
1861
- "documentation.whyVsWhat": "low",
1862
- "documentation.redundancy": "low",
1863
- // Category 6: Type System Usage
1864
- "typeSystem.annotationDensity": "high",
1865
- "typeSystem.explicitReturn": "high",
1866
- "typeSystem.moduleBoundaryTypes": "medium",
1867
- "typeSystem.inferrableTypes": "medium",
1868
- "typeSystem.interfaceVsType": "medium",
1869
- "typeSystem.genericUsage": "low",
1870
- "typeSystem.readonlyUsage": "medium",
1871
- "typeSystem.discriminatedUnions": "medium",
1872
- "typeSystem.utilityTypes": "low",
1861
+ "documentation.jsdoc-presence": "high",
1862
+ "documentation.public-coverage": "medium",
1863
+ "documentation.private-coverage": "medium",
1864
+ "documentation.inline-comment": "medium",
1865
+ "documentation.comment-placement": "medium",
1866
+ "documentation.jsdoc-tag": "medium",
1873
1867
  // Category 7: Formatting & Layout
1874
1868
  "formatting.indentStyle": "high",
1875
1869
  "formatting.indentSize": "high",
@@ -1877,31 +1871,12 @@ var STABILITY_MAP = {
1877
1871
  "formatting.quoteStyle": "high",
1878
1872
  "formatting.trailingCommas": "high",
1879
1873
  "formatting.braceStyle": "high",
1880
- "formatting.lineLength": "medium",
1881
- "formatting.blankLines": "medium",
1882
- "formatting.destructuring": "medium",
1883
- "formatting.defaultParams": "low",
1884
- "formatting.arrowVsFunction": "medium",
1885
1874
  "formatting.trailingNewline": "high",
1886
- // Category 8: Higher-Level Patterns
1887
- "patterns.compositionVsInheritance": "medium",
1888
- "patterns.classVsFunctional": "high",
1889
- "patterns.pureFunctions": "low",
1890
- "patterns.immutability": "medium",
1891
- "patterns.explicitVsImplicit": "medium",
1892
- "patterns.dryAdherence": "medium",
1893
1875
  // Category 9: Habitual Idioms
1894
1876
  "idiom.clone": "high",
1895
- "idiom.errorHandlingShape": "medium",
1896
- "idiom.dataTransformation": "medium",
1897
- "idiom.apiCallPattern": "medium",
1898
- "idiom.testStructure": "medium",
1899
1877
  // Category 10: Review Voice
1900
1878
  "reviewVoice.topicFrequency": "medium",
1901
1879
  "reviewVoice.keyword": "medium",
1902
- "reviewVoice.tone": "low",
1903
- "reviewVoice.themes": "low",
1904
- "reviewVoice.values": "low",
1905
1880
  // Complexity (from task-07)
1906
1881
  "complexity.functionLength": "high",
1907
1882
  "complexity.nestingDepth": "high",
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\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\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\" && NAMING_PATTERNS.SCREAMING_SNAKE!.test(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 node.parent?.type === \"module\" &&\n NAMING_PATTERNS.SCREAMING_SNAKE!.test(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 } 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 function mapSeverity(\n confidence: number,\n thresholds: SeverityThresholds = DEFAULT_SEVERITY_THRESHOLDS,\n): Severity {\n if (confidence >= thresholds.error) return \"error\";\n if (confidence >= thresholds.warn) return \"warn\";\n if (confidence >= thresholds.info) return \"info\";\n return \"off\";\n}\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: observation type (e.g., \"naming.variables\").\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 */\nexport const STABILITY_MAP: Record<string, Stability> = {\n // Category 1: Naming Conventions\n \"naming.variables\": \"high\",\n \"naming.functions\": \"high\",\n \"naming.types\": \"high\",\n \"naming.constants\": \"high\",\n \"naming.files\": \"high\",\n \"naming.booleans\": \"medium\",\n \"naming.abbreviations\": \"medium\",\n \"naming.parameters\": \"medium\",\n \"naming.enums\": \"high\",\n \"naming.privateMembers\": \"high\",\n\n // Category 2: Code Structure\n \"structure.import-group\": \"high\",\n \"structure.import-order\": \"high\",\n \"structure.importPathStyle\": \"medium\",\n \"structure.typeImportSeparation\": \"medium\",\n \"structure.export-style\": \"high\",\n \"structure.barrel-file\": \"medium\",\n \"structure.export-proximity\": \"medium\",\n \"structure.functionLength\": \"high\",\n \"structure.nestingDepth\": \"high\",\n \"structure.fileLength\": \"medium\",\n \"structure.moduleTopology\": \"low\",\n \"structure.fileOrganization\": \"low\",\n\n // Category 3: Control Flow Patterns\n \"controlFlow.guardClauses\": \"high\",\n \"controlFlow.earlyReturn\": \"high\",\n \"controlFlow.ternaryPreference\": \"medium\",\n \"controlFlow.arrayMethods\": \"high\",\n \"controlFlow.forStyle\": \"medium\",\n \"controlFlow.asyncAwait\": \"high\",\n \"controlFlow.switchVsIf\": \"medium\",\n \"controlFlow.optionalChaining\": \"medium\",\n \"controlFlow.nullishCoalescing\": \"low\",\n\n // Category 4: Error Handling\n \"errorHandling.tryCatchFrequency\": \"high\",\n \"errorHandling.catchSpecificity\": \"medium\",\n \"errorHandling.resultType\": \"high\",\n \"errorHandling.errorReturnTuples\": \"medium\",\n \"errorHandling.customErrorClasses\": \"medium\",\n \"errorHandling.exhaustiveSwitch\": \"high\",\n \"errorHandling.assertNever\": \"high\",\n \"errorHandling.floatingPromises\": \"medium\",\n \"errorHandling.errorBoundary\": \"low\",\n\n // Category 5: Documentation\n \"documentation.jsdocPresence\": \"high\",\n \"documentation.publicPrivateCoverage\": \"medium\",\n \"documentation.inlineCommentDensity\": \"medium\",\n \"documentation.commentPlacement\": \"medium\",\n \"documentation.sectionComments\": \"low\",\n \"documentation.moduleHeaders\": \"medium\",\n \"documentation.jsdocTags\": \"medium\",\n \"documentation.voice\": \"low\",\n \"documentation.whyVsWhat\": \"low\",\n \"documentation.redundancy\": \"low\",\n\n // Category 6: Type System Usage\n \"typeSystem.annotationDensity\": \"high\",\n \"typeSystem.explicitReturn\": \"high\",\n \"typeSystem.moduleBoundaryTypes\": \"medium\",\n \"typeSystem.inferrableTypes\": \"medium\",\n \"typeSystem.interfaceVsType\": \"medium\",\n \"typeSystem.genericUsage\": \"low\",\n \"typeSystem.readonlyUsage\": \"medium\",\n \"typeSystem.discriminatedUnions\": \"medium\",\n \"typeSystem.utilityTypes\": \"low\",\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.lineLength\": \"medium\",\n \"formatting.blankLines\": \"medium\",\n \"formatting.destructuring\": \"medium\",\n \"formatting.defaultParams\": \"low\",\n \"formatting.arrowVsFunction\": \"medium\",\n \"formatting.trailingNewline\": \"high\",\n\n // Category 8: Higher-Level Patterns\n \"patterns.compositionVsInheritance\": \"medium\",\n \"patterns.classVsFunctional\": \"high\",\n \"patterns.pureFunctions\": \"low\",\n \"patterns.immutability\": \"medium\",\n \"patterns.explicitVsImplicit\": \"medium\",\n \"patterns.dryAdherence\": \"medium\",\n\n // Category 9: Habitual Idioms\n \"idiom.clone\": \"high\",\n \"idiom.errorHandlingShape\": \"medium\",\n \"idiom.dataTransformation\": \"medium\",\n \"idiom.apiCallPattern\": \"medium\",\n \"idiom.testStructure\": \"medium\",\n\n // Category 10: Review Voice\n \"reviewVoice.topicFrequency\": \"medium\",\n \"reviewVoice.keyword\": \"medium\",\n \"reviewVoice.tone\": \"low\",\n \"reviewVoice.themes\": \"low\",\n \"reviewVoice.values\": \"low\",\n\n // Complexity (from task-07)\n \"complexity.functionLength\": \"high\",\n \"complexity.nestingDepth\": \"high\",\n \"complexity.cyclomatic\": \"high\",\n \"complexity.fileLength\": \"medium\",\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.voice\",\n \"documentation.whyVsWhat\",\n \"documentation.redundancy\",\n \"patterns.pureFunctions\",\n \"patterns.explicitVsImplicit\",\n \"errorHandling.errorBoundary\",\n \"structure.fileOrganization\",\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.tone\",\n \"reviewVoice.themes\",\n \"reviewVoice.values\",\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 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 } 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 function mapSeverity(\n confidence: number,\n thresholds: SeverityThresholds = DEFAULT_SEVERITY_THRESHOLDS,\n): Severity {\n if (confidence >= thresholds.error) return \"error\";\n if (confidence >= thresholds.warn) return \"warn\";\n if (confidence >= thresholds.info) return \"info\";\n return \"off\";\n}\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.voice\",\n \"documentation.whyVsWhat\",\n \"documentation.redundancy\",\n \"patterns.pureFunctions\",\n \"patterns.explicitVsImplicit\",\n \"errorHandling.errorBoundary\",\n \"structure.fileOrganization\",\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.tone\",\n \"reviewVoice.themes\",\n \"reviewVoice.values\",\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.0.0",
3
+ "version": "0.1.0",
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",
@@ -33,8 +33,8 @@
33
33
  "dependencies": {
34
34
  "@jscpd/core": "3.5.10",
35
35
  "@jscpd/tokenizer": "3.5.4",
36
- "@titan-design/style-profile": "^0.0.0",
37
- "@titan-design/code-parser": "^0.0.0"
36
+ "@titan-design/code-parser": "^0.1.0",
37
+ "@titan-design/style-profile": "^0.1.0"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "web-tree-sitter": "^0.26.6",