@@ -140,6 +140,57 @@ function repoRootNameMatches(selectedRepoName, expectedRepoRoot) {
140140 return selectedRepoName === expectedFolderName ;
141141}
142142
143+ function isPlainObject ( value ) {
144+ return Boolean ( value ) && typeof value === "object" && ! Array . isArray ( value ) ;
145+ }
146+
147+ function isWorkspaceManifest ( value ) {
148+ return isPlainObject ( value ) && value . documentKind === "workspace-manifest" ;
149+ }
150+
151+ function workspaceManifestFromLaunchContext ( launchContext ) {
152+ if ( isWorkspaceManifest ( launchContext ) ) {
153+ return launchContext ;
154+ }
155+ if ( isWorkspaceManifest ( launchContext ?. manifest ) ) {
156+ return launchContext . manifest ;
157+ }
158+ return null ;
159+ }
160+
161+ function displayRawLaunchFieldValue ( value ) {
162+ const text = String ( value || "" ) . trim ( ) ;
163+ return text || "(missing)" ;
164+ }
165+
166+ function launchPathFields ( launchContext , manifest ) {
167+ return [
168+ { label : "launchContext.repoPath" , value : launchContext ?. repoPath } ,
169+ { label : "launchContext.manifest.repoPath" , value : launchContext ?. manifest ?. repoPath } ,
170+ { label : "launchContext.repoRoot" , value : launchContext ?. repoRoot } ,
171+ { label : "manifest.repoPath" , value : manifest ?. repoPath } ,
172+ { label : "manifest.repoRoot" , value : manifest ?. repoRoot }
173+ ] . map ( ( field ) => ( {
174+ ...field ,
175+ text : String ( field . value || "" ) . trim ( )
176+ } ) ) ;
177+ }
178+
179+ function resolveRepoPathDecision ( pathFields ) {
180+ const repoPathFields = pathFields . filter ( ( field ) => field . label . endsWith ( ".repoPath" ) ) ;
181+ const firstAbsolute = repoPathFields . find ( ( field ) => field . text && isAbsoluteFilesystemPath ( field . text ) ) ;
182+ const firstAvailable = repoPathFields . find ( ( field ) => field . text ) ;
183+ const selected = firstAbsolute || firstAvailable || null ;
184+ return {
185+ checkedMissingFields : repoPathFields
186+ . filter ( ( field ) => ! field . text )
187+ . map ( ( field ) => field . label ) ,
188+ isAbsolute : Boolean ( selected ?. text && isAbsoluteFilesystemPath ( selected . text ) ) ,
189+ sourceField : selected ?. label || "(none)" ,
190+ value : selected ?. text || ""
191+ } ;
192+ }
193+
143194function isWorkspaceManagerLaunch ( ) {
144195 return runtimeParams . get ( "launch" ) === "workspace"
145196 && runtimeParams . get ( "fromTool" ) === "workspace-manager-v2" ;
@@ -158,17 +209,23 @@ function readWorkspaceLaunchContext() {
158209 return { ok : false , message : "Workspace Manager V2 manifest was not found in sessionStorage." } ;
159210 }
160211 try {
161- const manifest = JSON . parse ( rawValue ) ;
162- if ( manifest ?. documentKind !== "workspace-manifest" ) {
163- return { ok : false , message : "Workspace Manager V2 context is not a workspace manifest." } ;
212+ const launchContext = JSON . parse ( rawValue ) ;
213+ const manifest = workspaceManifestFromLaunchContext ( launchContext ) ;
214+ if ( ! manifest ) {
215+ return { ok : false , message : "Workspace Manager V2 context is not a workspace manifest or manifest launch payload." } ;
164216 }
165217 if ( ! manifest . gameId || ! manifest . gameRoot || ! manifest . assetsPath ) {
166218 return { ok : false , message : "Workspace Manager V2 manifest is missing gameId, gameRoot, or assetsPath." } ;
167219 }
168- if ( ! String ( manifest . repoRoot || "" ) . trim ( ) && ! String ( manifest . repoPath || "" ) . trim ( ) ) {
220+ const pathFields = launchPathFields ( launchContext , manifest ) ;
221+ const repoPathDecision = resolveRepoPathDecision ( pathFields ) ;
222+ const repoRootText = pathFields
223+ . filter ( ( field ) => field . label . endsWith ( ".repoRoot" ) )
224+ . find ( ( field ) => field . text ) ?. text || "" ;
225+ if ( ! repoRootText && ! String ( repoPathDecision . value || "" ) . trim ( ) ) {
169226 return { ok : false , message : "Workspace Manager V2 manifest is missing repoRoot display label and repoPath." } ;
170227 }
171- return { ok : true , manifest } ;
228+ return { ok : true , launchContext , manifest, pathFields , repoPathDecision } ;
172229 } catch ( error ) {
173230 return { ok : false , message : `Workspace Manager V2 manifest JSON is invalid: ${ error . message } ` } ;
174231 }
@@ -1043,6 +1100,16 @@ class PreviewGeneratorV2App {
10431100 }
10441101
10451102 const manifest = contextResult . manifest ;
1103+ contextResult . pathFields . forEach ( ( field ) => {
1104+ logger . log ( `Raw workspace launch path field ${ field . label } : ${ displayRawLaunchFieldValue ( field . text ) } ` ) ;
1105+ } ) ;
1106+ logger . log ( `Resolved repoPath decision source field used: ${ contextResult . repoPathDecision . sourceField } ` ) ;
1107+ logger . log ( `Resolved repoPath decision value: ${ displayRawLaunchFieldValue ( contextResult . repoPathDecision . value ) } ` ) ;
1108+ logger . log ( `Resolved repoPath decision absolute: ${ contextResult . repoPathDecision . isAbsolute ? "true" : "false" } ` ) ;
1109+ if ( ! contextResult . repoPathDecision . value ) {
1110+ logger . log ( `Missing repoPath fields checked: ${ contextResult . repoPathDecision . checkedMissingFields . join ( ", " ) } ` ) ;
1111+ }
1112+
10461113 const previewTarget = workspacePreviewTarget ( manifest ) ;
10471114 if ( ! previewTarget . ok ) {
10481115 logger . log ( `FAIL Workspace launch context hydration: ${ previewTarget . message } ` ) ;
@@ -1051,20 +1118,20 @@ class PreviewGeneratorV2App {
10511118 }
10521119
10531120 const manifestRepoRoot = String ( manifest . repoRoot || "" ) . trim ( ) ;
1054- const manifestRepoPath = String ( manifest . repoPath || "" ) . trim ( ) ;
1055- repoDisplayName = manifestRepoPath || manifestRepoRoot ;
1121+ const resolvedRepoPath = contextResult . repoPathDecision . value ;
1122+ repoDisplayName = resolvedRepoPath || manifestRepoRoot ;
10561123 repoDirHandle = null ;
10571124 workspaceLaunchHydrated = true ;
10581125 workspaceRepoRootName = manifestRepoRoot ;
10591126 workspacePreviewAssetFolder = previewTarget . previewAssetFolder ;
10601127 workspacePreviewGameId = manifest . gameId ;
10611128 workspaceManifestPreviewPath = previewTarget . manifestPreviewPath ;
10621129 workspaceGeneratedPreviewPath = previewTarget . generatedPreviewPath ;
1063- if ( manifestRepoPath ) {
1130+ if ( resolvedRepoPath ) {
10641131 try {
1065- workspaceAbsolutePreviewOutputPath = resolveWorkspaceAbsolutePreviewOutputPath ( manifestRepoPath , previewTarget . generatedPreviewPath ) ;
1132+ workspaceAbsolutePreviewOutputPath = resolveWorkspaceAbsolutePreviewOutputPath ( resolvedRepoPath , previewTarget . generatedPreviewPath ) ;
10661133 workspaceRepoPathHydrated = true ;
1067- workspaceResolvedRepoPath = manifestRepoPath ;
1134+ workspaceResolvedRepoPath = resolvedRepoPath ;
10681135 } catch ( error ) {
10691136 logger . log ( `WARN Workspace direct preview write unavailable: ${ error . message } ` ) ;
10701137 }
@@ -1077,7 +1144,7 @@ class PreviewGeneratorV2App {
10771144 await updatePathPreviewLabels ( ) ;
10781145 logger . log ( `OK Workspace launch context hydrated for ${ manifest . gameId } .` ) ;
10791146 logger . log ( `Workspace repoRoot display label available: ${ manifestRepoRoot || "(empty)" } .` ) ;
1080- logger . log ( `Workspace repoPath ${ manifestRepoPath ? `available: ${ manifestRepoPath } ` : "missing" } .` ) ;
1147+ logger . log ( `Workspace repoPath ${ resolvedRepoPath ? `available: ${ resolvedRepoPath } ` : "missing" } .` ) ;
10811148 if ( workspaceRepoPathHydrated ) {
10821149 logger . log ( `Resolved repoPath: ${ workspaceResolvedRepoPath } ` ) ;
10831150 logger . log ( `Resolved absolute preview output path: ${ workspaceAbsolutePreviewOutputPath } ` ) ;
0 commit comments