diff --git a/docs/TEST_INTEGRITY.md b/docs/TEST_INTEGRITY.md index 9b98139..bb6f2b2 100644 --- a/docs/TEST_INTEGRITY.md +++ b/docs/TEST_INTEGRITY.md @@ -2598,6 +2598,10 @@ test_integrity_note: given: "The Console is loaded at the organization-proposals or approval-request-list fragment" when: "The reader opens either direct link and uses browser Back and Forward" then: "Exactly the matching view is selected and the actual secondary target is focused inside the viewport" + - id: SCN-console-operational-deeplink-fleet + given: "Operations, resources, schedules, providers, decisions, context, and manager-wakes are grouped in the Fleet workspace" + when: "The reader loads #manager-wakes directly, follows its existing attention link, or returns to it through Back and Forward" + then: "Fleet is selected, the Operations disclosure opens, manager-wakes receives focus inside the viewport, and the entire Operations section is hidden on unrelated views" - id: SCN-console-view-drafts given: "A task draft and an owner approval preview are present" when: "The reader changes views and refreshes the sample Console" @@ -2610,10 +2614,12 @@ test_integrity_note: - "An unchanged current-revision preview, confirmation boundary, and draft retained after refresh" - "A regenerated preview token and displayed revision bound to N+1" - "Exact Overview and contextual view titles, plus focused in-viewport secondary targets across direct loads and browser history" + - "The manager-wakes route selects Fleet and opens/focuses its nested target across direct navigation and browser history; operations stay hidden outside Fleet" - "Visible recorded-evidence limitation beside owner briefing content while exact provenance remains compact and collapsed" - "No browser requests to live project APIs and no changes to tracked screenshot expectations" determinism_controls: - "The existing isolated sample Console, fixed Playwright clock, and fixed desktop/mobile viewports" + - "Manager-wakes routing uses the existing isolated sample Console and browser fragment history without changing project state" - "Newer evidence is introduced through the sample's supported preview/confirm API before an explicit refresh" - "The browser test advances only the isolated sample API; it never submits the priority form or mutates a live project" - "No network, live project mutation, retry, sleep, timeout, golden update, or direct fixture-source change" diff --git a/site/console.html b/site/console.html index 3df04ff..3ecc697 100644 --- a/site/console.html +++ b/site/console.html @@ -266,7 +266,7 @@
-
+
Operations, resources, and decisions

Worktrees

Branches and recoverability
diff --git a/site/console.js b/site/console.js index d929e24..9f545e5 100644 --- a/site/console.js +++ b/site/console.js @@ -54,6 +54,9 @@ function installConsoleViewRouting() { const target = document.getElementById(targetId); const targetView = target?.closest('[data-console-view]')?.dataset.consoleView; if (target && targetId !== view && targetView === view) { + for (let ancestor = target; ancestor; ancestor = ancestor.parentElement) { + if (ancestor instanceof HTMLDetailsElement) ancestor.open = true; + } if (!target.hasAttribute('tabindex') && !target.matches('a[href], button, input, select, textarea, summary')) { target.tabIndex = -1; } diff --git a/test/fleet/console-view-navigation.test.mjs b/test/fleet/console-view-navigation.test.mjs index a8ea65d..3e95116 100644 --- a/test/fleet/console-view-navigation.test.mjs +++ b/test/fleet/console-view-navigation.test.mjs @@ -211,6 +211,49 @@ test('SCN-console-view-navigation: fragments, direct loads, Back and Forward sel await assertSelectedView(page, 'flow-watch', 'Flow watch'); }); +test('SCN-console-operational-deeplink-fleet: manager-wakes belongs to Fleet across direct loads and history', async (t) => { + const { page } = await openDemo(t, { width: 1280, height: 900 }); + const base = `http://127.0.0.1:${new URL(page.url()).port}/console?demo=1`; + const assertManagerWakesTarget = async () => { + await assertSelectedView(page, 'fleet', 'Fleet'); + assert.equal(await page.locator('#fleet-operations').isVisible(), true); + assert.equal(await page.locator('#fleet-operations').evaluate((details) => details.open), true, + 'the Operations disclosure must open for its nested target'); + const target = await page.locator('#manager-wakes').evaluate((element) => { + const bounds = element.getBoundingClientRect(); + return { activeId: document.activeElement?.id, top: bounds.top, bottom: bounds.bottom, height: innerHeight }; + }); + assert.equal(target.activeId, 'manager-wakes', 'the actual fragment target must receive focus'); + assert.ok(target.top < target.height && target.bottom > 0, + `manager-wakes must intersect the viewport: ${JSON.stringify(target)}`); + }; + + await page.goto(`${base}#manager-wakes`); + await page.locator('#live-refresh-status[data-generation="1"]').waitFor(); + await assertManagerWakesTarget(); + + await page.locator('.console-rail a[href="#fleet"]').click(); + await assertSelectedView(page, 'fleet', 'Fleet'); + await page.goBack(); + await assertManagerWakesTarget(); + await page.goForward(); + await assertSelectedView(page, 'fleet', 'Fleet'); + + await page.goto(`${base}#overview`); + await page.locator('#live-refresh-status[data-generation="1"]').waitFor(); + await page.locator('#attention-list a[href="#manager-wakes"]').click(); + await assertManagerWakesTarget(); + await page.goBack(); + await assertSelectedView(page, 'overview', 'Overview'); + await page.goForward(); + await assertManagerWakesTarget(); + + await page.locator('.console-rail a[href="#work"]').click(); + await assertSelectedView(page, 'work', 'Work'); + assert.equal(await page.locator('#fleet-operations').isVisible(), false, + 'operational panels must be hidden outside the selected Fleet view'); +}); + test('SCN-console-mobile-navigation: every destination is visible at 390x844 without horizontal hunting', async (t) => { const { page } = await openDemo(t, { width: 390, height: 844 }); assert.equal(await page.locator('.console-rail a').count(), views.length);