From f9d320eee39c0daac4269f7d1112399a99c8d7ed Mon Sep 17 00:00:00 2001 From: DavidQ Date: Tue, 23 Jun 2026 20:33:49 -0400 Subject: [PATCH] ALFA 009 status bar single row rebuild --- assets/theme-v2/css/layout.css | 2 +- assets/theme-v2/css/status.css | 98 +++++++++---------- assets/theme-v2/js/toolbox-status-bar.js | 53 ++-------- docs_build/dev/BUILD_PR.md | 69 +++++++------ ...09-status-bar-single-row-rebuild_report.md | 32 ++++++ ...ngle-row-rebuild_requirements-checklist.md | 19 ++++ ...-bar-single-row-rebuild_validation-lane.md | 12 +++ .../dev/reports/codex_changed_files.txt | 10 +- docs_build/dev/reports/codex_review.diff | 2 +- .../ToolboxSelectedGameStatusBar.spec.mjs | 96 +++++++++++++----- 10 files changed, 238 insertions(+), 155 deletions(-) create mode 100644 docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_report.md create mode 100644 docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_requirements-checklist.md create mode 100644 docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_validation-lane.md diff --git a/assets/theme-v2/css/layout.css b/assets/theme-v2/css/layout.css index a9614b412..b392b3306 100644 --- a/assets/theme-v2/css/layout.css +++ b/assets/theme-v2/css/layout.css @@ -733,7 +733,7 @@ body.tool-focus-mode .tool-workspace--table-scroll-focus .tool-table-scroll-regi .footer { margin-top: var(--space-46); border-top: var(--border-standard); - padding: var(--space-24) var(--space-0); + padding: var(--space-0) var(--space-0) var(--space-24); color: var(--muted) } diff --git a/assets/theme-v2/css/status.css b/assets/theme-v2/css/status.css index 88e0d5e64..6acb4555b 100644 --- a/assets/theme-v2/css/status.css +++ b/assets/theme-v2/css/status.css @@ -36,7 +36,10 @@ } .toolbox-status-bar { + --toolbox-status-bar-height: var(--space-52); + --toolbox-status-game-max: 220px; width: 100%; + min-block-size: var(--toolbox-status-bar-height); border-block: var(--border-standard); background: var(--panel-overlay-strong); color: var(--text) @@ -47,7 +50,7 @@ margin: var(--space-0) auto; padding: var(--space-10) var(--space-0); display: grid; - grid-template-columns: minmax(var(--space-0), 1fr) minmax(var(--space-0), 2fr); + grid-template-columns: minmax(var(--space-0), max-content) minmax(var(--space-0), 1fr); gap: var(--space-16); align-items: center } @@ -56,34 +59,18 @@ min-width: var(--space-0); display: flex; align-items: center; - flex-wrap: wrap; - gap: var(--space-14); + justify-content: flex-start; text-align: left } -.toolbox-status-bar__field { - min-width: var(--space-0); - display: grid; - gap: var(--space-3) -} - -.toolbox-status-bar__label { - color: var(--muted); - font-size: var(--font-size-xs); - font-weight: var(--font-weight-heavy); - letter-spacing: var(--letter-spacing-kicker); - text-transform: uppercase -} - .toolbox-status-bar__game-name { color: var(--text); font-size: var(--font-size-base); - overflow-wrap: anywhere -} - -.toolbox-status-bar__purpose { - color: var(--muted); - font-size: var(--font-size-sm); + line-height: var(--line-height-tight); + max-width: min(30vw, var(--toolbox-status-game-max)); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; overflow-wrap: anywhere } @@ -92,25 +79,17 @@ display: flex; align-items: center; justify-content: center; - flex-wrap: wrap; - gap: var(--space-10); + justify-self: center; text-align: center } -.toolbox-status-bar__context-type { - flex: 0 0 auto -} - .toolbox-status-bar__message { margin: var(--space-0); max-width: var(--measure-lg); + line-height: var(--line-height-copy); overflow-wrap: anywhere } -.toolbox-status-bar__action { - flex: 0 0 auto -} - .toolbox-status-bar[data-selected-game-state="active"] { border-color: color-mix(in srgb, var(--green) 52%, var(--line)) } @@ -123,22 +102,6 @@ border-color: color-mix(in srgb, var(--red) 52%, var(--line)) } -.toolbox-status-bar[data-toolbox-status-context-kind="error"] .toolbox-status-bar__context-type { - border-color: color-mix(in srgb, var(--red) 62%, var(--line)); - color: var(--red) -} - -.toolbox-status-bar[data-toolbox-status-context-kind="warning"] .toolbox-status-bar__context-type, -.toolbox-status-bar[data-toolbox-status-context-kind="validation"] .toolbox-status-bar__context-type { - border-color: var(--gold-border-muted); - color: var(--gold) -} - -.toolbox-status-bar[data-toolbox-status-context-kind="save"] .toolbox-status-bar__context-type { - border-color: color-mix(in srgb, var(--green) 62%, var(--line)); - color: var(--green) -} - body.tool-focus-mode .toolbox-status-bar { position: fixed; inset-block-end: var(--space-0); @@ -148,6 +111,31 @@ body.tool-focus-mode .toolbox-status-bar { box-shadow: var(--shadow-md) } +body.tool-focus-mode { + --toolbox-status-bar-height: var(--space-52); + --toolbox-status-top-reserve: var(--space-0) +} + +body.tool-focus-mode:has(.platform-banner) { + --toolbox-status-top-reserve: var(--space-52) +} + +body.tool-focus-mode .tool-workspace { + box-sizing: border-box; + height: calc(100vh - var(--toolbox-status-bar-height) - var(--toolbox-status-top-reserve)); + max-height: calc(100vh - var(--toolbox-status-bar-height) - var(--toolbox-status-top-reserve)) +} + +body.tool-focus-mode .tool-column { + height: calc(100vh - var(--toolbox-status-bar-height) - var(--toolbox-status-top-reserve) - var(--space-20)); + max-height: calc(100vh - var(--toolbox-status-bar-height) - var(--toolbox-status-top-reserve) - var(--space-20)) +} + +body.tool-focus-mode .tool-center-panel { + box-sizing: border-box; + scroll-padding-block-end: var(--toolbox-status-bar-height) +} + .platform-banner { width: 100%; border-bottom: var(--border-standard); @@ -261,12 +249,16 @@ body.tool-focus-mode .toolbox-status-bar { @media (max-width: 720px) { .toolbox-status-bar__inner { width: var(--container-width); - grid-template-columns: 1fr; + grid-template-columns: minmax(var(--space-0), max-content) minmax(var(--space-0), 1fr); + gap: var(--space-10); text-align: center } - .toolbox-status-bar__game { - justify-content: center; - text-align: center + .toolbox-status-bar__game-name { + max-width: 34vw + } + + .toolbox-status-bar__message { + font-size: var(--font-size-sm) } } diff --git a/assets/theme-v2/js/toolbox-status-bar.js b/assets/theme-v2/js/toolbox-status-bar.js index fdb367328..24c935311 100644 --- a/assets/theme-v2/js/toolbox-status-bar.js +++ b/assets/theme-v2/js/toolbox-status-bar.js @@ -90,37 +90,16 @@ function createStatusBar() { game.className = "toolbox-status-bar__game"; game.dataset.toolboxSelectedGame = ""; - const nameField = document.createElement("div"); - nameField.className = "toolbox-status-bar__field"; - nameField.dataset.toolboxSelectedGameNameField = ""; - const nameLabel = createText("span", "toolbox-status-bar__label", "toolboxSelectedGameNameLabel"); - nameLabel.textContent = "Selected Game Name"; const name = createText("strong", "toolbox-status-bar__game-name", "toolboxSelectedGameName"); - nameField.append(nameLabel, name); - - const purposeField = document.createElement("div"); - purposeField.className = "toolbox-status-bar__field"; - purposeField.dataset.toolboxSelectedGamePurposeField = ""; - const purposeLabel = createText("span", "toolbox-status-bar__label", "toolboxSelectedGamePurposeLabel"); - purposeLabel.textContent = "Selected Game Purpose"; - const purpose = createText("span", "toolbox-status-bar__purpose", "toolboxSelectedGamePurpose"); - purpose.dataset.toolboxSelectedGameMeta = ""; - purposeField.append(purposeLabel, purpose); - game.append(nameField, purposeField); + game.append(name); const center = document.createElement("div"); center.className = "toolbox-status-bar__center"; center.dataset.toolboxStatusCenter = ""; - const contextType = createText("span", "pill toolbox-status-bar__context-type", "toolboxStatusContextType"); const message = createText("p", "toolbox-status-bar__message status", "toolboxStatusMessage"); message.setAttribute("role", "status"); - const action = document.createElement("a"); - action.className = "btn btn--compact toolbox-status-bar__action"; - action.dataset.toolboxStatusAction = ""; - action.href = mountOptions.gameHubHref; - action.textContent = "Open Game Hub"; - center.append(contextType, message, action); + center.append(message); inner.append(game, center); bar.append(inner); @@ -234,33 +213,30 @@ function publishSelectedGameContext(selectedGame, state) { function classifyToolContext(messageText, state, required) { const text = String(messageText || "").trim(); if (state === "error") { - return { kind: "error", label: "Error" }; + return { kind: "error" }; } if (required && state === "missing") { - return { kind: "action", label: "Tool Action" }; + return { kind: "action" }; } if (/\b(error|failed|malformed|unavailable|could not)\b/i.test(text)) { - return { kind: "error", label: "Error" }; + return { kind: "error" }; } if (/\b(sign in|refresh|try again|temporarily|blocked)\b/i.test(text)) { - return { kind: "warning", label: "Warning" }; + return { kind: "warning" }; } if (/\b(validation|requirement|requirements|missing|required|open or seed)\b/i.test(text)) { - return { kind: "validation", label: "Validation" }; + return { kind: "validation" }; } if (/\b(saved|created|deleted|updated|loaded|save changes)\b/i.test(text)) { - return { kind: "save", label: "Save State" }; + return { kind: "save" }; } - return { kind: "action", label: "Tool Action" }; + return { kind: "action" }; } function renderSelectedGame(bar, selectedGame, state, messageText) { const required = pageRequiresSelectedGame(); const name = bar.querySelector("[data-toolbox-selected-game-name]"); - const purpose = bar.querySelector("[data-toolbox-selected-game-purpose]"); - const contextType = bar.querySelector("[data-toolbox-status-context-type]"); const message = bar.querySelector("[data-toolbox-status-message]"); - const action = bar.querySelector("[data-toolbox-status-action]"); const nextMessage = messageText || latestToolMessage || (selectedGame ? `Tool context is filtered to ${selectedGame.name}.` : required @@ -271,38 +247,27 @@ function renderSelectedGame(bar, selectedGame, state, messageText) { bar.dataset.selectedGameState = state; bar.dataset.selectedGameRequired = String(required); bar.dataset.toolboxStatusContextKind = context.kind; - contextType.textContent = context.label; - action.hidden = false; - action.href = mountOptions.gameHubHref; if (selectedGame) { name.textContent = selectedGame.name; - purpose.textContent = selectedGame.purpose || "Game"; message.textContent = nextMessage; - action.textContent = "Open Game Hub"; return; } if (!required) { name.textContent = "No game selected"; - purpose.textContent = "Idea Board optional"; message.textContent = nextMessage; - action.textContent = "Open Game Hub"; return; } if (state === "error") { name.textContent = "Unavailable"; - purpose.textContent = "Game Hub selected game could not be read"; message.textContent = nextMessage; - action.textContent = "Open Game Hub"; return; } name.textContent = "No game selected"; - purpose.textContent = "Game Hub owns game selection"; message.textContent = "Select or create a game in Game Hub before using this toolbox page."; - action.textContent = "Select or Create in Game Hub"; } export function refreshToolboxStatusBar() { diff --git a/docs_build/dev/BUILD_PR.md b/docs_build/dev/BUILD_PR.md index dd5b4d28f..0778a1f1e 100644 --- a/docs_build/dev/BUILD_PR.md +++ b/docs_build/dev/BUILD_PR.md @@ -1,63 +1,70 @@ -# PR_26175_ALFA_008-game-hub-feature-matrix +# PR_26175_ALFA_009-status-bar-single-row-rebuild ## Purpose -Audit the current Game Hub workflow and publish a feature matrix that maps implemented creator-facing behavior to code and Playwright evidence. +Rebuild the shared toolbox status bar on current `main` so it is a single-row creator context bar. ## Source Of Truth -This `BUILD_PR.md` is the source of truth for `PR_26175_ALFA_008-game-hub-feature-matrix`. +This `BUILD_PR.md` is the source of truth for `PR_26175_ALFA_009-status-bar-single-row-rebuild`. ## Exact Scope -- Produce a Game Hub feature matrix only. -- Audit Game Hub table workflow, selected/open game behavior, create/edit/delete actions, child tables, guest save gating, empty/error states, Theme V2 layout, and targeted Game Hub coverage. -- Use current `main` behavior as evidence. -- Preserve Game Hub UI/product behavior. -- Preserve API/service/repository contracts. -- Preserve previous ALFA Game Hub cleanup and create-validation behavior. -- Do not implement product/UI changes unless validation exposes a requirement-critical defect. +- Display only the selected Game Hub game name on the left side of the toolbox status bar. +- Display only the current status message in the center of the toolbox status bar. +- Remove visible status bar labels: `Selected Game Name`, `Selected Game Purpose`, `Save State`, `Tool Action`, `Warning`, and `Error`. +- Remove selected-game purpose from the visible status bar. +- Preserve normal status bar placement above the footer. +- Remove extra status bar/footer spacing so the shared footer top padding resolves to `0px`. +- Preserve fullscreen/tool display mode bottom anchoring. +- Ensure fullscreen center scrollable content stops above the fixed status bar. +- Ensure fullscreen tool content is not hidden behind the status bar. +- Preserve Idea Board selected-game filtering exclusion. +- Preserve Game Hub as selected-game owner through the existing repository contract. +- Use shared Theme V2 CSS/classes only. +- Update targeted Playwright coverage for the single-row status bar, footer spacing, and fullscreen bottom reserve. ## Exact Targets - `docs_build/dev/BUILD_PR.md` -- `docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md` -- `docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md` -- `docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md` +- `assets/theme-v2/js/toolbox-status-bar.js` +- `assets/theme-v2/css/status.css` +- `assets/theme-v2/css/layout.css` +- `tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs` +- `docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_report.md` +- `docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_validation-lane.md` +- `docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_requirements-checklist.md` - `docs_build/dev/reports/codex_review.diff` - `docs_build/dev/reports/codex_changed_files.txt` -## Evidence Sources -- `toolbox/game-hub/index.html` -- `toolbox/project-workspace/index.html` -- `toolbox/game-hub/game-hub.js` -- `toolbox/game-hub/game-hub-api-client.js` -- `src/dev-runtime/persistence/tool-repositories/game-workspace-mock-repository.js` -- `tests/playwright/tools/GameHubMockRepository.spec.mjs` - ## Out Of Scope -- No Game Hub product or UI changes. -- No Game Journey changes. -- No shared toolbox status bar changes. -- No browser-owned product data as source of truth. +- No merge of PR #120. +- No reuse of stale ALFA_003 branch. +- No environment/server details in the status bar. +- No selected game purpose in the visible status bar. +- No visible status category labels in the status bar. +- No status action links in the visible status bar. +- No large banners. +- No modal messages or modal-style status messages. +- No row highlights. - No API/service/repository contract changes. +- No browser-owned product data as source of truth. - No inline styles, style blocks, or page-local CSS. - No engine core changes. - No `start_of_day` folder changes. -- No ALFA_007 work. ## Validation -Run targeted Game Hub validation: +Run targeted Playwright coverage: ```powershell -npx playwright test tests/playwright/tools/GameHubMockRepository.spec.mjs --workers=1 +npx playwright test tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs --workers=1 ``` -Also verify changed docs/reports do not introduce inline styles or style blocks: +Also verify changed source does not introduce inline styles or style blocks: ```powershell -rg -n "<[s]tyle|[s]tyle=" docs_build/dev/BUILD_PR.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md +rg -n "<[s]tyle|[s]tyle=" assets/theme-v2/js/toolbox-status-bar.js assets/theme-v2/css/status.css assets/theme-v2/css/layout.css tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs ``` ## Artifact Create repo-structured delta ZIP: ```text -tmp/PR_26175_ALFA_008-game-hub-feature-matrix_delta.zip +tmp/PR_26175_ALFA_009-status-bar-single-row-rebuild_delta.zip ``` diff --git a/docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_report.md b/docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_report.md new file mode 100644 index 000000000..e23234978 --- /dev/null +++ b/docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_report.md @@ -0,0 +1,32 @@ +# PR_26175_ALFA_009-status-bar-single-row-rebuild Report + +## Overall Status +PASS + +## Summary +ALFA_009 rebuilds the shared toolbox status bar from current clean `main` without merging PR #120 or reusing the stale ALFA_003 branch. The status bar now exposes a single visible row with selected game name on the left and the current status message centered. + +## Changes +- Replaced the status bar DOM with only the selected game name and status message as visible content. +- Removed visible status labels: `Selected Game Name`, `Selected Game Purpose`, `Save State`, `Tool Action`, `Warning`, and `Error`. +- Removed selected-game purpose and visible status action links from the status bar. +- Kept status context classification as non-visible dataset state for shared styling and behavior. +- Set shared Theme V2 footer top padding to `0px` while preserving bottom padding. +- Added shared fullscreen reserves so the fixed bottom status bar does not cover the center tool area. +- Preserved Game Hub selected-game ownership and Idea Board selected-game filtering exclusion. +- Updated targeted Playwright coverage for removed labels, visible game/message text, same-row layout, footer top padding, and fullscreen center-panel bounds. + +## Files Changed +- `assets/theme-v2/js/toolbox-status-bar.js` +- `assets/theme-v2/css/status.css` +- `assets/theme-v2/css/layout.css` +- `tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs` +- `docs_build/dev/BUILD_PR.md` +- ALFA_009 reports and Codex diff/change reports + +## Validation +- PASS: `npx playwright test tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs --workers=1` produced 6 passed, 0 failed after the fullscreen reserve correction. +- PASS: `rg -n "<[s]tyle|[s]tyle=" assets/theme-v2/js/toolbox-status-bar.js assets/theme-v2/css/status.css assets/theme-v2/css/layout.css tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs` returned no matches. + +## Artifact +- `tmp/PR_26175_ALFA_009-status-bar-single-row-rebuild_delta.zip` diff --git a/docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_requirements-checklist.md b/docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_requirements-checklist.md new file mode 100644 index 000000000..2e9aa4b1e --- /dev/null +++ b/docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_requirements-checklist.md @@ -0,0 +1,19 @@ +# PR_26175_ALFA_009-status-bar-single-row-rebuild Requirements Checklist + +| Requirement | Status | Evidence | +| --- | --- | --- | +| Start from clean synced `main` at `d9724b19b3f384aed1a082c3461ece4c16fe0f12` | PASS | Guardrail checks passed before branch creation: branch `main`, clean worktree, sync `0/0`, requested commit. | +| Do not merge PR #120 | PASS | ALFA_009 was rebuilt on a fresh branch from `main`; no PR #120 merge was performed. | +| Do not reuse stale ALFA_003 branch | PASS | Work was done on `codex/pr-26175-alfa-009-status-bar-single-row-rebuild`. | +| Status bar displays only selected game name on left and status message in center | PASS | `toolbox-status-bar.js` renders only `[data-toolbox-selected-game-name]` and `[data-toolbox-status-message]` as visible bar content. | +| Remove visible labels | PASS | Playwright asserts the status bar does not contain `Selected Game Name`, `Selected Game Purpose`, `Save State`, `Tool Action`, `Warning`, or `Error`. | +| Remove selected-game purpose from visible status bar | PASS | Purpose DOM is removed and Playwright asserts `[data-toolbox-selected-game-purpose]` has count `0`. | +| Remove extra footer top gap and make footer top padding resolve to `0px` | PASS | Shared `.footer` padding now starts at `var(--space-0)`, and Playwright verifies computed footer top padding is `0`. | +| Use shared Theme V2 styling | PASS | Changes are in `assets/theme-v2/css/status.css` and `assets/theme-v2/css/layout.css`; no inline styles or page-local CSS were added. | +| Preserve fullscreen bottom anchoring | PASS | Playwright verifies the status bar is fixed and bottom gap is within 2px in tool display mode. | +| Center scrollable content stops above status bar | PASS | Playwright verifies `.tool-center-panel` bottom is above the status bar top in tool display mode. | +| No content hidden behind status bar | PASS | Fullscreen workspace and columns reserve the platform banner and status bar height in shared CSS. | +| Preserve Idea Board exclusion | PASS | Playwright verifies Idea Board remains optional and does not show the missing-game prompt. | +| Preserve Game Hub selected-game ownership | PASS | Status bar still reads selected game through the existing Game Hub repository client; no API/service contract changes were made. | +| Update targeted Playwright coverage | PASS | `tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs` was updated and passed. | +| Produce required reports and ZIP | PASS | ALFA_009 report, validation lane, checklist, Codex reports, and delta ZIP were created. | diff --git a/docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_validation-lane.md b/docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_validation-lane.md new file mode 100644 index 000000000..0ec6d65af --- /dev/null +++ b/docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_validation-lane.md @@ -0,0 +1,12 @@ +# PR_26175_ALFA_009-status-bar-single-row-rebuild Validation Lane + +## Commands +| Command | Status | Evidence | +| --- | --- | --- | +| `npx playwright test tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs --workers=1` | PASS | Final run passed 6/6 tests. Coverage includes normal placement above footer, no visible removed labels, no visible purpose, save message updates, fullscreen bottom anchoring, center panel bottom above status bar, Game Hub selection updates, missing-game prompt, and Idea Board exclusion. | +| `rg -n "<[s]tyle|[s]tyle=" assets/theme-v2/js/toolbox-status-bar.js assets/theme-v2/css/status.css assets/theme-v2/css/layout.css tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs` | PASS | No inline style or style block matches. | + +## Notes +- An interim Playwright run failed the fullscreen center-panel bound assertion. The failure showed the center panel still extended below the fixed status bar. +- The final fix adds shared Theme V2 top and bottom reserves in `assets/theme-v2/css/status.css`, including the platform banner reserve used in tool display mode. +- Playwright-generated coverage reports were restored because they are outside ALFA_009 exact targets. diff --git a/docs_build/dev/reports/codex_changed_files.txt b/docs_build/dev/reports/codex_changed_files.txt index 15aa8521d..25b28f9ba 100644 --- a/docs_build/dev/reports/codex_changed_files.txt +++ b/docs_build/dev/reports/codex_changed_files.txt @@ -1,6 +1,10 @@ docs_build/dev/BUILD_PR.md -docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md -docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md -docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md +assets/theme-v2/js/toolbox-status-bar.js +assets/theme-v2/css/status.css +assets/theme-v2/css/layout.css +tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs +docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_report.md +docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_validation-lane.md +docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_requirements-checklist.md docs_build/dev/reports/codex_review.diff docs_build/dev/reports/codex_changed_files.txt diff --git a/docs_build/dev/reports/codex_review.diff b/docs_build/dev/reports/codex_review.diff index a180fc02c..84532d334 100644 --- a/docs_build/dev/reports/codex_review.diff +++ b/docs_build/dev/reports/codex_review.diff @@ -1 +1 @@ -diff --git a/docs_build/dev/BUILD_PR.md b/docs_build/dev/BUILD_PR.mdindex cf7378880..dd5b4d28f 100644--- a/docs_build/dev/BUILD_PR.md+++ b/docs_build/dev/BUILD_PR.md@@ -1,59 +1,63 @@-# PR_26175_ALFA_006-game-hub-create-project-validation+# PR_26175_ALFA_008-game-hub-feature-matrix ## Purpose-Add creator-facing validation for the Game Hub create-project row so blank game names do not silently create fallback projects.+Audit the current Game Hub workflow and publish a feature matrix that maps implemented creator-facing behavior to code and Playwright evidence. ## Source Of Truth-This `BUILD_PR.md` is the source of truth for `PR_26175_ALFA_006-game-hub-create-project-validation`.+This `BUILD_PR.md` is the source of truth for `PR_26175_ALFA_008-game-hub-feature-matrix`. ## Exact Scope-- Validate the Game Hub add-game row before calling the repository create method.-- Block signed-in creator saves when the game name is blank or whitespace-only.-- Keep the add-game row open after validation failure.-- Show a creator-safe validation message in the existing Game Hub status log.-- Mark the game name input invalid for accessibility.-- Preserve valid create/open/delete behavior.-- Preserve guest save redirect behavior.+- Produce a Game Hub feature matrix only.+- Audit Game Hub table workflow, selected/open game behavior, create/edit/delete actions, child tables, guest save gating, empty/error states, Theme V2 layout, and targeted Game Hub coverage.+- Use current `main` behavior as evidence.+- Preserve Game Hub UI/product behavior. - Preserve API/service/repository contracts.-- Add targeted Playwright coverage for the create validation path.+- Preserve previous ALFA Game Hub cleanup and create-validation behavior.+- Do not implement product/UI changes unless validation exposes a requirement-critical defect. ## Exact Targets - `docs_build/dev/BUILD_PR.md`-- `toolbox/game-hub/game-hub.js`-- `tests/playwright/tools/GameHubMockRepository.spec.mjs`-- `docs_build/dev/reports/PR_26175_ALFA_006-game-hub-create-project-validation_report.md`-- `docs_build/dev/reports/PR_26175_ALFA_006-game-hub-create-project-validation_validation-lane.md`-- `docs_build/dev/reports/PR_26175_ALFA_006-game-hub-create-project-validation_requirements-checklist.md`+- `docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md`+- `docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md`+- `docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md` - `docs_build/dev/reports/codex_review.diff` - `docs_build/dev/reports/codex_changed_files.txt` +## Evidence Sources+- `toolbox/game-hub/index.html`+- `toolbox/project-workspace/index.html`+- `toolbox/game-hub/game-hub.js`+- `toolbox/game-hub/game-hub-api-client.js`+- `src/dev-runtime/persistence/tool-repositories/game-workspace-mock-repository.js`+- `tests/playwright/tools/GameHubMockRepository.spec.mjs`+ ## Out Of Scope-- No repository/API/service contract changes.-- No Game Journey completion-metrics changes.+- No Game Hub product or UI changes.+- No Game Journey changes. - No shared toolbox status bar changes.-- No unrelated Game Hub workflow changes. - No browser-owned product data as source of truth.-- No silent create-name fallback in the Game Hub page flow.+- No API/service/repository contract changes. - No inline styles, style blocks, or page-local CSS. - No engine core changes. - No `start_of_day` folder changes.+- No ALFA_007 work. ## Validation-Run targeted create-project validation:+Run targeted Game Hub validation: ```powershell-npx playwright test tests/playwright/tools/GameHubMockRepository.spec.mjs --workers=1 --grep "Game Hub creates, opens, and deletes mock games"+npx playwright test tests/playwright/tools/GameHubMockRepository.spec.mjs --workers=1 ``` -Also verify changed source does not introduce inline styles or style blocks:+Also verify changed docs/reports do not introduce inline styles or style blocks: ```powershell-rg -n "<[s]tyle|[s]tyle=" toolbox/game-hub/game-hub.js tests/playwright/tools/GameHubMockRepository.spec.mjs docs_build/dev/BUILD_PR.md docs_build/dev/reports/PR_26175_ALFA_006-game-hub-create-project-validation_report.md docs_build/dev/reports/PR_26175_ALFA_006-game-hub-create-project-validation_validation-lane.md docs_build/dev/reports/PR_26175_ALFA_006-game-hub-create-project-validation_requirements-checklist.md+rg -n "<[s]tyle|[s]tyle=" docs_build/dev/BUILD_PR.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md ``` ## Artifact Create repo-structured delta ZIP: ```text-tmp/PR_26175_ALFA_006-game-hub-create-project-validation_delta.zip+tmp/PR_26175_ALFA_008-game-hub-feature-matrix_delta.zip ```diff --git a/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md b/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.mdnew file mode 100644index 000000000..3fbcfdb04--- /dev/null+++ b/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md@@ -0,0 +1,35 @@+# PR_26175_ALFA_008-game-hub-feature-matrix Report++## Overall Status+PASS++## Summary+ALFA_008 produced a report-only Game Hub feature matrix from current `main` behavior. No product/UI/source implementation changes were needed. Targeted Game Hub validation passed with 14/14 Playwright tests.++## Feature Matrix+| Feature Area | Status | Current Behavior | Source Evidence | Validation Evidence |+| --- | --- | --- | --- | --- |+| Deprecated project workspace route | PASS | Older Project Workspace links land on a Game Hub handoff page and expose one creator-facing Game Hub action. | `toolbox/project-workspace/index.html:17`, `toolbox/project-workspace/index.html:20`, `toolbox/project-workspace/index.html:21`, `toolbox/project-workspace/index.html:22` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:244`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:248`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:251` |+| Game Hub page shell | PASS | Game Hub uses Theme V2 shared classes, a wide tool workspace, center Games panel, and shared status elements. | `toolbox/game-hub/index.html:24`, `toolbox/game-hub/index.html:25`, `toolbox/game-hub/index.html:26`, `toolbox/game-hub/index.html:36`, `toolbox/game-hub/index.html:37`, `toolbox/game-hub/index.html:39` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:263`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:873`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:878`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:880` |+| Game table ownership | PASS | The Game Hub page owns the creator-facing game table and renders it in the center panel only. | `toolbox/game-hub/game-hub.js:538`, `toolbox/game-hub/game-hub.js:561`, `toolbox/game-hub/game-hub.js:563`, `toolbox/game-hub/game-hub.js:567`, `toolbox/game-hub/game-hub.js:569` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:288`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:289`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:296`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:298` |+| Parent row display | PASS | Parent rows display Game, Purpose, Status, and Actions without owner/role/next-tool columns. | `toolbox/game-hub/game-hub.js:500`, `toolbox/game-hub/game-hub.js:515`, `toolbox/game-hub/game-hub.js:518`, `toolbox/game-hub/game-hub.js:519`, `toolbox/game-hub/game-hub.js:523` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:298`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:304`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:305`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:306`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:307` |+| Selected/open game affordance | PASS | Selection is represented by the game toggle button only; rows do not gain active-row attributes or row highlighting. | `toolbox/game-hub/game-hub.js:500`, `toolbox/game-hub/game-hub.js:515`, `toolbox/game-hub/game-hub.js:768`, `toolbox/game-hub/game-hub.js:771`, `toolbox/game-hub/game-hub.js:776` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:308`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:311`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:314`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:324`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:326` |+| Add game workflow | PASS | Creators can open an add row, enter Game/Purpose/Status, save a new game, and cancel without saving. | `toolbox/game-hub/game-hub.js:428`, `toolbox/game-hub/game-hub.js:441`, `toolbox/game-hub/game-hub.js:448`, `toolbox/game-hub/game-hub.js:451`, `toolbox/game-hub/game-hub.js:699`, `toolbox/game-hub/game-hub.js:707` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:379`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:398`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:401`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:411`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:426`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:430` |+| Create-name validation | PASS | Blank and whitespace-only names are blocked in the page flow before repository create, keeping the add row open and showing a creator-safe status message. | `toolbox/game-hub/game-hub.js:681`, `toolbox/game-hub/game-hub.js:684`, `toolbox/game-hub/game-hub.js:687`, `toolbox/game-hub/game-hub.js:690`, `toolbox/game-hub/game-hub.js:703`, `toolbox/game-hub/game-hub.js:707` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:386`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:389`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:391`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:392`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:393`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:397` |+| Repository contract preservation | PASS | The Game Hub API client still uses the shared server repository client, and the mock repository contract remains unchanged. The lower-level repository still has defensive defaults, but ALFA_006 page validation prevents blank names from becoming creator-facing Game Hub creates. | `toolbox/game-hub/game-hub-api-client.js:1`, `toolbox/game-hub/game-hub-api-client.js:15`, `toolbox/game-hub/game-hub-api-client.js:16`, `src/dev-runtime/persistence/tool-repositories/game-workspace-mock-repository.js:378`, `src/dev-runtime/persistence/tool-repositories/game-workspace-mock-repository.js:381`, `src/dev-runtime/persistence/tool-repositories/game-workspace-mock-repository.js:419` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:391`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:392`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:396`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:397` |+| Edit game purpose/status | PASS | Existing game names are read-only in edit mode while Purpose and Status remain editable. | `toolbox/game-hub/game-hub.js:464`, `toolbox/game-hub/game-hub.js:470`, `toolbox/game-hub/game-hub.js:471`, `toolbox/game-hub/game-hub.js:475`, `toolbox/game-hub/game-hub.js:478`, `toolbox/game-hub/game-hub.js:727`, `toolbox/game-hub/game-hub.js:741`, `toolbox/game-hub/game-hub.js:752` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:413`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:417`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:418`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:419`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:424`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:780` |+| Delete open game | PASS | Signed-in creators can delete the active non-source-linked game, and source-linked games are protected. | `toolbox/game-hub/game-hub.js:834`, `toolbox/game-hub/game-hub.js:838`, `toolbox/game-hub/game-hub.js:845`, `toolbox/game-hub/game-hub.js:851`, `toolbox/game-hub/game-hub.js:852` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:451`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:452`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:454`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:860`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:861` |+| Source idea child table | PASS | Source-linked games can expose read-only Idea Board context without edit/delete controls. | `toolbox/game-hub/game-hub.js:399`, `toolbox/game-hub/game-hub.js:401`, `toolbox/game-hub/game-hub.js:404`, `toolbox/game-hub/game-hub.js:415`, `toolbox/game-hub/game-hub.js:422` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:462`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:559`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:563`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:568`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:576` |+| Readiness output child table | PASS | Every expanded game can expose readiness output and checklist context from Game Journey progress data. | `toolbox/game-hub/game-hub.js:353`, `toolbox/game-hub/game-hub.js:370`, `toolbox/game-hub/game-hub.js:372`, `toolbox/game-hub/game-hub.js:385`, `toolbox/game-hub/game-hub.js:386`, `toolbox/game-hub/game-hub.js:408` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:362`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:365`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:579`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:581`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:826`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:858` |+| Guest browsing/save gating | PASS | Guests can browse Game Hub but save operations redirect to sign-in and delete is disabled. | `toolbox/game-hub/game-hub.js:131`, `toolbox/game-hub/game-hub.js:139`, `toolbox/game-hub/game-hub.js:147`, `toolbox/game-hub/game-hub.js:151`, `toolbox/game-hub/game-hub.js:174`, `toolbox/game-hub/game-hub.js:178` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:593`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:601`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:603`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:604`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:617`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:623` |+| Empty state | PASS | Empty project lists show a creator-safe prompt and keep Add Game available. | `toolbox/game-hub/game-hub.js:557`, `toolbox/game-hub/game-hub.js:558`, `toolbox/game-hub/game-hub.js:570` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:633`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:680`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:687`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:688`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:690` |+| Unavailable/error states | PASS | Repository and active-game errors use creator-safe messages without leaking backend details. | `toolbox/game-hub/game-hub.js:66`, `toolbox/game-hub/game-hub.js:70`, `toolbox/game-hub/game-hub.js:82`, `toolbox/game-hub/game-hub.js:89`, `toolbox/game-hub/game-hub.js:549`, `toolbox/game-hub/game-hub.js:550` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:697`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:713`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:716`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:724`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:749`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:771` |+| Role-focused Toolbox discovery | PASS | Toolbox role filters still include Game Hub where expected while hiding unavailable role-focused tools. | `tests/playwright/tools/GameHubMockRepository.spec.mjs:996`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1000`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1002`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1010`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1012`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1030` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:996`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1012`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1024`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1034` |++## Validation+- PASS: `npx playwright test tests/playwright/tools/GameHubMockRepository.spec.mjs --workers=1`+- Result: 14 passed, 0 failed.+- PASS: Inline-style/style-block report scan completed with no matches after reports were created.++## Artifact+- `tmp/PR_26175_ALFA_008-game-hub-feature-matrix_delta.zip`diff --git a/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md b/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.mdnew file mode 100644index 000000000..25f65acd6--- /dev/null+++ b/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md@@ -0,0 +1,15 @@+# PR_26175_ALFA_008-game-hub-feature-matrix Requirements Checklist++| Requirement | Status | Evidence |+| --- | --- | --- |+| Replace stale BUILD source of truth with ALFA_008 | PASS | `docs_build/dev/BUILD_PR.md:1` identifies `PR_26175_ALFA_008-game-hub-feature-matrix`. |+| Produce a Game Hub feature matrix only | PASS | `docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md` contains the feature matrix and no product source files were changed. |+| Audit Game Hub table workflow completion | PASS | Matrix rows cover Game table ownership, parent rows, selection affordance, add/create validation, edit, delete, child tables, guest gating, and error states. |+| Use current main behavior as evidence | PASS | Matrix evidence points to `toolbox/game-hub/index.html`, `toolbox/project-workspace/index.html`, `toolbox/game-hub/game-hub.js`, `toolbox/game-hub/game-hub-api-client.js`, `src/dev-runtime/persistence/tool-repositories/game-workspace-mock-repository.js`, and `tests/playwright/tools/GameHubMockRepository.spec.mjs`. |+| Preserve Game Hub UI/product behavior | PASS | No Game Hub product/UI/source implementation files were modified in this PR. |+| Preserve API/service/repository contracts | PASS | No API, service, or repository files were modified. Matrix records existing API/repository evidence without changing contracts. |+| Preserve previous ALFA cleanup and create validation behavior | PASS | Targeted Game Hub spec passed 14/14 tests, including ALFA_005 selector cleanup and ALFA_006 create-name validation assertions. |+| Do not add browser-owned product data as source of truth | PASS | No runtime/product JSON or browser-owned data contract files were modified. |+| Do not add inline styles, style blocks, or page-local CSS | PASS | ALFA_008 changes are docs/reports only, and the targeted style scan found no matches. |+| Create required reports | PASS | Report, validation lane, requirements checklist, review diff, and changed-files report are included. |+| Create repo-structured delta ZIP | PASS | `tmp/PR_26175_ALFA_008-game-hub-feature-matrix_delta.zip` was created after reports were finalized. |diff --git a/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md b/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.mdnew file mode 100644index 000000000..71a5ec416--- /dev/null+++ b/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md@@ -0,0 +1,11 @@+# PR_26175_ALFA_008-game-hub-feature-matrix Validation Lane++## Commands+| Command | Status | Evidence |+| --- | --- | --- |+| `npx playwright test tests/playwright/tools/GameHubMockRepository.spec.mjs --workers=1` | PASS | 14 passed, 0 failed. Covered deprecated route, create/open/delete, parent/child tables, guest save gating, empty state, unavailable state, active-game error state, malformed active-game payloads, purpose/status edits, readiness rows, wide Theme V2 layout, representative toolbox layout, Learn guidance, and member-role filters. |+| `rg -n "<[s]tyle|[s]tyle=" docs_build/dev/BUILD_PR.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md` | PASS | No inline style or style block matches in ALFA_008 changed docs/reports. |++## Notes+- Playwright updated shared coverage report outputs during validation; those generated files were restored because they are outside ALFA_008 exact targets.+- No product/UI/source implementation files were changed for this audit.diff --git a/docs_build/dev/reports/codex_changed_files.txt b/docs_build/dev/reports/codex_changed_files.txtindex 9dca38cd8..15aa8521d 100644--- a/docs_build/dev/reports/codex_changed_files.txt+++ b/docs_build/dev/reports/codex_changed_files.txt@@ -1,23 +1,6 @@-?.env.example-admin/infrastructure.html-admin/system-health.html-assets/theme-v2/js/admin-infrastructure.js-assets/theme-v2/js/admin-system-health.js-docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard.md-docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard_PLAN.md-docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard-instruction-compliance-checklist.md-docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard-manual-validation-notes.md-docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization.md-docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization_PLAN.md-docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization-instruction-compliance-checklist.md-docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization-manual-validation-notes.md-docs_build/dev/reports/PR_26175_CHARLIE_EOD-branch-validation.md-docs_build/dev/reports/PR_26175_CHARLIE_EOD-closeout.md-docs_build/dev/reports/PR_26175_CHARLIE_EOD-merge-summary.md-scripts/validate-storage-config.mjs-src/dev-runtime/server/local-api-router.mjs-src/dev-runtime/storage/storage-config.mjs-tests/dev-runtime/AdminHealthOperations.test.mjs-tests/dev-runtime/StorageConfig.test.mjs-tests/playwright/tools/AdminHealthOperationsPage.spec.mjs-tests/playwright/tools/AdminPlatformToolsWireframes.spec.mjs+docs_build/dev/BUILD_PR.md+docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md+docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md+docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md+docs_build/dev/reports/codex_review.diff+docs_build/dev/reports/codex_changed_files.txt \ No newline at end of file +diff --git a/assets/theme-v2/css/layout.css b/assets/theme-v2/css/layout.cssindex a9614b412..b392b3306 100644--- a/assets/theme-v2/css/layout.css+++ b/assets/theme-v2/css/layout.css@@ -733,7 +733,7 @@ body.tool-focus-mode .tool-workspace--table-scroll-focus .tool-table-scroll-regi .footer { margin-top: var(--space-46); border-top: var(--border-standard);- padding: var(--space-24) var(--space-0);+ padding: var(--space-0) var(--space-0) var(--space-24); color: var(--muted) } diff --git a/assets/theme-v2/css/status.css b/assets/theme-v2/css/status.cssindex 88e0d5e64..6acb4555b 100644--- a/assets/theme-v2/css/status.css+++ b/assets/theme-v2/css/status.css@@ -36,7 +36,10 @@ } .toolbox-status-bar {+ --toolbox-status-bar-height: var(--space-52);+ --toolbox-status-game-max: 220px; width: 100%;+ min-block-size: var(--toolbox-status-bar-height); border-block: var(--border-standard); background: var(--panel-overlay-strong); color: var(--text)@@ -47,7 +50,7 @@ margin: var(--space-0) auto; padding: var(--space-10) var(--space-0); display: grid;- grid-template-columns: minmax(var(--space-0), 1fr) minmax(var(--space-0), 2fr);+ grid-template-columns: minmax(var(--space-0), max-content) minmax(var(--space-0), 1fr); gap: var(--space-16); align-items: center }@@ -56,34 +59,18 @@ min-width: var(--space-0); display: flex; align-items: center;- flex-wrap: wrap;- gap: var(--space-14);+ justify-content: flex-start; text-align: left } -.toolbox-status-bar__field {- min-width: var(--space-0);- display: grid;- gap: var(--space-3)-}--.toolbox-status-bar__label {- color: var(--muted);- font-size: var(--font-size-xs);- font-weight: var(--font-weight-heavy);- letter-spacing: var(--letter-spacing-kicker);- text-transform: uppercase-}- .toolbox-status-bar__game-name { color: var(--text); font-size: var(--font-size-base);- overflow-wrap: anywhere-}--.toolbox-status-bar__purpose {- color: var(--muted);- font-size: var(--font-size-sm);+ line-height: var(--line-height-tight);+ max-width: min(30vw, var(--toolbox-status-game-max));+ overflow: hidden;+ text-overflow: ellipsis;+ white-space: nowrap; overflow-wrap: anywhere } @@ -92,25 +79,17 @@ display: flex; align-items: center; justify-content: center;- flex-wrap: wrap;- gap: var(--space-10);+ justify-self: center; text-align: center } -.toolbox-status-bar__context-type {- flex: 0 0 auto-}- .toolbox-status-bar__message { margin: var(--space-0); max-width: var(--measure-lg);+ line-height: var(--line-height-copy); overflow-wrap: anywhere } -.toolbox-status-bar__action {- flex: 0 0 auto-}- .toolbox-status-bar[data-selected-game-state="active"] { border-color: color-mix(in srgb, var(--green) 52%, var(--line)) }@@ -123,22 +102,6 @@ border-color: color-mix(in srgb, var(--red) 52%, var(--line)) } -.toolbox-status-bar[data-toolbox-status-context-kind="error"] .toolbox-status-bar__context-type {- border-color: color-mix(in srgb, var(--red) 62%, var(--line));- color: var(--red)-}--.toolbox-status-bar[data-toolbox-status-context-kind="warning"] .toolbox-status-bar__context-type,-.toolbox-status-bar[data-toolbox-status-context-kind="validation"] .toolbox-status-bar__context-type {- border-color: var(--gold-border-muted);- color: var(--gold)-}--.toolbox-status-bar[data-toolbox-status-context-kind="save"] .toolbox-status-bar__context-type {- border-color: color-mix(in srgb, var(--green) 62%, var(--line));- color: var(--green)-}- body.tool-focus-mode .toolbox-status-bar { position: fixed; inset-block-end: var(--space-0);@@ -148,6 +111,31 @@ body.tool-focus-mode .toolbox-status-bar { box-shadow: var(--shadow-md) } +body.tool-focus-mode {+ --toolbox-status-bar-height: var(--space-52);+ --toolbox-status-top-reserve: var(--space-0)+}++body.tool-focus-mode:has(.platform-banner) {+ --toolbox-status-top-reserve: var(--space-52)+}++body.tool-focus-mode .tool-workspace {+ box-sizing: border-box;+ height: calc(100vh - var(--toolbox-status-bar-height) - var(--toolbox-status-top-reserve));+ max-height: calc(100vh - var(--toolbox-status-bar-height) - var(--toolbox-status-top-reserve))+}++body.tool-focus-mode .tool-column {+ height: calc(100vh - var(--toolbox-status-bar-height) - var(--toolbox-status-top-reserve) - var(--space-20));+ max-height: calc(100vh - var(--toolbox-status-bar-height) - var(--toolbox-status-top-reserve) - var(--space-20))+}++body.tool-focus-mode .tool-center-panel {+ box-sizing: border-box;+ scroll-padding-block-end: var(--toolbox-status-bar-height)+}+ .platform-banner { width: 100%; border-bottom: var(--border-standard);@@ -261,12 +249,16 @@ body.tool-focus-mode .toolbox-status-bar { @media (max-width: 720px) { .toolbox-status-bar__inner { width: var(--container-width);- grid-template-columns: 1fr;+ grid-template-columns: minmax(var(--space-0), max-content) minmax(var(--space-0), 1fr);+ gap: var(--space-10); text-align: center } - .toolbox-status-bar__game {- justify-content: center;- text-align: center+ .toolbox-status-bar__game-name {+ max-width: 34vw+ }++ .toolbox-status-bar__message {+ font-size: var(--font-size-sm) } }diff --git a/assets/theme-v2/js/toolbox-status-bar.js b/assets/theme-v2/js/toolbox-status-bar.jsindex fdb367328..24c935311 100644--- a/assets/theme-v2/js/toolbox-status-bar.js+++ b/assets/theme-v2/js/toolbox-status-bar.js@@ -90,37 +90,16 @@ function createStatusBar() { game.className = "toolbox-status-bar__game"; game.dataset.toolboxSelectedGame = ""; - const nameField = document.createElement("div");- nameField.className = "toolbox-status-bar__field";- nameField.dataset.toolboxSelectedGameNameField = "";- const nameLabel = createText("span", "toolbox-status-bar__label", "toolboxSelectedGameNameLabel");- nameLabel.textContent = "Selected Game Name"; const name = createText("strong", "toolbox-status-bar__game-name", "toolboxSelectedGameName");- nameField.append(nameLabel, name);-- const purposeField = document.createElement("div");- purposeField.className = "toolbox-status-bar__field";- purposeField.dataset.toolboxSelectedGamePurposeField = "";- const purposeLabel = createText("span", "toolbox-status-bar__label", "toolboxSelectedGamePurposeLabel");- purposeLabel.textContent = "Selected Game Purpose";- const purpose = createText("span", "toolbox-status-bar__purpose", "toolboxSelectedGamePurpose");- purpose.dataset.toolboxSelectedGameMeta = "";- purposeField.append(purposeLabel, purpose);- game.append(nameField, purposeField);+ game.append(name); const center = document.createElement("div"); center.className = "toolbox-status-bar__center"; center.dataset.toolboxStatusCenter = ""; - const contextType = createText("span", "pill toolbox-status-bar__context-type", "toolboxStatusContextType"); const message = createText("p", "toolbox-status-bar__message status", "toolboxStatusMessage"); message.setAttribute("role", "status");- const action = document.createElement("a");- action.className = "btn btn--compact toolbox-status-bar__action";- action.dataset.toolboxStatusAction = "";- action.href = mountOptions.gameHubHref;- action.textContent = "Open Game Hub";- center.append(contextType, message, action);+ center.append(message); inner.append(game, center); bar.append(inner);@@ -234,33 +213,30 @@ function publishSelectedGameContext(selectedGame, state) { function classifyToolContext(messageText, state, required) { const text = String(messageText || "").trim(); if (state === "error") {- return { kind: "error", label: "Error" };+ return { kind: "error" }; } if (required && state === "missing") {- return { kind: "action", label: "Tool Action" };+ return { kind: "action" }; } if (/\b(error|failed|malformed|unavailable|could not)\b/i.test(text)) {- return { kind: "error", label: "Error" };+ return { kind: "error" }; } if (/\b(sign in|refresh|try again|temporarily|blocked)\b/i.test(text)) {- return { kind: "warning", label: "Warning" };+ return { kind: "warning" }; } if (/\b(validation|requirement|requirements|missing|required|open or seed)\b/i.test(text)) {- return { kind: "validation", label: "Validation" };+ return { kind: "validation" }; } if (/\b(saved|created|deleted|updated|loaded|save changes)\b/i.test(text)) {- return { kind: "save", label: "Save State" };+ return { kind: "save" }; }- return { kind: "action", label: "Tool Action" };+ return { kind: "action" }; } function renderSelectedGame(bar, selectedGame, state, messageText) { const required = pageRequiresSelectedGame(); const name = bar.querySelector("[data-toolbox-selected-game-name]");- const purpose = bar.querySelector("[data-toolbox-selected-game-purpose]");- const contextType = bar.querySelector("[data-toolbox-status-context-type]"); const message = bar.querySelector("[data-toolbox-status-message]");- const action = bar.querySelector("[data-toolbox-status-action]"); const nextMessage = messageText || latestToolMessage || (selectedGame ? `Tool context is filtered to ${selectedGame.name}.` : required@@ -271,38 +247,27 @@ function renderSelectedGame(bar, selectedGame, state, messageText) { bar.dataset.selectedGameState = state; bar.dataset.selectedGameRequired = String(required); bar.dataset.toolboxStatusContextKind = context.kind;- contextType.textContent = context.label;- action.hidden = false;- action.href = mountOptions.gameHubHref; if (selectedGame) { name.textContent = selectedGame.name;- purpose.textContent = selectedGame.purpose || "Game"; message.textContent = nextMessage;- action.textContent = "Open Game Hub"; return; } if (!required) { name.textContent = "No game selected";- purpose.textContent = "Idea Board optional"; message.textContent = nextMessage;- action.textContent = "Open Game Hub"; return; } if (state === "error") { name.textContent = "Unavailable";- purpose.textContent = "Game Hub selected game could not be read"; message.textContent = nextMessage;- action.textContent = "Open Game Hub"; return; } name.textContent = "No game selected";- purpose.textContent = "Game Hub owns game selection"; message.textContent = "Select or create a game in Game Hub before using this toolbox page.";- action.textContent = "Select or Create in Game Hub"; } export function refreshToolboxStatusBar() {diff --git a/docs_build/dev/BUILD_PR.md b/docs_build/dev/BUILD_PR.mdindex dd5b4d28f..0778a1f1e 100644--- a/docs_build/dev/BUILD_PR.md+++ b/docs_build/dev/BUILD_PR.md@@ -1,63 +1,70 @@-# PR_26175_ALFA_008-game-hub-feature-matrix+# PR_26175_ALFA_009-status-bar-single-row-rebuild ## Purpose-Audit the current Game Hub workflow and publish a feature matrix that maps implemented creator-facing behavior to code and Playwright evidence.+Rebuild the shared toolbox status bar on current `main` so it is a single-row creator context bar. ## Source Of Truth-This `BUILD_PR.md` is the source of truth for `PR_26175_ALFA_008-game-hub-feature-matrix`.+This `BUILD_PR.md` is the source of truth for `PR_26175_ALFA_009-status-bar-single-row-rebuild`. ## Exact Scope-- Produce a Game Hub feature matrix only.-- Audit Game Hub table workflow, selected/open game behavior, create/edit/delete actions, child tables, guest save gating, empty/error states, Theme V2 layout, and targeted Game Hub coverage.-- Use current `main` behavior as evidence.-- Preserve Game Hub UI/product behavior.-- Preserve API/service/repository contracts.-- Preserve previous ALFA Game Hub cleanup and create-validation behavior.-- Do not implement product/UI changes unless validation exposes a requirement-critical defect.+- Display only the selected Game Hub game name on the left side of the toolbox status bar.+- Display only the current status message in the center of the toolbox status bar.+- Remove visible status bar labels: `Selected Game Name`, `Selected Game Purpose`, `Save State`, `Tool Action`, `Warning`, and `Error`.+- Remove selected-game purpose from the visible status bar.+- Preserve normal status bar placement above the footer.+- Remove extra status bar/footer spacing so the shared footer top padding resolves to `0px`.+- Preserve fullscreen/tool display mode bottom anchoring.+- Ensure fullscreen center scrollable content stops above the fixed status bar.+- Ensure fullscreen tool content is not hidden behind the status bar.+- Preserve Idea Board selected-game filtering exclusion.+- Preserve Game Hub as selected-game owner through the existing repository contract.+- Use shared Theme V2 CSS/classes only.+- Update targeted Playwright coverage for the single-row status bar, footer spacing, and fullscreen bottom reserve. ## Exact Targets - `docs_build/dev/BUILD_PR.md`-- `docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md`-- `docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md`-- `docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md`+- `assets/theme-v2/js/toolbox-status-bar.js`+- `assets/theme-v2/css/status.css`+- `assets/theme-v2/css/layout.css`+- `tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs`+- `docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_report.md`+- `docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_validation-lane.md`+- `docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_requirements-checklist.md` - `docs_build/dev/reports/codex_review.diff` - `docs_build/dev/reports/codex_changed_files.txt` -## Evidence Sources-- `toolbox/game-hub/index.html`-- `toolbox/project-workspace/index.html`-- `toolbox/game-hub/game-hub.js`-- `toolbox/game-hub/game-hub-api-client.js`-- `src/dev-runtime/persistence/tool-repositories/game-workspace-mock-repository.js`-- `tests/playwright/tools/GameHubMockRepository.spec.mjs`- ## Out Of Scope-- No Game Hub product or UI changes.-- No Game Journey changes.-- No shared toolbox status bar changes.-- No browser-owned product data as source of truth.+- No merge of PR #120.+- No reuse of stale ALFA_003 branch.+- No environment/server details in the status bar.+- No selected game purpose in the visible status bar.+- No visible status category labels in the status bar.+- No status action links in the visible status bar.+- No large banners.+- No modal messages or modal-style status messages.+- No row highlights. - No API/service/repository contract changes.+- No browser-owned product data as source of truth. - No inline styles, style blocks, or page-local CSS. - No engine core changes. - No `start_of_day` folder changes.-- No ALFA_007 work. ## Validation-Run targeted Game Hub validation:+Run targeted Playwright coverage: ```powershell-npx playwright test tests/playwright/tools/GameHubMockRepository.spec.mjs --workers=1+npx playwright test tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs --workers=1 ``` -Also verify changed docs/reports do not introduce inline styles or style blocks:+Also verify changed source does not introduce inline styles or style blocks: ```powershell-rg -n "<[s]tyle|[s]tyle=" docs_build/dev/BUILD_PR.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md+rg -n "<[s]tyle|[s]tyle=" assets/theme-v2/js/toolbox-status-bar.js assets/theme-v2/css/status.css assets/theme-v2/css/layout.css tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs ``` ## Artifact Create repo-structured delta ZIP: ```text-tmp/PR_26175_ALFA_008-game-hub-feature-matrix_delta.zip+tmp/PR_26175_ALFA_009-status-bar-single-row-rebuild_delta.zip ```diff --git a/docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_report.md b/docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_report.mdnew file mode 100644index 000000000..e23234978--- /dev/null+++ b/docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_report.md@@ -0,0 +1,32 @@+# PR_26175_ALFA_009-status-bar-single-row-rebuild Report++## Overall Status+PASS++## Summary+ALFA_009 rebuilds the shared toolbox status bar from current clean `main` without merging PR #120 or reusing the stale ALFA_003 branch. The status bar now exposes a single visible row with selected game name on the left and the current status message centered.++## Changes+- Replaced the status bar DOM with only the selected game name and status message as visible content.+- Removed visible status labels: `Selected Game Name`, `Selected Game Purpose`, `Save State`, `Tool Action`, `Warning`, and `Error`.+- Removed selected-game purpose and visible status action links from the status bar.+- Kept status context classification as non-visible dataset state for shared styling and behavior.+- Set shared Theme V2 footer top padding to `0px` while preserving bottom padding.+- Added shared fullscreen reserves so the fixed bottom status bar does not cover the center tool area.+- Preserved Game Hub selected-game ownership and Idea Board selected-game filtering exclusion.+- Updated targeted Playwright coverage for removed labels, visible game/message text, same-row layout, footer top padding, and fullscreen center-panel bounds.++## Files Changed+- `assets/theme-v2/js/toolbox-status-bar.js`+- `assets/theme-v2/css/status.css`+- `assets/theme-v2/css/layout.css`+- `tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs`+- `docs_build/dev/BUILD_PR.md`+- ALFA_009 reports and Codex diff/change reports++## Validation+- PASS: `npx playwright test tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs --workers=1` produced 6 passed, 0 failed after the fullscreen reserve correction.+- PASS: `rg -n "<[s]tyle|[s]tyle=" assets/theme-v2/js/toolbox-status-bar.js assets/theme-v2/css/status.css assets/theme-v2/css/layout.css tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs` returned no matches.++## Artifact+- `tmp/PR_26175_ALFA_009-status-bar-single-row-rebuild_delta.zip`diff --git a/docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_requirements-checklist.md b/docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_requirements-checklist.mdnew file mode 100644index 000000000..2e9aa4b1e--- /dev/null+++ b/docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_requirements-checklist.md@@ -0,0 +1,19 @@+# PR_26175_ALFA_009-status-bar-single-row-rebuild Requirements Checklist++| Requirement | Status | Evidence |+| --- | --- | --- |+| Start from clean synced `main` at `d9724b19b3f384aed1a082c3461ece4c16fe0f12` | PASS | Guardrail checks passed before branch creation: branch `main`, clean worktree, sync `0/0`, requested commit. |+| Do not merge PR #120 | PASS | ALFA_009 was rebuilt on a fresh branch from `main`; no PR #120 merge was performed. |+| Do not reuse stale ALFA_003 branch | PASS | Work was done on `codex/pr-26175-alfa-009-status-bar-single-row-rebuild`. |+| Status bar displays only selected game name on left and status message in center | PASS | `toolbox-status-bar.js` renders only `[data-toolbox-selected-game-name]` and `[data-toolbox-status-message]` as visible bar content. |+| Remove visible labels | PASS | Playwright asserts the status bar does not contain `Selected Game Name`, `Selected Game Purpose`, `Save State`, `Tool Action`, `Warning`, or `Error`. |+| Remove selected-game purpose from visible status bar | PASS | Purpose DOM is removed and Playwright asserts `[data-toolbox-selected-game-purpose]` has count `0`. |+| Remove extra footer top gap and make footer top padding resolve to `0px` | PASS | Shared `.footer` padding now starts at `var(--space-0)`, and Playwright verifies computed footer top padding is `0`. |+| Use shared Theme V2 styling | PASS | Changes are in `assets/theme-v2/css/status.css` and `assets/theme-v2/css/layout.css`; no inline styles or page-local CSS were added. |+| Preserve fullscreen bottom anchoring | PASS | Playwright verifies the status bar is fixed and bottom gap is within 2px in tool display mode. |+| Center scrollable content stops above status bar | PASS | Playwright verifies `.tool-center-panel` bottom is above the status bar top in tool display mode. |+| No content hidden behind status bar | PASS | Fullscreen workspace and columns reserve the platform banner and status bar height in shared CSS. |+| Preserve Idea Board exclusion | PASS | Playwright verifies Idea Board remains optional and does not show the missing-game prompt. |+| Preserve Game Hub selected-game ownership | PASS | Status bar still reads selected game through the existing Game Hub repository client; no API/service contract changes were made. |+| Update targeted Playwright coverage | PASS | `tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs` was updated and passed. |+| Produce required reports and ZIP | PASS | ALFA_009 report, validation lane, checklist, Codex reports, and delta ZIP were created. |diff --git a/docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_validation-lane.md b/docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_validation-lane.mdnew file mode 100644index 000000000..0ec6d65af--- /dev/null+++ b/docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_validation-lane.md@@ -0,0 +1,12 @@+# PR_26175_ALFA_009-status-bar-single-row-rebuild Validation Lane++## Commands+| Command | Status | Evidence |+| --- | --- | --- |+| `npx playwright test tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs --workers=1` | PASS | Final run passed 6/6 tests. Coverage includes normal placement above footer, no visible removed labels, no visible purpose, save message updates, fullscreen bottom anchoring, center panel bottom above status bar, Game Hub selection updates, missing-game prompt, and Idea Board exclusion. |+| `rg -n "<[s]tyle|[s]tyle=" assets/theme-v2/js/toolbox-status-bar.js assets/theme-v2/css/status.css assets/theme-v2/css/layout.css tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs` | PASS | No inline style or style block matches. |++## Notes+- An interim Playwright run failed the fullscreen center-panel bound assertion. The failure showed the center panel still extended below the fixed status bar.+- The final fix adds shared Theme V2 top and bottom reserves in `assets/theme-v2/css/status.css`, including the platform banner reserve used in tool display mode.+- Playwright-generated coverage reports were restored because they are outside ALFA_009 exact targets.diff --git a/docs_build/dev/reports/codex_changed_files.txt b/docs_build/dev/reports/codex_changed_files.txtindex 15aa8521d..25b28f9ba 100644--- a/docs_build/dev/reports/codex_changed_files.txt+++ b/docs_build/dev/reports/codex_changed_files.txt@@ -1,6 +1,10 @@ docs_build/dev/BUILD_PR.md-docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md-docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md-docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md+assets/theme-v2/js/toolbox-status-bar.js+assets/theme-v2/css/status.css+assets/theme-v2/css/layout.css+tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs+docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_report.md+docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_validation-lane.md+docs_build/dev/reports/PR_26175_ALFA_009-status-bar-single-row-rebuild_requirements-checklist.md docs_build/dev/reports/codex_review.diff docs_build/dev/reports/codex_changed_files.txtdiff --git a/tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs b/tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjsindex 065fbce4a..1a40d61c5 100644--- a/tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs+++ b/tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs@@ -113,20 +113,57 @@ function creatorSession() { }; } +const REMOVED_STATUS_BAR_LABELS = [+ "Selected Game Name",+ "Selected Game Purpose",+ "Save State",+ "Tool Action",+ "Warning",+ "Error",+];++async function expectRemovedStatusBarLabelsHidden(statusBar) {+ for (const label of REMOVED_STATUS_BAR_LABELS) {+ await expect(statusBar).not.toContainText(label);+ }+}+ async function statusBarSnapshot(page) { return page.locator("[data-toolbox-status-bar]").evaluate((bar) => {+ const boxSnapshot = (element) => {+ const box = element?.getBoundingClientRect();+ if (!box) {+ return null;+ }+ return {+ bottom: box.bottom,+ height: box.height,+ left: box.left,+ right: box.right,+ top: box.top,+ };+ }; const footer = document.querySelector("footer.footer");+ const footerStyle = footer ? getComputedStyle(footer) : null;+ const centerPanel = document.querySelector(".tool-center-panel");+ const gameName = bar.querySelector("[data-toolbox-selected-game-name]");+ const message = bar.querySelector("[data-toolbox-status-message]"); const position = getComputedStyle(bar).position; const barBox = bar.getBoundingClientRect(); const footerBox = footer?.getBoundingClientRect(); return { bottomGap: Math.round(window.innerHeight - barBox.bottom),+ barBox: boxSnapshot(bar),+ centerPanelBox: boxSnapshot(centerPanel), dataset: { ...bar.dataset }, filter: document.body.dataset.toolboxSelectedGameFilter || "", footerFollowsBar: footer ? Boolean(bar.compareDocumentPosition(footer) & Node.DOCUMENT_POSITION_FOLLOWING) : false,+ footerPaddingTop: footerStyle ? parseFloat(footerStyle.paddingTop) || 0 : null, gameId: document.body.dataset.toolboxSelectedGameId || "",- gameText: bar.querySelector("[data-toolbox-selected-game]")?.textContent.replace(/\s+/g, " ").trim() || "",- messageText: bar.querySelector("[data-toolbox-status-center]")?.textContent.replace(/\s+/g, " ").trim() || "",+ gameBox: boxSnapshot(gameName),+ gameText: gameName?.textContent.replace(/\s+/g, " ").trim() || "",+ messageBox: boxSnapshot(message),+ messageText: message?.textContent.replace(/\s+/g, " ").trim() || "", position, topBeforeFooter: footerBox ? barBox.bottom <= footerBox.top + 1 : false, };@@ -141,12 +178,12 @@ test("shared toolbox status bar shows selected Game Hub game above the footer", await expect(statusBar).toBeVisible(); await expect(page.locator("style, [style], script:not([src])")).toHaveCount(0); await expect(statusBar).not.toContainText("Environment");- await expect(statusBar.locator("[data-toolbox-selected-game-name-label]")).toHaveText("Selected Game Name");+ await expectRemovedStatusBarLabelsHidden(statusBar); await expect(statusBar.locator("[data-toolbox-selected-game-name]")).toHaveText("Demo Game");- await expect(statusBar.locator("[data-toolbox-selected-game-purpose-label]")).toHaveText("Selected Game Purpose");- await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveText("Game");+ await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveCount(0);+ await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveCount(0);+ await expect(statusBar.locator("[data-toolbox-status-action]")).toHaveCount(0); await expect(statusBar.locator("[data-toolbox-selected-game]")).not.toContainText("Under Construction");- await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveText("Tool Action"); await expect(statusBar.locator("[data-toolbox-status-message]")).toContainText("Game Design mock repository ready."); await expect(page.locator("body")).toHaveAttribute("data-toolbox-selected-game-id", "demo-game"); await expect(page.locator("body")).toHaveAttribute("data-toolbox-selected-game-filter", "active");@@ -154,9 +191,15 @@ test("shared toolbox status bar shows selected Game Hub game above the footer", const snapshot = await statusBarSnapshot(page); expect(snapshot.footerFollowsBar).toBe(true); expect(snapshot.topBeforeFooter).toBe(true);+ expect(snapshot.footerPaddingTop).toBe(0); expect(snapshot.position).not.toBe("fixed"); expect(snapshot.dataset.selectedGameState).toBe("active"); expect(snapshot.dataset.selectedGameRequired).toBe("true");+ expect(snapshot.gameText).toBe("Demo Game");+ expect(snapshot.messageText).toContain("Game Design mock repository ready.");+ expect(Math.max(snapshot.gameBox.top, snapshot.messageBox.top)).toBeLessThanOrEqual(+ Math.min(snapshot.gameBox.bottom, snapshot.messageBox.bottom),+ ); expectNoPageFailures(failures); } finally {@@ -175,11 +218,14 @@ test("shared toolbox status bar center reports save state after Game Hub saves", await addGameRow.getByLabel("Status").selectOption("Ready for Testing"); await addGameRow.getByRole("button", { name: "Save" }).click(); - await expect(page.locator("[data-toolbox-status-context-type]")).toHaveText("Save State");- await expect(page.locator("[data-toolbox-status-message]")).toHaveText("Created and opened Status Bar Save.");- await expect(page.locator("[data-toolbox-selected-game-name]")).toHaveText("Status Bar Save");- await expect(page.locator("[data-toolbox-selected-game-purpose]")).toHaveText("Learning Game");- await expect(page.locator("[data-toolbox-status-bar]")).not.toContainText("Environment");+ const statusBar = page.locator("[data-toolbox-status-bar]");+ await expectRemovedStatusBarLabelsHidden(statusBar);+ await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveCount(0);+ await expect(statusBar.locator("[data-toolbox-status-message]")).toHaveText("Created and opened Status Bar Save.");+ await expect(statusBar.locator("[data-toolbox-selected-game-name]")).toHaveText("Status Bar Save");+ await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveCount(0);+ await expect(statusBar).not.toContainText("Learning Game");+ await expect(statusBar).not.toContainText("Environment"); expectNoPageFailures(failures); } finally {@@ -198,7 +244,9 @@ test("shared toolbox status bar anchors to the bottom in tool display mode", asy const snapshot = await statusBarSnapshot(page); expect(snapshot.position).toBe("fixed"); expect(Math.abs(snapshot.bottomGap)).toBeLessThanOrEqual(2);- expect(snapshot.gameText).toContain("Demo Game");+ expect(snapshot.gameText).toBe("Demo Game");+ expect(snapshot.messageText).toContain("Game Design mock repository ready.");+ expect(snapshot.centerPanelBox.bottom).toBeLessThanOrEqual(snapshot.barBox.top + 1); expectNoPageFailures(failures); } finally {@@ -213,12 +261,15 @@ test("Game Hub owner selection updates the global toolbox status bar", async ({ await expect(page.locator("[data-toolbox-selected-game-name]")).toHaveText("Demo Game"); await page.locator("[data-game-toggle='gravity-demo']").click(); await expect(page.locator("[data-toolbox-selected-game-name]")).toHaveText("Gravity Demo");- await expect(page.locator("[data-toolbox-selected-game-purpose]")).toHaveText("Capability Demo");- await expect(page.locator("[data-toolbox-selected-game]")).not.toContainText("Wireframe");+ const statusBar = page.locator("[data-toolbox-status-bar]");+ await expectRemovedStatusBarLabelsHidden(statusBar);+ await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveCount(0);+ await expect(statusBar.locator("[data-toolbox-selected-game]")).not.toContainText("Capability Demo");+ await expect(statusBar.locator("[data-toolbox-selected-game]")).not.toContainText("Wireframe"); await expect(page.locator("body")).toHaveAttribute("data-toolbox-selected-game-id", "gravity-demo"); await expect(page.locator("body")).toHaveAttribute("data-toolbox-selected-game-filter", "active");- await expect(page.locator("[data-toolbox-status-context-type]")).toHaveText("Warning");- await expect(page.locator("[data-toolbox-status-message]")).toContainText("Sign in to create or update Game Hub projects.");+ await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveCount(0);+ await expect(statusBar.locator("[data-toolbox-status-message]")).toContainText("Sign in to create or update Game Hub projects."); expectNoPageFailures(failures); } finally {@@ -231,12 +282,12 @@ test("non-Idea Board toolbox pages show a creator-safe prompt when no Game Hub g try { const statusBar = page.locator("[data-toolbox-status-bar]");+ await expectRemovedStatusBarLabelsHidden(statusBar); await expect(statusBar.locator("[data-toolbox-selected-game-name]")).toHaveText("No game selected");- await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveText("Game Hub owns game selection");- await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveText("Tool Action");+ await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveCount(0);+ await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveCount(0); await expect(statusBar.locator("[data-toolbox-status-message]")).toHaveText("Select or create a game in Game Hub before using this toolbox page.");- await expect(statusBar.locator("[data-toolbox-status-action]")).toHaveText("Select or Create in Game Hub");- await expect(statusBar.locator("[data-toolbox-status-action]")).toHaveAttribute("href", /toolbox\/game-hub\/index\.html$/);+ await expect(statusBar.locator("[data-toolbox-status-action]")).toHaveCount(0); await expect(page.locator("body")).toHaveAttribute("data-toolbox-selected-game-filter", "missing"); await expect(page.locator("body")).not.toHaveAttribute("data-toolbox-selected-game-id", /.+/); @@ -256,9 +307,10 @@ test("Idea Board is excluded from selected-game filtering and does not show the try { const statusBar = page.locator("[data-toolbox-status-bar]"); await expect(statusBar).toBeVisible();+ await expectRemovedStatusBarLabelsHidden(statusBar); await expect(statusBar.locator("[data-toolbox-selected-game-name]")).toHaveText("No game selected");- await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveText("Idea Board optional");- await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveText("Tool Action");+ await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveCount(0);+ await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveCount(0); await expect(statusBar.locator("[data-toolbox-status-message]")).toContainText("Ready to shape ideas and notes."); await expect(statusBar.locator("[data-toolbox-status-message]")).not.toContainText("Select or create a game"); await expect(page.locator("body")).toHaveAttribute("data-toolbox-selected-game-filter", "optional"); \ No newline at end of file diff --git a/tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs b/tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs index 065fbce4a..1a40d61c5 100644 --- a/tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs +++ b/tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs @@ -113,20 +113,57 @@ function creatorSession() { }; } +const REMOVED_STATUS_BAR_LABELS = [ + "Selected Game Name", + "Selected Game Purpose", + "Save State", + "Tool Action", + "Warning", + "Error", +]; + +async function expectRemovedStatusBarLabelsHidden(statusBar) { + for (const label of REMOVED_STATUS_BAR_LABELS) { + await expect(statusBar).not.toContainText(label); + } +} + async function statusBarSnapshot(page) { return page.locator("[data-toolbox-status-bar]").evaluate((bar) => { + const boxSnapshot = (element) => { + const box = element?.getBoundingClientRect(); + if (!box) { + return null; + } + return { + bottom: box.bottom, + height: box.height, + left: box.left, + right: box.right, + top: box.top, + }; + }; const footer = document.querySelector("footer.footer"); + const footerStyle = footer ? getComputedStyle(footer) : null; + const centerPanel = document.querySelector(".tool-center-panel"); + const gameName = bar.querySelector("[data-toolbox-selected-game-name]"); + const message = bar.querySelector("[data-toolbox-status-message]"); const position = getComputedStyle(bar).position; const barBox = bar.getBoundingClientRect(); const footerBox = footer?.getBoundingClientRect(); return { bottomGap: Math.round(window.innerHeight - barBox.bottom), + barBox: boxSnapshot(bar), + centerPanelBox: boxSnapshot(centerPanel), dataset: { ...bar.dataset }, filter: document.body.dataset.toolboxSelectedGameFilter || "", footerFollowsBar: footer ? Boolean(bar.compareDocumentPosition(footer) & Node.DOCUMENT_POSITION_FOLLOWING) : false, + footerPaddingTop: footerStyle ? parseFloat(footerStyle.paddingTop) || 0 : null, gameId: document.body.dataset.toolboxSelectedGameId || "", - gameText: bar.querySelector("[data-toolbox-selected-game]")?.textContent.replace(/\s+/g, " ").trim() || "", - messageText: bar.querySelector("[data-toolbox-status-center]")?.textContent.replace(/\s+/g, " ").trim() || "", + gameBox: boxSnapshot(gameName), + gameText: gameName?.textContent.replace(/\s+/g, " ").trim() || "", + messageBox: boxSnapshot(message), + messageText: message?.textContent.replace(/\s+/g, " ").trim() || "", position, topBeforeFooter: footerBox ? barBox.bottom <= footerBox.top + 1 : false, }; @@ -141,12 +178,12 @@ test("shared toolbox status bar shows selected Game Hub game above the footer", await expect(statusBar).toBeVisible(); await expect(page.locator("style, [style], script:not([src])")).toHaveCount(0); await expect(statusBar).not.toContainText("Environment"); - await expect(statusBar.locator("[data-toolbox-selected-game-name-label]")).toHaveText("Selected Game Name"); + await expectRemovedStatusBarLabelsHidden(statusBar); await expect(statusBar.locator("[data-toolbox-selected-game-name]")).toHaveText("Demo Game"); - await expect(statusBar.locator("[data-toolbox-selected-game-purpose-label]")).toHaveText("Selected Game Purpose"); - await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveText("Game"); + await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveCount(0); + await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveCount(0); + await expect(statusBar.locator("[data-toolbox-status-action]")).toHaveCount(0); await expect(statusBar.locator("[data-toolbox-selected-game]")).not.toContainText("Under Construction"); - await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveText("Tool Action"); await expect(statusBar.locator("[data-toolbox-status-message]")).toContainText("Game Design mock repository ready."); await expect(page.locator("body")).toHaveAttribute("data-toolbox-selected-game-id", "demo-game"); await expect(page.locator("body")).toHaveAttribute("data-toolbox-selected-game-filter", "active"); @@ -154,9 +191,15 @@ test("shared toolbox status bar shows selected Game Hub game above the footer", const snapshot = await statusBarSnapshot(page); expect(snapshot.footerFollowsBar).toBe(true); expect(snapshot.topBeforeFooter).toBe(true); + expect(snapshot.footerPaddingTop).toBe(0); expect(snapshot.position).not.toBe("fixed"); expect(snapshot.dataset.selectedGameState).toBe("active"); expect(snapshot.dataset.selectedGameRequired).toBe("true"); + expect(snapshot.gameText).toBe("Demo Game"); + expect(snapshot.messageText).toContain("Game Design mock repository ready."); + expect(Math.max(snapshot.gameBox.top, snapshot.messageBox.top)).toBeLessThanOrEqual( + Math.min(snapshot.gameBox.bottom, snapshot.messageBox.bottom), + ); expectNoPageFailures(failures); } finally { @@ -175,11 +218,14 @@ test("shared toolbox status bar center reports save state after Game Hub saves", await addGameRow.getByLabel("Status").selectOption("Ready for Testing"); await addGameRow.getByRole("button", { name: "Save" }).click(); - await expect(page.locator("[data-toolbox-status-context-type]")).toHaveText("Save State"); - await expect(page.locator("[data-toolbox-status-message]")).toHaveText("Created and opened Status Bar Save."); - await expect(page.locator("[data-toolbox-selected-game-name]")).toHaveText("Status Bar Save"); - await expect(page.locator("[data-toolbox-selected-game-purpose]")).toHaveText("Learning Game"); - await expect(page.locator("[data-toolbox-status-bar]")).not.toContainText("Environment"); + const statusBar = page.locator("[data-toolbox-status-bar]"); + await expectRemovedStatusBarLabelsHidden(statusBar); + await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveCount(0); + await expect(statusBar.locator("[data-toolbox-status-message]")).toHaveText("Created and opened Status Bar Save."); + await expect(statusBar.locator("[data-toolbox-selected-game-name]")).toHaveText("Status Bar Save"); + await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveCount(0); + await expect(statusBar).not.toContainText("Learning Game"); + await expect(statusBar).not.toContainText("Environment"); expectNoPageFailures(failures); } finally { @@ -198,7 +244,9 @@ test("shared toolbox status bar anchors to the bottom in tool display mode", asy const snapshot = await statusBarSnapshot(page); expect(snapshot.position).toBe("fixed"); expect(Math.abs(snapshot.bottomGap)).toBeLessThanOrEqual(2); - expect(snapshot.gameText).toContain("Demo Game"); + expect(snapshot.gameText).toBe("Demo Game"); + expect(snapshot.messageText).toContain("Game Design mock repository ready."); + expect(snapshot.centerPanelBox.bottom).toBeLessThanOrEqual(snapshot.barBox.top + 1); expectNoPageFailures(failures); } finally { @@ -213,12 +261,15 @@ test("Game Hub owner selection updates the global toolbox status bar", async ({ await expect(page.locator("[data-toolbox-selected-game-name]")).toHaveText("Demo Game"); await page.locator("[data-game-toggle='gravity-demo']").click(); await expect(page.locator("[data-toolbox-selected-game-name]")).toHaveText("Gravity Demo"); - await expect(page.locator("[data-toolbox-selected-game-purpose]")).toHaveText("Capability Demo"); - await expect(page.locator("[data-toolbox-selected-game]")).not.toContainText("Wireframe"); + const statusBar = page.locator("[data-toolbox-status-bar]"); + await expectRemovedStatusBarLabelsHidden(statusBar); + await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveCount(0); + await expect(statusBar.locator("[data-toolbox-selected-game]")).not.toContainText("Capability Demo"); + await expect(statusBar.locator("[data-toolbox-selected-game]")).not.toContainText("Wireframe"); await expect(page.locator("body")).toHaveAttribute("data-toolbox-selected-game-id", "gravity-demo"); await expect(page.locator("body")).toHaveAttribute("data-toolbox-selected-game-filter", "active"); - await expect(page.locator("[data-toolbox-status-context-type]")).toHaveText("Warning"); - await expect(page.locator("[data-toolbox-status-message]")).toContainText("Sign in to create or update Game Hub projects."); + await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveCount(0); + await expect(statusBar.locator("[data-toolbox-status-message]")).toContainText("Sign in to create or update Game Hub projects."); expectNoPageFailures(failures); } finally { @@ -231,12 +282,12 @@ test("non-Idea Board toolbox pages show a creator-safe prompt when no Game Hub g try { const statusBar = page.locator("[data-toolbox-status-bar]"); + await expectRemovedStatusBarLabelsHidden(statusBar); await expect(statusBar.locator("[data-toolbox-selected-game-name]")).toHaveText("No game selected"); - await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveText("Game Hub owns game selection"); - await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveText("Tool Action"); + await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveCount(0); + await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveCount(0); await expect(statusBar.locator("[data-toolbox-status-message]")).toHaveText("Select or create a game in Game Hub before using this toolbox page."); - await expect(statusBar.locator("[data-toolbox-status-action]")).toHaveText("Select or Create in Game Hub"); - await expect(statusBar.locator("[data-toolbox-status-action]")).toHaveAttribute("href", /toolbox\/game-hub\/index\.html$/); + await expect(statusBar.locator("[data-toolbox-status-action]")).toHaveCount(0); await expect(page.locator("body")).toHaveAttribute("data-toolbox-selected-game-filter", "missing"); await expect(page.locator("body")).not.toHaveAttribute("data-toolbox-selected-game-id", /.+/); @@ -256,9 +307,10 @@ test("Idea Board is excluded from selected-game filtering and does not show the try { const statusBar = page.locator("[data-toolbox-status-bar]"); await expect(statusBar).toBeVisible(); + await expectRemovedStatusBarLabelsHidden(statusBar); await expect(statusBar.locator("[data-toolbox-selected-game-name]")).toHaveText("No game selected"); - await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveText("Idea Board optional"); - await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveText("Tool Action"); + await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveCount(0); + await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveCount(0); await expect(statusBar.locator("[data-toolbox-status-message]")).toContainText("Ready to shape ideas and notes."); await expect(statusBar.locator("[data-toolbox-status-message]")).not.toContainText("Select or create a game"); await expect(page.locator("body")).toHaveAttribute("data-toolbox-selected-game-filter", "optional");