From cd38b098e9094e0f034a02d4fa39ce3455196095 Mon Sep 17 00:00:00 2001 From: Charlie Team <97194984+ToolboxAid@users.noreply.github.com> Date: Wed, 24 Jun 2026 14:33:00 -0400 Subject: [PATCH 1/2] PR_26175_CHARLIE_010-system-health-history-and-closeout --- admin/system-health.html | 18 +++++ assets/theme-v2/js/admin-system-health.js | 42 +++++++++++ ..._010-system-health-history-and-closeout.md | 68 +++++++++++++++++ .../reports/coverage_changed_js_guardrail.txt | 2 +- .../reports/playwright_v8_coverage_report.txt | 6 +- src/dev-runtime/server/local-api-router.mjs | 73 +++++++++++++++++++ .../AdminHealthOperations.test.mjs | 8 ++ .../tools/AdminHealthOperationsPage.spec.mjs | 14 ++++ 8 files changed, 227 insertions(+), 4 deletions(-) create mode 100644 docs_build/dev/reports/PR_26175_CHARLIE_010-system-health-history-and-closeout.md diff --git a/admin/system-health.html b/admin/system-health.html index 9d251340f..8573b3310 100644 --- a/admin/system-health.html +++ b/admin/system-health.html @@ -43,6 +43,7 @@

Admin

Local API Startup

Database Health

Storage Health

+

Health Check History

Runtime Environment

Limits & Capacity

Diagnostics Plan

@@ -152,6 +153,23 @@

System Health Tables

+
+ + + + + + + + + + + + + + +
Health Check History
TimeEnvironmentAreaResultSummary
LoadingLoadingCurrent environmentPENDINGWaiting for safe API status.
+
diff --git a/assets/theme-v2/js/admin-system-health.js b/assets/theme-v2/js/admin-system-health.js index c0f7051b4..e0c2cab9f 100644 --- a/assets/theme-v2/js/admin-system-health.js +++ b/assets/theme-v2/js/admin-system-health.js @@ -47,6 +47,7 @@ class AdminSystemHealthController { node.dataset.adminSystemHealthStorageStatus, node, ])); + this.historyRows = root.querySelector("[data-admin-system-health-history-rows]"); this.startupRows = root.querySelector("[data-admin-system-health-startup-rows]"); this.runtimeRows = root.querySelector("[data-admin-system-health-runtime-rows]"); } @@ -107,6 +108,7 @@ class AdminSystemHealthController { }); this.renderStartupPending(reason); this.renderStoragePending(reason); + this.renderHistoryPending(reason); } renderEnvironmentIdentity(environmentIdentity = {}) { @@ -222,6 +224,45 @@ class AdminSystemHealthController { } } + renderHistoryPending(reason) { + if (!this.historyRows) { + return; + } + const row = document.createElement("tr"); + row.append( + this.createCell("not available"), + this.createCell("current environment"), + this.createCell("Health Check History"), + this.createStatusCell("PENDING", reason), + this.createCell("Safe health check history is not available."), + ); + this.historyRows.replaceChildren(row); + } + + renderHealthCheckHistory(historyRows = []) { + if (!this.historyRows) { + return; + } + const rows = Array.isArray(historyRows) ? historyRows : []; + if (!rows.length) { + this.renderHistoryPending("Safe Admin System Health API returned no current-environment health check history rows."); + return; + } + const fragment = document.createDocumentFragment(); + rows.forEach((historyRow) => { + const row = document.createElement("tr"); + row.append( + this.createCell(historyRow.checkedAt), + this.createCell(historyRow.environmentName), + this.createCell(historyRow.area), + this.createStatusCell(historyRow.result || historyRow.status, historyRow.summary), + this.createCell(historyRow.summary), + ); + fragment.append(row); + }); + this.historyRows.replaceChildren(fragment); + } + runStorageDiagnostics() { STORAGE_DIAGNOSTIC_ACTIONS.forEach(({ key }) => { this.setStorageStatus(key, "PENDING", "R2 diagnostic is running through the safe Admin System Health API."); @@ -302,6 +343,7 @@ class AdminSystemHealthController { this.renderStartupDiagnostics(data?.localApiStartup || {}); this.renderStorageStatus(data?.storageStatus || {}); this.runStorageDiagnostics(); + this.renderHealthCheckHistory(data?.healthCheckHistory || []); this.renderRuntimeEnvironment(data?.runtimeEnvironment || {}); } catch (error) { const message = error instanceof Error ? error.message : "Safe Admin System Health API is unavailable."; diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_010-system-health-history-and-closeout.md b/docs_build/dev/reports/PR_26175_CHARLIE_010-system-health-history-and-closeout.md new file mode 100644 index 000000000..c8f5ff396 --- /dev/null +++ b/docs_build/dev/reports/PR_26175_CHARLIE_010-system-health-history-and-closeout.md @@ -0,0 +1,68 @@ +# PR_26175_CHARLIE_010 System Health History and Closeout + +## Scope + +Team: Charlie + +Purpose: Add current-environment Health Check History and close out the System Health stacked expansion chain. + +## Chain + +- `PR_26175_CHARLIE_006-project-instructions-system-health-infrastructure` + - Branch: `PR_26175_CHARLIE_006-project-instructions-system-health-infrastructure` + - Commit: `c870b812faded383094fb13fc60ae9cfc7f14889` + - Result: pushed to origin, not merged. +- `PR_26175_CHARLIE_007-system-health-environment-identity` + - Branch: `pr/26175-CHARLIE-007-system-health-environment-identity` + - Commit: `6556e73efcd8ae13b51b56288416c88688e67634` + - Draft PR: https://github.com/ToolboxAid/HTML-JavaScript-Gaming/pull/151 +- `PR_26175_CHARLIE_008-system-health-current-database-health` + - Branch: `pr/26175-CHARLIE-008-system-health-current-database-health` + - Commit: `2603aeb6e5a7ccca516051953cbd70a5a6c94c4b` + - Draft PR: https://github.com/ToolboxAid/HTML-JavaScript-Gaming/pull/152 +- `PR_26175_CHARLIE_009-system-health-current-r2-health` + - Branch: `pr/26175-CHARLIE-009-system-health-current-r2-health` + - Commit: `9740705fbe73dffd43744ab66338f8e4a925eed4` + - Draft PR: https://github.com/ToolboxAid/HTML-JavaScript-Gaming/pull/153 +- `PR_26175_CHARLIE_010-system-health-history-and-closeout` + - Branch: `pr/26175-CHARLIE-010-system-health-history-and-closeout` + - Commit and draft PR URL are assigned after this report is committed and pushed. + +## Changes + +- Added Health Check History to the Admin System Health page. +- Health Check History is derived from the current deployment only: + - Environment Summary + - Database Health + - Storage Health + - Runtime Health +- Warning and failure rows are generated only from current-environment health rows. +- Creator sessions remain blocked from Admin System Health and do not trigger status or storage health requests. + +## Governance + +- PASS: System Health is one page per deployed environment. +- PASS: Each deployment actively checks only itself. +- PASS: The Environment Map remains a static reference for Local, DEV, IST, UAT, and PRD. +- PASS: System Health does not actively check peer databases or peer R2 folders. +- PASS: Cancelled initiatives remain not doing: + - Environment Isolation & Developer Experience + - multi-port workspace framework + - Alpha/Beta/User runtime separation + - runtime port management initiative + +## Validation + +- PASS: `node --check src/dev-runtime/server/local-api-router.mjs` +- PASS: `node --check assets/theme-v2/js/admin-system-health.js` +- PASS: `git diff --check` +- PASS: `node --test tests/dev-runtime/AdminHealthOperations.test.mjs` +- PASS: `node --test tests/dev-runtime/PublicEnvironmentConfig.test.mjs` +- PASS: `npx playwright test tests/playwright/tools/AdminHealthOperationsPage.spec.mjs --workers=1 --reporter=line` + +## Artifacts + +- `tmp/PR_26175_CHARLIE_007-system-health-environment-identity_delta.zip` +- `tmp/PR_26175_CHARLIE_008-system-health-current-database-health_delta.zip` +- `tmp/PR_26175_CHARLIE_009-system-health-current-r2-health_delta.zip` +- `tmp/PR_26175_CHARLIE_010-system-health-history-and-closeout_delta.zip` diff --git a/docs_build/dev/reports/coverage_changed_js_guardrail.txt b/docs_build/dev/reports/coverage_changed_js_guardrail.txt index e6251e0a0..0003bcc7e 100644 --- a/docs_build/dev/reports/coverage_changed_js_guardrail.txt +++ b/docs_build/dev/reports/coverage_changed_js_guardrail.txt @@ -7,7 +7,7 @@ Source: Playwright/Chromium built-in V8 coverage from the active Playwright run. Changed runtime JS files considered: (0%) src/dev-runtime/server/local-api-router.mjs - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only -(89%) assets/theme-v2/js/admin-system-health.js - executed lines 294/294; executed functions 33/37 +(88%) assets/theme-v2/js/admin-system-health.js - executed lines 334/334; executed functions 35/40 Guardrail warnings: (0%) src/dev-runtime/server/local-api-router.mjs - WARNING: changed runtime JS file missing from coverage; advisory only diff --git a/docs_build/dev/reports/playwright_v8_coverage_report.txt b/docs_build/dev/reports/playwright_v8_coverage_report.txt index 9154f603b..82d39d813 100644 --- a/docs_build/dev/reports/playwright_v8_coverage_report.txt +++ b/docs_build/dev/reports/playwright_v8_coverage_report.txt @@ -18,7 +18,7 @@ Exercised tool entry points detected: Changed runtime JS files covered: (0%) src/dev-runtime/server/local-api-router.mjs - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only -(89%) assets/theme-v2/js/admin-system-health.js - executed lines 294/294; executed functions 33/37 +(88%) assets/theme-v2/js/admin-system-health.js - executed lines 334/334; executed functions 35/40 Files with executed line/function counts where available: (36%) src/api/server-api-client.js - executed lines 167/167; executed functions 5/14 @@ -28,7 +28,7 @@ Files with executed line/function counts where available: (74%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 1001/1001; executed functions 69/93 (80%) src/api/admin-owner-navigation.js - executed lines 42/42; executed functions 4/5 (83%) assets/js/shared/status.js - executed lines 37/37; executed functions 5/6 -(89%) assets/theme-v2/js/admin-system-health.js - executed lines 294/294; executed functions 33/37 +(88%) assets/theme-v2/js/admin-system-health.js - executed lines 334/334; executed functions 35/40 (91%) assets/theme-v2/js/admin-owner-navigation.js - executed lines 58/58; executed functions 10/11 (100%) src/api/admin-system-health-api-client.js - executed lines 19/19; executed functions 3/3 @@ -39,4 +39,4 @@ Changed JS files considered: (0%) src/dev-runtime/server/local-api-router.mjs - changed JS file not collected as browser runtime coverage (0%) tests/dev-runtime/AdminHealthOperations.test.mjs - changed JS file not collected as browser runtime coverage (0%) tests/playwright/tools/AdminHealthOperationsPage.spec.mjs - changed JS file not collected as browser runtime coverage -(89%) assets/theme-v2/js/admin-system-health.js - changed JS file with browser V8 coverage +(88%) assets/theme-v2/js/admin-system-health.js - changed JS file with browser V8 coverage diff --git a/src/dev-runtime/server/local-api-router.mjs b/src/dev-runtime/server/local-api-router.mjs index 2f1550b82..194ba4622 100644 --- a/src/dev-runtime/server/local-api-router.mjs +++ b/src/dev-runtime/server/local-api-router.mjs @@ -1028,6 +1028,71 @@ function systemHealthRuntimeEnvironment(env = process.env) { }; } +function systemHealthHistoryRow({ checkedAt, environmentName, area, result, summary, kind = "recent check" }) { + return { + area, + checkedAt, + environmentName, + kind, + result: normalizeHealthStatus(result), + summary: String(summary || "No summary returned."), + }; +} + +function systemHealthCheckHistory({ + checkedAt, + databaseStatus = {}, + environmentIdentity = {}, + runtimeEnvironment = {}, + storageStatus = {}, +}) { + const environmentName = environmentIdentity.name || "Unknown"; + const databaseResponseTime = Number.isFinite(databaseStatus.responseTimeMs) + ? `${databaseStatus.responseTimeMs} ms` + : "not available"; + const recentChecks = [ + systemHealthHistoryRow({ + area: "Environment Summary", + checkedAt, + environmentName, + result: environmentIdentity.status, + summary: `Current deployment ${environmentName}; hosting ${environmentIdentity.hostingModel || "not configured"}; storage folder ${environmentIdentity.storageFolder || "not configured"}.`, + }), + systemHealthHistoryRow({ + area: "Database Health", + checkedAt, + environmentName, + result: databaseStatus.connectivityStatus || databaseStatus.status, + summary: `${databaseStatus.databaseType || "PostgreSQL"} connectivity ${databaseStatus.connectivity || "not configured"}; response time ${databaseResponseTime}; version ${databaseStatus.version || "not available"}.`, + }), + systemHealthHistoryRow({ + area: "Storage Health", + checkedAt, + environmentName, + result: storageStatus.status, + summary: `Cloudflare R2 folder ${storageStatus.environmentFolder || environmentIdentity.storageFolder || "not configured"}; bucket ${storageStatus.configured ? "configured" : "not configured"}; last checked ${storageStatus.lastChecked || checkedAt}.`, + }), + systemHealthHistoryRow({ + area: "Runtime Health", + checkedAt, + environmentName, + result: runtimeEnvironment.status, + summary: runtimeEnvironment.message || "Runtime environment health unavailable.", + }), + ]; + const issueRows = recentChecks + .filter((row) => row.result !== "PASS") + .map((row) => systemHealthHistoryRow({ + area: `${row.area} ${row.result === "FAIL" ? "Failure" : "Warning"}`, + checkedAt: row.checkedAt, + environmentName: row.environmentName, + kind: row.result === "FAIL" ? "failure" : "warning", + result: row.result, + summary: row.summary, + })); + return [...recentChecks, ...issueRows]; +} + function systemHealthR2Readiness(storageStatus) { const credentialsConfigured = storageStatus.accessKeyConfigured === true && storageStatus.secretKeyConfigured === true; const configurationReady = storageStatus.configured === true @@ -3838,6 +3903,13 @@ LIMIT 1; const r2Readiness = systemHealthR2Readiness(storageStatus); const runtimeEnvironment = systemHealthRuntimeEnvironment(); const operationsHealth = adminOperationsHealth(this.standaloneTables); + const healthCheckHistory = systemHealthCheckHistory({ + checkedAt, + databaseStatus, + environmentIdentity, + runtimeEnvironment, + storageStatus, + }); const importBlocked = promotionFoundation.importOverwriteAllowed === false && promotionFoundation.browserExecutionAllowed === false && promotionFoundation.destructiveOperationsAllowed === false; @@ -3961,6 +4033,7 @@ LIMIT 1; message: "Admin System Health loaded safe status only.", environmentIdentity, environmentMap, + healthCheckHistory, operationsHealth, overview, pressureLabels: SYSTEM_HEALTH_LIMIT_PRESSURE_LABELS, diff --git a/tests/dev-runtime/AdminHealthOperations.test.mjs b/tests/dev-runtime/AdminHealthOperations.test.mjs index 0e7782c7f..fc0d28ea7 100644 --- a/tests/dev-runtime/AdminHealthOperations.test.mjs +++ b/tests/dev-runtime/AdminHealthOperations.test.mjs @@ -144,6 +144,14 @@ test("Admin can view operational health while Creator sessions are blocked", asy assert.equal(typeof health.databaseStatus.version, "string"); assert.equal(health.storageStatus.environmentFolder, "/local"); assert.equal(typeof health.storageStatus.lastChecked, "string"); + assert.equal(Array.isArray(health.healthCheckHistory), true); + assert.deepEqual( + health.healthCheckHistory.slice(0, 4).map((row) => row.area), + ["Environment Summary", "Database Health", "Storage Health", "Runtime Health"], + ); + assert.equal(health.healthCheckHistory.every((row) => row.environmentName === "Local"), true); + assert.equal(JSON.stringify(health.healthCheckHistory).includes("/dev"), false); + assert.equal(JSON.stringify(health.healthCheckHistory).includes("/uat"), false); assert.deepEqual( health.environmentMap.map((row) => row.name), ["Local", "DEV", "IST", "UAT", "PRD"], diff --git a/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs b/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs index 0379a6ed8..021c845c5 100644 --- a/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs +++ b/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs @@ -164,6 +164,19 @@ test("Admin System Health renders Postgres diagnostics through the safe status A await expect(page.locator("[data-admin-system-health-storage-value='upload']")).toContainText("/dev"); await expect(page.locator("[data-admin-system-health-storage-value='read']")).not.toHaveText("Health object"); await expect(page.locator("[data-admin-system-health-storage-value='delete']")).not.toHaveText("Health object"); + const historyTable = page.getByRole("table", { name: "Health check history" }); + await expect(historyTable).toContainText("DEV"); + await expect(historyTable).toContainText("Environment Summary"); + await expect(historyTable).toContainText("Database Health"); + await expect(historyTable).toContainText("Storage Health"); + await expect(historyTable).toContainText("Runtime Health"); + await expect(historyTable).not.toContainText("IST"); + await expect(historyTable).not.toContainText("UAT"); + await expect(historyTable).not.toContainText("PRD"); + await expect(historyTable).not.toContainText("/local"); + await expect(historyTable).not.toContainText("/ist"); + await expect(historyTable).not.toContainText("/uat"); + await expect(historyTable).not.toContainText("/prd"); await expect(page.getByRole("table", { name: "Runtime environment" })).toContainText("********"); await expect(page.getByRole("table", { name: "Runtime environment" })).toContainText("GAMEFOUNDRY_ADMIN_HEALTH_DATABASE_URL"); await expect(page.getByRole("table", { name: "Runtime environment" })).toContainText("GAMEFOUNDRY_ADMIN_HEALTH_PUBLIC_FLAG"); @@ -216,6 +229,7 @@ test("Creator sessions cannot access Admin System Health operations", async ({ p await expect(page.locator("[data-session-access-blocked='admin']")).toBeVisible(); await expect(page.getByRole("table", { name: "Environment identity" })).toHaveCount(0); await expect(page.getByRole("table", { name: "Environment map" })).toHaveCount(0); + await expect(page.getByRole("table", { name: "Health check history" })).toHaveCount(0); expect(context.requestUrls.some((url) => url.includes("/api/admin/system-health/status"))).toBe(false); expect(context.requestUrls.some((url) => url.includes("/api/admin/system-health/storage-connectivity-action"))).toBe(false); expect(context.pageErrors).toEqual([]); From 250b32f7666b2f1d71ae6fb61b1f812a47c3d356 Mon Sep 17 00:00:00 2001 From: Charlie Team <97194984+ToolboxAid@users.noreply.github.com> Date: Wed, 24 Jun 2026 15:30:41 -0400 Subject: [PATCH 2/2] Alphabetize Admin submenu navigation --- ...nu-alphabetical-order-branch-validation.md | 15 + ...habetical-order-manual-validation-notes.md | 26 ++ ...lphabetical-order-requirement-checklist.md | 42 +++ ...n-submenu-alphabetical-order-validation.md | 22 ++ ...IE_011-admin-submenu-alphabetical-order.md | 47 +++ .../dev/reports/codex_changed_files.txt | 23 +- docs_build/dev/reports/codex_review.diff | 333 +++++++++++------- .../reports/coverage_changed_js_guardrail.txt | 4 +- .../reports/playwright_v8_coverage_report.txt | 32 +- src/api/admin-owner-navigation.js | 2 +- tests/dev-runtime/ApiMenuPathCleanup.test.mjs | 8 +- ...hitectureCleanupApiNavInvitations.test.mjs | 2 +- .../tools/AdminInvitationsNavPage.spec.mjs | 2 +- .../AdminOwnerNavigationBoundary.spec.mjs | 11 +- 14 files changed, 406 insertions(+), 163 deletions(-) create mode 100644 docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-branch-validation.md create mode 100644 docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-manual-validation-notes.md create mode 100644 docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-requirement-checklist.md create mode 100644 docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-validation.md create mode 100644 docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order.md diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-branch-validation.md b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-branch-validation.md new file mode 100644 index 000000000..e2d3a2b30 --- /dev/null +++ b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-branch-validation.md @@ -0,0 +1,15 @@ +# PR_26175_CHARLIE_011 Branch Validation + +## Start Gate + +- PASS: Current branch was `pr/26175-CHARLIE-010-system-health-history-and-closeout`. +- PASS: Worktree was clean before implementation. +- PASS: Build remained on the current Charlie continuation branch. +- PASS: No rebase was performed. +- PASS: No new root branch was created. + +## Final Branch Target + +- Branch to push: `pr/26175-CHARLIE-010-system-health-history-and-closeout` +- Expected draft PR to update: https://github.com/ToolboxAid/HTML-JavaScript-Gaming/pull/155 +- Merge status: no merge requested or performed. diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-manual-validation-notes.md b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-manual-validation-notes.md new file mode 100644 index 000000000..e8b6eae26 --- /dev/null +++ b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-manual-validation-notes.md @@ -0,0 +1,26 @@ +# PR_26175_CHARLIE_011 Manual Validation Notes + +## Admin Submenu Order + +Visible labels after the change: + +`Admin Tools`, `Analytics`, `Controls`, `Creators`, `DB Viewer`, `Environments`, `Game Migration`, `Infrastructure`, `Invites`, `Moderation`, `Operations`, `Platform Settings`, `Ratings`, `Responsibilities`, `Site Setup`, `System Health`, `Tool Votes` + +## Route Preservation + +The only source navigation reorder moved this existing item: + +- `Creators` + - path remained `admin/users.html` + - route remained `admin-users` + - label remained `Creators` + +All other Admin navigation objects remained unchanged. + +## Open-Page Check + +The targeted Playwright navigation test collected every active Admin submenu href from the rendered submenu and requested each page through the local test server. Every response returned a status below HTTP 400. + +## Duplicate Check + +The targeted Playwright navigation test checks for duplicate rendered labels and duplicate active hrefs. The targeted unit script also checks duplicate labels and existing active paths. diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-requirement-checklist.md b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-requirement-checklist.md new file mode 100644 index 000000000..39afb7966 --- /dev/null +++ b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-requirement-checklist.md @@ -0,0 +1,42 @@ +# PR_26175_CHARLIE_011 Requirement Checklist + +## Branch Rules + +- PASS: Continued on `pr/26175-CHARLIE-010-system-health-history-and-closeout`. +- PASS: Did not return to `main`. +- PASS: Did not rebase. +- PASS: Did not create a new root branch. +- PASS: Hard stop conditions were checked before implementation. + +## Objective + +- PASS: Admin submenu entries are alphabetized by displayed text. + +## Scope + +- PASS: Located Admin submenu definition in `src/api/admin-owner-navigation.js`. +- PASS: Sorted submenu entries by displayed text. +- PASS: Preserved routes, URLs, IDs, CSS classes, Theme V2 styling, and existing renderer behavior. +- PASS: Did not rename pages. +- PASS: Did not rename folders. +- PASS: Did not modify page content. +- PASS: No unrelated cleanup. + +## Validation + +- PASS: Verified submenu labels are alphabetical. +- PASS: Verified every Admin page path exists and every Admin submenu href opens below HTTP 400 in targeted Playwright. +- PASS: Verified no duplicate labels or hrefs. +- PASS: Ran affected Playwright navigation tests. +- PASS: Ran affected targeted unit tests. + +## Artifacts + +- PASS: `docs_build/dev/reports/codex_review.diff` +- PASS: `docs_build/dev/reports/codex_changed_files.txt` +- PASS: `docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order.md` +- PASS: validation report +- PASS: branch validation report +- PASS: requirement checklist +- PASS: manual validation notes +- PASS: repository ZIP under `tmp/` diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-validation.md b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-validation.md new file mode 100644 index 000000000..aeec3f443 --- /dev/null +++ b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-validation.md @@ -0,0 +1,22 @@ +# PR_26175_CHARLIE_011 Validation Report + +## Commands + +- PASS: `node --check src/api/admin-owner-navigation.js` +- PASS: `node --input-type=module` alphabetical/duplicate/path verification script + - Result: `PASS labels=17 active=16` + - Order: `Admin Tools | Analytics | Controls | Creators | DB Viewer | Environments | Game Migration | Infrastructure | Invites | Moderation | Operations | Platform Settings | Ratings | Responsibilities | Site Setup | System Health | Tool Votes` +- PASS: `git diff --check` + - Result: no whitespace errors; CRLF conversion warnings only. +- PASS: `node --test tests/dev-runtime/ApiMenuPathCleanup.test.mjs` + - Result: 6 passed. +- PASS: `node --test --test-name-pattern "Admin and Owner navigation are shared" tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs` + - Result: 1 passed. +- PASS: `npx playwright test tests/playwright/tools/AdminOwnerNavigationBoundary.spec.mjs --workers=1 --reporter=line` + - Result: 4 passed. +- PASS: `npx playwright test tests/playwright/tools/AdminInvitationsNavPage.spec.mjs --workers=1 --reporter=line` + - Result: 3 passed. + +## Note + +A non-targeted full-file run of `tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs` was not used for final validation because its first non-navigation test fails on a pre-existing missing `src/engine/api` directory assertion. The affected navigation subtest passed by name. diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order.md b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order.md new file mode 100644 index 000000000..7dcbe5262 --- /dev/null +++ b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order.md @@ -0,0 +1,47 @@ +# PR_26175_CHARLIE_011 Admin Submenu Alphabetical Order + +## Scope + +Team: Charlie + +Purpose: Alphabetize the Admin submenu by visible menu labels only. + +## Branch + +- Continuation branch: `pr/26175-CHARLIE-010-system-health-history-and-closeout` +- Start gate: PASS + - Current branch matched the expected Charlie continuation branch. + - Worktree was clean before implementation. + +## Changes + +- Moved `Creators` into its alphabetical position in `src/api/admin-owner-navigation.js`. +- Preserved each Admin menu item label, path, route id, disabled state, and renderer behavior. +- Updated affected navigation tests that pin visible Admin menu label order. +- Added Playwright coverage of: + - alphabetical visible label order + - duplicate detection + - duplicate href detection + - each Admin submenu href opening with an HTTP status below 400 + +## Non-Changes + +- No page files were renamed. +- No folders were renamed. +- No page content was modified. +- No routes, URLs, permissions, icons, IDs, CSS classes, Theme V2 styling, or event handlers were changed. +- No menu outside the Admin submenu was reordered. + +## Validation Summary + +- PASS: Admin labels are alphabetical. +- PASS: No duplicate Admin labels. +- PASS: No duplicate Admin hrefs. +- PASS: Every active Admin submenu item points to an existing page path. +- PASS: Every Admin submenu href opened with an HTTP status below 400 in the targeted Playwright navigation test. +- PASS: Targeted unit tests passed. +- PASS: Targeted Playwright navigation tests passed. + +## Artifact + +- `tmp/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order_delta.zip` diff --git a/docs_build/dev/reports/codex_changed_files.txt b/docs_build/dev/reports/codex_changed_files.txt index 666e52912..3149474c1 100644 --- a/docs_build/dev/reports/codex_changed_files.txt +++ b/docs_build/dev/reports/codex_changed_files.txt @@ -1,9 +1,14 @@ -# git status --short - - -# git diff --name-status main...HEAD -A docs_build/dev/reports/PR_26175_OWNER_049-governance-report-merge-batch.md - -# git diff --stat main...HEAD - ...6175_OWNER_049-governance-report-merge-batch.md | 128 +++++++++++++++++++++ - 1 file changed, 128 insertions(+) +docs_build/dev/reports/codex_changed_files.txt +docs_build/dev/reports/codex_review.diff +docs_build/dev/reports/coverage_changed_js_guardrail.txt +docs_build/dev/reports/playwright_v8_coverage_report.txt +docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order.md +docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-branch-validation.md +docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-manual-validation-notes.md +docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-requirement-checklist.md +docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-validation.md +src/api/admin-owner-navigation.js +tests/dev-runtime/ApiMenuPathCleanup.test.mjs +tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs +tests/playwright/tools/AdminInvitationsNavPage.spec.mjs +tests/playwright/tools/AdminOwnerNavigationBoundary.spec.mjs diff --git a/docs_build/dev/reports/codex_review.diff b/docs_build/dev/reports/codex_review.diff index e28da9065..dd6b1f346 100644 --- a/docs_build/dev/reports/codex_review.diff +++ b/docs_build/dev/reports/codex_review.diff @@ -1,134 +1,199 @@ -diff --git a/docs_build/dev/reports/PR_26175_OWNER_049-governance-report-merge-batch.md b/docs_build/dev/reports/PR_26175_OWNER_049-governance-report-merge-batch.md -new file mode 100644 -index 000000000..ed334afcd ---- /dev/null -+++ b/docs_build/dev/reports/PR_26175_OWNER_049-governance-report-merge-batch.md -@@ -0,0 +1,128 @@ -+# PR_26175_OWNER_049-governance-report-merge-batch -+ -+## Purpose -+ -+Document the current OWNER-approved governance decisions for the next report/cleanup batch. -+ -+This PR is report-only. It does not merge PRs, close PRs, delete branches, or modify runtime code. -+ -+## Source State -+ -+| Item | GitHub state at review | Decision documented here | -+| --- | --- | --- | -+| PR #129 | Open draft, not merged, currently not mergeable as-is | MERGE APPROVED | -+| PR #132 | Open draft, not merged, currently not mergeable as-is | MERGE APPROVED | -+| PR #134 | Open draft, not merged, currently not mergeable as-is | MERGE APPROVED | -+| PR #3 | Open, not merged, currently not mergeable | CLOSE APPROVED | -+| PR #51 | Open draft, not merged, currently not mergeable | CLOSE APPROVED | -+| PR #50 | Open draft, not merged, currently not mergeable | HOLD | -+| PR #118 | Open draft, not merged, currently mergeable to its non-main base branch | HOLD | -+ -+## OWNER Decisions -+ -+### MERGE APPROVED -+ -+| PR | Title | Rationale | Dependency impact | Expected post-merge state | -+| --- | --- | --- | --- | --- | -+| #129 | `[codex] PR_26175_OWNER_046 targeted PR review packets` | Establishes the OWNER_046 governance/report foundation: Team Gamma retired, Team Golf replacement active ownership lane, and GitHub-authoritative review packets for PR #3, #50, #51, and #118. | Merge before #132 because #132 cites the OWNER_046 review packets as supporting evidence. Because #129 changes Project Instructions and was based on older `main`, it likely needs normal ready/update/conflict handling before merge execution. | `main` contains the Golf/Gamma governance migration note and review packets `PR_REVIEW_003.md`, `PR_REVIEW_050.md`, `PR_REVIEW_051.md`, and `PR_REVIEW_118.md`. | -+| #132 | `PR_26175_OWNER_047: add targeted PR action decision report` | Captures the OWNER_047 action decision report for PR #3, #50, #51, and #118, including #3 code-diff risks, #50 Golf/Gamma historical decision, #51 superseded governance comparison, and #118 Alfa closeout evidence decision. | Merge after #129 so the review packets it uses are already present on `main`. It is report-only but currently not mergeable as-is, so it may require normal branch update handling before execution. | `main` contains the targeted action decision report that supports closing #3/#51 and holding #50/#118. | -+| #134 | `PR_26175_BRAVO_001: add PR 003 Messages code review` | Adds the Bravo code-review report for PR #3 focused on Messages / Emotion Profiles. It documents the key reason PR #3 should close: stale, not mergeable, targets removed SQLite service path, and mixes future BUILD specs into the PR_006 lane. | Independent of #129/#132 for file content, but it strengthens the evidence record for closing #3. It should merge before closing #3 so the code-review evidence is preserved on `main`. | `main` contains the Bravo PR #3 code-review report, giving the close action an auditable technical basis. | -+ -+### CLOSE APPROVED -+ -+| PR | Title | Rationale | Replacement / superseded reference | Dependency impact | Expected post-close state | -+| --- | --- | --- | --- | --- | --- | -+| #3 | `Pr/PR 26171 006 message emotion profile management` | Superseded by the current PostgreSQL Messages direction. The PR targets the removed SQLite Messages service path and is not mergeable. It also contains out-of-scope future BUILD specs for later Messages/TTS/playback lanes. | Current PostgreSQL-backed Messages implementation on `main`; OWNER_047 decision report from #132; Bravo code-review evidence from #134. | Close after #132 and #134 merge so both decision and code-review evidence are present on `main`. Do not delete the branch unless a later OWNER-approved cleanup task explicitly scopes branch deletion. | PR #3 is closed as superseded; PostgreSQL Messages remains the active direction; branch remains untouched. | -+| #51 | `PR_26172_MASTER_001-project-instructions-readme-and-root` | Superseded by the current Project Instructions governance state. It bootstraps an older ProjectInstructions root using MASTER wording and placeholder structure, while current `main` already has OWNER governance, addendums, team assignment rules, and archive history. | Current `docs_build/dev/ProjectInstructions/` state on `main`; OWNER_047 decision report from #132; OWNER_048 superseded closure decision log. | Close after #132 merges, or with #132/#134 evidence batch, so the decision trail is preserved. Do not delete the branch unless later explicitly approved. | PR #51 is closed as superseded; current OWNER Project Instructions remain authoritative; branch remains untouched. | -+ -+### HOLD -+ -+| PR | Title | Rationale | Dependency impact | Expected hold state | -+| --- | --- | --- | --- | --- | -+| #50 | `PR_26171_GAMMA_028-final-sqlite-clean-status-report` | Hold as historical Golf/Gamma SQLite closeout evidence. It may still be useful as reference material, but it should not be merged or closed in this batch until the OWNER confirms whether the final Gamma-era report should be preserved on `main` or left as PR evidence. | Related to #129 because #129 retires Gamma and replaces it with Golf as the active lane. Holding #50 avoids mixing historical Gamma closeout disposition with the approved merge/close batch. | PR #50 remains open/draft and untouched. | -+| #118 | `PR_26174_ALFA_EOD-final-closeout` | Hold as Alfa EOD closeout evidence. It targets a non-main base branch and is not needed before merging the OWNER/Bravo governance evidence batch. | It may remain useful for Alfa stack review, but it should not be merged into the governance batch or closed until OWNER completes the Alfa stack disposition. | PR #118 remains open/draft and untouched. | -+ -+## Dependency Order -+ -+Recommended execution order for the already-approved future actions: -+ -+1. Prepare #129 for merge, then merge #129. -+2. Prepare #132 for merge, then merge #132. -+3. Prepare #134 for merge, then merge #134. -+4. Close #3 as superseded by the current PostgreSQL Messages direction after #132/#134 evidence is on `main`. -+5. Close #51 as superseded by the current Project Instructions governance state after #132 evidence is on `main`. -+6. Keep #50 and #118 open on hold. -+ -+## Replacement And Superseded References -+ -+| Superseded / held item | Replacement or current reference | -+| --- | --- | -+| PR #3 | PostgreSQL-backed Messages direction on `main`; evidence in #132 and #134. | -+| PR #51 | Current OWNER Project Instructions on `main`; evidence in #132 and OWNER_048 decision log. | -+| PR #50 | Held as final Gamma/Golf historical SQLite closeout evidence; #129 establishes Team Golf as active replacement lane. | -+| PR #118 | Held as Alfa closeout evidence for later Alfa stack disposition. | -+ -+## Expected Post-Merge State -+ -+After #129, #132, and #134 are merged, and #3/#51 are closed in a later approved action: -+ -+- `main` contains OWNER_046 review packets for #3, #50, #51, and #118. -+- `main` contains OWNER_047 targeted action decision report. -+- `main` contains Bravo PR #3 code-review report. -+- PR #3 is closed as superseded by PostgreSQL Messages direction. -+- PR #51 is closed as superseded by current Project Instructions governance. -+- PR #50 remains open/draft on hold. -+- PR #118 remains open/draft on hold. -+- No branches are deleted unless a later OWNER-approved branch cleanup task explicitly scopes deletion. -+ -+## Changed File Inventory For Reviewed Merge PRs -+ -+| PR | Changed files reviewed | -+| --- | --- | -+| #129 | `docs_build/dev/ProjectInstructions/PROJECT_INSTRUCTIONS.md`; `docs_build/dev/ProjectInstructions/TEAM_START_COMMANDS.md`; `docs_build/dev/ProjectInstructions/addendums/multi_team.md`; `docs_build/dev/ProjectInstructions/addendums/pr_workflow.md`; `docs_build/dev/ProjectInstructions/addendums/team_release_readiness.md`; `docs_build/dev/ProjectInstructions/addendums/team_start_and_release.md`; `docs_build/dev/ProjectInstructions/backlog/BACKLOG_MASTER.md`; `docs_build/dev/ProjectInstructions/team_assignments/ACTIVE_TEAM_REGISTRY.md`; `docs_build/dev/ProjectInstructions/team_assignments/TEAM_ASSIGNMENTS.md`; `docs_build/dev/ProjectInstructions/team_assignments/team_ownership.md`; `docs_build/dev/reports/PR_26175_OWNER_046-pr-targeted-review-packets.md`; `docs_build/dev/reports/PR_REVIEW_003.md`; `docs_build/dev/reports/PR_REVIEW_050.md`; `docs_build/dev/reports/PR_REVIEW_051.md`; `docs_build/dev/reports/PR_REVIEW_118.md`; `docs_build/dev/reports/codex_changed_files.txt`; `docs_build/dev/reports/codex_review.diff` | -+| #132 | `docs_build/dev/reports/PR_26175_OWNER_047-targeted-pr-action-decision-report.md`; `docs_build/dev/reports/codex_changed_files.txt`; `docs_build/dev/reports/codex_review.diff` | -+| #134 | `docs_build/dev/reports/PR_26175_BRAVO_001-pr-003-messages-emotion-profiles-code-review.md`; `docs_build/dev/reports/codex_changed_files.txt`; `docs_build/dev/reports/codex_review.diff` | -+ -+## Requirement Checklist -+ -+| Requirement | Status | Notes | -+| --- | --- | --- | -+| Start from `main` | PASS | Hard-stop gate confirmed current branch was `main` before branch creation. | -+| Worktree clean | PASS | Hard-stop gate confirmed clean worktree before branch creation. | -+| Local/origin sync `0 0` | PASS | Hard-stop gate confirmed `main...origin/main` was `0 0`. | -+| Read all Project Instructions | PASS | Read files under `docs_build/dev/ProjectInstructions/` before report creation. | -+| Review PR #129 | PASS | GitHub metadata and changed-file list reviewed. | -+| Review PR #132 | PASS | GitHub metadata and changed-file list reviewed. | -+| Review PR #134 | PASS | GitHub metadata and changed-file list reviewed. | -+| Document MERGE APPROVED decisions | PASS | #129, #132, and #134 documented. | -+| Document CLOSE APPROVED decisions | PASS | #3 and #51 documented. | -+| Document HOLD decisions | PASS | #50 and #118 documented. | -+| Include rationale | PASS | Included per decision table. | -+| Include dependency impact | PASS | Included per decision table and order section. | -+| Include replacement/superseded references | PASS | Included in close/hold and replacement tables. | -+| Include expected post-merge state | PASS | Included above. | -+| Do not merge PRs | PASS | No merge action performed. | -+| Do not close PRs | PASS | No close action performed. | -+| Do not delete branches | PASS | No branch deletion performed. | -+| Do not modify runtime code | PASS | Report-only changes under `docs_build/dev/reports/`. | -+ -+## Validation Lane Report -+ -+- PASS: GitHub PR metadata fetched for #129, #132, #134, #3, #51, #50, and #118. -+- PASS: GitHub changed-file lists fetched for #129, #132, and #134. -+- PASS: Scope stayed report-only under `docs_build/dev/reports/`. -+- PASS: No runtime validation required because no runtime code changed. -+ -+## Manual Validation Notes -+ -+- Confirmed #129, #132, and #134 remain unmerged at report time; this PR documents approval only and does not execute merges. -+- Confirmed #3 and #51 remain open at report time; this PR documents approval only and does not execute closures. -+- Confirmed #50 and #118 remain held and untouched. -+- Confirmed branch deletion is explicitly out of scope. -+ -+## Artifacts -+ -+- `docs_build/dev/reports/PR_26175_OWNER_049-governance-report-merge-batch.md` -+- `docs_build/dev/reports/codex_changed_files.txt` -+- `docs_build/dev/reports/codex_review.diff` -+- `tmp/PR_26175_OWNER_049-governance-report-merge-batch_delta.zip` +diff --git a/docs_build/dev/reports/coverage_changed_js_guardrail.txt b/docs_build/dev/reports/coverage_changed_js_guardrail.txt +index 0003bcc7e..8df1af057 100644 +--- a/docs_build/dev/reports/coverage_changed_js_guardrail.txt ++++ b/docs_build/dev/reports/coverage_changed_js_guardrail.txt +@@ -6,8 +6,10 @@ Missing changed runtime JS files are WARN, not FAIL. + Source: Playwright/Chromium built-in V8 coverage from the active Playwright run. + + Changed runtime JS files considered: ++(0%) assets/theme-v2/js/admin-system-health.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only + (0%) src/dev-runtime/server/local-api-router.mjs - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only +-(88%) assets/theme-v2/js/admin-system-health.js - executed lines 334/334; executed functions 35/40 ++(100%) src/api/admin-owner-navigation.js - executed lines 42/42; executed functions 5/5 + + Guardrail warnings: ++(0%) assets/theme-v2/js/admin-system-health.js - WARNING: changed runtime JS file missing from coverage; advisory only + (0%) src/dev-runtime/server/local-api-router.mjs - WARNING: changed runtime JS file missing from coverage; advisory only +diff --git a/docs_build/dev/reports/playwright_v8_coverage_report.txt b/docs_build/dev/reports/playwright_v8_coverage_report.txt +index 82d39d813..be704e176 100644 +--- a/docs_build/dev/reports/playwright_v8_coverage_report.txt ++++ b/docs_build/dev/reports/playwright_v8_coverage_report.txt +@@ -12,31 +12,41 @@ Note: entry percentages use function coverage when available, otherwise line cov + Note: coverage entries are aggregated across every page/tool where coverageReporter.start(page) and coverageReporter.stop(page) ran. + + Exercised tool entry points detected: +-(46%) Toolbox Index - exercised 1 runtime JS files ++(35%) Toolbox Index - exercised 1 runtime JS files + (0%) Tool Template V2 - not exercised by this Playwright run +-(78%) Theme V2 Shared JS - exercised 4 runtime JS files ++(70%) Theme V2 Shared JS - exercised 5 runtime JS files + + Changed runtime JS files covered: ++(0%) assets/theme-v2/js/admin-system-health.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only + (0%) src/dev-runtime/server/local-api-router.mjs - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only +-(88%) assets/theme-v2/js/admin-system-health.js - executed lines 334/334; executed functions 35/40 ++(100%) src/api/admin-owner-navigation.js - executed lines 42/42; executed functions 5/5 + + Files with executed line/function counts where available: ++(35%) toolbox/tool-registry-api-client.js - executed lines 155/155; executed functions 9/26 + (36%) src/api/server-api-client.js - executed lines 167/167; executed functions 5/14 +-(46%) toolbox/tool-registry-api-client.js - executed lines 155/155; executed functions 12/26 ++(40%) src/api/admin-invitations-api-client.js - executed lines 40/40; executed functions 2/5 ++(50%) assets/js/shared/status.js - executed lines 37/37; executed functions 3/6 ++(53%) assets/theme-v2/js/admin-invitations.js - executed lines 156/156; executed functions 9/17 ++(59%) assets/theme-v2/js/owner-memberships.js - executed lines 248/248; executed functions 16/27 + (64%) assets/theme-v2/js/tool-display-mode.js - executed lines 204/204; executed functions 9/14 +-(65%) src/api/public-config-client.js - executed lines 209/209; executed functions 17/26 ++(67%) src/api/owner-memberships-api-client.js - executed lines 19/19; executed functions 2/3 ++(71%) src/api/public-config-client.js - executed lines 209/209; executed functions 20/28 + (74%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 1001/1001; executed functions 69/93 +-(80%) src/api/admin-owner-navigation.js - executed lines 42/42; executed functions 4/5 +-(83%) assets/js/shared/status.js - executed lines 37/37; executed functions 5/6 +-(88%) assets/theme-v2/js/admin-system-health.js - executed lines 334/334; executed functions 35/40 +-(91%) assets/theme-v2/js/admin-owner-navigation.js - executed lines 58/58; executed functions 10/11 +-(100%) src/api/admin-system-health-api-client.js - executed lines 19/19; executed functions 3/3 ++(89%) src/dev-runtime/admin/admin-notes-viewer.js - executed lines 533/533; executed functions 49/55 ++(100%) assets/theme-v2/js/admin-owner-navigation.js - executed lines 58/58; executed functions 11/11 ++(100%) src/api/admin-owner-navigation.js - executed lines 42/42; executed functions 5/5 + + Uncovered or low-coverage changed JS files: ++(0%) assets/theme-v2/js/admin-system-health.js - WARNING: uncovered changed runtime JS file; advisory only + (0%) src/dev-runtime/server/local-api-router.mjs - WARNING: uncovered changed runtime JS file; advisory only + + Changed JS files considered: ++(0%) assets/theme-v2/js/admin-system-health.js - changed JS file not collected as browser runtime coverage + (0%) src/dev-runtime/server/local-api-router.mjs - changed JS file not collected as browser runtime coverage + (0%) tests/dev-runtime/AdminHealthOperations.test.mjs - changed JS file not collected as browser runtime coverage ++(0%) tests/dev-runtime/ApiMenuPathCleanup.test.mjs - changed JS file not collected as browser runtime coverage ++(0%) tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs - changed JS file not collected as browser runtime coverage + (0%) tests/playwright/tools/AdminHealthOperationsPage.spec.mjs - changed JS file not collected as browser runtime coverage +-(88%) assets/theme-v2/js/admin-system-health.js - changed JS file with browser V8 coverage ++(0%) tests/playwright/tools/AdminInvitationsNavPage.spec.mjs - changed JS file not collected as browser runtime coverage ++(0%) tests/playwright/tools/AdminOwnerNavigationBoundary.spec.mjs - changed JS file not collected as browser runtime coverage ++(100%) src/api/admin-owner-navigation.js - changed JS file with browser V8 coverage +diff --git a/src/api/admin-owner-navigation.js b/src/api/admin-owner-navigation.js +index b80366641..592647346 100644 +--- a/src/api/admin-owner-navigation.js ++++ b/src/api/admin-owner-navigation.js +@@ -2,6 +2,7 @@ const ADMIN_NAVIGATION_ITEMS = Object.freeze([ + Object.freeze({ disabled: true, label: "Admin Tools", planned: false }), + Object.freeze({ label: "Analytics", path: "admin/analytics.html", route: "admin-analytics" }), + Object.freeze({ label: "Controls", path: "admin/controls.html", route: "admin-controls" }), ++ Object.freeze({ label: "Creators", path: "admin/users.html", route: "admin-users" }), + Object.freeze({ label: "DB Viewer", path: "admin/db-viewer.html", route: "admin-db-viewer" }), + Object.freeze({ label: "Environments", path: "admin/environments.html", route: "admin-environments" }), + Object.freeze({ label: "Game Migration", path: "admin/game-migration.html", route: "admin-game-migration" }), +@@ -15,7 +16,6 @@ const ADMIN_NAVIGATION_ITEMS = Object.freeze([ + Object.freeze({ label: "Site Setup", path: "admin/site-setup.html", route: "admin-site-setup" }), + Object.freeze({ label: "System Health", path: "admin/system-health.html", route: "admin-system-health" }), + Object.freeze({ label: "Tool Votes", path: "admin/tool-votes.html", route: "admin-tool-votes" }), +- Object.freeze({ label: "Creators", path: "admin/users.html", route: "admin-users" }), + ]); + + const OWNER_NAVIGATION_ITEMS = Object.freeze([ +diff --git a/tests/dev-runtime/ApiMenuPathCleanup.test.mjs b/tests/dev-runtime/ApiMenuPathCleanup.test.mjs +index deb1027fe..abc1b76ef 100644 +--- a/tests/dev-runtime/ApiMenuPathCleanup.test.mjs ++++ b/tests/dev-runtime/ApiMenuPathCleanup.test.mjs +@@ -21,20 +21,20 @@ const EXPECTED_ADMIN_LABELS = Object.freeze([ + "Admin Tools", + "Analytics", + "Controls", ++ "Creators", + "DB Viewer", + "Environments", + "Game Migration", + "Infrastructure", +- "Invitations", ++ "Invites", + "Moderation", + "Operations", + "Platform Settings", + "Ratings", +- "Roles", ++ "Responsibilities", + "Site Setup", + "System Health", + "Tool Votes", +- "Users", + ]); + + const EXPECTED_OWNER_LABELS = Object.freeze([ +@@ -98,7 +98,7 @@ test("Admin and Owner shared menus are non-overlapping by responsibility", () => + ["Branding", "Design System", "Grouping Colors", "Legal", "Marketplace Settings", "Notes", "Revenue", "Site Settings", "Themes"].forEach((label) => { + assert.equal(adminItems.some((item) => item.label === label), false, `Admin menu must not include Owner business item ${label}`); + }); +- ["DB Viewer", "Infrastructure", "Invitations", "Operations", "Platform Settings", "System Health", "Users"].forEach((label) => { ++ ["Creators", "DB Viewer", "Infrastructure", "Invites", "Operations", "Platform Settings", "System Health"].forEach((label) => { + assert.equal(ownerItems.some((item) => item.label === label), false, `Owner menu must not duplicate Admin operations item ${label}`); + }); + }); +diff --git a/tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs b/tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs +index fdb745e4c..a896dcb9c 100644 +--- a/tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs ++++ b/tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs +@@ -92,7 +92,7 @@ test("product and web API clients live under src/api while engine API keeps only + test("Admin and Owner navigation are shared and include present operational/business pages", async () => { + const adminLabels = getAdminNavigationItems().map((item) => item.label); + const ownerLabels = getOwnerNavigationItems().map((item) => item.label); +- ["Admin Tools", "Infrastructure", "Invitations", "Operations", "System Health", "Tool Votes", "Users"].forEach((label) => { ++ ["Admin Tools", "Creators", "Infrastructure", "Invites", "Operations", "System Health", "Tool Votes"].forEach((label) => { + assert.equal(adminLabels.includes(label), true, `Admin navigation should include ${label}`); + }); + ["Owner Tools", "AI Credits", "Branding", "Grouping Colors", "Memberships", "Revenue"].forEach((label) => { +diff --git a/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs b/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs +index bb20304ab..d5ff2cda0 100644 +--- a/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs ++++ b/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs +@@ -83,6 +83,7 @@ test("Admin Invites uses shared navigation and creates personalized Beta invite + await expect(page.locator("nav[aria-label='Admin tool pages'] a")).toContainText([ + "Analytics", + "Controls", ++ "Creators", + "DB Viewer", + "Environments", + "Game Migration", +@@ -96,7 +97,6 @@ test("Admin Invites uses shared navigation and creates personalized Beta invite + "Site Setup", + "System Health", + "Tool Votes", +- "Creators", + ]); + await expect(page.locator("nav[aria-label='Admin tool pages'] a[aria-current='page']")).toHaveText("Invites"); + +diff --git a/tests/playwright/tools/AdminOwnerNavigationBoundary.spec.mjs b/tests/playwright/tools/AdminOwnerNavigationBoundary.spec.mjs +index 79890522e..f4b68a097 100644 +--- a/tests/playwright/tools/AdminOwnerNavigationBoundary.spec.mjs ++++ b/tests/playwright/tools/AdminOwnerNavigationBoundary.spec.mjs +@@ -7,6 +7,7 @@ const ADMIN_LABELS = Object.freeze([ + "Admin Tools", + "Analytics", + "Controls", ++ "Creators", + "DB Viewer", + "Environments", + "Game Migration", +@@ -20,7 +21,6 @@ const ADMIN_LABELS = Object.freeze([ + "Site Setup", + "System Health", + "Tool Votes", +- "Creators", + ]); + + const OWNER_LABELS = Object.freeze([ +@@ -160,6 +160,15 @@ test("Admin menu renders operational platform pages only", async ({ page }) => { + try { + await expect(page.locator("nav[aria-label='Admin tool pages'] :is(a, span)")).toHaveText(ADMIN_LABELS); + const adminLinks = page.locator("nav[aria-label='Admin tool pages'] a"); ++ const adminRenderedLabels = await page.locator("nav[aria-label='Admin tool pages'] :is(a, span)").allTextContents(); ++ expect(adminRenderedLabels).toEqual([...adminRenderedLabels].sort((left, right) => left.localeCompare(right))); ++ expect(new Set(adminRenderedLabels).size).toBe(adminRenderedLabels.length); ++ const adminHrefs = await adminLinks.evaluateAll((links) => links.map((link) => link.getAttribute("href") || "")); ++ expect(new Set(adminHrefs).size).toBe(adminHrefs.length); ++ for (const href of adminHrefs) { ++ const response = await page.request.get(new URL(href, context.server.baseUrl).toString()); ++ expect(response.status(), `${href} should open`).toBeLessThan(400); ++ } + const adminLinkText = (await adminLinks.allTextContents()).join("\n"); + for (const label of [ + "Branding", diff --git a/docs_build/dev/reports/coverage_changed_js_guardrail.txt b/docs_build/dev/reports/coverage_changed_js_guardrail.txt index 0003bcc7e..8df1af057 100644 --- a/docs_build/dev/reports/coverage_changed_js_guardrail.txt +++ b/docs_build/dev/reports/coverage_changed_js_guardrail.txt @@ -6,8 +6,10 @@ Missing changed runtime JS files are WARN, not FAIL. Source: Playwright/Chromium built-in V8 coverage from the active Playwright run. Changed runtime JS files considered: +(0%) assets/theme-v2/js/admin-system-health.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only (0%) src/dev-runtime/server/local-api-router.mjs - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only -(88%) assets/theme-v2/js/admin-system-health.js - executed lines 334/334; executed functions 35/40 +(100%) src/api/admin-owner-navigation.js - executed lines 42/42; executed functions 5/5 Guardrail warnings: +(0%) assets/theme-v2/js/admin-system-health.js - WARNING: changed runtime JS file missing from coverage; advisory only (0%) src/dev-runtime/server/local-api-router.mjs - WARNING: changed runtime JS file missing from coverage; advisory only diff --git a/docs_build/dev/reports/playwright_v8_coverage_report.txt b/docs_build/dev/reports/playwright_v8_coverage_report.txt index 82d39d813..be704e176 100644 --- a/docs_build/dev/reports/playwright_v8_coverage_report.txt +++ b/docs_build/dev/reports/playwright_v8_coverage_report.txt @@ -12,31 +12,41 @@ Note: entry percentages use function coverage when available, otherwise line cov Note: coverage entries are aggregated across every page/tool where coverageReporter.start(page) and coverageReporter.stop(page) ran. Exercised tool entry points detected: -(46%) Toolbox Index - exercised 1 runtime JS files +(35%) Toolbox Index - exercised 1 runtime JS files (0%) Tool Template V2 - not exercised by this Playwright run -(78%) Theme V2 Shared JS - exercised 4 runtime JS files +(70%) Theme V2 Shared JS - exercised 5 runtime JS files Changed runtime JS files covered: +(0%) assets/theme-v2/js/admin-system-health.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only (0%) src/dev-runtime/server/local-api-router.mjs - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only -(88%) assets/theme-v2/js/admin-system-health.js - executed lines 334/334; executed functions 35/40 +(100%) src/api/admin-owner-navigation.js - executed lines 42/42; executed functions 5/5 Files with executed line/function counts where available: +(35%) toolbox/tool-registry-api-client.js - executed lines 155/155; executed functions 9/26 (36%) src/api/server-api-client.js - executed lines 167/167; executed functions 5/14 -(46%) toolbox/tool-registry-api-client.js - executed lines 155/155; executed functions 12/26 +(40%) src/api/admin-invitations-api-client.js - executed lines 40/40; executed functions 2/5 +(50%) assets/js/shared/status.js - executed lines 37/37; executed functions 3/6 +(53%) assets/theme-v2/js/admin-invitations.js - executed lines 156/156; executed functions 9/17 +(59%) assets/theme-v2/js/owner-memberships.js - executed lines 248/248; executed functions 16/27 (64%) assets/theme-v2/js/tool-display-mode.js - executed lines 204/204; executed functions 9/14 -(65%) src/api/public-config-client.js - executed lines 209/209; executed functions 17/26 +(67%) src/api/owner-memberships-api-client.js - executed lines 19/19; executed functions 2/3 +(71%) src/api/public-config-client.js - executed lines 209/209; executed functions 20/28 (74%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 1001/1001; executed functions 69/93 -(80%) src/api/admin-owner-navigation.js - executed lines 42/42; executed functions 4/5 -(83%) assets/js/shared/status.js - executed lines 37/37; executed functions 5/6 -(88%) assets/theme-v2/js/admin-system-health.js - executed lines 334/334; executed functions 35/40 -(91%) assets/theme-v2/js/admin-owner-navigation.js - executed lines 58/58; executed functions 10/11 -(100%) src/api/admin-system-health-api-client.js - executed lines 19/19; executed functions 3/3 +(89%) src/dev-runtime/admin/admin-notes-viewer.js - executed lines 533/533; executed functions 49/55 +(100%) assets/theme-v2/js/admin-owner-navigation.js - executed lines 58/58; executed functions 11/11 +(100%) src/api/admin-owner-navigation.js - executed lines 42/42; executed functions 5/5 Uncovered or low-coverage changed JS files: +(0%) assets/theme-v2/js/admin-system-health.js - WARNING: uncovered changed runtime JS file; advisory only (0%) src/dev-runtime/server/local-api-router.mjs - WARNING: uncovered changed runtime JS file; advisory only Changed JS files considered: +(0%) assets/theme-v2/js/admin-system-health.js - changed JS file not collected as browser runtime coverage (0%) src/dev-runtime/server/local-api-router.mjs - changed JS file not collected as browser runtime coverage (0%) tests/dev-runtime/AdminHealthOperations.test.mjs - changed JS file not collected as browser runtime coverage +(0%) tests/dev-runtime/ApiMenuPathCleanup.test.mjs - changed JS file not collected as browser runtime coverage +(0%) tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs - changed JS file not collected as browser runtime coverage (0%) tests/playwright/tools/AdminHealthOperationsPage.spec.mjs - changed JS file not collected as browser runtime coverage -(88%) assets/theme-v2/js/admin-system-health.js - changed JS file with browser V8 coverage +(0%) tests/playwright/tools/AdminInvitationsNavPage.spec.mjs - changed JS file not collected as browser runtime coverage +(0%) tests/playwright/tools/AdminOwnerNavigationBoundary.spec.mjs - changed JS file not collected as browser runtime coverage +(100%) src/api/admin-owner-navigation.js - changed JS file with browser V8 coverage diff --git a/src/api/admin-owner-navigation.js b/src/api/admin-owner-navigation.js index b80366641..592647346 100644 --- a/src/api/admin-owner-navigation.js +++ b/src/api/admin-owner-navigation.js @@ -2,6 +2,7 @@ const ADMIN_NAVIGATION_ITEMS = Object.freeze([ Object.freeze({ disabled: true, label: "Admin Tools", planned: false }), Object.freeze({ label: "Analytics", path: "admin/analytics.html", route: "admin-analytics" }), Object.freeze({ label: "Controls", path: "admin/controls.html", route: "admin-controls" }), + Object.freeze({ label: "Creators", path: "admin/users.html", route: "admin-users" }), Object.freeze({ label: "DB Viewer", path: "admin/db-viewer.html", route: "admin-db-viewer" }), Object.freeze({ label: "Environments", path: "admin/environments.html", route: "admin-environments" }), Object.freeze({ label: "Game Migration", path: "admin/game-migration.html", route: "admin-game-migration" }), @@ -15,7 +16,6 @@ const ADMIN_NAVIGATION_ITEMS = Object.freeze([ Object.freeze({ label: "Site Setup", path: "admin/site-setup.html", route: "admin-site-setup" }), Object.freeze({ label: "System Health", path: "admin/system-health.html", route: "admin-system-health" }), Object.freeze({ label: "Tool Votes", path: "admin/tool-votes.html", route: "admin-tool-votes" }), - Object.freeze({ label: "Creators", path: "admin/users.html", route: "admin-users" }), ]); const OWNER_NAVIGATION_ITEMS = Object.freeze([ diff --git a/tests/dev-runtime/ApiMenuPathCleanup.test.mjs b/tests/dev-runtime/ApiMenuPathCleanup.test.mjs index deb1027fe..abc1b76ef 100644 --- a/tests/dev-runtime/ApiMenuPathCleanup.test.mjs +++ b/tests/dev-runtime/ApiMenuPathCleanup.test.mjs @@ -21,20 +21,20 @@ const EXPECTED_ADMIN_LABELS = Object.freeze([ "Admin Tools", "Analytics", "Controls", + "Creators", "DB Viewer", "Environments", "Game Migration", "Infrastructure", - "Invitations", + "Invites", "Moderation", "Operations", "Platform Settings", "Ratings", - "Roles", + "Responsibilities", "Site Setup", "System Health", "Tool Votes", - "Users", ]); const EXPECTED_OWNER_LABELS = Object.freeze([ @@ -98,7 +98,7 @@ test("Admin and Owner shared menus are non-overlapping by responsibility", () => ["Branding", "Design System", "Grouping Colors", "Legal", "Marketplace Settings", "Notes", "Revenue", "Site Settings", "Themes"].forEach((label) => { assert.equal(adminItems.some((item) => item.label === label), false, `Admin menu must not include Owner business item ${label}`); }); - ["DB Viewer", "Infrastructure", "Invitations", "Operations", "Platform Settings", "System Health", "Users"].forEach((label) => { + ["Creators", "DB Viewer", "Infrastructure", "Invites", "Operations", "Platform Settings", "System Health"].forEach((label) => { assert.equal(ownerItems.some((item) => item.label === label), false, `Owner menu must not duplicate Admin operations item ${label}`); }); }); diff --git a/tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs b/tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs index fdb745e4c..a896dcb9c 100644 --- a/tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs +++ b/tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs @@ -92,7 +92,7 @@ test("product and web API clients live under src/api while engine API keeps only test("Admin and Owner navigation are shared and include present operational/business pages", async () => { const adminLabels = getAdminNavigationItems().map((item) => item.label); const ownerLabels = getOwnerNavigationItems().map((item) => item.label); - ["Admin Tools", "Infrastructure", "Invitations", "Operations", "System Health", "Tool Votes", "Users"].forEach((label) => { + ["Admin Tools", "Creators", "Infrastructure", "Invites", "Operations", "System Health", "Tool Votes"].forEach((label) => { assert.equal(adminLabels.includes(label), true, `Admin navigation should include ${label}`); }); ["Owner Tools", "AI Credits", "Branding", "Grouping Colors", "Memberships", "Revenue"].forEach((label) => { diff --git a/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs b/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs index bb20304ab..d5ff2cda0 100644 --- a/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs +++ b/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs @@ -83,6 +83,7 @@ test("Admin Invites uses shared navigation and creates personalized Beta invite await expect(page.locator("nav[aria-label='Admin tool pages'] a")).toContainText([ "Analytics", "Controls", + "Creators", "DB Viewer", "Environments", "Game Migration", @@ -96,7 +97,6 @@ test("Admin Invites uses shared navigation and creates personalized Beta invite "Site Setup", "System Health", "Tool Votes", - "Creators", ]); await expect(page.locator("nav[aria-label='Admin tool pages'] a[aria-current='page']")).toHaveText("Invites"); diff --git a/tests/playwright/tools/AdminOwnerNavigationBoundary.spec.mjs b/tests/playwright/tools/AdminOwnerNavigationBoundary.spec.mjs index 79890522e..f4b68a097 100644 --- a/tests/playwright/tools/AdminOwnerNavigationBoundary.spec.mjs +++ b/tests/playwright/tools/AdminOwnerNavigationBoundary.spec.mjs @@ -7,6 +7,7 @@ const ADMIN_LABELS = Object.freeze([ "Admin Tools", "Analytics", "Controls", + "Creators", "DB Viewer", "Environments", "Game Migration", @@ -20,7 +21,6 @@ const ADMIN_LABELS = Object.freeze([ "Site Setup", "System Health", "Tool Votes", - "Creators", ]); const OWNER_LABELS = Object.freeze([ @@ -160,6 +160,15 @@ test("Admin menu renders operational platform pages only", async ({ page }) => { try { await expect(page.locator("nav[aria-label='Admin tool pages'] :is(a, span)")).toHaveText(ADMIN_LABELS); const adminLinks = page.locator("nav[aria-label='Admin tool pages'] a"); + const adminRenderedLabels = await page.locator("nav[aria-label='Admin tool pages'] :is(a, span)").allTextContents(); + expect(adminRenderedLabels).toEqual([...adminRenderedLabels].sort((left, right) => left.localeCompare(right))); + expect(new Set(adminRenderedLabels).size).toBe(adminRenderedLabels.length); + const adminHrefs = await adminLinks.evaluateAll((links) => links.map((link) => link.getAttribute("href") || "")); + expect(new Set(adminHrefs).size).toBe(adminHrefs.length); + for (const href of adminHrefs) { + const response = await page.request.get(new URL(href, context.server.baseUrl).toString()); + expect(response.status(), `${href} should open`).toBeLessThan(400); + } const adminLinkText = (await adminLinks.allTextContents()).join("\n"); for (const label of [ "Branding",
Runtime Environment - Alphabetical Variables