@@ -37,7 +37,7 @@ const MAX_TREE_ITEMS = 80;
3737const MAX_LIST_ITEMS = 80 ;
3838const MAX_PROMPT_CHARS = 14_000 ;
3939const MAX_MEMORY_CONTEXT_CHARS = 4_000 ;
40- const REPO_BRIEF_CACHE_VERSION = "brief:v5 " ;
40+ const REPO_BRIEF_CACHE_VERSION = "brief:v6 " ;
4141
4242const IMPACT_SYSTEM_PROMPT =
4343 "Analyze this code diff for a developer. Return only valid JSON with this shape: {\"schemaVersion\":1,\"feature\":\"impact\",\"summary\":\"1 short sentence\",\"confidence\":\"low|medium|high\",\"warnings\":[\"...\"],\"data\":{\"intent\":\"...\",\"modules\":[{\"name\":\"...\",\"paths\":[\"...\"],\"changeType\":\"added|modified|removed|mixed\"}],\"risks\":[{\"severity\":\"low|medium|high\",\"area\":\"...\",\"reason\":\"...\",\"files\":[\"...\"]}],\"checks\":[{\"command\":\"optional command\",\"reason\":\"...\"}],\"recommendation\":\"...\"}}. No markdown fences." ;
@@ -1234,7 +1234,10 @@ function buildRepoBriefPrompt(payload: BriefPayload): string | null {
12341234 payload . changedFiles ?. filter ( Boolean ) ?? [ ] ,
12351235 MAX_LIST_ITEMS ,
12361236 ) ;
1237- const readme = truncateText ( payload . readme ?. trim ( ) ?? "" , MAX_README_CHARS ) ;
1237+ const readme = truncateText (
1238+ sanitizeRepositoryEvidenceText ( payload . readme ?. trim ( ) ?? "" ) ,
1239+ MAX_README_CHARS ,
1240+ ) ;
12381241
12391242 const hasRealData =
12401243 tree . length > 0 ||
@@ -1503,9 +1506,7 @@ function buildLocalRepoBriefData(payload: BriefPayload): RepoBriefData {
15031506 ] ) ;
15041507 const readme = summarizeReadme ( payload . readme ?? "" ) ;
15051508
1506- const purpose = readme
1507- ? readme
1508- : "Purpose is not explicit in the available README/package data. Start by inspecting the top-level files and primary source directories." ;
1509+ const purpose = buildLocalRepoBriefPurpose ( payload , readme , tree ) ;
15091510
15101511 return {
15111512 purpose,
@@ -1532,6 +1533,30 @@ function buildLocalRepoBriefData(payload: BriefPayload): RepoBriefData {
15321533 } ;
15331534}
15341535
1536+ function buildLocalRepoBriefPurpose (
1537+ payload : BriefPayload ,
1538+ readme : string ,
1539+ tree : string [ ] ,
1540+ ) : string {
1541+ if ( readme . length >= 40 ) return readme ;
1542+
1543+ const label = cleanRepositoryLabel ( readme || payload . repoName || payload . repoId ) ;
1544+ const modules = tree
1545+ . map ( ( item ) => item . replace ( / \/ + $ / , "" ) )
1546+ . filter ( Boolean )
1547+ . slice ( 0 , 6 ) ;
1548+ if ( label && modules . length > 0 ) {
1549+ return `${ label } repository. Local evidence includes ${ formatNaturalList ( modules ) } .` ;
1550+ }
1551+ if ( label ) {
1552+ return `${ label } repository. Purpose is not explicit in the available README/package data.` ;
1553+ }
1554+ if ( modules . length > 0 ) {
1555+ return `Purpose is not explicit in README/package data. Local evidence includes ${ formatNaturalList ( modules ) } .` ;
1556+ }
1557+ return "Purpose is not explicit in the available README/package data. Start by inspecting the top-level files and primary source directories." ;
1558+ }
1559+
15351560function buildLocalPRReviewData ( detail : PullRequestDetail ) : PRReviewData {
15361561 const failing = detail . checks . filter ( ( check ) => check . conclusion === "failure" ) . length ;
15371562 const pending = detail . checks . filter ( ( check ) => ! check . conclusion || check . status !== "completed" ) . length ;
@@ -1947,23 +1972,65 @@ function groupPathsByTopLevel(paths: string[]): Array<[string, string[]]> {
19471972}
19481973
19491974function summarizeReadme ( value : string ) : string {
1950- const lines = value
1975+ const lines = sanitizeRepositoryEvidenceText ( value )
19511976 . split ( "\n" )
1952- . map ( ( line ) => line . trim ( ) )
1953- . filter ( Boolean )
1954- . filter ( ( line ) => ! / ^ ( n a m e | v e r s i o n | d e s c r i p t i o n | s c r i p t s | d e p e n d e n c i e s | d e v D e p e n d e n c i e s ) : / i. test ( line ) ) ;
1955- const heading = lines . find ( ( line ) => / ^ # \s + / . test ( line ) ) ;
1977+ . map ( ( line ) => ( {
1978+ raw : line . trim ( ) ,
1979+ clean : cleanReadmeLine ( line ) ,
1980+ } ) )
1981+ . filter ( ( line ) => line . clean )
1982+ . filter (
1983+ ( line ) =>
1984+ ! / ^ ( n a m e | v e r s i o n | d e s c r i p t i o n | s c r i p t s | d e p e n d e n c i e s | d e v D e p e n d e n c i e s ) : / i. test ( line . clean ) ,
1985+ ) ;
1986+ const heading = lines . find ( ( line ) => / ^ # \s + / . test ( line . raw ) ) ?. clean ;
19561987 const prose = lines . find (
19571988 ( line ) =>
1958- ! line . startsWith ( "#" ) &&
1959- ! line . startsWith ( "[" ) &&
1960- ! line . startsWith ( "!" ) &&
1961- ! / ^ < \/ ? ( p | i m g | p i c t u r e | s o u r c e | h 1 | h 2 | h 3 | s t r o n g | e m | d i v | s p a n ) \b / i. test ( line ) &&
1962- ! / < i m g \b / i. test ( line ) &&
1963- ! / s h i e l d s \. i o | b a d g e / i. test ( line ) &&
1964- line . length > 30 ,
1989+ ! line . raw . startsWith ( "#" ) &&
1990+ ! line . raw . startsWith ( "[" ) &&
1991+ ! line . raw . startsWith ( "!" ) &&
1992+ ! / ^ < \/ ? ( p | i m g | p i c t u r e | s o u r c e | h 1 | h 2 | h 3 | s t r o n g | e m | d i v | s p a n ) \b / i. test ( line . raw ) &&
1993+ ! / < i m g \b / i. test ( line . raw ) &&
1994+ ! / s h i e l d s \. i o | b a d g e / i. test ( line . raw ) &&
1995+ line . clean . length > 30 ,
19651996 ) ;
1966- return truncateText ( [ heading , prose ] . filter ( Boolean ) . join ( " " ) , 700 ) ;
1997+ return truncateText ( [ heading , prose ?. clean ] . filter ( Boolean ) . join ( " " ) , 700 ) ;
1998+ }
1999+
2000+ function sanitizeRepositoryEvidenceText ( value : string ) : string {
2001+ return value
2002+ . replace ( / < ! - - [ \s \S ] * ?- - > / g, " " )
2003+ . replace ( / \b M A R K E E : (?: S T A R T | E N D ) : [ A - Z a - z 0 - 9 : _ - ] + \b / gi, " " )
2004+ . split ( "\n" )
2005+ . map ( ( line ) => line . replace ( / \s + / g, " " ) . trim ( ) )
2006+ . filter ( Boolean )
2007+ . join ( "\n" ) ;
2008+ }
2009+
2010+ function cleanReadmeLine ( value : string ) : string {
2011+ return value
2012+ . replace ( / ^ # { 1 , 6 } \s + / , "" )
2013+ . replace ( / ^ [ - * ] \s + / , "" )
2014+ . replace ( / ! \[ [ ^ \] ] * ] \( [ ^ ) ] * \) / g, " " )
2015+ . replace ( / \[ ( [ ^ \] ] + ) ] \( [ ^ ) ] * \) / g, "$1" )
2016+ . replace ( / ` ( [ ^ ` ] + ) ` / g, "$1" )
2017+ . replace ( / \s + / g, " " )
2018+ . trim ( ) ;
2019+ }
2020+
2021+ function cleanRepositoryLabel ( value : string | undefined ) : string {
2022+ return ( value ?? "" )
2023+ . replace ( / ^ # { 1 , 6 } \s + / , "" )
2024+ . replace ( / < ! - - [ \s \S ] * ?- - > / g, " " )
2025+ . replace ( / \b M A R K E E : (?: S T A R T | E N D ) : [ A - Z a - z 0 - 9 : _ - ] + \b / gi, " " )
2026+ . replace ( / \s + / g, " " )
2027+ . trim ( ) ;
2028+ }
2029+
2030+ function formatNaturalList ( items : string [ ] ) : string {
2031+ if ( items . length <= 1 ) return items [ 0 ] ?? "" ;
2032+ if ( items . length === 2 ) return `${ items [ 0 ] } and ${ items [ 1 ] } ` ;
2033+ return `${ items . slice ( 0 , - 1 ) . join ( ", " ) } , and ${ items [ items . length - 1 ] } ` ;
19672034}
19682035
19692036function formatList ( items : string [ ] , emptyText : string ) : string {
0 commit comments