From 8b598f3cb1acc09afee175242d74b5404567ac67 Mon Sep 17 00:00:00 2001 From: Alfa Team Date: Sun, 28 Jun 2026 20:01:10 -0400 Subject: [PATCH] Clean remaining legacy layout roots --- .../PROJECT_INSTRUCTIONS.md | 2 +- .../PROJECT_INSTRUCTIONS_VERSION.md | 3 +- .../ProjectInstructions/PROJECT_STATE.md | 12 +- .../environment_configuration_standards.md | 12 + .../backlog/BACKLOG_MASTER.md | 4 +- .../canonical_repository_structure.md | 9 + .../repository_layout_architecture_plan.md | 10 +- ...legacy-layout-cleanup_branch-validation.md | 10 + ...-layout-cleanup_manual-validation-notes.md | 8 + ...-remaining-legacy-layout-cleanup_report.md | 48 + ...cy-layout-cleanup_requirement-checklist.md | 15 + ...legacy-layout-cleanup_validation-report.md | 15 + dev/reports/codex_changed_files.txt | 81 +- dev/reports/codex_review.diff | 1633 +++-------------- .../PS/deploy/WebsiteRepoDeploymentCommon.ps1 | 2 +- .../StaticWebRootCompatibility.test.mjs | 11 + .../tools/AdminHealthOperationsPage.spec.mjs | 4 +- .../tools/AdminInvitationsNavPage.spec.mjs | 2 +- .../tools/GameAssetManifestDiscovery.test.mjs | 4 +- favicon.svg => www/favicon.svg | 0 20 files changed, 453 insertions(+), 1432 deletions(-) create mode 100644 dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_branch-validation.md create mode 100644 dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_manual-validation-notes.md create mode 100644 dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_report.md create mode 100644 dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_requirement-checklist.md create mode 100644 dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_validation-report.md rename favicon.svg => www/favicon.svg (100%) diff --git a/dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS.md b/dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS.md index 765f465fc..1043124e0 100644 --- a/dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS.md +++ b/dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS.md @@ -117,7 +117,7 @@ Rules: ## Current Version/Date -- Project Instructions Version: 2026.06.28.013 +- Project Instructions Version: 2026.06.28.014 - Date: 2026-06-28 - Owner: OWNER diff --git a/dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS_VERSION.md b/dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS_VERSION.md index a46ee7657..9fdf174e2 100644 --- a/dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS_VERSION.md +++ b/dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS_VERSION.md @@ -1,6 +1,6 @@ # Project Instructions Version -Current Project Instructions Version: 2026.06.28.013 +Current Project Instructions Version: 2026.06.28.014 Last Updated: 2026-06-28 @@ -21,6 +21,7 @@ Last Updated: 2026-06-28 - Finalized moved test and validation path assumptions for the `www/`, `api/`, and `dev/local-runtime/` layout. - Updated CI, package scripts, and developer utilities for the `www/`, `api/`, and `dev/` layout. - Removed active references to obsolete legacy layout paths after the `www/`, `api/`, and `dev/` migration steps. +- Moved the tracked browser-served favicon under `www/`, added remaining root/src audit governance, and documented root `.env` placement policy. - Codex must read this version file and the latest repository copy of `PROJECT_INSTRUCTIONS.md` before performing work. - Codex must discard previously remembered Project Instructions and treat the repository copy as authoritative. - Codex must validate canonical report and ZIP paths, branching model, and legacy path avoidance before work proceeds. diff --git a/dev/build/ProjectInstructions/PROJECT_STATE.md b/dev/build/ProjectInstructions/PROJECT_STATE.md index 0e5fac9bd..716598321 100644 --- a/dev/build/ProjectInstructions/PROJECT_STATE.md +++ b/dev/build/ProjectInstructions/PROJECT_STATE.md @@ -1,7 +1,7 @@ # Project State ```yaml -project_state_version: "2026.06.28.013" +project_state_version: "2026.06.28.014" last_updated: "2026-06-28" current_main_commit: "40de767476d70cadfd1292c916844c2f31b6f185" repository_status: @@ -10,9 +10,9 @@ repository_status: runtime_database: "Postgres" creator_metadata: "API to Postgres" creator_assets: "API to R2" -project_instructions_version: "2026.06.28.013" -repository_structure_version: "2026.06.28.013" -canonical_layout_version: "2026.06.28.013" +project_instructions_version: "2026.06.28.014" +repository_structure_version: "2026.06.28.014" +canonical_layout_version: "2026.06.28.014" active_teams: - "Owner" - "Alfa" @@ -20,8 +20,8 @@ active_teams: - "Charlie" - "Delta" - "Golf" -latest_owner_pr: "PR_26180_OWNER_013-remove-legacy-layout" -latest_structure_pr: "PR_26180_OWNER_013-remove-legacy-layout" +latest_owner_pr: "PR_26180_OWNER_014-remaining-legacy-layout-cleanup" +latest_structure_pr: "PR_26180_OWNER_014-remaining-legacy-layout-cleanup" valid_top_level_folders: - "api/" - "deploy/" diff --git a/dev/build/ProjectInstructions/addendums/environment_configuration_standards.md b/dev/build/ProjectInstructions/addendums/environment_configuration_standards.md index f01811895..e78c2ca98 100644 --- a/dev/build/ProjectInstructions/addendums/environment_configuration_standards.md +++ b/dev/build/ProjectInstructions/addendums/environment_configuration_standards.md @@ -56,6 +56,18 @@ Runtime startup still reads `.env` values only. The official flow is for each en `.env.prd` is legacy technical debt only. Do not introduce new references to `.env.prd` except when documenting migration or historical compatibility. +## Runtime Placement Policy + +Local `.env` may exist at repository root for developer startup only. + +Root `.env` is user/environment-owned, ignored, and never deployed as part of `www/` or `api/`. + +Production uses deployment environment variables and environment-managed secrets instead of committed `.env` files. + +`www/` must never contain secrets or environment-owned `.env` files. + +`api/` reads environment values from `process.env` and the deployment environment. + ## Environment Identity Allowed `GAMEFOUNDRY_ENVIRONMENT` values: diff --git a/dev/build/ProjectInstructions/backlog/BACKLOG_MASTER.md b/dev/build/ProjectInstructions/backlog/BACKLOG_MASTER.md index 047761f31..535d71a1d 100644 --- a/dev/build/ProjectInstructions/backlog/BACKLOG_MASTER.md +++ b/dev/build/ProjectInstructions/backlog/BACKLOG_MASTER.md @@ -39,8 +39,8 @@ The backlog is the authoritative source for determining the next logical PRs. - Team: Owner - Product Area: Repository Architecture Simplification - Status: Active -- Percent Complete: 80% -- Active PR: PR_26180_OWNER_013-remove-legacy-layout +- Percent Complete: 90% +- Active PR: PR_26180_OWNER_014-remaining-legacy-layout-cleanup - Next Milestone: Final layout validation and completion report - Source / Reference: `dev/build/ProjectInstructions/repository/repository_layout_architecture_plan.md`; `dev/build/ProjectInstructions/repository/www_migration_map.md` diff --git a/dev/build/ProjectInstructions/repository/canonical_repository_structure.md b/dev/build/ProjectInstructions/repository/canonical_repository_structure.md index 3220aea3b..f1561c28e 100644 --- a/dev/build/ProjectInstructions/repository/canonical_repository_structure.md +++ b/dev/build/ProjectInstructions/repository/canonical_repository_structure.md @@ -121,6 +121,15 @@ These legacy transition buckets may remain until explicit migration PRs move the - Environment differences must come from `.env` values or environment-managed secrets. - Runtime source filenames must not use team names. +## Environment File Placement + +- Local `.env` may exist at repository root for developer startup only. +- Root `.env` is user/environment-owned, ignored, and never deployed as part of `www/` or `api/`. +- Production uses deployment environment variables and environment-managed secrets instead of committed `.env` files. +- `www/` must never contain secrets or environment-owned `.env` files. +- `api/` reads environment values from `process.env` and the deployment environment. +- Only `.env.example` is tracked as a repository template. + ## PR Chain Boundary The development workspace restructure must proceed through sequential scoped PRs. A PR may only move or update the paths named in its purpose. diff --git a/dev/build/ProjectInstructions/repository/repository_layout_architecture_plan.md b/dev/build/ProjectInstructions/repository/repository_layout_architecture_plan.md index fadb42722..aea15aa1e 100644 --- a/dev/build/ProjectInstructions/repository/repository_layout_architecture_plan.md +++ b/dev/build/ProjectInstructions/repository/repository_layout_architecture_plan.md @@ -36,6 +36,8 @@ No browser, API, server, test, script, or runtime files move in the scaffold or `PR_26180_OWNER_013-remove-legacy-layout` removes active stale references to obsolete legacy paths after the tracked `www/`, `api/`, and `dev/` migration steps. +`PR_26180_OWNER_014-remaining-legacy-layout-cleanup` audits remaining tracked root and `src/` layout items, moves the browser-served favicon into `www/`, and records root `.env` placement policy before final validation. + ## Proposed Future Layout ```text @@ -165,7 +167,13 @@ Rules: - Remove or retire obsolete legacy paths after all references are updated. - Hard stop if any runtime, test, or CI reference still points to old locations. -10. `PR_26180_OWNER_014-final-layout-validation` +10. `PR_26180_OWNER_014-remaining-legacy-layout-cleanup` + - Audit remaining tracked root and `src/` layout items after the `www/`, `api/`, and `dev/` migrations. + - Move browser-served root assets that now belong under `www/`. + - Document `.env` placement policy for local and deployed environments. + - Preserve product behavior and public routes. + +11. `PR_26180_OWNER_015-final-layout-validation` - Validate final repository layout. - Confirm `www/` owns the browser-served app, `api/` owns the server app, and `dev/` owns the developer workspace. - Confirm runtime does not depend on `dev/`, browser code does not import `api/`, and legacy references are removed or documented. diff --git a/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_branch-validation.md b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_branch-validation.md new file mode 100644 index 000000000..fa315c33a --- /dev/null +++ b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_branch-validation.md @@ -0,0 +1,10 @@ +# PR_26180_OWNER_014 Branch Validation + +| Check | Result | Evidence | +|---|---:|---| +| Current branch | PASS | `PR_26180_OWNER_014-remaining-legacy-layout-cleanup` | +| Expected stacked base | PASS | Created from `PR_26180_OWNER_013-remove-legacy-layout` | +| Project Instructions loaded | PASS | Repository Project Instructions version `2026.06.28.014` | +| Branching policy loaded | PASS | `PROJECT_BRANCHING_POLICY.md` version `2026.06.28.002` | +| Scope | PASS | Remaining layout cleanup, favicon move, environment policy documentation, tests/references only | +| Runtime/API/database implementation changes | PASS | None | diff --git a/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_manual-validation-notes.md b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_manual-validation-notes.md new file mode 100644 index 000000000..a5e12d3fb --- /dev/null +++ b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_manual-validation-notes.md @@ -0,0 +1,8 @@ +# PR_26180_OWNER_014 Manual Validation Notes + +- Public favicon URL remains `/favicon.svg`. +- Static route compatibility now verifies that `/favicon.svg` resolves to the browser-served `www/favicon.svg` file. +- No `.env` files were moved into `www/` or `api/`. +- `src/` remains in place because current application, API client, shared runtime, dev tooling, and tests still reference it. +- Root ignored/generated artifacts were not staged. +- Playwright coverage output generated by the local run was not included as a PR change. diff --git a/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_report.md b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_report.md new file mode 100644 index 000000000..604dd5ec3 --- /dev/null +++ b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_report.md @@ -0,0 +1,48 @@ +# PR_26180_OWNER_014 Remaining Legacy Layout Cleanup Report + +## Executive Summary + +PR_26180_OWNER_014 audits the remaining tracked repository layout after the `www/`, `api/`, and `dev/` migration stack. The only tracked browser-served root file found in scope was `favicon.svg`, which is now under `www/favicon.svg` while public references remain `/favicon.svg`. + +The PR also documents environment file placement policy: local `.env` files remain user/environment-owned at the repository root and are never deployed; production uses deployment-managed environment variables/secrets; `www/` must not contain secrets; `api/` reads environment values from `process.env` and the deployment environment. + +## Scope Decision + +- Browser-served favicon moved from repository root to `www/`. +- Public favicon URL `/favicon.svg` preserved. +- `src/` retained as an active transition namespace because tracked browser, API, dev tooling, and tests still import from it. +- No `.env` files moved into `www/` or `api/`. +- No runtime/API/UI/database behavior changed. + +## Root Audit + +Tracked root entries are limited to standard repository metadata/config plus `api/`, `dev/`, `src/`, and `www/`. Ignored local folders/files such as local `.env*`, generated workspace outputs, and dependency folders are not part of this PR and were not staged. + +Additional standard root files retained as repository configuration/history: + +- `.codex/` +- `.gitattributes` +- `.githooks/` +- `.gitignore` +- `AGENTS.md` +- `LICENSE` + +## src/ Audit + +`src/` is not empty and remains referenced by current `www/`, `api/`, `dev/tests/`, and `dev/tools/` surfaces. Current Project Instructions document `src/advanced`, `src/api`, `src/engine`, `src/shared`, `src/tools`, and `src/dev-runtime/admin` as legacy transition buckets pending explicit follow-up migration. This PR does not move or delete `src/`. + +## File Evidence + +- `www/favicon.svg`: browser-served favicon location after the move. +- `dev/tests/dev-runtime/StaticWebRootCompatibility.test.mjs`: verifies `/favicon.svg` resolves to `www/favicon.svg`. +- `dev/scripts/PS/deploy/WebsiteRepoDeploymentCommon.ps1`: deployment include list now references `www/favicon.svg`. +- `dev/build/ProjectInstructions/repository/canonical_repository_structure.md`: documents root `.env`, `www/`, and `api/` environment ownership. +- `dev/build/ProjectInstructions/addendums/environment_configuration_standards.md`: adds the runtime placement policy for environment values. + +## Remaining Technical Debt + +The PowerShell deployment helper still contains broader legacy include defaults such as root `index.html`, `games`, `samples`, `src`, and `tools`. This PR updates only the tracked favicon path because changing the broader deploy staging semantics would be a separate deployment-layout PR. + +## Owner Recommendation + +Keep this PR focused as the remaining legacy layout cleanup pass. Follow with the final layout validation PR after stacked dependencies land. diff --git a/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_requirement-checklist.md b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_requirement-checklist.md new file mode 100644 index 000000000..d765ab7cf --- /dev/null +++ b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_requirement-checklist.md @@ -0,0 +1,15 @@ +# PR_26180_OWNER_014 Requirement Checklist + +| Requirement | Result | Notes | +|---|---:|---| +| Base on `PR_26180_OWNER_013-remove-legacy-layout` | PASS | Stacked branch created from PR013 branch. | +| Identify remaining old folders/files outside `www/`, `api/`, and `dev/` | PASS | Tracked root scan found no tracked legacy browser/dev folders; standard repo config files remain. | +| Determine whether each remaining root item is allowed, should move, or should be removed | PASS | Standard repo config retained; `favicon.svg` moved; `src/` retained as documented transition namespace. | +| Move `favicon.svg` into `www/` if browser-served | PASS | `favicon.svg` moved to `www/favicon.svg`. | +| Update references to `favicon.svg` after move | PASS | Deployment include list and route-root test updated; public `/favicon.svg` references intentionally preserved. | +| Audit remaining `src/` contents | PASS | `src/` remains actively referenced and is documented as a transition namespace. | +| Do not move `.env` into `www/` or `api/` | PASS | No `.env` files moved. | +| Document `.env` policy | PASS | Policy added to canonical repository structure and environment configuration standards. | +| Do not change product behavior | PASS | Public URLs and route behavior preserved. | +| Required reports under `dev/reports/` | PASS | PR-specific reports generated. | +| Required ZIP under `dev/workspace/zips/` | PASS | ZIP generated during closeout. | diff --git a/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_validation-report.md b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_validation-report.md new file mode 100644 index 000000000..2427b8ca6 --- /dev/null +++ b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_validation-report.md @@ -0,0 +1,15 @@ +# PR_26180_OWNER_014 Validation Report + +| Validation | Result | Notes | +|---|---:|---| +| `node --test dev/tests/dev-runtime/StaticWebRootCompatibility.test.mjs dev/tests/dev-runtime/TeamAwareBootstrap.test.mjs dev/tests/tools/GameAssetManifestDiscovery.test.mjs` | PASS | 18 tests passed. | +| `npx playwright test dev/tests/playwright/tools/StaticWebRootCompatibility.spec.mjs dev/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs dev/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs` | PASS | 8 Playwright tests passed. | +| Targeted legacy layout scan | PASS | No tracked root legacy browser/dev folders remain; active scripts/tests only reference dev-owned script paths. | +| `node --test dev/tests/dev-runtime/TeamAwareBootstrap.test.mjs` | PASS | 12 tests passed. | +| Package script command surface check | PASS | `dev:bootstrap`, `dev:api`, `dev:web`, and `dev:local-api` are present. | +| `git diff --check` | PASS | Whitespace check passed; Git reported line-ending conversion warnings only. | +| `npm run validate:canonical-structure` | PASS | Blocking violations: 0; approved legacy exceptions: 503. | + +## Notes + +The targeted Playwright run updated a shared coverage artifact during execution. That generated churn was not retained in this PR; validation evidence is captured in the PR-specific reports instead. diff --git a/dev/reports/codex_changed_files.txt b/dev/reports/codex_changed_files.txt index 924abfb8a..032772b2c 100644 --- a/dev/reports/codex_changed_files.txt +++ b/dev/reports/codex_changed_files.txt @@ -1,61 +1,20 @@ -dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS.md -dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS_VERSION.md -dev/build/ProjectInstructions/PROJECT_STATE.md -dev/build/ProjectInstructions/backlog/BACKLOG_MASTER.md -dev/build/ProjectInstructions/repository/repository_layout_architecture_plan.md -dev/reports/PR_26180_OWNER_013-remove-legacy-layout_branch-validation.md -dev/reports/PR_26180_OWNER_013-remove-legacy-layout_manual-validation-notes.md -dev/reports/PR_26180_OWNER_013-remove-legacy-layout_report.md -dev/reports/PR_26180_OWNER_013-remove-legacy-layout_requirement-checklist.md -dev/reports/PR_26180_OWNER_013-remove-legacy-layout_validation-report.md -dev/reports/codex_changed_files.txt -dev/reports/codex_review.diff -dev/tests/dev-runtime/AdminNotesBoundary.test.mjs -dev/tests/dev-runtime/ApiMenuPathCleanup.test.mjs -dev/tests/final/ToolchainEngineIntegrationValidation.test.mjs -dev/tests/fixtures/games/AsteroidsValidation.test.mjs.patch -dev/tests/fixtures/tools/VectorNativeTemplate.test.mjs.patch -dev/tests/fixtures/workspace-v2/uat.manifest.json -dev/tests/helpers/playwrightV8CoverageReporter.mjs -dev/tests/helpers/testCoverageCatalog.mjs -dev/tests/playwright_installation.txt -dev/tests/production/TestsValidationCombinedPass.test.mjs -dev/tests/runtime/V2BlockFakeSessionSave.test.mjs -dev/tests/runtime/V2ClearStaleMergePreview.test.mjs -dev/tests/runtime/V2ConfirmPreviewEnableState.test.mjs -dev/tests/runtime/V2CrossToolFlow.test.mjs -dev/tests/runtime/V2CrossToolMergeBlock.test.mjs -dev/tests/runtime/V2DeterministicStateTransitions.test.mjs -dev/tests/runtime/V2DiffViewerMessaging.test.mjs -dev/tests/runtime/V2DiffViewerSummaryCounts.test.mjs -dev/tests/runtime/V2EnableStateFeedback.test.mjs -dev/tests/runtime/V2MergeConflictSummary.test.mjs -dev/tests/runtime/V2MergeOutputPersistence.test.mjs -dev/tests/runtime/V2MergePreviewOverlayFix.test.mjs -dev/tests/runtime/V2MergeResultSummary.test.mjs -dev/tests/runtime/V2MergeStateSingleSourceOfTruth.test.mjs -dev/tests/runtime/V2MergeStateStatusReset.test.mjs -dev/tests/runtime/V2MergedRecentSessionRegistration.test.mjs -dev/tests/runtime/V2SaveLibraryFromRecentSession.test.mjs -dev/tests/runtime/V2SavedSessionRowActions.test.mjs -dev/tests/runtime/V2SelectionSyncRowActions.test.mjs -dev/tests/runtime/V2SessionLibraryActionCleanup.test.mjs -dev/tests/runtime/V2SessionLibraryActionLabel.test.mjs -dev/tests/runtime/V2SessionLibraryActions.test.mjs -dev/tests/runtime/V2SessionLibraryCardOverwrite.test.mjs -dev/tests/runtime/V2SessionLibrarySaveGuard.test.mjs -dev/tests/runtime/V2SessionStateModelConsolidation.test.mjs -dev/tests/runtime/V2SessionToolsCloseoutBundle.test.mjs -dev/tests/runtime/V2SessionUxStabilization.test.mjs -dev/tests/runtime/V2ToolLaunch.test.mjs -dev/tests/runtime/V2UndoButtonRender.test.mjs -dev/tests/runtime/V2UndoEnableStateActualAvailability.test.mjs -dev/tests/runtime/V2UndoEnableStateRefresh.test.mjs -dev/tests/runtime/V2UndoLastMerge.test.mjs -dev/tests/runtime/V2WorkspaceDefaultToolInitialization.test.mjs -dev/tests/schemas/tool.manifest.schema.json -dev/tests/shared/ContractFixtureIsolationValidation.test.mjs -dev/tests/shared/ContractIndexValidation.test.mjs -dev/tests/shared/ContractNegativeCaseCoverage.test.mjs -dev/tests/tools/ToolManifestBoundary.test.mjs -www/owner/notes.html +M dev/reports/codex_changed_files.txt +M dev/reports/codex_review.diff +M dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS.md +M dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS_VERSION.md +M dev/build/ProjectInstructions/PROJECT_STATE.md +M dev/build/ProjectInstructions/addendums/environment_configuration_standards.md +M dev/build/ProjectInstructions/backlog/BACKLOG_MASTER.md +M dev/build/ProjectInstructions/repository/canonical_repository_structure.md +M dev/build/ProjectInstructions/repository/repository_layout_architecture_plan.md +A dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_branch-validation.md +A dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_manual-validation-notes.md +A dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_report.md +A dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_requirement-checklist.md +A dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_validation-report.md +M dev/scripts/PS/deploy/WebsiteRepoDeploymentCommon.ps1 +M dev/tests/dev-runtime/StaticWebRootCompatibility.test.mjs +M dev/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs +M dev/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs +M dev/tests/tools/GameAssetManifestDiscovery.test.mjs +R100 favicon.svg www/favicon.svg diff --git a/dev/reports/codex_review.diff b/dev/reports/codex_review.diff index 388fc7320..d0b6b2d8c 100644 --- a/dev/reports/codex_review.diff +++ b/dev/reports/codex_review.diff @@ -1,46 +1,46 @@ diff --git a/dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS.md b/dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS.md -index b925f8c69..765f465fc 100644 +index 765f465fc..1043124e0 100644 --- a/dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS.md +++ b/dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS.md @@ -117,7 +117,7 @@ Rules: ## Current Version/Date --- Project Instructions Version: 2026.06.28.012 -+- Project Instructions Version: 2026.06.28.013 +-- Project Instructions Version: 2026.06.28.013 ++- Project Instructions Version: 2026.06.28.014 - Date: 2026-06-28 - Owner: OWNER diff --git a/dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS_VERSION.md b/dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS_VERSION.md -index f16929b46..a46ee7657 100644 +index a46ee7657..9fdf174e2 100644 --- a/dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS_VERSION.md +++ b/dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS_VERSION.md @@ -1,6 +1,6 @@ # Project Instructions Version --Current Project Instructions Version: 2026.06.28.012 -+Current Project Instructions Version: 2026.06.28.013 +-Current Project Instructions Version: 2026.06.28.013 ++Current Project Instructions Version: 2026.06.28.014 Last Updated: 2026-06-28 -@@ -20,6 +20,7 @@ Last Updated: 2026-06-28 - - Moved developer-only local runtime/bootstrap entrypoints under `dev/local-runtime/` and preserved the public npm command surface. +@@ -21,6 +21,7 @@ Last Updated: 2026-06-28 - Finalized moved test and validation path assumptions for the `www/`, `api/`, and `dev/local-runtime/` layout. - Updated CI, package scripts, and developer utilities for the `www/`, `api/`, and `dev/` layout. -+- Removed active references to obsolete legacy layout paths after the `www/`, `api/`, and `dev/` migration steps. + - Removed active references to obsolete legacy layout paths after the `www/`, `api/`, and `dev/` migration steps. ++- Moved the tracked browser-served favicon under `www/`, added remaining root/src audit governance, and documented root `.env` placement policy. - Codex must read this version file and the latest repository copy of `PROJECT_INSTRUCTIONS.md` before performing work. - Codex must discard previously remembered Project Instructions and treat the repository copy as authoritative. - Codex must validate canonical report and ZIP paths, branching model, and legacy path avoidance before work proceeds. diff --git a/dev/build/ProjectInstructions/PROJECT_STATE.md b/dev/build/ProjectInstructions/PROJECT_STATE.md -index ad1fd5158..0e5fac9bd 100644 +index 0e5fac9bd..716598321 100644 --- a/dev/build/ProjectInstructions/PROJECT_STATE.md +++ b/dev/build/ProjectInstructions/PROJECT_STATE.md @@ -1,7 +1,7 @@ # Project State ```yaml --project_state_version: "2026.06.28.012" -+project_state_version: "2026.06.28.013" +-project_state_version: "2026.06.28.013" ++project_state_version: "2026.06.28.014" last_updated: "2026-06-28" current_main_commit: "40de767476d70cadfd1292c916844c2f31b6f185" repository_status: @@ -48,12 +48,12 @@ index ad1fd5158..0e5fac9bd 100644 runtime_database: "Postgres" creator_metadata: "API to Postgres" creator_assets: "API to R2" --project_instructions_version: "2026.06.28.012" --repository_structure_version: "2026.06.28.012" --canonical_layout_version: "2026.06.28.012" -+project_instructions_version: "2026.06.28.013" -+repository_structure_version: "2026.06.28.013" -+canonical_layout_version: "2026.06.28.013" +-project_instructions_version: "2026.06.28.013" +-repository_structure_version: "2026.06.28.013" +-canonical_layout_version: "2026.06.28.013" ++project_instructions_version: "2026.06.28.014" ++repository_structure_version: "2026.06.28.014" ++canonical_layout_version: "2026.06.28.014" active_teams: - "Owner" - "Alfa" @@ -61,1397 +61,322 @@ index ad1fd5158..0e5fac9bd 100644 - "Charlie" - "Delta" - "Golf" --latest_owner_pr: "PR_26180_OWNER_012-update-ci-and-scripts" --latest_structure_pr: "PR_26180_OWNER_012-update-ci-and-scripts" -+latest_owner_pr: "PR_26180_OWNER_013-remove-legacy-layout" -+latest_structure_pr: "PR_26180_OWNER_013-remove-legacy-layout" +-latest_owner_pr: "PR_26180_OWNER_013-remove-legacy-layout" +-latest_structure_pr: "PR_26180_OWNER_013-remove-legacy-layout" ++latest_owner_pr: "PR_26180_OWNER_014-remaining-legacy-layout-cleanup" ++latest_structure_pr: "PR_26180_OWNER_014-remaining-legacy-layout-cleanup" valid_top_level_folders: - "api/" - "deploy/" +diff --git a/dev/build/ProjectInstructions/addendums/environment_configuration_standards.md b/dev/build/ProjectInstructions/addendums/environment_configuration_standards.md +index f01811895..e78c2ca98 100644 +--- a/dev/build/ProjectInstructions/addendums/environment_configuration_standards.md ++++ b/dev/build/ProjectInstructions/addendums/environment_configuration_standards.md +@@ -56,6 +56,18 @@ Runtime startup still reads `.env` values only. The official flow is for each en + + `.env.prd` is legacy technical debt only. Do not introduce new references to `.env.prd` except when documenting migration or historical compatibility. + ++## Runtime Placement Policy ++ ++Local `.env` may exist at repository root for developer startup only. ++ ++Root `.env` is user/environment-owned, ignored, and never deployed as part of `www/` or `api/`. ++ ++Production uses deployment environment variables and environment-managed secrets instead of committed `.env` files. ++ ++`www/` must never contain secrets or environment-owned `.env` files. ++ ++`api/` reads environment values from `process.env` and the deployment environment. ++ + ## Environment Identity + + Allowed `GAMEFOUNDRY_ENVIRONMENT` values: diff --git a/dev/build/ProjectInstructions/backlog/BACKLOG_MASTER.md b/dev/build/ProjectInstructions/backlog/BACKLOG_MASTER.md -index d0d974e9c..047761f31 100644 +index 047761f31..535d71a1d 100644 --- a/dev/build/ProjectInstructions/backlog/BACKLOG_MASTER.md +++ b/dev/build/ProjectInstructions/backlog/BACKLOG_MASTER.md -@@ -39,9 +39,9 @@ The backlog is the authoritative source for determining the next logical PRs. +@@ -39,8 +39,8 @@ The backlog is the authoritative source for determining the next logical PRs. - Team: Owner - Product Area: Repository Architecture Simplification - Status: Active --- Percent Complete: 70% --- Active PR: PR_26180_OWNER_012-update-ci-and-scripts --- Next Milestone: Remove or retire obsolete legacy paths after all references are updated -+- Percent Complete: 80% -+- Active PR: PR_26180_OWNER_013-remove-legacy-layout -+- Next Milestone: Final layout validation and completion report +-- Percent Complete: 80% +-- Active PR: PR_26180_OWNER_013-remove-legacy-layout ++- Percent Complete: 90% ++- Active PR: PR_26180_OWNER_014-remaining-legacy-layout-cleanup + - Next Milestone: Final layout validation and completion report - Source / Reference: `dev/build/ProjectInstructions/repository/repository_layout_architecture_plan.md`; `dev/build/ProjectInstructions/repository/www_migration_map.md` - ## Game Journey MVP +diff --git a/dev/build/ProjectInstructions/repository/canonical_repository_structure.md b/dev/build/ProjectInstructions/repository/canonical_repository_structure.md +index 3220aea3b..f1561c28e 100644 +--- a/dev/build/ProjectInstructions/repository/canonical_repository_structure.md ++++ b/dev/build/ProjectInstructions/repository/canonical_repository_structure.md +@@ -121,6 +121,15 @@ These legacy transition buckets may remain until explicit migration PRs move the + - Environment differences must come from `.env` values or environment-managed secrets. + - Runtime source filenames must not use team names. + ++## Environment File Placement ++ ++- Local `.env` may exist at repository root for developer startup only. ++- Root `.env` is user/environment-owned, ignored, and never deployed as part of `www/` or `api/`. ++- Production uses deployment environment variables and environment-managed secrets instead of committed `.env` files. ++- `www/` must never contain secrets or environment-owned `.env` files. ++- `api/` reads environment values from `process.env` and the deployment environment. ++- Only `.env.example` is tracked as a repository template. ++ + ## PR Chain Boundary + + The development workspace restructure must proceed through sequential scoped PRs. A PR may only move or update the paths named in its purpose. diff --git a/dev/build/ProjectInstructions/repository/repository_layout_architecture_plan.md b/dev/build/ProjectInstructions/repository/repository_layout_architecture_plan.md -index c9dd538ec..fadb42722 100644 +index fadb42722..aea15aa1e 100644 --- a/dev/build/ProjectInstructions/repository/repository_layout_architecture_plan.md +++ b/dev/build/ProjectInstructions/repository/repository_layout_architecture_plan.md -@@ -34,6 +34,8 @@ No browser, API, server, test, script, or runtime files move in the scaffold or +@@ -36,6 +36,8 @@ No browser, API, server, test, script, or runtime files move in the scaffold or - `PR_26180_OWNER_012-update-ci-and-scripts` updates CI, package scripts, and developer utilities for the `www/`, `api/`, and `dev/` layout while preserving the public developer command surface. + `PR_26180_OWNER_013-remove-legacy-layout` removes active stale references to obsolete legacy paths after the tracked `www/`, `api/`, and `dev/` migration steps. -+`PR_26180_OWNER_013-remove-legacy-layout` removes active stale references to obsolete legacy paths after the tracked `www/`, `api/`, and `dev/` migration steps. ++`PR_26180_OWNER_014-remaining-legacy-layout-cleanup` audits remaining tracked root and `src/` layout items, moves the browser-served favicon into `www/`, and records root `.env` placement policy before final validation. + ## Proposed Future Layout ```text -diff --git a/dev/reports/PR_26180_OWNER_013-remove-legacy-layout_branch-validation.md b/dev/reports/PR_26180_OWNER_013-remove-legacy-layout_branch-validation.md +@@ -165,7 +167,13 @@ Rules: + - Remove or retire obsolete legacy paths after all references are updated. + - Hard stop if any runtime, test, or CI reference still points to old locations. + +-10. `PR_26180_OWNER_014-final-layout-validation` ++10. `PR_26180_OWNER_014-remaining-legacy-layout-cleanup` ++ - Audit remaining tracked root and `src/` layout items after the `www/`, `api/`, and `dev/` migrations. ++ - Move browser-served root assets that now belong under `www/`. ++ - Document `.env` placement policy for local and deployed environments. ++ - Preserve product behavior and public routes. ++ ++11. `PR_26180_OWNER_015-final-layout-validation` + - Validate final repository layout. + - Confirm `www/` owns the browser-served app, `api/` owns the server app, and `dev/` owns the developer workspace. + - Confirm runtime does not depend on `dev/`, browser code does not import `api/`, and legacy references are removed or documented. +diff --git a/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_branch-validation.md b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_branch-validation.md new file mode 100644 -index 000000000..f2e3e086b +index 000000000..2a325d6f5 --- /dev/null -+++ b/dev/reports/PR_26180_OWNER_013-remove-legacy-layout_branch-validation.md -@@ -0,0 +1,74 @@ -+# PR_26180_OWNER_013-remove-legacy-layout Branch Validation -+ -+Generated: 2026-06-28T23:33:01.682Z ++++ b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_branch-validation.md +@@ -0,0 +1,11 @@ ++# PR_26180_OWNER_014 Branch Validation + +| Check | Result | Evidence | -+|---|---|---| -+| Current branch | PASS | PR_26180_OWNER_013-remove-legacy-layout | -+| Expected branch | PASS | PR_26180_OWNER_013-remove-legacy-layout | -+| Stacked base | PASS | PR_26180_OWNER_012-update-ci-and-scripts is an ancestor of HEAD | -+| Worktree reviewed | PASS | Only governance, dev test/reference cleanup, reports, and one path-copy Owner page update are in scope | -+| Runtime behavior change | PASS | No product behavior change intended | -+| New www/api/dev files moved | PASS | No move of new www/api/dev application files in this PR | -+| Legacy folders deleted | PASS | No tracked legacy folders remained to delete; untracked/ignored local files left untouched | -+ -+HEAD at start of report: b802afcd33b892d33610a577b160cb096fe2e721 -+ -+## Current Status Snapshot -+ -+```text -+M dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS.md -+ M dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS_VERSION.md -+ M dev/build/ProjectInstructions/PROJECT_STATE.md -+ M dev/build/ProjectInstructions/backlog/BACKLOG_MASTER.md -+ M dev/build/ProjectInstructions/repository/repository_layout_architecture_plan.md -+ M dev/tests/dev-runtime/AdminNotesBoundary.test.mjs -+ M dev/tests/dev-runtime/ApiMenuPathCleanup.test.mjs -+ M dev/tests/final/ToolchainEngineIntegrationValidation.test.mjs -+ M dev/tests/fixtures/games/AsteroidsValidation.test.mjs.patch -+ M dev/tests/fixtures/tools/VectorNativeTemplate.test.mjs.patch -+ M dev/tests/fixtures/workspace-v2/uat.manifest.json -+ M dev/tests/helpers/playwrightV8CoverageReporter.mjs -+ M dev/tests/helpers/testCoverageCatalog.mjs -+ M dev/tests/playwright_installation.txt -+ M dev/tests/production/TestsValidationCombinedPass.test.mjs -+ M dev/tests/runtime/V2BlockFakeSessionSave.test.mjs -+ M dev/tests/runtime/V2ClearStaleMergePreview.test.mjs -+ M dev/tests/runtime/V2ConfirmPreviewEnableState.test.mjs -+ M dev/tests/runtime/V2CrossToolFlow.test.mjs -+ M dev/tests/runtime/V2CrossToolMergeBlock.test.mjs -+ M dev/tests/runtime/V2DeterministicStateTransitions.test.mjs -+ M dev/tests/runtime/V2DiffViewerMessaging.test.mjs -+ M dev/tests/runtime/V2DiffViewerSummaryCounts.test.mjs -+ M dev/tests/runtime/V2EnableStateFeedback.test.mjs -+ M dev/tests/runtime/V2MergeConflictSummary.test.mjs -+ M dev/tests/runtime/V2MergeOutputPersistence.test.mjs -+ M dev/tests/runtime/V2MergePreviewOverlayFix.test.mjs -+ M dev/tests/runtime/V2MergeResultSummary.test.mjs -+ M dev/tests/runtime/V2MergeStateSingleSourceOfTruth.test.mjs -+ M dev/tests/runtime/V2MergeStateStatusReset.test.mjs -+ M dev/tests/runtime/V2MergedRecentSessionRegistration.test.mjs -+ M dev/tests/runtime/V2SaveLibraryFromRecentSession.test.mjs -+ M dev/tests/runtime/V2SavedSessionRowActions.test.mjs -+ M dev/tests/runtime/V2SelectionSyncRowActions.test.mjs -+ M dev/tests/runtime/V2SessionLibraryActionCleanup.test.mjs -+ M dev/tests/runtime/V2SessionLibraryActionLabel.test.mjs -+ M dev/tests/runtime/V2SessionLibraryActions.test.mjs -+ M dev/tests/runtime/V2SessionLibraryCardOverwrite.test.mjs -+ M dev/tests/runtime/V2SessionLibrarySaveGuard.test.mjs -+ M dev/tests/runtime/V2SessionStateModelConsolidation.test.mjs -+ M dev/tests/runtime/V2SessionToolsCloseoutBundle.test.mjs -+ M dev/tests/runtime/V2SessionUxStabilization.test.mjs -+ M dev/tests/runtime/V2ToolLaunch.test.mjs -+ M dev/tests/runtime/V2UndoButtonRender.test.mjs -+ M dev/tests/runtime/V2UndoEnableStateActualAvailability.test.mjs -+ M dev/tests/runtime/V2UndoEnableStateRefresh.test.mjs -+ M dev/tests/runtime/V2UndoLastMerge.test.mjs -+ M dev/tests/runtime/V2WorkspaceDefaultToolInitialization.test.mjs -+ M dev/tests/schemas/tool.manifest.schema.json -+ M dev/tests/shared/ContractFixtureIsolationValidation.test.mjs -+ M dev/tests/shared/ContractIndexValidation.test.mjs -+ M dev/tests/shared/ContractNegativeCaseCoverage.test.mjs -+ M dev/tests/tools/ToolManifestBoundary.test.mjs -+ M www/owner/notes.html -+``` -diff --git a/dev/reports/PR_26180_OWNER_013-remove-legacy-layout_manual-validation-notes.md b/dev/reports/PR_26180_OWNER_013-remove-legacy-layout_manual-validation-notes.md ++|---|---:|---| ++| Current branch | PASS | `PR_26180_OWNER_014-remaining-legacy-layout-cleanup` | ++| Expected stacked base | PASS | Created from `PR_26180_OWNER_013-remove-legacy-layout` | ++| Project Instructions loaded | PASS | Repository Project Instructions version `2026.06.28.014` | ++| Branching policy loaded | PASS | `PROJECT_BRANCHING_POLICY.md` version `2026.06.28.002` | ++| Scope | PASS | Remaining layout cleanup, favicon move, environment policy documentation, tests/references only | ++| Runtime/API/database implementation changes | PASS | None | ++ +diff --git a/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_manual-validation-notes.md b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_manual-validation-notes.md new file mode 100644 -index 000000000..866319806 +index 000000000..ca0138110 --- /dev/null -+++ b/dev/reports/PR_26180_OWNER_013-remove-legacy-layout_manual-validation-notes.md -@@ -0,0 +1,10 @@ -+# PR_26180_OWNER_013-remove-legacy-layout Manual Validation Notes -+ -+Generated: 2026-06-28T23:33:01.682Z -+ -+- Reviewed changed files for scope: governance/status docs, dev test/reference cleanup, validation evidence, and one Owner notes archived path reference. -+- Confirmed no UI redesign, API behavior change, database change, or product feature work is included. -+- Confirmed public URL references remain intentionally preserved for route compatibility. -+- Confirmed tracked obsolete root legacy folders were not present for deletion in this PR. -+- Confirmed untracked/ignored local legacy-looking files were not staged or committed. -+- Outcome ZIP is expected at dev/workspace/zips/PR_26180_OWNER_013-remove-legacy-layout_delta.zip. -diff --git a/dev/reports/PR_26180_OWNER_013-remove-legacy-layout_report.md b/dev/reports/PR_26180_OWNER_013-remove-legacy-layout_report.md ++++ b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_manual-validation-notes.md +@@ -0,0 +1,9 @@ ++# PR_26180_OWNER_014 Manual Validation Notes ++ ++- Public favicon URL remains `/favicon.svg`. ++- Static route compatibility now verifies that `/favicon.svg` resolves to the browser-served `www/favicon.svg` file. ++- No `.env` files were moved into `www/` or `api/`. ++- `src/` remains in place because current application, API client, shared runtime, dev tooling, and tests still reference it. ++- Root ignored/generated artifacts were not staged. ++- Playwright coverage output generated by the local run was not included as a PR change. ++ +diff --git a/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_report.md b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_report.md new file mode 100644 -index 000000000..ea68ec1b5 +index 000000000..bdcb8e9ab --- /dev/null -+++ b/dev/reports/PR_26180_OWNER_013-remove-legacy-layout_report.md -@@ -0,0 +1,104 @@ -+# PR_26180_OWNER_013-remove-legacy-layout Report ++++ b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_report.md +@@ -0,0 +1,49 @@ ++# PR_26180_OWNER_014 Remaining Legacy Layout Cleanup Report ++ ++## Executive Summary + -+Generated: 2026-06-28T23:33:01.682Z -+Team: Owner -+Mode: BUILD_PR -+Branch: PR_26180_OWNER_013-remove-legacy-layout -+Base dependency: PR_26180_OWNER_012-update-ci-and-scripts -+Stack order: after PR_26180_OWNER_012, before final layout validation ++PR_26180_OWNER_014 audits the remaining tracked repository layout after the `www/`, `api/`, and `dev/` migration stack. The only tracked browser-served root file found in scope was `favicon.svg`, which is now under `www/favicon.svg` while public references remain `/favicon.svg`. + -+## Purpose ++The PR also documents environment file placement policy: local `.env` files remain user/environment-owned at the repository root and are never deployed; production uses deployment-managed environment variables/secrets; `www/` must not contain secrets; `api/` reads environment values from `process.env` and the deployment environment. + -+Remove active obsolete legacy layout references after the www/api/dev migration stack, without changing product behavior or moving the new www/api/dev files. ++## Scope Decision + -+## Scope Summary ++- Browser-served favicon moved from repository root to `www/`. ++- Public favicon URL `/favicon.svg` preserved. ++- `src/` retained as an active transition namespace because tracked browser, API, dev tooling, and tests still import from it. ++- No `.env` files moved into `www/` or `api/`. ++- No runtime/API/UI/database behavior changed. + -+- Updated Project Instructions, project state, backlog, and repository layout plan to version 2026.06.28.013 and this PR's migration status. -+- Retired active references to obsolete filesystem paths such as root tests/, docs_build/, root toolbox filesystem references, and dev/build/dev contract spec paths. -+- Updated dev test helpers and validation evidence to use canonical dev/tests, www/, and dev/build/ProjectInstructions paths. -+- Kept public URL compatibility references such as /toolbox, /assets, and /games intentionally intact. -+- Updated www/owner/notes.html only to point its Admin Notes status/help text at the archived dev location already used by the service. ++## Root Audit + -+## Files Changed ++Tracked root entries are limited to standard repository metadata/config plus `api/`, `dev/`, `src/`, and `www/`. Ignored local folders/files such as local `.env*`, generated workspace outputs, and dependency folders are not part of this PR and were not staged. + -+- dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS.md -+- dev/build/ProjectInstructions/PROJECT_INSTRUCTIONS_VERSION.md -+- dev/build/ProjectInstructions/PROJECT_STATE.md -+- dev/build/ProjectInstructions/backlog/BACKLOG_MASTER.md -+- dev/build/ProjectInstructions/repository/repository_layout_architecture_plan.md -+- dev/reports/PR_26180_OWNER_013-remove-legacy-layout_branch-validation.md -+- dev/reports/PR_26180_OWNER_013-remove-legacy-layout_manual-validation-notes.md -+- dev/reports/PR_26180_OWNER_013-remove-legacy-layout_report.md -+- dev/reports/PR_26180_OWNER_013-remove-legacy-layout_requirement-checklist.md -+- dev/reports/PR_26180_OWNER_013-remove-legacy-layout_validation-report.md -+- dev/reports/codex_changed_files.txt -+- dev/reports/codex_review.diff -+- dev/tests/dev-runtime/AdminNotesBoundary.test.mjs -+- dev/tests/dev-runtime/ApiMenuPathCleanup.test.mjs -+- dev/tests/final/ToolchainEngineIntegrationValidation.test.mjs -+- dev/tests/fixtures/games/AsteroidsValidation.test.mjs.patch -+- dev/tests/fixtures/tools/VectorNativeTemplate.test.mjs.patch -+- dev/tests/fixtures/workspace-v2/uat.manifest.json -+- dev/tests/helpers/playwrightV8CoverageReporter.mjs -+- dev/tests/helpers/testCoverageCatalog.mjs -+- dev/tests/playwright_installation.txt -+- dev/tests/production/TestsValidationCombinedPass.test.mjs -+- dev/tests/runtime/V2BlockFakeSessionSave.test.mjs -+- dev/tests/runtime/V2ClearStaleMergePreview.test.mjs -+- dev/tests/runtime/V2ConfirmPreviewEnableState.test.mjs -+- dev/tests/runtime/V2CrossToolFlow.test.mjs -+- dev/tests/runtime/V2CrossToolMergeBlock.test.mjs -+- dev/tests/runtime/V2DeterministicStateTransitions.test.mjs -+- dev/tests/runtime/V2DiffViewerMessaging.test.mjs -+- dev/tests/runtime/V2DiffViewerSummaryCounts.test.mjs -+- dev/tests/runtime/V2EnableStateFeedback.test.mjs -+- dev/tests/runtime/V2MergeConflictSummary.test.mjs -+- dev/tests/runtime/V2MergeOutputPersistence.test.mjs -+- dev/tests/runtime/V2MergePreviewOverlayFix.test.mjs -+- dev/tests/runtime/V2MergeResultSummary.test.mjs -+- dev/tests/runtime/V2MergeStateSingleSourceOfTruth.test.mjs -+- dev/tests/runtime/V2MergeStateStatusReset.test.mjs -+- dev/tests/runtime/V2MergedRecentSessionRegistration.test.mjs -+- dev/tests/runtime/V2SaveLibraryFromRecentSession.test.mjs -+- dev/tests/runtime/V2SavedSessionRowActions.test.mjs -+- dev/tests/runtime/V2SelectionSyncRowActions.test.mjs -+- dev/tests/runtime/V2SessionLibraryActionCleanup.test.mjs -+- dev/tests/runtime/V2SessionLibraryActionLabel.test.mjs -+- dev/tests/runtime/V2SessionLibraryActions.test.mjs -+- dev/tests/runtime/V2SessionLibraryCardOverwrite.test.mjs -+- dev/tests/runtime/V2SessionLibrarySaveGuard.test.mjs -+- dev/tests/runtime/V2SessionStateModelConsolidation.test.mjs -+- dev/tests/runtime/V2SessionToolsCloseoutBundle.test.mjs -+- dev/tests/runtime/V2SessionUxStabilization.test.mjs -+- dev/tests/runtime/V2ToolLaunch.test.mjs -+- dev/tests/runtime/V2UndoButtonRender.test.mjs -+- dev/tests/runtime/V2UndoEnableStateActualAvailability.test.mjs -+- dev/tests/runtime/V2UndoEnableStateRefresh.test.mjs -+- dev/tests/runtime/V2UndoLastMerge.test.mjs -+- dev/tests/runtime/V2WorkspaceDefaultToolInitialization.test.mjs -+- dev/tests/schemas/tool.manifest.schema.json -+- dev/tests/shared/ContractFixtureIsolationValidation.test.mjs -+- dev/tests/shared/ContractIndexValidation.test.mjs -+- dev/tests/shared/ContractNegativeCaseCoverage.test.mjs -+- dev/tests/tools/ToolManifestBoundary.test.mjs -+- www/owner/notes.html ++Additional standard root files retained as repository configuration/history: + -+## Legacy Layout Decision ++- `.codex/` ++- `.gitattributes` ++- `.githooks/` ++- `.gitignore` ++- `AGENTS.md` ++- `LICENSE` + -+No tracked root legacy folders were removed because git tracking showed no active tracked files under obsolete root locations such as docs_build/, tests/, archive/, tmp/, projects/, scripts/, project-instructions/, dev/docs_build/, dev/project-instructions/, dev/workspace/artifacts/, or dev/build/dev/. ++## src/ Audit + -+Local ignored or untracked legacy-looking files were left untouched and were not staged. ++`src/` is not empty and remains referenced by current `www/`, `api/`, `dev/tests/`, and `dev/tools/` surfaces. Current Project Instructions document `src/advanced`, `src/api`, `src/engine`, `src/shared`, `src/tools`, and `src/dev-runtime/admin` as legacy transition buckets pending explicit follow-up migration. This PR does not move or delete `src/`. + -+## Compatibility Notes ++## File Evidence + -+Browser public routes remain unchanged. References to /toolbox, /assets, /games, /account, /admin, and related public URLs are compatibility routes, not obsolete filesystem references. ++- `www/favicon.svg`: browser-served favicon location after the move. ++- `dev/tests/dev-runtime/StaticWebRootCompatibility.test.mjs`: verifies `/favicon.svg` resolves to `www/favicon.svg`. ++- `dev/scripts/PS/deploy/WebsiteRepoDeploymentCommon.ps1`: deployment include list now references `www/favicon.svg`. ++- `dev/build/ProjectInstructions/repository/canonical_repository_structure.md`: documents root `.env`, `www/`, and `api/` environment ownership. ++- `dev/build/ProjectInstructions/addendums/environment_configuration_standards.md`: adds the runtime placement policy for environment values. + -+## Dependency Order ++## Remaining Technical Debt + -+- Previous dependency: PR_26180_OWNER_012-update-ci-and-scripts -+- Current PR: PR_26180_OWNER_013-remove-legacy-layout -+- Next dependency: final layout validation PR ++The PowerShell deployment helper still contains broader legacy include defaults such as root `index.html`, `games`, `samples`, `src`, and `tools`. This PR updates only the tracked favicon path because changing the broader deploy staging semantics would be a separate deployment-layout PR. + +## Owner Recommendation + -+Ready for review after validation, with no product behavior changes and no new feature scope. -diff --git a/dev/reports/PR_26180_OWNER_013-remove-legacy-layout_requirement-checklist.md b/dev/reports/PR_26180_OWNER_013-remove-legacy-layout_requirement-checklist.md ++Keep this PR focused as the remaining legacy layout cleanup pass. Follow with the final layout validation PR after stacked dependencies land. ++ +diff --git a/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_requirement-checklist.md b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_requirement-checklist.md new file mode 100644 -index 000000000..16c303f6a +index 000000000..9dfc5a54b --- /dev/null -+++ b/dev/reports/PR_26180_OWNER_013-remove-legacy-layout_requirement-checklist.md -@@ -0,0 +1,14 @@ -+# PR_26180_OWNER_013-remove-legacy-layout Requirement Checklist -+ -+Generated: 2026-06-28T23:33:01.682Z ++++ b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_requirement-checklist.md +@@ -0,0 +1,16 @@ ++# PR_26180_OWNER_014 Requirement Checklist + +| Requirement | Result | Notes | -+|---|---|---| -+| Remove or retire obsolete legacy layout paths | PASS | Active stale references were updated to canonical www/api/dev/dev-build paths. | -+| Confirm references are updated before removal | PASS | Targeted legacy-path scan passed for active code/config/tests/package/CI surfaces. | -+| Hard stop if active runtime/test/CI/package references still point to obsolete paths | PASS | No blocking active references found after cleanup. | -+| Preserve documented compatibility references only where intentional | PASS | Public URLs like /toolbox and /assets remain intentionally preserved. | -+| Do not change product behavior | PASS | Changes are reference/path cleanup and validation alignment. | -+| Do not move new www/api/dev files | PASS | No www/api/dev application move was performed. | -+| Update required reports under dev/reports | PASS | Required reports generated. | -+| Produce repo-structured ZIP under dev/workspace/zips | PASS | ZIP generated during closeout. | -diff --git a/dev/reports/PR_26180_OWNER_013-remove-legacy-layout_validation-report.md b/dev/reports/PR_26180_OWNER_013-remove-legacy-layout_validation-report.md ++|---|---:|---| ++| Base on `PR_26180_OWNER_013-remove-legacy-layout` | PASS | Stacked branch created from PR013 branch. | ++| Identify remaining old folders/files outside `www/`, `api/`, and `dev/` | PASS | Tracked root scan found no tracked legacy browser/dev folders; standard repo config files remain. | ++| Determine whether each remaining root item is allowed, should move, or should be removed | PASS | Standard repo config retained; `favicon.svg` moved; `src/` retained as documented transition namespace. | ++| Move `favicon.svg` into `www/` if browser-served | PASS | `favicon.svg` moved to `www/favicon.svg`. | ++| Update references to `favicon.svg` after move | PASS | Deployment include list and route-root test updated; public `/favicon.svg` references intentionally preserved. | ++| Audit remaining `src/` contents | PASS | `src/` remains actively referenced and is documented as a transition namespace. | ++| Do not move `.env` into `www/` or `api/` | PASS | No `.env` files moved. | ++| Document `.env` policy | PASS | Policy added to canonical repository structure and environment configuration standards. | ++| Do not change product behavior | PASS | Public URLs and route behavior preserved. | ++| Required reports under `dev/reports/` | PASS | PR-specific reports generated. | ++| Required ZIP under `dev/workspace/zips/` | PASS | ZIP generated during closeout. | ++ +diff --git a/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_validation-report.md b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_validation-report.md new file mode 100644 -index 000000000..a124ab9d1 +index 000000000..906822fb1 --- /dev/null -+++ b/dev/reports/PR_26180_OWNER_013-remove-legacy-layout_validation-report.md -@@ -0,0 +1,31 @@ -+# PR_26180_OWNER_013-remove-legacy-layout Validation Report -+ -+Generated: 2026-06-28T23:33:01.682Z -+ -+## Commands -+ -+| Command | Result | -+|---|---| -+| git diff --check | PASS | -+| npm run validate:canonical-structure | PASS | -+| npm run validate:platform | PASS | -+| targeted legacy-path scan | PASS | -+| node --test dev/tests/dev-runtime/TeamAwareBootstrap.test.mjs dev/tests/runtime/V2ToolLaunch.test.mjs dev/tests/shared/ContractIndexValidation.test.mjs dev/tests/dev-runtime/AdminNotesBoundary.test.mjs dev/tests/tools/ToolManifestBoundary.test.mjs dev/tests/production/TestsValidationCombinedPass.test.mjs dev/tests/shared/ContractFixtureIsolationValidation.test.mjs dev/tests/shared/ContractNegativeCaseCoverage.test.mjs dev/tests/dev-runtime/ApiMenuPathCleanup.test.mjs | PASS | -+ -+## Platform Validation -+ -+`npm run validate:platform` completed successfully with 8/8 scenarios passing. -+ -+## Canonical Structure -+ -+`npm run validate:canonical-structure` completed successfully with 0 blocking violations. -+ -+## Legacy Path Scan -+ -+Targeted scan excluded reports, archives, and generated workspace output, and checked active GitHub workflows, api, dev/scripts, dev/tests, src, www, and package.json for obsolete filesystem references. -+ -+Result: PASS. -+ -+## Bootstrap Command Check -+ -+Covered by targeted TeamAwareBootstrap test. The public command surface remains preserved by prior PR012 and is not changed by this PR. -diff --git a/dev/tests/dev-runtime/AdminNotesBoundary.test.mjs b/dev/tests/dev-runtime/AdminNotesBoundary.test.mjs -index 5918522ba..c75f6c641 100644 ---- a/dev/tests/dev-runtime/AdminNotesBoundary.test.mjs -+++ b/dev/tests/dev-runtime/AdminNotesBoundary.test.mjs -@@ -194,14 +194,14 @@ test("Owner Notes route is the only production-facing Admin Notes viewer route", - assert.doesNotMatch(ownerNotesSource, /\son[a-z]+\s*=/i, "Owner Notes page must not contain inline event handlers"); - assert.match(ownerNotesSource, /data-owner-notes/, "Owner Notes page keeps Owner route marker"); - assert.match(ownerNotesSource, /data-admin-notes-viewer/, "Owner Notes page reuses the Admin Notes viewer pattern"); -- assert.match(ownerNotesSource, /docs_build\/dev\/admin-notes/, "Owner Notes page points at the admin-notes source folder"); -+ assert.match(ownerNotesSource, /dev\/archive\/legacy-docs-build\/admin-notes/, "Owner Notes page points at the admin-notes source folder"); - assert.match(ownerNotesSource, /\.\.\/src\/dev-runtime\/admin\/admin-notes-viewer\.js/, "Owner Notes page reuses the existing viewer script"); - assert.doesNotMatch(ownerNotesSource, /Game Journey owns note editing|Open Game Journey/, "Owner Notes page must not use the old placeholder workflow"); ++++ b/dev/reports/PR_26180_OWNER_014-remaining-legacy-layout-cleanup_validation-report.md +@@ -0,0 +1,16 @@ ++# PR_26180_OWNER_014 Validation Report ++ ++| Validation | Result | Notes | ++|---|---:|---| ++| `node --test dev/tests/dev-runtime/StaticWebRootCompatibility.test.mjs dev/tests/dev-runtime/TeamAwareBootstrap.test.mjs dev/tests/tools/GameAssetManifestDiscovery.test.mjs` | PASS | 18 tests passed. | ++| `npx playwright test dev/tests/playwright/tools/StaticWebRootCompatibility.spec.mjs dev/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs dev/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs` | PASS | 8 Playwright tests passed. | ++| Targeted legacy layout scan | PASS | No tracked root legacy browser/dev folders remain; active scripts/tests only reference dev-owned script paths. | ++| `node --test dev/tests/dev-runtime/TeamAwareBootstrap.test.mjs` | PASS | 12 tests passed. | ++| Package script command surface check | PASS | `dev:bootstrap`, `dev:api`, `dev:web`, and `dev:local-api` are present. | ++| `git diff --check` | PASS | Whitespace check passed; Git reported line-ending conversion warnings only. | ++| `npm run validate:canonical-structure` | PASS | Blocking violations: 0; approved legacy exceptions: 503. | ++ ++## Notes ++ ++The targeted Playwright run updated a shared coverage artifact during execution. That generated churn was not retained in this PR; validation evidence is captured in the PR-specific reports instead. ++ +diff --git a/dev/scripts/PS/deploy/WebsiteRepoDeploymentCommon.ps1 b/dev/scripts/PS/deploy/WebsiteRepoDeploymentCommon.ps1 +index 99942faab..8003e5b70 100644 +--- a/dev/scripts/PS/deploy/WebsiteRepoDeploymentCommon.ps1 ++++ b/dev/scripts/PS/deploy/WebsiteRepoDeploymentCommon.ps1 +@@ -702,7 +702,7 @@ function New-WebsiteDeploymentPlan { + function Get-DefaultWebsiteIncludePaths { + return @( + "index.html", +- "favicon.svg", ++ "www/favicon.svg", + "games", + "samples", + "src", +diff --git a/dev/tests/dev-runtime/StaticWebRootCompatibility.test.mjs b/dev/tests/dev-runtime/StaticWebRootCompatibility.test.mjs +index 3510f2af6..884f7aec8 100644 +--- a/dev/tests/dev-runtime/StaticWebRootCompatibility.test.mjs ++++ b/dev/tests/dev-runtime/StaticWebRootCompatibility.test.mjs +@@ -55,6 +55,17 @@ test("static route target can prefer a configured www root before repo-root fall + assert.equal(routeTarget.webRoot.relativePath, "www"); }); - test("production-facing paths only expose Admin Notes through Owner Notes", () => { - const headerSource = fs.readFileSync(repoPath("www/assets/theme-v2/partials/header-nav.html"), "utf8"); -- assert.doesNotMatch(headerSource, /docs_build\/dev\/admin-notes|admin-notes-dev|data-admin-notes-local-menu|data-admin-my-stuff-menu|My Stuff|Admin Notes/); -+ assert.doesNotMatch(headerSource, /dev\/archive\/legacy-docs-build\/admin-notes|admin-notes-dev|data-admin-notes-local-menu|data-admin-my-stuff-menu|My Stuff|Admin Notes/); - for (const label of devOnlyAdminLabels) { - assert.doesNotMatch(headerSource, new RegExp(`>${label}<\\/a>`), `production Admin menu omits dev-only ${label}`); - } -@@ -216,7 +216,7 @@ test("production-facing paths only expose Admin Notes through Owner Notes", () = - return false; - } - const source = fs.readFileSync(filePath, "utf8"); -- return /docs_build\/dev\/admin-notes|docs_build\\dev\\admin-notes|src\/dev-runtime\/admin|src\\dev-runtime\\admin|data-admin-my-stuff-menu|My Stuff|admin-notes|Admin Notes/.test(source); -+ return /dev\/archive\/legacy-docs-build\/admin-notes|dev\\archive\\legacy-docs-build\\admin-notes|src\/dev-runtime\/admin|src\\dev-runtime\\admin|data-admin-my-stuff-menu|My Stuff|admin-notes|Admin Notes/.test(source); - }) - .map(relativePath); - -@@ -306,7 +306,7 @@ test("Admin page left menus use dynamic placeholders without Notes duplication", - for (const label of devOnlyAdminLabels) { - assert.doesNotMatch(source, new RegExp(`>${label}<\\/a>`), `${pageName} left menu omits ${label}`); - } -- assert.doesNotMatch(source, /docs_build\/dev\/admin-notes|src\/dev-runtime\/admin|admin-notes|Admin Notes/); -+ assert.doesNotMatch(source, /dev\/archive\/legacy-docs-build\/admin-notes|src\/dev-runtime\/admin|admin-notes|Admin Notes/); - } - - assert.ok(checkedPages.length > 0, "Admin pages with side menus were checked"); -diff --git a/dev/tests/dev-runtime/ApiMenuPathCleanup.test.mjs b/dev/tests/dev-runtime/ApiMenuPathCleanup.test.mjs -index 086b1a9a3..82ee5db82 100644 ---- a/dev/tests/dev-runtime/ApiMenuPathCleanup.test.mjs -+++ b/dev/tests/dev-runtime/ApiMenuPathCleanup.test.mjs -@@ -131,9 +131,9 @@ test("business-control pages moved under owner and are absent from admin", () => - test("active app code no longer links to moved Admin business paths", () => { - const offenders = activeTextSources() - .filter(({ fileName, source }) => { -- if (fileName.startsWith("tests/playwright/tools/LoginSessionMode.spec.mjs") -- || fileName.startsWith("tests/playwright/tools/RootToolsFutureState.spec.mjs") -- || fileName.startsWith("tests/playwright/tools/AdminPlatformToolsWireframes.spec.mjs")) { -+ if (fileName.startsWith("dev/tests/playwright/tools/LoginSessionMode.spec.mjs") -+ || fileName.startsWith("dev/tests/playwright/tools/RootToolsFutureState.spec.mjs") -+ || fileName.startsWith("dev/tests/playwright/tools/AdminPlatformToolsWireframes.spec.mjs")) { - return false; - } - return /admin\/(branding|design-system|grouping-colors|site-settings|themes)\.html|admin-(branding|design-system|grouping-colors|site-settings|themes)/.test(source); -diff --git a/dev/tests/final/ToolchainEngineIntegrationValidation.test.mjs b/dev/tests/final/ToolchainEngineIntegrationValidation.test.mjs -index fcda15676..aec97733a 100644 ---- a/dev/tests/final/ToolchainEngineIntegrationValidation.test.mjs -+++ b/dev/tests/final/ToolchainEngineIntegrationValidation.test.mjs -@@ -24,19 +24,19 @@ function runNodeTestFile(relativeTestPath) { - const TRACK_E_TOOLCHAIN_VALIDATION_STAGES = Object.freeze([ - Object.freeze({ - id: "tool-entry-launch-contract", -- run: async () => runNodeTestFile("tests/tools/ToolEntryLaunchContract.test.mjs") -+ run: async () => runNodeTestFile("dev/tests/tools/ToolEntryLaunchContract.test.mjs") - }), - Object.freeze({ - id: "project-tool-data-contracts", -- run: async () => runNodeTestFile("tests/tools/ProjectToolDataContracts.test.mjs") -+ run: async () => runNodeTestFile("dev/tests/tools/ProjectToolDataContracts.test.mjs") - }), - Object.freeze({ - id: "runtime-asset-loader", -- run: async () => runNodeTestFile("tests/tools/RuntimeAssetLoader.test.mjs") -+ run: async () => runNodeTestFile("dev/tests/tools/RuntimeAssetLoader.test.mjs") - }), - Object.freeze({ - id: "render-pipeline-contract-all-4-tools", -- run: async () => runNodeTestFile("tests/tools/RenderPipelineContractAll4Tools.test.mjs") -+ run: async () => runNodeTestFile("dev/tests/tools/RenderPipelineContractAll4Tools.test.mjs") - }), - Object.freeze({ - id: "runtime-scene-loader-hot-reload", -diff --git a/dev/tests/fixtures/games/AsteroidsValidation.test.mjs.patch b/dev/tests/fixtures/games/AsteroidsValidation.test.mjs.patch -index d7cd2648b..7051760b9 100644 ---- a/dev/tests/fixtures/games/AsteroidsValidation.test.mjs.patch -+++ b/dev/tests/fixtures/games/AsteroidsValidation.test.mjs.patch -@@ -1,4 +1,4 @@ --*** MANUAL PATCH FOR tests/games/AsteroidsValidation.test.mjs *** -+*** MANUAL PATCH FOR dev/tests/games/AsteroidsValidation.test.mjs *** - - 1) Export the test runner function - -diff --git a/dev/tests/fixtures/tools/VectorNativeTemplate.test.mjs.patch b/dev/tests/fixtures/tools/VectorNativeTemplate.test.mjs.patch -index 6d0183cf5..13cb2b4e3 100644 ---- a/dev/tests/fixtures/tools/VectorNativeTemplate.test.mjs.patch -+++ b/dev/tests/fixtures/tools/VectorNativeTemplate.test.mjs.patch -@@ -1,4 +1,4 @@ --*** MANUAL PATCH FOR tests/tools/VectorNativeTemplate.test.mjs *** -+*** MANUAL PATCH FOR dev/tests/tools/VectorNativeTemplate.test.mjs *** - - Find: - /Template path: templates\/vector-native-arcade\// -diff --git a/dev/tests/fixtures/workspace-v2/uat.manifest.json b/dev/tests/fixtures/workspace-v2/uat.manifest.json -index 08101a0dc..ba92a4da7 100644 ---- a/dev/tests/fixtures/workspace-v2/uat.manifest.json -+++ b/dev/tests/fixtures/workspace-v2/uat.manifest.json -@@ -20,7 +20,7 @@ - "id": "workspace-manager-v2-uat-sample", - "name": "Workspace Manager V2 UAT Sample Palette", - "source": "Workspace Manager V2 temporary UAT sample", -- "sourceId": "tests/fixtures/workspace-v2/uat.manifest.json", -+ "sourceId": "dev/tests/fixtures/workspace-v2/uat.manifest.json", - "locked": true, - "swatches": [ - { -diff --git a/dev/tests/helpers/playwrightV8CoverageReporter.mjs b/dev/tests/helpers/playwrightV8CoverageReporter.mjs -index 774e18996..dabe614e2 100644 ---- a/dev/tests/helpers/playwrightV8CoverageReporter.mjs -+++ b/dev/tests/helpers/playwrightV8CoverageReporter.mjs -@@ -276,11 +276,10 @@ export class PlaywrightV8CoverageReporter { - return false; - } - return filePath.startsWith("src/") -- || filePath.startsWith("admin/") -- || filePath.startsWith("assets/theme-v2/js/") -- || filePath.startsWith("games/Asteroids/") -- || filePath.startsWith("toolbox/") -- || filePath.startsWith("common/"); -+ || filePath.startsWith("www/admin/") -+ || filePath.startsWith("www/assets/theme-v2/js/") -+ || filePath.startsWith("www/games/Asteroids/") -+ || filePath.startsWith("www/toolbox/"); - } - - pathFromStatusLine(line) { -@@ -327,9 +326,9 @@ export class PlaywrightV8CoverageReporter { ++test("favicon resolves from the browser-served www root", async () => { ++ const routeTarget = await resolveStaticRouteTarget({ ++ decodedPath: "/favicon.svg", ++ repoRoot, ++ webRoot: WWW_LOCAL_WEB_ROOT, ++ }); ++ assert.equal(routeTarget.routePath, "/favicon.svg"); ++ assert.equal(routeTarget.targetPath, path.join(repoRoot, "www", "favicon.svg")); ++ assert.equal(routeTarget.webRoot.relativePath, "www"); ++}); ++ + test("local static web server can serve from a configurable web root", async () => { + const fixtureRoot = path.join(repoRoot, "dev", "workspace", "tmp", "static-web-root-compatibility"); + await fs.rm(fixtureRoot, { force: true, recursive: true }); +diff --git a/dev/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs b/dev/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs +index d75e47cb0..a4e17660c 100644 +--- a/dev/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs ++++ b/dev/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs +@@ -345,7 +345,7 @@ test("Creator sessions cannot access Admin System Health operations", async ({ p + + test("Admin System Health operations page keeps scripts and styles external", async () => { + const retiredFileDbToken = "SQL" + "ite"; +- const pageSource = await fs.readFile(path.resolve("admin/system-health.html"), "utf8"); ++ const pageSource = await fs.readFile(path.resolve("www/admin/system-health.html"), "utf8"); + expect(pageSource).not.toMatch(/]+src=)/i); + expect(pageSource).not.toMatch(/\son[a-z]+\s*=/i); +@@ -374,7 +374,7 @@ test("Admin System Health operations page keeps scripts and styles external", as + expect(pageSource).toContain("Server-owned Cloudflare R2 storage diagnostic"); + expect(pageSource).toContain("assets/theme-v2/js/admin-system-health.js"); + expect(pageSource).toContain("assets/theme-v2/js/admin-owner-navigation.js"); +- const runtimeSource = await fs.readFile(path.resolve("assets/theme-v2/js/admin-system-health.js"), "utf8"); ++ const runtimeSource = await fs.readFile(path.resolve("www/assets/theme-v2/js/admin-system-health.js"), "utf8"); + expect(runtimeSource).not.toContain(retiredFileDbToken); + expect(runtimeSource).not.toContain("localStorage"); + expect(runtimeSource).not.toContain("sessionStorage"); +diff --git a/dev/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs b/dev/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs +index 782a813a2..e93cca610 100644 +--- a/dev/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs ++++ b/dev/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs +@@ -138,7 +138,7 @@ test("non-Admin users cannot access Admin Invites", async ({ page }) => { + }); - formatToolEntryPoints(coverageByPath) { - const toolEntryPoints = [ -- { name: "Toolbox Index", prefix: "toolbox/" }, -+ { name: "Toolbox Index", prefix: "www/toolbox/" }, - { name: "Tool Template V2", prefix: "dev/templates/tool-template-v2/" }, -- { name: "Theme V2 Shared JS", prefix: "assets/theme-v2/js/" } -+ { name: "Theme V2 Shared JS", prefix: "www/assets/theme-v2/js/" } - ]; - return toolEntryPoints.map(({ name, prefix }) => { - const records = [...coverageByPath.values()].filter((record) => record.repoPath.startsWith(prefix)); -diff --git a/dev/tests/helpers/testCoverageCatalog.mjs b/dev/tests/helpers/testCoverageCatalog.mjs -index aabfa3f21..4295165ef 100644 ---- a/dev/tests/helpers/testCoverageCatalog.mjs -+++ b/dev/tests/helpers/testCoverageCatalog.mjs + test("Admin Invites page keeps scripts and styles external", async () => { +- const pageSource = await fs.readFile(path.resolve("admin/invitations.html"), "utf8"); ++ const pageSource = await fs.readFile(path.resolve("www/admin/invitations.html"), "utf8"); + expect(pageSource).not.toMatch(/]+src=)/i); + expect(pageSource).not.toMatch(/\son[a-z]+\s*=/i); +diff --git a/dev/tests/tools/GameAssetManifestDiscovery.test.mjs b/dev/tests/tools/GameAssetManifestDiscovery.test.mjs +index d499e9249..be4b55705 100644 +--- a/dev/tests/tools/GameAssetManifestDiscovery.test.mjs ++++ b/dev/tests/tools/GameAssetManifestDiscovery.test.mjs @@ -1,6 +1,6 @@ - import path from "node:path"; - --export const TESTS_ROOT = path.resolve("tests"); -+export const TESTS_ROOT = path.resolve("dev/tests"); - - export const REQUIRED_TEST_DIRECTORIES = Object.freeze([ - "core", -@@ -16,23 +16,23 @@ export const REQUIRED_TEST_DIRECTORIES = Object.freeze([ - ]); - - export const UNIT_COVERAGE_ANCHORS = Object.freeze([ -- "tests/core/EngineCoreBoundaryBaseline.test.mjs", -- "tests/shared/SharedFoundationCombinedPass.test.mjs", -- "tests/tools/ToolBoundaryEnforcement.test.mjs" -+ "dev/tests/core/EngineCoreBoundaryBaseline.test.mjs", -+ "dev/tests/shared/SharedFoundationCombinedPass.test.mjs", -+ "dev/tests/tools/ToolBoundaryEnforcement.test.mjs" - ]); - - export const INTEGRATION_COVERAGE_ANCHORS = Object.freeze([ -- "tests/world/WorldGameStateSystem.test.mjs", -- "tests/replay/ReplaySystem.test.mjs", -- "tests/render/Renderer.test.mjs", -- "tests/tools/RuntimeAssetBinding.test.mjs", -- "tests/core/Engine2DCapabilityCombinedFoundation.test.mjs" -+ "dev/tests/world/WorldGameStateSystem.test.mjs", -+ "dev/tests/replay/ReplaySystem.test.mjs", -+ "dev/tests/render/Renderer.test.mjs", -+ "dev/tests/tools/RuntimeAssetBinding.test.mjs", -+ "dev/tests/core/Engine2DCapabilityCombinedFoundation.test.mjs" - ]); - - export const FIXTURE_ARTIFACTS = Object.freeze([ -- "tests/fixtures/games/AsteroidsValidation.snippet.js", -- "tests/fixtures/games/AsteroidsValidation.test.mjs.patch", -- "tests/fixtures/tools/VectorNativeTemplate.regex.before.txt", -- "tests/fixtures/tools/VectorNativeTemplate.regex.after.txt", -- "tests/fixtures/tools/VectorNativeTemplate.test.mjs.patch" -+ "dev/tests/fixtures/games/AsteroidsValidation.snippet.js", -+ "dev/tests/fixtures/games/AsteroidsValidation.test.mjs.patch", -+ "dev/tests/fixtures/tools/VectorNativeTemplate.regex.before.txt", -+ "dev/tests/fixtures/tools/VectorNativeTemplate.regex.after.txt", -+ "dev/tests/fixtures/tools/VectorNativeTemplate.test.mjs.patch" - ]); -diff --git a/dev/tests/playwright_installation.txt b/dev/tests/playwright_installation.txt -index dc1bae980..064c65600 100644 ---- a/dev/tests/playwright_installation.txt -+++ b/dev/tests/playwright_installation.txt -@@ -47,7 +47,7 @@ npx playwright --version - ## ▶️ Run your test - - ```powershell --npx playwright test tests/ui/workspace-v2.asset-manager.spec.js -+npx playwright test dev/tests/ui/workspace-v2.asset-manager.spec.js - ``` - - --- -@@ -100,7 +100,7 @@ npx playwright show-trace - - ```text - HTML-JavaScript-Gaming/ --├── tests/ -+├── dev/tests/ - │ └── ui/ - │ └── workspace-v2.asset-manager.spec.js <<<< test code goes here - ├── dev/config/playwright.config.cjs -diff --git a/dev/tests/production/TestsValidationCombinedPass.test.mjs b/dev/tests/production/TestsValidationCombinedPass.test.mjs -index 3cbe41b75..572d34377 100644 ---- a/dev/tests/production/TestsValidationCombinedPass.test.mjs -+++ b/dev/tests/production/TestsValidationCombinedPass.test.mjs -@@ -24,7 +24,7 @@ function assertRepoDirectory(relativePath) { - - export function run() { - REQUIRED_TEST_DIRECTORIES.forEach((dir) => { -- assertRepoDirectory(`tests/${dir}`); -+ assertRepoDirectory(`dev/tests/${dir}`); - }); - - UNIT_COVERAGE_ANCHORS.forEach((filePath) => { -diff --git a/dev/tests/runtime/V2BlockFakeSessionSave.test.mjs b/dev/tests/runtime/V2BlockFakeSessionSave.test.mjs -index 29b30b29c..48b0233b3 100644 ---- a/dev/tests/runtime/V2BlockFakeSessionSave.test.mjs -+++ b/dev/tests/runtime/V2BlockFakeSessionSave.test.mjs -@@ -109,7 +109,7 @@ export function run() { - - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2BlockFakeSessionSave.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2BlockFakeSessionSave.test.mjs failed syntax check."); - - const requiredTokens = [ - "readSessionPayloadForLibraryWrite(sessionId)", -diff --git a/dev/tests/runtime/V2ClearStaleMergePreview.test.mjs b/dev/tests/runtime/V2ClearStaleMergePreview.test.mjs -index 337bc2bbf..f928cf560 100644 ---- a/dev/tests/runtime/V2ClearStaleMergePreview.test.mjs -+++ b/dev/tests/runtime/V2ClearStaleMergePreview.test.mjs -@@ -64,7 +64,7 @@ export function run() { - - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2ClearStaleMergePreview.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2ClearStaleMergePreview.test.mjs failed syntax check."); - - const requiredTokens = [ - "handleMergeSelectionChange()", -diff --git a/dev/tests/runtime/V2ConfirmPreviewEnableState.test.mjs b/dev/tests/runtime/V2ConfirmPreviewEnableState.test.mjs -index e2066591d..021b2226d 100644 ---- a/dev/tests/runtime/V2ConfirmPreviewEnableState.test.mjs -+++ b/dev/tests/runtime/V2ConfirmPreviewEnableState.test.mjs -@@ -52,7 +52,7 @@ export function run() { - if (!htmlExists) failures.push("Missing toolbox/workspace-v2/index.html."); - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2ConfirmPreviewEnableState.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2ConfirmPreviewEnableState.test.mjs failed syntax check."); - - const requiredTokens = [ - "conflictCount: Object.keys(result.conflicts).length", -diff --git a/dev/tests/runtime/V2CrossToolFlow.test.mjs b/dev/tests/runtime/V2CrossToolFlow.test.mjs -index a766fe254..65563ea64 100644 ---- a/dev/tests/runtime/V2CrossToolFlow.test.mjs -+++ b/dev/tests/runtime/V2CrossToolFlow.test.mjs -@@ -56,7 +56,7 @@ function validateFlow(flow) { - let launchUrl = ""; - - if (!sourceFixtureExists) { -- failures.push(`Missing source fixture: tests/fixtures/v2-tools/${flow.sourceTool}.json`); -+ failures.push(`Missing source fixture: dev/tests/fixtures/v2-tools/${flow.sourceTool}.json`); - } else { - const beforeText = fs.readFileSync(sourceFixturePath, "utf8"); - let sourceFixture = null; -@@ -67,7 +67,7 @@ function validateFlow(flow) { - sourceFixtureValid = false; - } - if (!sourceFixtureValid) { -- failures.push(`Invalid source fixture JSON: tests/fixtures/v2-tools/${flow.sourceTool}.json`); -+ failures.push(`Invalid source fixture JSON: dev/tests/fixtures/v2-tools/${flow.sourceTool}.json`); - } else { - sourceHostContextId = typeof sourceFixture.hostContextId === "string" ? sourceFixture.hostContextId.trim() : ""; - if (!sourceHostContextId) { -diff --git a/dev/tests/runtime/V2CrossToolMergeBlock.test.mjs b/dev/tests/runtime/V2CrossToolMergeBlock.test.mjs -index 218ca64b1..5bb344bf1 100644 ---- a/dev/tests/runtime/V2CrossToolMergeBlock.test.mjs -+++ b/dev/tests/runtime/V2CrossToolMergeBlock.test.mjs -@@ -53,7 +53,7 @@ export function run() { - - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2CrossToolMergeBlock.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2CrossToolMergeBlock.test.mjs failed syntax check."); - - const requiredTokens = [ - "Cross-tool merge is not supported. Select two sessions with the same toolId.", -diff --git a/dev/tests/runtime/V2DeterministicStateTransitions.test.mjs b/dev/tests/runtime/V2DeterministicStateTransitions.test.mjs -index a59281aea..f058fd597 100644 ---- a/dev/tests/runtime/V2DeterministicStateTransitions.test.mjs -+++ b/dev/tests/runtime/V2DeterministicStateTransitions.test.mjs -@@ -59,7 +59,7 @@ export function run() { - - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2DeterministicStateTransitions.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2DeterministicStateTransitions.test.mjs failed syntax check."); - - const requiredTokens = [ - "this.workspaceTransitionState = \"idle\";", -diff --git a/dev/tests/runtime/V2DiffViewerMessaging.test.mjs b/dev/tests/runtime/V2DiffViewerMessaging.test.mjs -index 05db01823..684096575 100644 ---- a/dev/tests/runtime/V2DiffViewerMessaging.test.mjs -+++ b/dev/tests/runtime/V2DiffViewerMessaging.test.mjs -@@ -43,7 +43,7 @@ export function run() { - - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2DiffViewerMessaging.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2DiffViewerMessaging.test.mjs failed syntax check."); - - if (!js.includes("No differences. The selected sessions are identical.")) { - failures.push("Missing empty-diff message."); -diff --git a/dev/tests/runtime/V2DiffViewerSummaryCounts.test.mjs b/dev/tests/runtime/V2DiffViewerSummaryCounts.test.mjs -index 3850c3cd3..059a94448 100644 ---- a/dev/tests/runtime/V2DiffViewerSummaryCounts.test.mjs -+++ b/dev/tests/runtime/V2DiffViewerSummaryCounts.test.mjs -@@ -46,7 +46,7 @@ export function run() { - if (!htmlExists) failures.push("Missing toolbox/workspace-v2/index.html."); - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2DiffViewerSummaryCounts.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2DiffViewerSummaryCounts.test.mjs failed syntax check."); - - if (!html.includes('id="workspaceV2DiffSummary"')) { - failures.push("Missing Diff summary node in Workspace V2 Diff Viewer."); -diff --git a/dev/tests/runtime/V2EnableStateFeedback.test.mjs b/dev/tests/runtime/V2EnableStateFeedback.test.mjs -index b01e490d4..74352eedf 100644 ---- a/dev/tests/runtime/V2EnableStateFeedback.test.mjs -+++ b/dev/tests/runtime/V2EnableStateFeedback.test.mjs -@@ -43,7 +43,7 @@ export function run() { - if (!htmlExists) failures.push("Missing toolbox/workspace-v2/index.html."); - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2EnableStateFeedback.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2EnableStateFeedback.test.mjs failed syntax check."); - - if (!html.includes("id=\"workspaceV2DiffEnableState\"")) failures.push("Missing Diff enable-state line."); - if (!html.includes("id=\"workspaceV2MergeEnableState\"")) failures.push("Missing Merge enable-state line."); -diff --git a/dev/tests/runtime/V2MergeConflictSummary.test.mjs b/dev/tests/runtime/V2MergeConflictSummary.test.mjs -index 0e995c350..f234d3a4f 100644 ---- a/dev/tests/runtime/V2MergeConflictSummary.test.mjs -+++ b/dev/tests/runtime/V2MergeConflictSummary.test.mjs -@@ -69,7 +69,7 @@ export function run() { - if (!htmlExists) failures.push("Missing toolbox/workspace-v2/index.html."); - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2MergeConflictSummary.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2MergeConflictSummary.test.mjs failed syntax check."); - - if (!html.includes("id=\"workspaceV2MergeConflictSummary\"")) failures.push("Missing merge conflict summary node."); - if (!html.includes("id=\"workspaceV2MergeOutput\"")) failures.push("Missing raw merge JSON preview node."); -diff --git a/dev/tests/runtime/V2MergeOutputPersistence.test.mjs b/dev/tests/runtime/V2MergeOutputPersistence.test.mjs -index 785354f96..aed5a2fb6 100644 ---- a/dev/tests/runtime/V2MergeOutputPersistence.test.mjs -+++ b/dev/tests/runtime/V2MergeOutputPersistence.test.mjs -@@ -69,7 +69,7 @@ export function run() { - if (!htmlExists) failures.push("Missing toolbox/workspace-v2/index.html."); - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2MergeOutputPersistence.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2MergeOutputPersistence.test.mjs failed syntax check."); - - const requiredHtml = [ - "id=\"workspaceV2MergedSessionId\"", -diff --git a/dev/tests/runtime/V2MergePreviewOverlayFix.test.mjs b/dev/tests/runtime/V2MergePreviewOverlayFix.test.mjs -index 233a17322..c1380b960 100644 ---- a/dev/tests/runtime/V2MergePreviewOverlayFix.test.mjs -+++ b/dev/tests/runtime/V2MergePreviewOverlayFix.test.mjs -@@ -59,7 +59,7 @@ export function run() { - if (!htmlExists) failures.push("Missing toolbox/workspace-v2/index.html."); - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2MergePreviewOverlayFix.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2MergePreviewOverlayFix.test.mjs failed syntax check."); - - if (!html.includes("id=\"workspaceV2MergeOutput\"")) failures.push("Merge preview output node is missing."); - if (!html.includes("max-height: 18rem; overflow: auto; position: relative;")) { -diff --git a/dev/tests/runtime/V2MergeResultSummary.test.mjs b/dev/tests/runtime/V2MergeResultSummary.test.mjs -index 234cbb8c9..e3a2ced4a 100644 ---- a/dev/tests/runtime/V2MergeResultSummary.test.mjs -+++ b/dev/tests/runtime/V2MergeResultSummary.test.mjs -@@ -64,7 +64,7 @@ export function run() { - if (!htmlExists) failures.push("Missing toolbox/workspace-v2/index.html."); - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2MergeResultSummary.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2MergeResultSummary.test.mjs failed syntax check."); - - const requiredHtml = [ - "id=\"workspaceV2MergeResultSummary\"", -diff --git a/dev/tests/runtime/V2MergeStateSingleSourceOfTruth.test.mjs b/dev/tests/runtime/V2MergeStateSingleSourceOfTruth.test.mjs -index e1278d73a..646e018e0 100644 ---- a/dev/tests/runtime/V2MergeStateSingleSourceOfTruth.test.mjs -+++ b/dev/tests/runtime/V2MergeStateSingleSourceOfTruth.test.mjs -@@ -54,7 +54,7 @@ export function run() { - - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2MergeStateSingleSourceOfTruth.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2MergeStateSingleSourceOfTruth.test.mjs failed syntax check."); - - const requiredTokens = [ - "resolveAuthoritativeLastMergedHostContextId()", -diff --git a/dev/tests/runtime/V2MergeStateStatusReset.test.mjs b/dev/tests/runtime/V2MergeStateStatusReset.test.mjs -index bbc2a65ff..8d66d953c 100644 ---- a/dev/tests/runtime/V2MergeStateStatusReset.test.mjs -+++ b/dev/tests/runtime/V2MergeStateStatusReset.test.mjs -@@ -59,7 +59,7 @@ export function run() { - if (!htmlExists) failures.push("Missing toolbox/workspace-v2/index.html."); - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2MergeStateStatusReset.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2MergeStateStatusReset.test.mjs failed syntax check."); - - const requiredTokens = [ - "clearMergePanelTransientState(summaryMessage, outputMessage, statusMessage)", -diff --git a/dev/tests/runtime/V2MergedRecentSessionRegistration.test.mjs b/dev/tests/runtime/V2MergedRecentSessionRegistration.test.mjs -index 1bd4e8321..10ffa8b67 100644 ---- a/dev/tests/runtime/V2MergedRecentSessionRegistration.test.mjs -+++ b/dev/tests/runtime/V2MergedRecentSessionRegistration.test.mjs -@@ -65,7 +65,7 @@ export function run() { - - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2MergedRecentSessionRegistration.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2MergedRecentSessionRegistration.test.mjs failed syntax check."); - - const requiredTokens = [ - "createMergedHostContextId(toolId)", -diff --git a/dev/tests/runtime/V2SaveLibraryFromRecentSession.test.mjs b/dev/tests/runtime/V2SaveLibraryFromRecentSession.test.mjs -index c5163f753..bac5ea682 100644 ---- a/dev/tests/runtime/V2SaveLibraryFromRecentSession.test.mjs -+++ b/dev/tests/runtime/V2SaveLibraryFromRecentSession.test.mjs -@@ -132,7 +132,7 @@ export function run() { - - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2SaveLibraryFromRecentSession.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2SaveLibraryFromRecentSession.test.mjs failed syntax check."); - - const mustContain = [ - "readSessionPayloadFromRecentSessionId(sessionId)", -diff --git a/dev/tests/runtime/V2SavedSessionRowActions.test.mjs b/dev/tests/runtime/V2SavedSessionRowActions.test.mjs -index 9427094ff..bd1109eb9 100644 ---- a/dev/tests/runtime/V2SavedSessionRowActions.test.mjs -+++ b/dev/tests/runtime/V2SavedSessionRowActions.test.mjs -@@ -50,7 +50,7 @@ export function run() { - if (!htmlExists) failures.push("Missing toolbox/workspace-v2/index.html."); - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2SavedSessionRowActions.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2SavedSessionRowActions.test.mjs failed syntax check."); - - if (!html.includes("Saved sessions are stored in Session Library. Recent sessions are temporary.")) { - failures.push("Helper text is not updated to saved-vs-recent clarification."); -diff --git a/dev/tests/runtime/V2SelectionSyncRowActions.test.mjs b/dev/tests/runtime/V2SelectionSyncRowActions.test.mjs -index 2043421bd..64cfb1df8 100644 ---- a/dev/tests/runtime/V2SelectionSyncRowActions.test.mjs -+++ b/dev/tests/runtime/V2SelectionSyncRowActions.test.mjs -@@ -69,7 +69,7 @@ export function run() { - - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2SelectionSyncRowActions.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2SelectionSyncRowActions.test.mjs failed syntax check."); - - const requiredTokens = [ - "syncSelectionSlotsFromContextId(leftSelectNode, rightSelectNode, candidates, contextId)", -diff --git a/dev/tests/runtime/V2SessionLibraryActionCleanup.test.mjs b/dev/tests/runtime/V2SessionLibraryActionCleanup.test.mjs -index 2174527c9..08798f140 100644 ---- a/dev/tests/runtime/V2SessionLibraryActionCleanup.test.mjs -+++ b/dev/tests/runtime/V2SessionLibraryActionCleanup.test.mjs -@@ -36,7 +36,7 @@ export function run() { - if (!htmlExists) failures.push("Missing toolbox/workspace-v2/index.html."); - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2SessionLibraryActionCleanup.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2SessionLibraryActionCleanup.test.mjs failed syntax check."); - - const requiredHtmlTokens = [ - '', -diff --git a/dev/tests/runtime/V2SessionLibraryActionLabel.test.mjs b/dev/tests/runtime/V2SessionLibraryActionLabel.test.mjs -index 41992b4f9..20a61a873 100644 ---- a/dev/tests/runtime/V2SessionLibraryActionLabel.test.mjs -+++ b/dev/tests/runtime/V2SessionLibraryActionLabel.test.mjs -@@ -63,7 +63,7 @@ export function run() { - - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2SessionLibraryActionLabel.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2SessionLibraryActionLabel.test.mjs failed syntax check."); - - if (!js.includes("useInLibraryButton.textContent = \"Use in Diff/Merge\";")) { - failures.push("Saved Session Library row action label was not renamed to Use in Diff/Merge."); -diff --git a/dev/tests/runtime/V2SessionLibraryActions.test.mjs b/dev/tests/runtime/V2SessionLibraryActions.test.mjs -index 1a7e2cd85..e1302984d 100644 ---- a/dev/tests/runtime/V2SessionLibraryActions.test.mjs -+++ b/dev/tests/runtime/V2SessionLibraryActions.test.mjs -@@ -116,7 +116,7 @@ export function run() { - if (!htmlExists) failures.push("Missing toolbox/workspace-v2/index.html."); - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2SessionLibraryActions.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2SessionLibraryActions.test.mjs failed syntax check."); - - if (!html.includes("id=\"workspaceV2LibraryStatus\"")) { - failures.push("Missing explicit Session Library status output area."); -diff --git a/dev/tests/runtime/V2SessionLibraryCardOverwrite.test.mjs b/dev/tests/runtime/V2SessionLibraryCardOverwrite.test.mjs -index ce0cb671f..c9c59ff07 100644 ---- a/dev/tests/runtime/V2SessionLibraryCardOverwrite.test.mjs -+++ b/dev/tests/runtime/V2SessionLibraryCardOverwrite.test.mjs -@@ -44,7 +44,7 @@ export function run() { - - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2SessionLibraryCardOverwrite.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2SessionLibraryCardOverwrite.test.mjs failed syntax check."); - - const requiredTokens = [ - "overwriteButton.textContent = \"Overwrite\";", -diff --git a/dev/tests/runtime/V2SessionLibrarySaveGuard.test.mjs b/dev/tests/runtime/V2SessionLibrarySaveGuard.test.mjs -index 5d8949400..9fc924ffb 100644 ---- a/dev/tests/runtime/V2SessionLibrarySaveGuard.test.mjs -+++ b/dev/tests/runtime/V2SessionLibrarySaveGuard.test.mjs -@@ -36,7 +36,7 @@ export function run() { - - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2SessionLibrarySaveGuard.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2SessionLibrarySaveGuard.test.mjs failed syntax check."); - - const requiredTokens = [ - "hasActiveWorkspaceSessionForSave()", -diff --git a/dev/tests/runtime/V2SessionStateModelConsolidation.test.mjs b/dev/tests/runtime/V2SessionStateModelConsolidation.test.mjs -index fb7366c34..09776406b 100644 ---- a/dev/tests/runtime/V2SessionStateModelConsolidation.test.mjs -+++ b/dev/tests/runtime/V2SessionStateModelConsolidation.test.mjs -@@ -65,7 +65,7 @@ export function run() { - - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2SessionStateModelConsolidation.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2SessionStateModelConsolidation.test.mjs failed syntax check."); - - const requiredTokens = [ - "computeWorkspaceSessionUiStateModel()", -diff --git a/dev/tests/runtime/V2SessionToolsCloseoutBundle.test.mjs b/dev/tests/runtime/V2SessionToolsCloseoutBundle.test.mjs -index 56eeb0e92..de12f3f38 100644 ---- a/dev/tests/runtime/V2SessionToolsCloseoutBundle.test.mjs -+++ b/dev/tests/runtime/V2SessionToolsCloseoutBundle.test.mjs -@@ -53,7 +53,7 @@ export function run() { - - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2SessionToolsCloseoutBundle.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2SessionToolsCloseoutBundle.test.mjs failed syntax check."); - - const requiredTokens = [ - "this.diffOutputSelectionKey = \"\";", -diff --git a/dev/tests/runtime/V2SessionUxStabilization.test.mjs b/dev/tests/runtime/V2SessionUxStabilization.test.mjs -index 9904a5793..113556fa2 100644 ---- a/dev/tests/runtime/V2SessionUxStabilization.test.mjs -+++ b/dev/tests/runtime/V2SessionUxStabilization.test.mjs -@@ -64,7 +64,7 @@ export function run() { - - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2SessionUxStabilization.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2SessionUxStabilization.test.mjs failed syntax check."); - - const requiredTokens = [ - "updateSessionLibraryActionState()", -diff --git a/dev/tests/runtime/V2ToolLaunch.test.mjs b/dev/tests/runtime/V2ToolLaunch.test.mjs -index 97acbfedd..2faabfb13 100644 ---- a/dev/tests/runtime/V2ToolLaunch.test.mjs -+++ b/dev/tests/runtime/V2ToolLaunch.test.mjs -@@ -1,23 +1,22 @@ import assert from "node:assert/strict"; - import fs from "node:fs"; - import path from "node:path"; --import { execFileSync } from "node:child_process"; - import { fileURLToPath, pathToFileURL } from "node:url"; - - const __filename = fileURLToPath(import.meta.url); - const __dirname = path.dirname(__filename); - const repoRoot = path.resolve(__dirname, "..", "..", ".."); - const toolsRoot = path.join(repoRoot, "www", "toolbox"); --const fixturesRoot = path.join(repoRoot, "tests", "fixtures", "v2-tools"); -+const fixturesRoot = path.join(repoRoot, "dev", "tests", "fixtures", "v2-tools"); - const toolsIndexPath = path.join(toolsRoot, "index.html"); - const resultsPath = path.join(repoRoot, "dev", "workspace", "tmp", "v2-tool-launch-results.json"); - --const REQUIRED_V2_TOOLS = [ -+const RETIRED_FIXTURE_ONLY_V2_TOOLS = [ - "asset-manager-v2", - "palette-manager-v2", - "svg-asset-studio-v2", - "tilemap-studio-v2", -- "vector-map-editor-v2" -+ "vector-map-editor-v2", - ]; - - function readText(filePath) { -@@ -35,119 +34,52 @@ function hasIndexRoute(indexHtmlText, toolId) { - ); - } - --function hasToolSpecificPayload(toolId, fixtureJson) { -- const sessionContext = fixtureJson?.sessionContext; -- if (!sessionContext || typeof sessionContext !== "object" || Array.isArray(sessionContext)) { -- return false; -- } -- if (toolId === "asset-manager-v2") { -- return Boolean(sessionContext?.payloadJson?.assetCatalog); -- } -- if (toolId === "palette-manager-v2") { -- return Boolean(sessionContext?.paletteJson); -- } -- if (toolId === "svg-asset-studio-v2") { -- return Boolean(sessionContext?.payloadJson?.vectorAssetDocument); -- } -- if (toolId === "tilemap-studio-v2") { -- return Boolean(sessionContext?.payloadJson?.tileMapDocument); -- } -- if (toolId === "vector-map-editor-v2") { -- return Boolean(sessionContext?.payloadJson?.vectorMapDocument); -- } -- return false; --} -- --function checkJsSyntax(jsPath) { -- try { -- execFileSync(process.execPath, ["--check", jsPath], { -- cwd: repoRoot, -- stdio: ["ignore", "pipe", "pipe"] -- }); -- return { syntaxValid: true, syntaxError: "" }; -- } catch (error) { -- return { -- syntaxValid: false, -- syntaxError: (error?.stderr || error?.stdout || error?.message || "").toString().trim() -- }; -- } --} -- --function validateTool(toolId, toolsIndexHtmlText) { -+function validateRetiredTool(toolId, toolsIndexHtmlText) { - const toolIndexHtmlPath = path.join(toolsRoot, toolId, "index.html"); - const toolIndexJsPath = path.join(toolsRoot, toolId, "index.js"); - const fixturePath = path.join(fixturesRoot, `${toolId}.json`); - -- const routeFromIndexValid = hasIndexRoute(toolsIndexHtmlText, toolId); -+ const routeFromIndexPresent = hasIndexRoute(toolsIndexHtmlText, toolId); - const routePathExists = fs.existsSync(toolIndexHtmlPath); -- const directUrl = `toolbox/${toolId}/index.html`; -+ const routeScriptExists = fs.existsSync(toolIndexJsPath); - const fixtureExists = fs.existsSync(fixturePath); - - let fixtureValidJson = false; -- let hostContextId = ""; -- let fixtureToolId = ""; -- let fixtureToolIdMatches = false; -- let fixtureHasSessionContext = false; -- let fixtureHasToolPayload = false; - if (fixtureExists) { - try { -- const fixtureJson = JSON.parse(readText(fixturePath)); -+ JSON.parse(readText(fixturePath)); - fixtureValidJson = true; -- hostContextId = typeof fixtureJson?.hostContextId === "string" ? fixtureJson.hostContextId.trim() : ""; -- fixtureToolId = typeof fixtureJson?.sessionContext?.toolId === "string" ? fixtureJson.sessionContext.toolId.trim() : ""; -- fixtureToolIdMatches = fixtureToolId === toolId; -- fixtureHasSessionContext = Boolean( -- fixtureJson?.sessionContext && -- typeof fixtureJson.sessionContext === "object" && -- !Array.isArray(fixtureJson.sessionContext) -- ); -- fixtureHasToolPayload = hasToolSpecificPayload(toolId, fixtureJson); - } catch { - fixtureValidJson = false; - } - } - -- const launchUrlWithHostContextId = `${directUrl}?hostContextId=${encodeURIComponent(hostContextId)}`; -- const { syntaxValid, syntaxError } = checkJsSyntax(toolIndexJsPath); -- - const failures = []; -- if (!routeFromIndexValid) failures.push("Missing V2 route from toolbox/index.html."); -- if (!routePathExists) failures.push("Missing toolbox/-v2/index.html route target."); -- if (!fs.existsSync(toolIndexJsPath)) failures.push("Missing toolbox/-v2/index.js route runtime target."); -- if (!fixtureExists) failures.push("Missing fixture file."); -+ if (routeFromIndexPresent) failures.push("Retired V2 route still appears in www/toolbox/index.html."); -+ if (routePathExists) failures.push("Retired www/toolbox/-v2/index.html route target still exists."); -+ if (routeScriptExists) failures.push("Retired www/toolbox/-v2/index.js route runtime target still exists."); -+ if (!fixtureExists) failures.push("Retired V2 fixture evidence is missing from dev/tests/fixtures/v2-tools."); - if (fixtureExists && !fixtureValidJson) failures.push("Fixture is not valid JSON."); -- if (fixtureValidJson && !hostContextId) failures.push("Fixture hostContextId is missing or empty."); -- if (fixtureValidJson && !fixtureToolIdMatches) failures.push(`Fixture sessionContext.toolId does not match tool (${fixtureToolId || "missing"}).`); -- if (fixtureValidJson && !fixtureHasSessionContext) failures.push("Fixture sessionContext object is missing."); -- if (fixtureValidJson && !fixtureHasToolPayload) failures.push("Fixture is missing tool-specific payload."); -- if (!syntaxValid) failures.push("Tool index.js failed node --check."); - - return { - tool: toolId, -- routeFromIndexValid, -+ retired: true, -+ routeFromIndexPresent, - routePath: path.relative(repoRoot, toolIndexHtmlPath).replace(/\\/g, "/"), - routePathExists, -- directUrl, -- launchUrlWithHostContextId, -+ routeScriptPath: path.relative(repoRoot, toolIndexJsPath).replace(/\\/g, "/"), -+ routeScriptExists, - fixturePath: path.relative(repoRoot, fixturePath).replace(/\\/g, "/"), - fixtureExists, - fixtureValidJson, -- hostContextId, -- fixtureToolId, -- fixtureToolIdMatches, -- fixtureHasSessionContext, -- fixtureHasToolPayload, -- syntaxCheckedPath: path.relative(repoRoot, toolIndexJsPath).replace(/\\/g, "/"), -- syntaxValid, -- syntaxError, -- failures -+ failures, - }; - } - - export function run() { -- assert.ok(fs.existsSync(toolsIndexPath), "toolbox/index.html is missing."); -+ assert.ok(fs.existsSync(toolsIndexPath), "www/toolbox/index.html is missing."); - const toolsIndexHtmlText = readText(toolsIndexPath); -- const rows = REQUIRED_V2_TOOLS.map((toolId) => validateTool(toolId, toolsIndexHtmlText)); -+ const rows = RETIRED_FIXTURE_ONLY_V2_TOOLS.map((toolId) => validateRetiredTool(toolId, toolsIndexHtmlText)); - const failures = rows.flatMap((row) => row.failures.map((entry) => `${row.tool}: ${entry}`)); - - fs.mkdirSync(path.dirname(resultsPath), { recursive: true }); -@@ -155,11 +87,11 @@ export function run() { - generatedAt: new Date().toISOString(), - toolCount: rows.length, - failures, -- rows -+ rows, - }, null, 2)}\n`, "utf8"); - -- console.log(`v2 tool launch results: ${resultsPath}`); -- assert.equal(failures.length, 0, `V2 tool launch failures: ${failures.join(" | ")}`); -+ console.log(`v2 tool retirement results: ${resultsPath}`); -+ assert.equal(failures.length, 0, `V2 tool retirement failures: ${failures.join(" | ")}`); - return { toolCount: rows.length, failures, rows }; - } - -diff --git a/dev/tests/runtime/V2UndoButtonRender.test.mjs b/dev/tests/runtime/V2UndoButtonRender.test.mjs -index dcbd6c575..9dc883b01 100644 ---- a/dev/tests/runtime/V2UndoButtonRender.test.mjs -+++ b/dev/tests/runtime/V2UndoButtonRender.test.mjs -@@ -39,7 +39,7 @@ export function run() { - if (!htmlExists) failures.push("Missing toolbox/workspace-v2/index.html."); - if (!jsExists) failures.push("Missing toolbox/workspace-v2/index.js."); - if (!jsSyntax.ok) failures.push("toolbox/workspace-v2/index.js failed syntax check."); -- if (!testSyntax.ok) failures.push("tests/runtime/V2UndoButtonRender.test.mjs failed syntax check."); -+ if (!testSyntax.ok) failures.push("dev/tests/runtime/V2UndoButtonRender.test.mjs failed syntax check."); - - const mergeActionGroupPattern = /
\s*
--

Loading docs_build/dev/admin-notes/index.txt.

-+

Loading dev/archive/legacy-docs-build/admin-notes/index.txt.

- -
- + const lookup = createRuntimeManifestAssetLookup({ +diff --git a/favicon.svg b/www/favicon.svg +similarity index 100% +rename from favicon.svg +rename to www/favicon.svg diff --git a/dev/scripts/PS/deploy/WebsiteRepoDeploymentCommon.ps1 b/dev/scripts/PS/deploy/WebsiteRepoDeploymentCommon.ps1 index 99942faab..8003e5b70 100644 --- a/dev/scripts/PS/deploy/WebsiteRepoDeploymentCommon.ps1 +++ b/dev/scripts/PS/deploy/WebsiteRepoDeploymentCommon.ps1 @@ -702,7 +702,7 @@ function New-WebsiteDeploymentPlan { function Get-DefaultWebsiteIncludePaths { return @( "index.html", - "favicon.svg", + "www/favicon.svg", "games", "samples", "src", diff --git a/dev/tests/dev-runtime/StaticWebRootCompatibility.test.mjs b/dev/tests/dev-runtime/StaticWebRootCompatibility.test.mjs index 3510f2af6..884f7aec8 100644 --- a/dev/tests/dev-runtime/StaticWebRootCompatibility.test.mjs +++ b/dev/tests/dev-runtime/StaticWebRootCompatibility.test.mjs @@ -55,6 +55,17 @@ test("static route target can prefer a configured www root before repo-root fall assert.equal(routeTarget.webRoot.relativePath, "www"); }); +test("favicon resolves from the browser-served www root", async () => { + const routeTarget = await resolveStaticRouteTarget({ + decodedPath: "/favicon.svg", + repoRoot, + webRoot: WWW_LOCAL_WEB_ROOT, + }); + assert.equal(routeTarget.routePath, "/favicon.svg"); + assert.equal(routeTarget.targetPath, path.join(repoRoot, "www", "favicon.svg")); + assert.equal(routeTarget.webRoot.relativePath, "www"); +}); + test("local static web server can serve from a configurable web root", async () => { const fixtureRoot = path.join(repoRoot, "dev", "workspace", "tmp", "static-web-root-compatibility"); await fs.rm(fixtureRoot, { force: true, recursive: true }); diff --git a/dev/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs b/dev/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs index d75e47cb0..a4e17660c 100644 --- a/dev/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs +++ b/dev/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs @@ -345,7 +345,7 @@ test("Creator sessions cannot access Admin System Health operations", async ({ p test("Admin System Health operations page keeps scripts and styles external", async () => { const retiredFileDbToken = "SQL" + "ite"; - const pageSource = await fs.readFile(path.resolve("admin/system-health.html"), "utf8"); + const pageSource = await fs.readFile(path.resolve("www/admin/system-health.html"), "utf8"); expect(pageSource).not.toMatch(/]+src=)/i); expect(pageSource).not.toMatch(/\son[a-z]+\s*=/i); @@ -374,7 +374,7 @@ test("Admin System Health operations page keeps scripts and styles external", as expect(pageSource).toContain("Server-owned Cloudflare R2 storage diagnostic"); expect(pageSource).toContain("assets/theme-v2/js/admin-system-health.js"); expect(pageSource).toContain("assets/theme-v2/js/admin-owner-navigation.js"); - const runtimeSource = await fs.readFile(path.resolve("assets/theme-v2/js/admin-system-health.js"), "utf8"); + const runtimeSource = await fs.readFile(path.resolve("www/assets/theme-v2/js/admin-system-health.js"), "utf8"); expect(runtimeSource).not.toContain(retiredFileDbToken); expect(runtimeSource).not.toContain("localStorage"); expect(runtimeSource).not.toContain("sessionStorage"); diff --git a/dev/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs b/dev/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs index 782a813a2..e93cca610 100644 --- a/dev/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs +++ b/dev/tests/playwright/tools/AdminInvitationsNavPage.spec.mjs @@ -138,7 +138,7 @@ test("non-Admin users cannot access Admin Invites", async ({ page }) => { }); test("Admin Invites page keeps scripts and styles external", async () => { - const pageSource = await fs.readFile(path.resolve("admin/invitations.html"), "utf8"); + const pageSource = await fs.readFile(path.resolve("www/admin/invitations.html"), "utf8"); expect(pageSource).not.toMatch(/]+src=)/i); expect(pageSource).not.toMatch(/\son[a-z]+\s*=/i); diff --git a/dev/tests/tools/GameAssetManifestDiscovery.test.mjs b/dev/tests/tools/GameAssetManifestDiscovery.test.mjs index d499e9249..be4b55705 100644 --- a/dev/tests/tools/GameAssetManifestDiscovery.test.mjs +++ b/dev/tests/tools/GameAssetManifestDiscovery.test.mjs @@ -1,6 +1,6 @@ import assert from "node:assert/strict"; import { existsSync } from "node:fs"; -import asteroidsGameManifest from "../../../games/Asteroids/game.manifest.json" with { type: "json" }; +import asteroidsGameManifest from "../../../dev/archive/v1-v2/games/Asteroids/game.manifest.json" with { type: "json" }; import { discoverRuntimeAssetSourcesFromManifest, validateGameAssetManifestStructure @@ -35,7 +35,7 @@ export async function run() { Object.values(asteroidsManifest.domains).flat().forEach((record) => { assert.equal(record.runtimePath.startsWith("games/Asteroids/game.manifest.json#"), true); assert.equal(record.toolDataPath.startsWith("games/Asteroids/game.manifest.json#"), true); - assert.equal(existsSync("games/Asteroids/game.manifest.json"), true); + assert.equal(existsSync("dev/archive/v1-v2/games/Asteroids/game.manifest.json"), true); }); const lookup = createRuntimeManifestAssetLookup({ diff --git a/favicon.svg b/www/favicon.svg similarity index 100% rename from favicon.svg rename to www/favicon.svg