diff --git a/dev/reports/PR_26180_OWNER_022-resolve-remaining-src-dependencies_branch-validation.md b/dev/reports/PR_26180_OWNER_022-resolve-remaining-src-dependencies_branch-validation.md new file mode 100644 index 000000000..b2e948e62 --- /dev/null +++ b/dev/reports/PR_26180_OWNER_022-resolve-remaining-src-dependencies_branch-validation.md @@ -0,0 +1,18 @@ +# Branch Validation - PR_26180_OWNER_022-resolve-remaining-src-dependencies + +- Current branch: `PR_26180_OWNER_022-resolve-remaining-src-dependencies` +- Current branch is not `main`: PASS +- Base branch used: `PR_26180_OWNER_021-archive-legacy-games-samples-teardown` +- Base commit: `2e38e9e31` +- `www/` exists: PASS +- `api/` exists: PASS +- Root tracked `assets/`: 0 files, PASS +- Root tracked `games/`: 0 files, PASS +- Root tracked `learn/`: 0 files, PASS +- Root tracked `toolbox/`: 0 files, PASS +- Root `src` files before cleanup: 65 +- Root `src` files after cleanup: 64 + +## Result + +PASS diff --git a/dev/reports/PR_26180_OWNER_022-resolve-remaining-src-dependencies_manual-validation-notes.md b/dev/reports/PR_26180_OWNER_022-resolve-remaining-src-dependencies_manual-validation-notes.md new file mode 100644 index 000000000..fb621aaef --- /dev/null +++ b/dev/reports/PR_26180_OWNER_022-resolve-remaining-src-dependencies_manual-validation-notes.md @@ -0,0 +1,6 @@ +# Manual Validation Notes - PR_26180_OWNER_022-resolve-remaining-src-dependencies + +- No manual browser route validation was required because public URLs and product behavior were not changed. +- `www/toolbox/toolRegistry.js` import smoke returned 47 tools after the path correction. +- Full `src/` retirement remains out of scope. +- `-v2` contracts and manifest/sample schemas remain root `src` transition files because active validation still references them. diff --git a/dev/reports/PR_26180_OWNER_022-resolve-remaining-src-dependencies_report.md b/dev/reports/PR_26180_OWNER_022-resolve-remaining-src-dependencies_report.md new file mode 100644 index 000000000..c5ea83e5f --- /dev/null +++ b/dev/reports/PR_26180_OWNER_022-resolve-remaining-src-dependencies_report.md @@ -0,0 +1,71 @@ +# PR_26180_OWNER_022-resolve-remaining-src-dependencies Report + +## Executive Summary + +Rebuilt PR022 from the migration stack base `PR_26180_OWNER_021-archive-legacy-games-samples-teardown` at `2e38e9e31`, not from `main`. + +The rebuilt PR is intentionally narrow: + +- Deletes obsolete `src/shared/projectDataStore/inMemoryProjectDataStore.js`. +- Deletes the stale self-test that only validated that obsolete in-memory store. +- Confirms `src/shared/number/numbers.js` is not present on PR021 and the active equivalent remains at `www/src/shared/number/numbers.js`. +- Preserves `-v2` tool contract files because active dev contract tests still import them. +- Preserves manifest-era/sample-era schemas because active validation still references them. +- Updates `www/toolbox/toolRegistry.js` to import the existing `www/src/shared/toolbox/tool-metadata-inventory.js` equivalent rather than traversing to root `src`. + +## Branch Model + +- Model: Owner stacked PR +- Base branch: `PR_26180_OWNER_021-archive-legacy-games-samples-teardown` +- Base commit: `2e38e9e31` +- Source branch: `PR_26180_OWNER_022-resolve-remaining-src-dependencies` +- Rebuilt from migration stack: YES +- Used `main` as base: NO + +## Migration Stack Gates + +| Gate | Result | +|---|---:| +| Current branch is not `main` | PASS | +| `www/` exists | PASS | +| `api/` exists | PASS | +| root `assets/` tracked active folder absent | PASS | +| root `games/` tracked active folder absent | PASS | +| root `learn/` tracked active folder absent | PASS | +| root `toolbox/` tracked active folder absent | PASS | + +## Root Src Count + +- Before: 65 tracked files under `src/` +- After: 64 tracked files under `src/` + +## Cleanup Decisions + +| Item | Decision | Reason | +|---|---|---| +| `src/shared/projectDataStore/inMemoryProjectDataStore.js` | Deleted | Obsolete in-memory project data store; no active references remain after deleting stale self-test. | +| `dev/tests/shared/InMemoryProjectDataStore.test.mjs` | Deleted | Test only validated the deleted obsolete helper. | +| `src/shared/number/numbers.js` | No action | Root file is absent; active equivalent exists under `www/src/shared/number/numbers.js`. | +| `-v2` tool contract files under `src/shared/contracts/tools/` | Preserved | Active dev contract tests import these modules directly. | +| `src/shared/schemas/game.manifest.schema.json` | Preserved | Active `validate-json-contracts` and fixtures still reference it. | +| `src/shared/schemas/samples/sample.tool-payload.schema.json` | Preserved | Active sample validation reports and `ToolManifestBoundary` still reference it. | +| `www/toolbox/toolRegistry.js` import path | Updated | Existing equivalent is under `www/src/shared/toolbox/`; avoids root `src` traversal. | + +## Protected Paths + +No files under `dev/workspace/generated/tool-images/**` were touched. + +## Validation Summary + +- `git diff --check`: PASS +- `npm run validate:canonical-structure`: PASS +- `node --check www/toolbox/toolRegistry.js`: PASS +- Browser registry import smoke: PASS, returned 47 tools +- `node ./dev/tests/shared/ProjectDataStoreContract.test.mjs`: PASS +- `node ./dev/tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs`: PASS +- `node ./dev/tests/tools/ToolManifestBoundary.test.mjs`: PASS +- Targeted root `src` reference scans: PASS with active references documented and preserved + +## Outcome + +PR022 has been rebuilt from PR021 and is ready as a narrow migration-stack cleanup branch. It does not attempt broad `src/` retirement. diff --git a/dev/reports/PR_26180_OWNER_022-resolve-remaining-src-dependencies_requirement-checklist.md b/dev/reports/PR_26180_OWNER_022-resolve-remaining-src-dependencies_requirement-checklist.md new file mode 100644 index 000000000..14a8c8754 --- /dev/null +++ b/dev/reports/PR_26180_OWNER_022-resolve-remaining-src-dependencies_requirement-checklist.md @@ -0,0 +1,17 @@ +# Requirement Checklist - PR_26180_OWNER_022-resolve-remaining-src-dependencies + +| Requirement | Status | Notes | +|---|---:|---| +| Checkout PR021 base | PASS | Rebuilt from `PR_26180_OWNER_021-archive-legacy-games-samples-teardown`. | +| Hard stop if current branch is main | PASS | Work performed on PR022 branch. | +| Hard stop if `www/` or `api/` missing | PASS | Both present. | +| Hard stop if root tracked `assets/`, `games/`, `learn/`, `toolbox/` exist | PASS | Tracked counts are 0. | +| Confirm remaining root `src` files | PASS | 65 before cleanup. | +| Delete `inMemoryProjectDataStore.js` | PASS | Deleted. | +| Resolve `src/shared/number/numbers.js` | PASS | Root file absent; `www/src/shared/number/numbers.js` exists. | +| Delete/archive obsolete `-v2` toolId files | PASS | None deleted because active tests reference them. | +| Delete/archive manifest/sample files only after scan | PASS | Preserved due active validation references. | +| Do not touch `dev/workspace/generated/tool-images/**` | PASS | Protected path untouched. | +| Preserve runtime behavior | PASS | Only path correction and obsolete validation helper deletion. | +| Run required validation | PASS | See validation report. | +| Produce ZIP under `dev/workspace/zips/` | PASS | `_delta.zip` created. | diff --git a/dev/reports/PR_26180_OWNER_022-resolve-remaining-src-dependencies_validation-report.md b/dev/reports/PR_26180_OWNER_022-resolve-remaining-src-dependencies_validation-report.md new file mode 100644 index 000000000..921e4955c --- /dev/null +++ b/dev/reports/PR_26180_OWNER_022-resolve-remaining-src-dependencies_validation-report.md @@ -0,0 +1,41 @@ +# Validation Report - PR_26180_OWNER_022-resolve-remaining-src-dependencies + +## Commands + +```text +git diff --check +npm run validate:canonical-structure +node --check www/toolbox/toolRegistry.js +node --input-type=module -e "const m=await import('./www/toolbox/toolRegistry.js'); console.log(m.getToolRegistrySnapshot().tools.length);" +node ./dev/tests/shared/ProjectDataStoreContract.test.mjs +node ./dev/tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs +node ./dev/tests/tools/ToolManifestBoundary.test.mjs +``` + +## Targeted Scans + +- `git ls-files -- src` count before/after +- active references to `src/shared/projectDataStore/inMemoryProjectDataStore.js` +- active references to root `src/shared/number/numbers.js` +- `toolId: "*-v2"` files under `src` +- active imports of matching `-v2` contract files +- active references to `game.manifest.schema.json` and `sample.tool-payload.schema.json` + +## Results + +- `git diff --check`: PASS +- `npm run validate:canonical-structure`: PASS +- `node --check www/toolbox/toolRegistry.js`: PASS +- Browser registry import smoke: PASS, returned 47 tools +- `ProjectDataStoreContract.test.mjs`: PASS +- `ArchitectureCleanupApiNavInvitations.test.mjs`: PASS +- `ToolManifestBoundary.test.mjs`: PASS +- Root `src` count: 65 before, 64 after +- In-memory store scan: PASS, no active references remain +- Root number helper scan: PASS, root file absent; active references use `www/src/shared/number/numbers.js` +- `-v2` contract scan: PASS, active test references documented and preserved +- Manifest/sample schema scan: PASS, active validation references documented and preserved + +## Result + +PASS diff --git a/dev/reports/codex_changed_files.txt b/dev/reports/codex_changed_files.txt index 843a15fdf..9c9db7205 100644 Binary files a/dev/reports/codex_changed_files.txt and b/dev/reports/codex_changed_files.txt differ diff --git a/dev/reports/codex_review.diff b/dev/reports/codex_review.diff index a7784c727..641fe74ad 100644 Binary files a/dev/reports/codex_review.diff and b/dev/reports/codex_review.diff differ diff --git a/dev/tests/shared/InMemoryProjectDataStore.test.mjs b/dev/tests/shared/InMemoryProjectDataStore.test.mjs deleted file mode 100644 index 27cc98718..000000000 --- a/dev/tests/shared/InMemoryProjectDataStore.test.mjs +++ /dev/null @@ -1,147 +0,0 @@ -/* -Toolbox Aid -David Quesenberry -06/03/2026 -InMemoryProjectDataStore.test.mjs -*/ - -import assert from "node:assert/strict"; -import { readFileSync } from "node:fs"; -import { - PROJECT_DATA_STORE_CONTRACT_ERRORS, - PROJECT_DATA_STORE_RECORD_TYPES, - validateProjectDataStoreAdapter, -} from "../../../src/shared/contracts/projectDataStoreContract.js"; -import { - IN_MEMORY_PROJECT_DATA_STORE_KIND, - createInMemoryProjectDataStore, -} from "../../../src/shared/projectDataStore/inMemoryProjectDataStore.js"; - -function createRecord(recordType, recordId, payload = {}, overrides = {}) { - return { - recordType, - recordId, - ownerId: "user.owner", - projectId: "project.alpha", - payload, - ...overrides, - }; -} - -export function run() { - const projectRecord = createRecord(PROJECT_DATA_STORE_RECORD_TYPES.PROJECT, "project.alpha", { - projectType: "game", - title: "Alpha", - }); - const manifestRecord = createRecord(PROJECT_DATA_STORE_RECORD_TYPES.MANIFEST, "manifest.alpha", { - manifestId: "manifest.alpha", - sceneCount: 2, - }); - const assetRecord = createRecord(PROJECT_DATA_STORE_RECORD_TYPES.ASSET, "asset.vector.alpha", { - assetType: "vector", - }); - const approvalRecord = createRecord(PROJECT_DATA_STORE_RECORD_TYPES.CUSTOM_EXTENSION_APPROVAL, "approval.weather", { - approvalStatus: "submitted", - }); - const publishRecord = createRecord(PROJECT_DATA_STORE_RECORD_TYPES.PUBLISH_STATE, "publish-state.alpha", { - publishStatus: "blocked", - }, { - ownerId: "user.publisher", - }); - - const store = createInMemoryProjectDataStore({ - initialRecords: [projectRecord], - }); - - assert.equal(store.kind, IN_MEMORY_PROJECT_DATA_STORE_KIND); - assert.equal(Object.isFrozen(store), true); - assert.equal(validateProjectDataStoreAdapter(store).valid, true); - assert.deepEqual(store.listRecords().map((record) => record.recordId), ["project.alpha"]); - - const putManifestResult = store.putRecord(manifestRecord); - assert.equal(putManifestResult.valid, true); - assert.deepEqual(putManifestResult.errors, []); - assert.equal(putManifestResult.record.recordId, "manifest.alpha"); - - const mutableAssetRecord = structuredClone(assetRecord); - const putAssetResult = store.putRecord(mutableAssetRecord); - mutableAssetRecord.payload.assetType = "mutated-after-put"; - assert.equal(putAssetResult.valid, true); - assert.equal(store.getRecord(PROJECT_DATA_STORE_RECORD_TYPES.ASSET, "asset.vector.alpha").payload.assetType, "vector"); - - assert.equal(store.putRecord(approvalRecord).valid, true); - assert.equal(store.putRecord(publishRecord).valid, true); - - const fetchedManifest = store.getRecord(PROJECT_DATA_STORE_RECORD_TYPES.MANIFEST, "manifest.alpha"); - assert.equal(fetchedManifest.payload.sceneCount, 2); - assert.equal(Object.isFrozen(fetchedManifest), true); - assert.equal(Object.isFrozen(fetchedManifest.payload), true); - - assert.throws(() => { - fetchedManifest.payload.sceneCount = 99; - }, TypeError); - assert.equal(store.getRecord(PROJECT_DATA_STORE_RECORD_TYPES.MANIFEST, "manifest.alpha").payload.sceneCount, 2); - - const replacementManifest = { - ...manifestRecord, - payload: { - manifestId: "manifest.alpha", - sceneCount: 3, - }, - }; - assert.equal(store.putRecord(replacementManifest).valid, true); - assert.equal(store.getRecord(PROJECT_DATA_STORE_RECORD_TYPES.MANIFEST, "manifest.alpha").payload.sceneCount, 3); - - assert.deepEqual(store.listRecords({ projectId: "project.alpha" }).map((record) => record.recordId), [ - "asset.vector.alpha", - "approval.weather", - "manifest.alpha", - "project.alpha", - "publish-state.alpha", - ]); - assert.deepEqual(store.listRecords({ ownerId: "user.publisher" }).map((record) => record.recordId), [ - "publish-state.alpha", - ]); - assert.deepEqual(store.listRecords({ recordType: PROJECT_DATA_STORE_RECORD_TYPES.MANIFEST }).map((record) => record.recordId), [ - "manifest.alpha", - ]); - - const invalidPut = store.putRecord({ - ...manifestRecord, - recordId: "manifest.invalid", - payload: { - manifestId: "manifest.invalid", - localStorage: {}, - }, - }); - assert.equal(invalidPut.valid, false); - assert.deepEqual(invalidPut.errors.map((error) => error.code), [PROJECT_DATA_STORE_CONTRACT_ERRORS.FIELD_NOT_ALLOWED]); - assert.equal(store.getRecord(PROJECT_DATA_STORE_RECORD_TYPES.MANIFEST, "manifest.invalid"), null); - - assert.equal(store.deleteRecord(PROJECT_DATA_STORE_RECORD_TYPES.ASSET, "asset.vector.alpha"), true); - assert.equal(store.getRecord(PROJECT_DATA_STORE_RECORD_TYPES.ASSET, "asset.vector.alpha"), null); - assert.equal(store.deleteRecord(PROJECT_DATA_STORE_RECORD_TYPES.ASSET, "asset.vector.alpha"), false); - - assert.equal(store.clear(), true); - assert.deepEqual(store.listRecords(), []); - - assert.throws(() => createInMemoryProjectDataStore({ - initialRecords: [{ - ...projectRecord, - recordId: "project.invalid", - payload: { - projectType: "game", - sessionStorage: {}, - }, - }], - }), /PROJECT_DATA_STORE_FIELD_NOT_ALLOWED/); - - const storeSource = readFileSync("src/shared/projectDataStore/inMemoryProjectDataStore.js", "utf8"); - assert.equal(/localStorage/.test(storeSource), false); - assert.equal(/sessionStorage/.test(storeSource), false); - assert.equal(/indexedDB/.test(storeSource), false); -} - -if (import.meta.url === `file://${process.argv[1]}`) { - run(); -} diff --git a/dev/workspace/zips/PR_26180_OWNER_022-resolve-remaining-src-dependencies_delta.zip b/dev/workspace/zips/PR_26180_OWNER_022-resolve-remaining-src-dependencies_delta.zip new file mode 100644 index 000000000..bdf86e1ab Binary files /dev/null and b/dev/workspace/zips/PR_26180_OWNER_022-resolve-remaining-src-dependencies_delta.zip differ diff --git a/src/shared/projectDataStore/inMemoryProjectDataStore.js b/src/shared/projectDataStore/inMemoryProjectDataStore.js deleted file mode 100644 index 5130adaf7..000000000 --- a/src/shared/projectDataStore/inMemoryProjectDataStore.js +++ /dev/null @@ -1,109 +0,0 @@ -/* -Toolbox Aid -David Quesenberry -06/03/2026 -inMemoryProjectDataStore.js -*/ - -import { - PROJECT_DATA_STORE_ADAPTER_METHODS, - createProjectDataStoreKey, - validateProjectDataStoreRecord, -} from "../contracts/projectDataStoreContract.js"; - -export const IN_MEMORY_PROJECT_DATA_STORE_KIND = "in-memory-project-data-store"; - -export function createInMemoryProjectDataStore({ initialRecords = [] } = {}) { - const records = new Map(); - - const adapter = { - kind: IN_MEMORY_PROJECT_DATA_STORE_KIND, - methods: PROJECT_DATA_STORE_ADAPTER_METHODS, - putRecord(record) { - const validation = validateProjectDataStoreRecord(record); - - if (!validation.valid) { - return freezeResult({ - valid: false, - record: null, - errors: validation.errors, - }); - } - - const storedRecord = freezeJsonClone(record); - records.set(createProjectDataStoreKey(storedRecord.recordType, storedRecord.recordId), storedRecord); - - return freezeResult({ - valid: true, - record: cloneRecord(storedRecord), - errors: Object.freeze([]), - }); - }, - getRecord(recordType, recordId) { - const storedRecord = records.get(createProjectDataStoreKey(recordType, recordId)); - return storedRecord ? cloneRecord(storedRecord) : null; - }, - listRecords(filters = {}) { - const recordType = filters?.recordType || null; - const projectId = filters?.projectId || null; - const ownerId = filters?.ownerId || null; - - return Object.freeze([...records.values()] - .filter((record) => !recordType || record.recordType === recordType) - .filter((record) => !projectId || record.projectId === projectId) - .filter((record) => !ownerId || record.ownerId === ownerId) - .sort(compareProjectDataStoreRecords) - .map((record) => cloneRecord(record))); - }, - deleteRecord(recordType, recordId) { - return records.delete(createProjectDataStoreKey(recordType, recordId)); - }, - clear() { - records.clear(); - return true; - }, - }; - - initialRecords.forEach((record) => { - const result = adapter.putRecord(record); - - if (!result.valid) { - throw new Error(`Invalid initial in-memory project data store record: ${result.errors.map((error) => error.code).join(",")}`); - } - }); - - return Object.freeze(adapter); -} - -function compareProjectDataStoreRecords(left, right) { - const leftKey = createProjectDataStoreKey(left.recordType, left.recordId); - const rightKey = createProjectDataStoreKey(right.recordType, right.recordId); - return leftKey.localeCompare(rightKey); -} - -function cloneRecord(record) { - return freezeJsonClone(record); -} - -function freezeResult(result) { - return Object.freeze({ - ...result, - errors: Object.freeze([...result.errors]), - }); -} - -function freezeJsonClone(value) { - return deepFreeze(JSON.parse(JSON.stringify(value))); -} - -function deepFreeze(value) { - if (value && typeof value === "object") { - Object.freeze(value); - - Object.values(value).forEach((child) => { - deepFreeze(child); - }); - } - - return value; -} diff --git a/www/toolbox/toolRegistry.js b/www/toolbox/toolRegistry.js index 69de63147..5f1fbead6 100644 --- a/www/toolbox/toolRegistry.js +++ b/www/toolbox/toolRegistry.js @@ -25,7 +25,7 @@ import { getVisibleActiveToolRegistry, isApprovedToolImagePath, toolRegistryMetadataDiagnostic, -} from "../../src/shared/toolbox/tool-metadata-inventory.js"; +} from "../src/shared/toolbox/tool-metadata-inventory.js"; export { TOOL_IMAGE_BADGE_ROOT,