Skip to content

Notifications still fail to switch workspace tabs when navigating to an AI session #1628

Closed

Description

@JoshuaRowePhantom

Summary

The Notifications window still cannot visibly navigate to an AI/agent-session tab in a different, already-open workspace tab. In the reported example, Phantom.Workspaces is selected and clicking the House Agent Session notification does not select House or bring its agent tab into view.

Diagnosis: the current navigation host updates the logical SelectedWorkspacePane and activates the target's inner content document, but does not activate the outer WorkspacePaneDocument that makes that workspace visible. Those are separate dock layouts. A successful logical selection is therefore not a successful visible workspace-tab switch.

Steps to reproduce

  1. Open two workspace tabs: House and Phantom.Workspaces.
  2. Have the House Agent Session AI tab in the House workspace produce a notification.
  3. Select the Phantom.Workspaces workspace tab, leaving House open but inactive.
  4. Open the Notifications window.
  5. Click the House Agent Session notification entry to navigate to that session.

Expected: select the existing House workspace tab, activate the existing House Agent Session AI tab within it, and bring that session into view.

Actual: the app does not visibly switch to the House workspace tab; cross-workspace navigation from the notification remains broken.

Observed context and limits

Reported October 9, 2026. Application version/build was not provided. The diagnosis below is static source evidence at local clean checkout 1b86a98feb52d32a4bbfef82d624117a57b8fdd4 (merge PR #1626), not proof that the user's executable is that build.

The screenshot is intentionally not uploaded or attached. It was not accessed during this investigation; the reproduction context above comes from the report.

Root Cause

All paths and line numbers below refer to the pinned commit. Pinned source tree.

Confirmed defect: logical pane selection omits outer dock activation

  1. The real notification button reaches the centralized navigator. Phantom.Workspaces\Controls\NotificationsControl.axaml:39–40 binds the button to NavigateCommand. Phantom.Workspaces\ViewModels\NotificationsViewModel.cs:161–176 constructs the command:

    this.TriggerFadeClose();
    await this.navigator.NavigateAsync(
        new NavigationTarget
        {
            Path = UiPath.ForTab(
                this.notificationService.Notifications
                    .FirstOrDefault(e => e.TabKey == tabKey)?.TabDescriptor.WorkspaceId,
                tabKey),
        },
        new NavigationOptions { PushHistory = true, FocusWindow = true });

    The click is not using an obsolete notification-specific activation implementation. Its boolean result is ignored, so a failure still fades the popup.

  2. Phase 1 only assigns a view-model property. Phantom.Workspaces\ViewModels\MainWindowViewModel.cs:2598–2604 handles an already-open hinted pane:

    this.SelectedWorkspacePane = targetPane;
    if (await targetPane.NavigateToDocumentTabAsync(documentTabId, deferIfAbsent: openedJustNow))
    {
        return true;
    }

    The all-panes fallback does the same at 2617–2620. Neither activates the owning outer pane document. The SelectedWorkspacePane setter at 472–483 only changes the field and raises ActiveAgentViewModel; it performs no docking operation.

    Host activation source.

  3. Phase 2 only activates the inner document. Phantom.Workspaces\ViewModels\WorkspacePaneViewModel.cs:295–314 resolves the document from the owning pane's registry and executes:

    var documentDock = FindDocumentDock(this.ContentLayout);
    this.environment?.DockFactory.SetActiveDockable(doc);
    if (documentDock is not null)
    {
        this.environment?.DockFactory.SetFocusedDockable(documentDock, doc);
    }
    return Task.FromResult(true);

    This operates on the content layout, not the outer workspace-tab layout. The deferred counterpart, ActivateMaterializedDocument, at 352–363, also only calls environment.SelectPane(this) before activating the inner document. That callback is wired at MainWindowViewModel.cs:4800 to the same property assignment.

  4. The two layouts are distinct, not one continuous dock-parent chain. Phantom.Workspaces\ViewModels\WorkspaceDockFactory.cs:88–125 creates the outer WorkspacesPaneDock and root. 153–183 separately creates each workspace's content root. Phantom.Workspaces\MainWindow.axaml:254–257 renders Layout in TopLevelDockControl; Phantom.Workspaces\Templates\DockDataTemplates.axaml:111–115 renders each WorkspacePaneDocument using a nested DockControl bound to WorkspacePane.ContentLayout. There is no binding from outer docking selection to SelectedWorkspacePane in this presentation path. Activating a content document is not a request to select its containing outer workspace tab.

  5. Existing workspace-opening code explicitly performs the missing operation. For an already-open workspace, MainWindowViewModel.cs:2290–2301 sets SelectedWorkspacePane, finds the outer WorkspacePaneDocument, and calls dockFactory.SetActiveDockable(existingDocument). AddWorkspacePaneToDock at 2380–2401 likewise activates the pane document, using GetPaneDocument(workspacePane.Id) at 2394. The notification host omits this operation when the target is already open.

    The reverse synchronization exists: OnActiveDockableChanged at 4653–4655 updates SelectedWorkspacePane when an outer WorkspacePaneDocument is activated. That is dock → view model, not the missing view-model navigation → dock activation.

Identity and restored inactive tabs: checked, not assumed broken

  • AgentSessionWorkspaceTabViewModel.CreateTabDescriptor at Phantom.Workspaces\ViewModels\AgentSessionWorkspaceTabViewModel.cs:420–426 emits TabId = this.Id and WorkspaceId = this.WorkspacePaneId. WorkspacePaneViewModel.OnTabsCollectionChanged at 169–183 stamps every added tab with the owning pane's ID, including restored tabs. Phantom.Workspaces\Services\Notifications\NotificationService.cs:52–56 retains the supplied descriptor in the notification entry.
  • Phantom.Workspaces\Services\Navigation\UiPath.cs:27–28 maps a missing workspace ID to the wildcard *. The current host's fallback searches per-pane materialized document registries; it does not depend solely on the currently-selected pane. A missing identity is therefore not required to explain this already-open scenario.
  • WorkspacePaneViewModel.TryRestoreFromDockLayoutAsync at 608–618 initializes/restores the content layout and wires every content region; 632–643 adds restored tabs and checks the per-pane document registry. A restored tab with a correct registry entry still reaches the same outer-activation omission. There is no evidence that House's actual registry or descriptor was corrupt.
  • MainWindowTabNavigator.NavigateAsync at Phantom.Workspaces\Services\Navigation\MainWindowTabNavigator.cs:33–67 treats host true as success, then focuses the window, marks notifications read, and pushes history. MainWindowViewModel.FocusWindow at 4834–4869 activates the hosting window, not the outer workspace document. It cannot substitute for selecting House.
  • The current centralized navigator has no blanket exception-swallowing catch. Do not reuse that historical explanation from F8/F7 notification navigation cannot cross workspaces or reach detached windows; centralized navigator swallows failures #1460.

Confidence: high that the missing outer-document activation is a present source defect and explains the reported visible behavior, even with correct identities and fully-materialized tabs. Matching the user's running build and reproducing the visible result in a live/headless window remain unverified. Unknown/stale identities, missing documents, and deferred activation timing are additional cases to test, not established causes of this report.

Why previous fixes/tests did not catch this

  • Clicking a notification for a tab in a different workspace does not navigate to that workspace #934/Status-button navigation (running-agents brain / notifications bell) fails cross-workspace: only navigates within the active workspace #1135 addressed missing/stale workspace identity; current producer and owning-pane stamping contain those fixes.
  • Notification click does not switch workspace or activate tab when target workspace is open but not currently selected #1157 addressed document lookup and early return/deferred activation. The current host selects the logical pane before navigation and retains fallback behavior; that old early-return explanation is not the defect diagnosed here.
  • MainWindowIntegrationTests.ActivateTabById_WhenTargetWorkspaceIsOpenButNotSelected_SelectsTargetWorkspaceAndActivatesTab (10792–10836) and NotificationNavigate_WhenTargetWorkspaceIsOpenButNotSelected_SwitchesToTargetWorkspaceAndTab (10875–10925) set SelectedWorkspacePane directly during setup, create no shown MainWindow, and assert the logical pane plus an inner dock selection. GetDocumentDock (6130–6138) reads SelectedWorkspacePane.ContentLayout, so those assertions follow the logical selection without checking the actual outer active pane.
  • The F8 regression NavigateNextNotificationCommand_WhenTabIsInNonSelectedPane_SwitchesWorkspacePane (8646–8715) has the same blind spot. It can pass even when the visible workspace never changes.
  • NotificationsViewModelTests.NavigateCommand_ResolvesWorkspacePaneIdFromNotificationDescriptor (599–618) tests delegation through FakeTabNavigator; MainWindowTabNavigatorTests uses FakeHost (16–32); WorkspacePaneViewModelTests.WorkspacePaneViewModel_NavigateToDocumentTabAsync_ActivatesAndFocusesWithinOwnLayout (533–555) checks only an inner layout. None establishes the outer-selection invariant.
  • WorkspaceDockPersistenceIntegrationTests.WorkspaceDockFactory_GetDocumentForTab_AfterRestoreOfBloatedTree_ReturnsSingleCanonicalInstance (26–98) validates restored document identity/ownership and serialization, not cross-workspace visibility.

Validation performed

Read the current notification UI, producers, navigator/host, docking presentation, restoration code, relevant existing tests, and related issue findings. No application code was edited.

A targeted run was attempted through the mandated scripts\run-tests.ps1 using -NoBuild and the existing notification identity/cross-pane test selectors. The default scripts\test-results.log was locked by another process, so the attempt was retried with an isolated log. It then reported the Phantom.Workspaces.Tests\bin\Debug\net10.0\Phantom.Workspaces.Tests.dll test assembly was absent: zero tests executed; no passing test result is claimed. The isolated scratch log was removed. No dependencies/tools were installed and no application rebuild was performed.

Affected Files

File / lines at pinned commit Role / recommended change
Phantom.Workspaces\ViewModels\MainWindowViewModel.cs:472–483, 2567–2627, 4800 Primary defect: navigation changes logical pane selection without activating the outer workspace document; shared pane-selection callback has the same limitation.
Phantom.Workspaces\ViewModels\WorkspaceDockFactory.cs:82–83, 88–125, 153–183 Existing pane-document registry and separate outer/inner layouts; reuse registry and docking APIs, do not create another workspace.
Phantom.Workspaces\ViewModels\WorkspacePaneViewModel.cs:295–363, 608–643 Inner navigation and deferred/restored activation must cooperate with actual host-pane selection.
Phantom.Workspaces\Services\Navigation\MainWindowTabNavigator.cs:33–67 Shared orchestration must only record success when the activation contract is satisfied.
Phantom.Workspaces\Controls\NotificationsControl.axaml:39–40; Phantom.Workspaces\ViewModels\NotificationsViewModel.cs:161–176 Real click path; exercise the actual command/control in regression tests. Not an identity-producer fix.
Phantom.Workspaces\MainWindow.axaml:254–257; Phantom.Workspaces\Templates\DockDataTemplates.axaml:111–115 Presentation evidence: outer active workspace controls which nested content layout is visible. No template change is required by the diagnosis.
Phantom.Workspaces.Tests\MainWindowIntegrationTests.cs:6130–6188, 8646–8715, 10792–10925 Extend regression setup/assertions to activate and observe the outer dock and shown window, not just logical pane properties.
Phantom.Workspaces.Tests\WorkspaceDockPersistenceIntegrationTests.cs; NotificationsViewModelTests.cs; MainWindowTabNavigatorTests.cs; AgentSessionNotificationTests.cs Existing classes for restored-target, delegation/success, and identity regression coverage.

Design / Fix

Chosen recommendation: centralize an explicit select and activate the hosting workspace pane primitive in MainWindowViewModel, then use it in both Phase-1 activation branches and the WorkspacePaneEnvironment.SelectPane callback used by deferred activation. Use the existing WorkspaceDockFactory.GetPaneDocument(pane.Id) registry and the actual pane document's owner; do not replace it with a new OpenWorkspaceAsync round trip or duplicate the AI session in the currently-active workspace.

Illustrative sketch (not implemented):

private void SelectAndActivateWorkspacePane(WorkspacePaneViewModel pane)
{
    var paneDocument = this.dockFactory.GetPaneDocument(pane.Id);
    // Resolve through the existing outer document registry / owning dock.
    // Missing host documents must be handled by the activation contract,
    // not reported as successful visible navigation.
    this.SelectedWorkspacePane = pane;
    this.dockFactory.SetActiveDockable(paneDocument);
    this.dockFactory.SetFocusedDockable((IDock)paneDocument.Owner, paneDocument);
}

// Hinted pane and all-panes fallback, before inner-document activation:
this.SelectAndActivateWorkspacePane(targetPane);
await targetPane.NavigateToDocumentTabAsync(documentTabId, deferIfAbsent: openedJustNow);

// Deferred materialization uses the same outer-selection primitive:
SelectPane = this.SelectAndActivateWorkspacePane;

This sketch omits null/deferred-result handling deliberately: implementation must preserve current missing-tab/stale-ID fallback and genuinely deferred restoration behavior rather than assuming every pane document exists. Resolve the target document/owner before final success where possible; do not mark read or push successful history for a target that cannot be brought into view. Test missing targets explicitly.

Activate in order: outer hosting pane document → inner target document → correct host window/focus. For split/restored content, focus the target's actual owning dock rather than blindly using the first primary content dock. Reuse the existing centralized navigator for notification clicks, F7/F8, history, and running-agent navigation; avoid adding an independent notification-only workaround.

Keep SelectedWorkspacePane as logical state if desired, but require navigation to synchronize it with the outer active dockable. Avoid an unconditional setter side effect without reviewing dock-event reentrancy: OnActiveDockableChanged already assigns that property.

Considered / Background: correcting notification descriptors or reinstating the #1157 document-lookup fix alone does not address the confirmed outer-selection omission. Reopening an already-open workspace might activate its outer document through the existing open path, but unnecessarily invokes loading/opening machinery and is not the recommended fix.

Expected Tests

Proposed names use Subject_Scenario_ExpectedOutcome and existing test classes in Phantom.Workspaces.Tests. Existing named regressions above should also gain outer-dock assertions.

Test Name Class What It Verifies
NotificationNavigate_WhenAgentTabIsInInactiveWorkspace_SelectsOuterWorkspaceAndShowsAgentTab MainWindowIntegrationTests Show a real MainWindow with House and Phantom.Workspaces; activate Phantom.Workspaces through the outer dock; click the House notification control (or execute its real row command), drain UI work, and assert outer WorkspacePaneDocument, selected workspace, inner active document, and visible agent content all identify House/the original session.
ActivateTabByRequest_WhenWorkspaceIdIsMissing_SelectsOwningOuterWorkspaceAndTab MainWindowIntegrationTests Wildcard fallback selects the actual outer host pane and its inner document, not merely the logical pane property.
ActivateTabByRequest_WhenWorkspaceIdIsStale_SelectsActualOwningOuterWorkspaceAndTab MainWindowIntegrationTests An incorrect workspace hint cannot strand the user on the wrong visible pane when the target is already registered elsewhere.
NotificationNavigate_WhenTargetWorkspaceIsCurrent_ActivatesExistingTabWithoutDuplicatingSession MainWindowIntegrationTests Same-workspace behavior remains correct and workspace/tab counts and document instance identity are unchanged.
NavigateNextNotificationCommand_WhenTargetWorkspaceIsInactive_SelectsOuterWorkspaceAndShowsTargetTab MainWindowIntegrationTests F8 reaches the same visible result as a notification click; cover F7 direction as well.
NotificationNavigate_WhenTargetTabIsRestoredInInactiveWorkspace_SelectsCanonicalOuterWorkspaceAndDocument WorkspaceDockPersistenceIntegrationTests Restore a target content layout, make another outer workspace active, then navigate; assert outer activation and the canonical registry document (including a secondary split-region case).
NotificationNavigate_WhenTargetWorkspaceIsHydrating_ActivatesOuterWorkspaceAndMaterializedTab MainWindowIntegrationTests Use deterministic population/materialization gating; deferred completion activates both levels and does not hang or duplicate tabs.
NotificationNavigate_WhenTargetTabCannotBeResolved_DoesNotMarkReadOrPushSuccessfulHistory MainWindowIntegrationTests Missing target failure is not treated as visible navigation success.
NavigateCommand_WhenDescriptorIdentifiesInactiveWorkspace_PassesOwningWorkspaceAndTabToNavigator NotificationsViewModelTests Retain identity/delegation coverage without treating the fake navigator as proof of visibility.
TabNavigator_NavigateAsync_WhenActivateTabFails_ReturnsFalseWithoutSideEffects (existing) MainWindowTabNavigatorTests Retain the existing false-result side-effect guarantee; a failed host activation must not be recorded as success.

Retain AgentSessionNotificationTests.Notify_SetsWorkspaceId_FromOwningPane and Notify_SetsWorkspaceId_FromWorkspacePaneId as producer checks. They do not replace shown-window navigation tests.

Related navigation issues

Acceptance criteria

  • With House and Phantom.Workspaces open and Phantom.Workspaces visibly active, clicking the House Agent Session notification selects House's outer workspace tab, activates its existing AI tab, and shows/focuses that session.
  • Outer dock selection, SelectedWorkspacePane, owning inner active document, and displayed content agree after navigation; changing only logical view-model state does not satisfy acceptance.
  • No duplicate workspace, session tab, or restored document is created.
  • The behavior works for freshly-created and restored inactive workspaces, stale/missing identity fallback, same-workspace navigation, and deferred tab materialization.
  • F7/F8 and the other centralized navigation callers share the corrected host activation behavior; existing window-focus behavior is preserved.
  • Successful read/history side effects follow real target activation; missing targets do not record false success.
  • Shown-window regression tests exercise the actual notification click path and assert outer selection plus visible content, not only SelectedWorkspacePane.ContentLayout.
  • Verify the user's application build when validating the fix. No screenshot upload or attachment is required.

Activity

  1. JoshuaRowePhantom commented on Oct 10, 2026

    @JoshuaRowePhantom
    OwnerAuthor

    Implementation notes

    Implemented locally in commit 86ab26c (not pushed), based on the diagnosed baseline. Centralized navigation activates the existing outer WorkspacePaneDocument before its existing content document, with focus on the actual owning content region. Deferred navigation awaits real document registration and activation before reporting success; missing targets, removed tabs, failed population and closed panes cannot produce successful read/history side effects. The logical property setter remains free of unconditional dock activation.

    Shown MainWindow tests exercise the real notification row command, outer active document, logical workspace, visible original agent content, wildcard/stale hints, current workspace, F7/F8 and restored secondary split-region canonical documents. The shown restored case exposed initial tabstrip-binding focus overwrite; navigation now waits for observable target-strip realization before final focus. Notification rows expose awaitable AsyncRelayCommand completion. Existing regression tests gained outer-dock assertions.

    Tests were written first and failed at the outer activation/deferred success contract. Application targeted union: 254 passed, 0 failed. No release, PR or issue closure performed. The installed user build and real-desktop House/Phantom.Workspaces acceptance remain for the release coordinator.

  2. added 2 commits that reference this issue on Oct 11, 2026
    86ab26c
    50ecc08
  3. JoshuaRowePhantom commented on Oct 13, 2026

    @JoshuaRowePhantom
    OwnerAuthor

    User live verification on 2026-10-13 confirms notifications now switch to open workspace/agent tabs. Fix available on local and remote features at d2a1a3b. No release has been issued yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdiagnosedRoot cause identified

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions