@@ -325,6 +325,109 @@ describe('agent workspace runtime behavior', () => {
325325 ) ;
326326 } ) ;
327327
328+ test ( 'keeps focus mode and path dock coexistence during fullscreen lifecycle' , async ( ) => {
329+ const fetchMock = jest . fn ( ) . mockResolvedValue ( {
330+ ok : true ,
331+ status : 200 ,
332+ json : async ( ) => ( {
333+ success : true ,
334+ result : {
335+ userId : 'agent_user_default' ,
336+ message : 'Found 1 local knowledge point(s).' ,
337+ knowledgePoints : [
338+ {
339+ atomId : 'atom-coexist-1' ,
340+ title : 'Coexist Candidate' ,
341+ snippet : 'Focus then path dock.' ,
342+ score : 0.73 ,
343+ capabilities : [
344+ {
345+ actionId : 'open_focus_mode' ,
346+ label : 'Focus' ,
347+ request : { userId : 'agent_user_default' , atomId : 'atom-coexist-1' } ,
348+ execution : { kind : 'frontend_only' } ,
349+ } ,
350+ ] ,
351+ } ,
352+ ] ,
353+ } ,
354+ } ) ,
355+ } ) ;
356+ ( global as unknown as Record < string , unknown > ) . fetch = fetchMock ;
357+
358+ const runtime = runtimeModule . createAgentWorkspaceRuntime ( { defaultUserId : 'agent_user_default' } ) ;
359+ runtime . init ( ) ;
360+
361+ const input = document . getElementById ( 'agent-workspace-input' ) as HTMLTextAreaElement ;
362+ const form = document . getElementById ( 'agent-workspace-form' ) as HTMLFormElement ;
363+ input . value = 'focus then open path' ;
364+ form . dispatchEvent ( new dom ! . window . Event ( 'submit' , { bubbles : true , cancelable : true } ) ) ;
365+ await flushAsync ( ) ;
366+
367+ const pointCard = document . querySelector ( '.agent-workspace-point-card' ) as HTMLElement ;
368+ expect ( pointCard ) . not . toBeNull ( ) ;
369+ pointCard . click ( ) ;
370+
371+ runtime . openLearningPathDock ( 'atom-coexist-1' ) ;
372+ await flushAsync ( ) ;
373+
374+ expect ( document . body . classList . contains ( 'agent-workspace-enabled' ) ) . toBe ( true ) ;
375+ expect ( document . body . classList . contains ( 'agent-workspace-path-visible' ) ) . toBe ( true ) ;
376+ expect ( document . body . classList . contains ( 'agent-workspace-path-fullscreen' ) ) . toBe ( false ) ;
377+ const graphWrapper = document . getElementById ( 'graph-wrapper' ) as HTMLElement ;
378+ expect ( graphWrapper . style . display ) . toBe ( 'block' ) ;
379+
380+ runtime . togglePathFullscreen ( ) ;
381+ expect ( document . body . classList . contains ( 'agent-workspace-path-fullscreen' ) ) . toBe ( true ) ;
382+ runtime . togglePathFullscreen ( ) ;
383+ expect ( document . body . classList . contains ( 'agent-workspace-path-fullscreen' ) ) . toBe ( false ) ;
384+
385+ const pathApp = ( global as unknown as Record < string , unknown > ) . pathApp as Record < string , jest . Mock > ;
386+ expect ( pathApp . requestBridgeWindowVisibility ) . toHaveBeenCalledWith (
387+ true ,
388+ expect . objectContaining ( { reason : 'agent-workspace-open-path-dock' } )
389+ ) ;
390+ const focusOnNode = ( global as unknown as Record < string , unknown > ) . focusOnNode as jest . Mock ;
391+ expect ( focusOnNode ) . toHaveBeenCalledWith ( 'atom-coexist-1' ) ;
392+ } ) ;
393+
394+ test ( 'sends deterministic bridge-hide transitions for close button and path exit event' , async ( ) => {
395+ const runtime = runtimeModule . createAgentWorkspaceRuntime ( { defaultUserId : 'agent_user_default' } ) ;
396+ runtime . init ( ) ;
397+
398+ runtime . openLearningPathDock ( 'atom-close-1' ) ;
399+ await flushAsync ( ) ;
400+
401+ const pathApp = ( global as unknown as Record < string , unknown > ) . pathApp as Record < string , jest . Mock > ;
402+ pathApp . requestBridgeWindowVisibility . mockClear ( ) ;
403+
404+ const closeButton = document . getElementById ( 'agent-workspace-close-learning-path' ) as HTMLButtonElement ;
405+ closeButton . click ( ) ;
406+ await flushAsync ( ) ;
407+
408+ expect ( document . body . classList . contains ( 'agent-workspace-path-visible' ) ) . toBe ( false ) ;
409+ expect ( document . body . classList . contains ( 'agent-workspace-path-fullscreen' ) ) . toBe ( false ) ;
410+ const pathContainer = document . getElementById ( 'path-container' ) as HTMLElement ;
411+ expect ( pathContainer . style . display ) . toBe ( 'none' ) ;
412+ expect ( pathApp . requestBridgeWindowVisibility ) . toHaveBeenCalledWith (
413+ false ,
414+ expect . objectContaining ( { reason : 'agent-workspace-hide-path-dock' } )
415+ ) ;
416+
417+ runtime . openLearningPathDock ( 'atom-close-2' ) ;
418+ await flushAsync ( ) ;
419+ pathApp . requestBridgeWindowVisibility . mockClear ( ) ;
420+
421+ dom ! . window . dispatchEvent ( new dom ! . window . CustomEvent ( 'nc:pathmode:exited' ) ) ;
422+ await flushAsync ( ) ;
423+
424+ expect ( document . body . classList . contains ( 'agent-workspace-path-visible' ) ) . toBe ( false ) ;
425+ expect ( pathApp . requestBridgeWindowVisibility ) . toHaveBeenCalledWith (
426+ false ,
427+ expect . objectContaining ( { reason : 'agent-workspace-hide-path-dock' } )
428+ ) ;
429+ } ) ;
430+
328431 test ( 'executes study session capability and renders summary message' , async ( ) => {
329432 const fetchMock = jest
330433 . fn ( )
0 commit comments