11import { createHash } from 'node:crypto' ;
22import path from 'node:path' ;
33import type {
4- DecisionCard ,
54 PatternResponse ,
65 SearchQuality ,
7- SearchResultItem ,
8- SearchResponse
6+ SearchResponse ,
7+ SearchResultItem
98} from './tools/types.js' ;
109
1110const IDENTIFIER_RE = / [ A - Z a - z _ $ ] [ A - Z a - z 0 - 9 _ $ ] * / g;
@@ -116,7 +115,7 @@ export interface ReviewSearchResult {
116115 query : string ;
117116 sourceFiles : string [ ] ;
118117 searchQuality ?: SearchQuality ;
119- preflight ?: DecisionCard | SearchResponse [ 'preflight' ] ;
118+ preflight ?: SearchResponse [ 'preflight' ] ;
120119 results : ReviewRelatedResult [ ] ;
121120 error ?: string ;
122121}
@@ -192,9 +191,7 @@ export function parseNameStatus(output: string): ChangedFileDescriptor[] {
192191 }
193192
194193 const filePath = parts [ 1 ] ;
195- if ( filePath ) {
196- files . push ( { path : filePath , status, rawStatus } ) ;
197- }
194+ if ( filePath ) files . push ( { path : filePath , status, rawStatus } ) ;
198195 }
199196
200197 return files ;
@@ -226,8 +223,7 @@ export function extractChangedIdentifiers(patch: string, limit = 10): string[] {
226223 const isDeletion = line . startsWith ( '-' ) && ! line . startsWith ( '---' ) ;
227224 if ( ! isAddition && ! isDeletion ) continue ;
228225
229- const source = line . slice ( 1 ) ;
230- for ( const match of source . matchAll ( IDENTIFIER_RE ) ) {
226+ for ( const match of line . slice ( 1 ) . matchAll ( IDENTIFIER_RE ) ) {
231227 const identifier = match [ 0 ] ;
232228 if ( identifier . length < 3 ) continue ;
233229 if ( IDENTIFIER_STOPWORDS . has ( identifier . toLowerCase ( ) ) ) continue ;
@@ -248,30 +244,31 @@ export function extractChangedIdentifiers(patch: string, limit = 10): string[] {
248244}
249245
250246function fallbackIdentifiersForPath ( filePath : string ) : string [ ] {
251- const withoutExtension = filePath . replace ( / \. [ ^ . \/ ] + $ / , '' ) ;
252- const segments = withoutExtension . split ( / [ \\ / . _ - ] + / ) . filter ( Boolean ) ;
247+ const withoutExtension = filePath . replace ( / \. [ ^ . / ] + $ / , '' ) ;
253248 const basename = path . basename ( withoutExtension ) ;
254- const ordered = [ basename , ...segments . reverse ( ) ] ;
249+ const parentSegments = path . dirname ( withoutExtension ) . split ( / [ \\ / . _ - ] + / ) . filter ( Boolean ) . reverse ( ) ;
250+ const ordered = [ basename , ...parentSegments ] ;
255251 const seen = new Set < string > ( ) ;
256252
257253 return ordered . filter ( ( part ) => {
258254 const normalized = part . toLowerCase ( ) ;
259- if ( part . length < 3 || IDENTIFIER_STOPWORDS . has ( normalized ) || seen . has ( normalized ) ) return false ;
255+ if ( part . length < 3 || IDENTIFIER_STOPWORDS . has ( normalized ) || seen . has ( normalized ) ) {
256+ return false ;
257+ }
260258 seen . add ( normalized ) ;
261259 return true ;
262260 } ) ;
263261}
264262
265- export function buildReviewQueries (
266- files : ChangedFileContext [ ] ,
267- maxQueries = 8
268- ) : ReviewQuery [ ] {
263+ export function buildReviewQueries ( files : ChangedFileContext [ ] , maxQueries = 8 ) : ReviewQuery [ ] {
269264 const selected = [ ...files ]
270265 . sort ( ( a , b ) => {
271266 const identifierDelta = b . identifiers . length - a . identifiers . length ;
272267 if ( identifierDelta !== 0 ) return identifierDelta ;
268+
273269 const changeDelta = b . additions + b . deletions - ( a . additions + a . deletions ) ;
274270 if ( changeDelta !== 0 ) return changeDelta ;
271+
275272 return a . path . localeCompare ( b . path ) ;
276273 } )
277274 . slice ( 0 , Math . max ( 0 , maxQueries ) ) ;
@@ -307,6 +304,8 @@ export function fingerprintDiff(rawDiff: string): string {
307304}
308305
309306function compactSearchResult ( result : SearchResultItem ) : ReviewRelatedResult {
307+ const importedByCount = result . relationships ?. importedByCount ?? result . importedByCount ;
308+
310309 return {
311310 file : result . file ,
312311 summary : result . summary ,
@@ -319,11 +318,7 @@ function compactSearchResult(result: SearchResultItem): ReviewRelatedResult {
319318 ...( result . scope ? { scope : result . scope } : { } ) ,
320319 ...( result . signaturePreview ? { signaturePreview : result . signaturePreview } : { } ) ,
321320 ...( result . snippet ? { snippet : result . snippet . slice ( 0 , 1200 ) } : { } ) ,
322- ...( result . relationships ?. importedByCount != null
323- ? { importedByCount : result . relationships . importedByCount }
324- : result . importedByCount != null
325- ? { importedByCount : result . importedByCount }
326- : { } ) ,
321+ ...( importedByCount != null ? { importedByCount } : { } ) ,
327322 ...( result . relationships ?. hasTests != null ? { hasTests : result . relationships . hasTests } : { } )
328323 } ;
329324}
@@ -339,6 +334,7 @@ export async function buildReviewContextPacket(
339334 const changedFiles = options . changedFiles . map ( ( file ) => {
340335 const patch = options . patchesByPath . get ( file . path ) ?? '' ;
341336 if ( ! patch ) warnings . push ( `No textual patch captured for ${ file . path } ` ) ;
337+
342338 const stats = inspectPatch ( patch ) ;
343339 return {
344340 ...file ,
0 commit comments