1111
1212import { isRemoteSession , getServerHostname , getServerPort } from "./remote" ;
1313import type { Origin } from "@plannotator/shared/agents" ;
14- import { type DiffType , type GitContext , runVcsDiff , getVcsFileContentsForDiff , canStageFiles , stageFile , unstageFile , resolveVcsCwd , validateFilePath , getVcsContext , gitRuntime } from "./vcs" ;
15- import { parseWorktreeDiffType , detectRemoteDefaultBranch , resolveBaseBranch } from "@plannotator/shared/review-core" ;
14+ import { type DiffType , type GitContext , runVcsDiff , getVcsFileContentsForDiff , canStageFiles , stageFile , unstageFile , resolveVcsCwd , validateFilePath , getVcsContext , detectRemoteDefaultCompareTarget , gitRuntime } from "./vcs" ;
15+ import { parseWorktreeDiffType , resolveBaseBranch } from "@plannotator/shared/review-core" ;
1616import {
1717 getPRDiffScopeOptions ,
1818 getPRStackInfo ,
@@ -164,15 +164,20 @@ export async function startReviewServer(
164164 // read this (not gitContext.defaultBranch) so they analyze the same diff
165165 // the reviewer is currently looking at. Honors an explicit initialBase from
166166 // the caller — e.g. programmatic Pi callers can request a non-detected base.
167- let currentBase = options . initialBase || gitContext ?. defaultBranch || "main" ;
167+ const detectedCompareTarget = ( ) : string => gitContext ?. defaultBranch || gitContext ?. compareTarget ?. fallback || "main" ;
168+ let currentBase = options . initialBase || detectedCompareTarget ( ) ;
168169 let baseEverSwitched = false ;
169170
171+ const resolveReviewBase = ( requestedBase ?: string ) : string => {
172+ return resolveBaseBranch ( requestedBase , detectedCompareTarget ( ) ) ;
173+ } ;
174+
170175 // Fire-and-forget: query the remote for its actual default branch. If it
171176 // arrives before the user interacts, quietly upgrade currentBase from the
172177 // local fallback (e.g. "main") to the upstream ref (e.g. "origin/main").
173178 // Non-blocking — the server is already listening by the time this resolves.
174179 if ( gitContext && ! options . initialBase && ! isPRMode ) {
175- detectRemoteDefaultBranch ( gitRuntime , gitContext . cwd ) . then ( ( remote ) => {
180+ detectRemoteDefaultCompareTarget ( gitContext . cwd ) . then ( ( remote ) => {
176181 if ( remote && ! baseEverSwitched ) currentBase = remote ;
177182 } ) ;
178183 }
@@ -415,6 +420,9 @@ export async function startReviewServer(
415420 let repoInfo = isPRMode && prMetadata
416421 ? { display : getDisplayRepo ( prMetadata ) , branch : `${ getMRLabel ( prMetadata ) } ${ getMRNumberLabel ( prMetadata ) } ` }
417422 : await getRepoInfo ( ) ;
423+ if ( gitContext ?. repository ?. displayFallback ) {
424+ repoInfo = { display : repoInfo ?. display || gitContext . repository . displayFallback } ;
425+ }
418426
419427 // Fetch current platform user (for own-PR/MR detection)
420428 let prRef = isPRMode && prMetadata ? prRefFromMetadata ( prMetadata ) : null ;
@@ -560,12 +568,11 @@ export async function startReviewServer(
560568 currentHideWhitespace = body . hideWhitespace ;
561569 }
562570
563- const detectedBase = gitContext ?. defaultBranch || "main" ;
564571 // Guard against non-string payloads — resolveBaseBranch calls
565572 // string methods and would throw a TypeError otherwise. Mirrors
566573 // Pi's guard so both runtimes validate identically.
567574 const requestedBase = typeof body . base === "string" ? body . base : undefined ;
568- const base = resolveBaseBranch ( requestedBase , detectedBase ) ;
575+ const base = resolveReviewBase ( requestedBase ) ;
569576 const defaultCwd = gitContext ?. cwd ;
570577
571578 // Run the new diff
@@ -863,11 +870,8 @@ export async function startReviewServer(
863870
864871 // Local review: read file contents from local git
865872 if ( hasLocalAccess ) {
866- const detectedBase = gitContext ?. defaultBranch || "main" ;
867- const base = resolveBaseBranch (
868- url . searchParams . get ( "base" ) ?? undefined ,
869- detectedBase ,
870- ) ;
873+ const requestedBase = url . searchParams . get ( "base" ) ?? undefined ;
874+ const base = resolveReviewBase ( requestedBase ) ;
871875 const defaultCwd = gitContext ?. cwd ;
872876 const result = await getVcsFileContentsForDiff (
873877 currentDiffType ,
@@ -896,7 +900,8 @@ export async function startReviewServer(
896900
897901 // API: Stage / unstage a file (disabled when VCS doesn't support it)
898902 if ( url . pathname === "/api/git-add" && req . method === "POST" ) {
899- if ( isPRMode || ! canStageFiles ( currentDiffType ) ) {
903+ const stageCwd = resolveVcsCwd ( currentDiffType , gitContext ?. cwd ) ;
904+ if ( isPRMode || ! ( await canStageFiles ( currentDiffType , stageCwd ) ) ) {
900905 return Response . json (
901906 { error : "Staging not available" } ,
902907 { status : 400 } ,
@@ -908,12 +913,10 @@ export async function startReviewServer(
908913 return Response . json ( { error : "Missing filePath" } , { status : 400 } ) ;
909914 }
910915
911- const cwd = resolveVcsCwd ( currentDiffType , gitContext ?. cwd ) ;
912-
913916 if ( body . undo ) {
914- await unstageFile ( currentDiffType , body . filePath , cwd ) ;
917+ await unstageFile ( currentDiffType , body . filePath , stageCwd ) ;
915918 } else {
916- await stageFile ( currentDiffType , body . filePath , cwd ) ;
919+ await stageFile ( currentDiffType , body . filePath , stageCwd ) ;
917920 }
918921
919922 return Response . json ( { ok : true } ) ;
0 commit comments