@@ -2036,4 +2036,133 @@ describe('ModeHandler', () => {
20362036 expect ( JSON . parse ( reserialized ) ) . toEqual ( parsed . councilScene ) ;
20372037 } ) ;
20382038 } ) ;
2039+
2040+ describe ( 'reviewContext (#1411)' , ( ) => {
2041+ it ( 'should include reviewContext when EVAL prompt contains PR #N' , async ( ) => {
2042+ mockKeywordService . parseMode = vi . fn ( ) . mockResolvedValue ( {
2043+ ...mockParseModeResult ,
2044+ mode : 'EVAL' ,
2045+ originalPrompt : 'EVAL: review PR #42' ,
2046+ } ) ;
2047+
2048+ const result = await handler . handle ( 'parse_mode' , {
2049+ prompt : 'EVAL: review PR #42' ,
2050+ } ) ;
2051+
2052+ expect ( result ?. isError ) . toBeFalsy ( ) ;
2053+ const parsed = JSON . parse ( ( result ?. content [ 0 ] as { text : string } ) . text ) ;
2054+ expect ( parsed . reviewContext ) . toEqual ( {
2055+ detected : true ,
2056+ pr_number : 42 ,
2057+ hint : 'Call review_pr({ pr_number: 42 }) to get structured review data including diff, checklists, and specialist recommendations.' ,
2058+ } ) ;
2059+ } ) ;
2060+
2061+ it ( 'should include reviewContext when EVAL prompt contains PR N (no hash)' , async ( ) => {
2062+ mockKeywordService . parseMode = vi . fn ( ) . mockResolvedValue ( {
2063+ ...mockParseModeResult ,
2064+ mode : 'EVAL' ,
2065+ originalPrompt : 'EVAL: review PR 100' ,
2066+ } ) ;
2067+
2068+ const result = await handler . handle ( 'parse_mode' , {
2069+ prompt : 'EVAL: review PR 100' ,
2070+ } ) ;
2071+
2072+ expect ( result ?. isError ) . toBeFalsy ( ) ;
2073+ const parsed = JSON . parse ( ( result ?. content [ 0 ] as { text : string } ) . text ) ;
2074+ expect ( parsed . reviewContext ) . toEqual ( {
2075+ detected : true ,
2076+ pr_number : 100 ,
2077+ hint : 'Call review_pr({ pr_number: 100 }) to get structured review data including diff, checklists, and specialist recommendations.' ,
2078+ } ) ;
2079+ } ) ;
2080+
2081+ it ( 'should include reviewContext with issue_number when prompt contains both PR and issue' , async ( ) => {
2082+ mockKeywordService . parseMode = vi . fn ( ) . mockResolvedValue ( {
2083+ ...mockParseModeResult ,
2084+ mode : 'EVAL' ,
2085+ originalPrompt : 'EVAL: review PR #42 issue #1364' ,
2086+ } ) ;
2087+
2088+ const result = await handler . handle ( 'parse_mode' , {
2089+ prompt : 'EVAL: review PR #42 issue #1364' ,
2090+ } ) ;
2091+
2092+ expect ( result ?. isError ) . toBeFalsy ( ) ;
2093+ const parsed = JSON . parse ( ( result ?. content [ 0 ] as { text : string } ) . text ) ;
2094+ expect ( parsed . reviewContext ) . toEqual ( {
2095+ detected : true ,
2096+ pr_number : 42 ,
2097+ issue_number : 1364 ,
2098+ hint : 'Call review_pr({ pr_number: 42, issue_number: 1364 }) to get structured review data including diff, checklists, and specialist recommendations.' ,
2099+ } ) ;
2100+ } ) ;
2101+
2102+ it ( 'should include reviewContext when prompt contains "pull request"' , async ( ) => {
2103+ mockKeywordService . parseMode = vi . fn ( ) . mockResolvedValue ( {
2104+ ...mockParseModeResult ,
2105+ mode : 'EVAL' ,
2106+ originalPrompt : 'EVAL: review pull request #55' ,
2107+ } ) ;
2108+
2109+ const result = await handler . handle ( 'parse_mode' , {
2110+ prompt : 'EVAL: review pull request #55' ,
2111+ } ) ;
2112+
2113+ expect ( result ?. isError ) . toBeFalsy ( ) ;
2114+ const parsed = JSON . parse ( ( result ?. content [ 0 ] as { text : string } ) . text ) ;
2115+ expect ( parsed . reviewContext ) . toBeDefined ( ) ;
2116+ expect ( parsed . reviewContext . detected ) . toBe ( true ) ;
2117+ expect ( parsed . reviewContext . pr_number ) . toBe ( 55 ) ;
2118+ } ) ;
2119+
2120+ it ( 'should NOT include reviewContext when EVAL prompt has no PR reference' , async ( ) => {
2121+ mockKeywordService . parseMode = vi . fn ( ) . mockResolvedValue ( {
2122+ ...mockParseModeResult ,
2123+ mode : 'EVAL' ,
2124+ originalPrompt : 'EVAL: evaluate implementation quality' ,
2125+ } ) ;
2126+
2127+ const result = await handler . handle ( 'parse_mode' , {
2128+ prompt : 'EVAL: evaluate implementation quality' ,
2129+ } ) ;
2130+
2131+ expect ( result ?. isError ) . toBeFalsy ( ) ;
2132+ const parsed = JSON . parse ( ( result ?. content [ 0 ] as { text : string } ) . text ) ;
2133+ expect ( parsed . reviewContext ) . toBeUndefined ( ) ;
2134+ } ) ;
2135+
2136+ it ( 'should NOT include reviewContext for non-EVAL modes even with PR reference' , async ( ) => {
2137+ mockKeywordService . parseMode = vi . fn ( ) . mockResolvedValue ( {
2138+ ...mockParseModeResult ,
2139+ mode : 'PLAN' ,
2140+ originalPrompt : 'PLAN: design PR #42 review feature' ,
2141+ } ) ;
2142+
2143+ const result = await handler . handle ( 'parse_mode' , {
2144+ prompt : 'PLAN: design PR #42 review feature' ,
2145+ } ) ;
2146+
2147+ expect ( result ?. isError ) . toBeFalsy ( ) ;
2148+ const parsed = JSON . parse ( ( result ?. content [ 0 ] as { text : string } ) . text ) ;
2149+ expect ( parsed . reviewContext ) . toBeUndefined ( ) ;
2150+ } ) ;
2151+
2152+ it ( 'should handle malformed PR reference gracefully' , async ( ) => {
2153+ mockKeywordService . parseMode = vi . fn ( ) . mockResolvedValue ( {
2154+ ...mockParseModeResult ,
2155+ mode : 'EVAL' ,
2156+ originalPrompt : 'EVAL: review PR abc' ,
2157+ } ) ;
2158+
2159+ const result = await handler . handle ( 'parse_mode' , {
2160+ prompt : 'EVAL: review PR abc' ,
2161+ } ) ;
2162+
2163+ expect ( result ?. isError ) . toBeFalsy ( ) ;
2164+ const parsed = JSON . parse ( ( result ?. content [ 0 ] as { text : string } ) . text ) ;
2165+ expect ( parsed . reviewContext ) . toBeUndefined ( ) ;
2166+ } ) ;
2167+ } ) ;
20392168} ) ;
0 commit comments