Skip to content

Commit 7a12a77

Browse files
author
DavidQ
committed
Flatten manifest asset contract and fix runtime/tool loaders - PR 11.95.
1 parent afd5ea1 commit 7a12a77

16 files changed

Lines changed: 358 additions & 151 deletions

docs/dev/codex_commands.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,28 @@
1-
# Codex Command — PR 11.93
1+
# Codex Command — PR 11.95
22

33
Model: GPT-5.4
44
Reasoning: high
55

66
```text
7-
Apply PR 11.93. Inspect games/Asteroids/game.manifest.json and align the asset-browser manifest shape with the expected flat asset map. Move every entry currently under tools.asset-browser.assets.media into tools.asset-browser.assets keyed directly by asset id, then remove the media wrapper. Preserve all audio entries, ensure image.asteroids.bezel uses /games/Asteroids/assets/images/bezel.png with stretchOverride.uniformEdgeStretchPx = 10, ensure image.asteroids.background uses /games/Asteroids/assets/images/deluxe.png, and add font.asteroids.vector-battle using /games/Asteroids/assets/fonts/vector_battle.ttf if missing. Do not create asset-browser.assets.bezel, do not use bezel1.png, and do not add fallback asset-loading paths. Run targeted manifest validation and write findings to docs/dev/reports/PR_11_93_validation.md.
7+
Run BUILD_PR for PR_11_95_FLATTEN_MANIFEST_ASSETS_AND_FIX_LOADERS.
8+
9+
Read docs/pr/PR_11_95_FLATTEN_MANIFEST_ASSETS_AND_FIX_LOADERS.md.
10+
11+
Implement the smallest complete code change that makes asset-browser.assets the single flat manifest source of truth for all asset kinds.
12+
13+
Fix manifests and code together:
14+
- Remove nested asset-browser.assets.media usage.
15+
- Update runtime loaders to read manifest["asset-browser"].assets directly.
16+
- Update Workspace Manager, Asset Browser, and SVG Asset Studio consumers to list assets from the flat map.
17+
- Preserve kind-based filtering for image/font/audio/svg.
18+
- Keep Asteroids bezel path as /games/Asteroids/assets/images/bezel.png.
19+
- Keep Asteroids background path as /games/Asteroids/assets/images/deluxe.png.
20+
- Add/keep font.asteroids.vector-battle under the flat assets map.
21+
- Keep stretchOverride only on image.*.bezel entries.
22+
- Do not add aliases, shims, fallback paths, or media compatibility layers.
23+
24+
After implementation, run targeted validation commands from the PR doc and write findings to docs/dev/reports/PR_11_95_validation.md.
25+
26+
Package changed files into repo-structured ZIP:
27+
<project folder>/tmp/PR_11_95_FLATTEN_MANIFEST_ASSETS_AND_FIX_LOADERS.zip
828
```

docs/dev/commit_comment.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Align Asteroids manifest asset-browser assets to flat schema and add font asset - PR 11.93
1+
Flatten manifest asset contract and fix runtime/tool loaders - PR 11.95
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# PR 11.95 Validation
2+
3+
## Scope
4+
Applied `docs/pr/PR_11_95_FLATTEN_MANIFEST_ASSETS_AND_FIX_LOADERS.md`.
5+
Implemented flat `tools["asset-browser"].assets` contract as the single manifest source for asset kinds across runtime + game manifests + key consumers.
6+
7+
## Files Changed
8+
- `games/AITargetDummy/game.manifest.json`
9+
- `games/GravityWell/game.manifest.json`
10+
- `games/Pacman/game.manifest.json`
11+
- `games/SpaceDuel/game.manifest.json`
12+
- `games/SpaceInvaders/game.manifest.json`
13+
- `games/vector-arcade-sample/game.manifest.json`
14+
- `games/shared/workspaceGameAssetCatalog.js`
15+
- `src/engine/runtime/gameImageConvention.js`
16+
- `src/engine/runtime/fullscreenBezel.js`
17+
- `tests/runtime/GamesIndexWorkspaceManagerOpen.test.mjs`
18+
- `tests/core/BackgroundImageAndFullscreenBezel.test.mjs`
19+
- `tools/shared/asteroidsPlatformDemo.js`
20+
- `docs/dev/reports/PR_11_95_validation.md`
21+
22+
## Implementation Summary
23+
- Flattened all game manifests still using `tools.asset-browser.assets.media` into direct flat map entries under `tools.asset-browser.assets`.
24+
- Updated runtime loaders to consume flat `assets` directly:
25+
- `workspaceGameAssetCatalog` manifest extraction now reads `tools["asset-browser"].assets`.
26+
- `gameImageConvention` now collects image assets directly from flat `tools["asset-browser"].assets`.
27+
- `fullscreenBezel` stretch config extraction now scans flat asset map for bezel image entries with `stretchOverride`.
28+
- Updated consumers/tests referencing nested media:
29+
- Workspace Manager runtime test now reads `assets` directly.
30+
- Asteroids shared demo manifest path updated to flat asset path fragment.
31+
- Bezel stretch test fragment path updated to `tools.asset-browser.assets.image.asteroids.bezel.stretchOverride`.
32+
33+
## Asteroids Contract Checks
34+
- `image.asteroids.bezel.path` remains `/games/Asteroids/assets/images/bezel.png`.
35+
- `image.asteroids.background.path` remains `/games/Asteroids/assets/images/deluxe.png`.
36+
- `font.asteroids.vector-battle` exists under flat `tools.asset-browser.assets`.
37+
- `stretchOverride.uniformEdgeStretchPx = 10` remains on `image.asteroids.bezel`.
38+
- No `bezel1.png` references in source/manifests.
39+
- No `asset-browser.assets.bezel` duplicate contract in source/manifests.
40+
41+
## Targeted Validation Commands and Results
42+
43+
### PR-doc search commands (equivalent recursive form)
44+
Note: PowerShell `Select-String` in this environment does not support `-Recurse`, so equivalent `Get-ChildItem -Recurse -File | Select-String` was used.
45+
46+
1. `assets.media` search:
47+
- Runtime/tool/test source scope (`src`, `games`, `tools`, `tests`): no matches.
48+
- Repo-wide scan returns docs/history and temp browser cache text only.
49+
50+
2. `asset-browser.*media` search:
51+
- Runtime/tool/test source scope: no matches.
52+
- Repo-wide scan returns docs/history and temp browser cache text only.
53+
54+
3. `bezel1.png` search:
55+
- Source/manifests scope: no matches.
56+
- Repo-wide scan returns historical docs/reports/PR docs only.
57+
58+
4. `image.asteroids.bezel` search:
59+
- Active manifest entry present in `games/Asteroids/game.manifest.json`.
60+
61+
5. `font.asteroids.vector-battle` search:
62+
- Active manifest entry present in `games/Asteroids/game.manifest.json`.
63+
64+
### Syntax checks
65+
- `node --check games/shared/workspaceGameAssetCatalog.js` PASS
66+
- `node --check src/engine/runtime/gameImageConvention.js` PASS
67+
- `node --check src/engine/runtime/fullscreenBezel.js` PASS
68+
- `node --check tests/runtime/GamesIndexWorkspaceManagerOpen.test.mjs` PASS
69+
- `node --check tools/shared/asteroidsPlatformDemo.js` PASS
70+
- `node --check tests/core/BackgroundImageAndFullscreenBezel.test.mjs` PASS
71+
72+
### Targeted runtime checks
73+
- `npm run test:workspace-manager:games` PASS
74+
- `npm run test:manifest-payload:games` PASS
75+
76+
## Notes
77+
- No aliases, shims, fallback paths, or media-compatibility layers were added.
78+
- Full samples suite was skipped (targeted validation only, per PR scope).
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# PR 11.95 — Flatten Manifest Assets and Fix Loaders
2+
3+
## Purpose
4+
Correct the manifest asset contract so `asset-browser.assets` is the single flat source of truth for all game assets, including images, fonts, audio, SVG, and any future asset kinds.
5+
6+
This PR must fix the code that still expects nested `media` sections instead of restoring or preserving `media` as a special case.
7+
8+
## Scope
9+
- Update game manifests to use a flat `asset-browser.assets` map.
10+
- Remove nested `asset-browser.assets.media` usage.
11+
- Update runtime loaders to read assets directly from `asset-browser.assets`.
12+
- Update Workspace Manager / Asset Browser / SVG Asset Studio consumers to read the same flat map.
13+
- Preserve existing asset IDs such as:
14+
- `image.asteroids.bezel`
15+
- `image.asteroids.background`
16+
- `font.asteroids.vector-battle`
17+
- `audio.*`
18+
- `svg.*`
19+
- Keep `kind` as the asset type discriminator.
20+
- Keep bezel stretch data on `image.*.bezel` entries only.
21+
22+
## Required Manifest Shape
23+
24+
```json
25+
{
26+
"asset-browser": {
27+
"assets": {
28+
"image.asteroids.bezel": {
29+
"path": "/games/Asteroids/assets/images/bezel.png",
30+
"kind": "image",
31+
"source": "workspace-manager",
32+
"stretchOverride": {
33+
"uniformEdgeStretchPx": 10
34+
}
35+
},
36+
"image.asteroids.background": {
37+
"path": "/games/Asteroids/assets/images/deluxe.png",
38+
"kind": "image",
39+
"source": "workspace-manager"
40+
},
41+
"font.asteroids.vector-battle": {
42+
"path": "/games/Asteroids/assets/fonts/vector_battle.ttf",
43+
"kind": "font",
44+
"source": "workspace-manager"
45+
},
46+
"audio.asteroids.fire": {
47+
"path": "/games/Asteroids/assets/audio/fire.mp3",
48+
"kind": "audio",
49+
"source": "workspace-manager"
50+
}
51+
}
52+
}
53+
}
54+
```
55+
56+
## Explicitly Forbidden
57+
- Do not restore `asset-browser.assets.media`.
58+
- Do not create separate contracts for audio vs image/font/svg.
59+
- Do not hardcode fallback asset paths.
60+
- Do not guess `bezel.png`, `background.png`, `deluxe.png`, or any audio file path outside the manifest.
61+
- Do not add alias/pass-through loaders that simply remap `media` to `assets`.
62+
- Do not place bezel stretch under `asset-browser.assets.bezel`.
63+
64+
## Loader Fix Requirements
65+
Search for and update all code paths that read any of these old shapes:
66+
67+
```text
68+
assetBrowser.assets.media
69+
asset-browser.assets.media
70+
assets.media
71+
manifest.media
72+
media.audio
73+
media.image
74+
media.font
75+
media.svg
76+
```
77+
78+
Replace with flat iteration/filtering over:
79+
80+
```text
81+
manifest["asset-browser"].assets
82+
```
83+
84+
Asset consumers must filter by `kind`:
85+
86+
```js
87+
const assets = manifest?.["asset-browser"]?.assets ?? {};
88+
const imageAssets = Object.entries(assets).filter(([, asset]) => asset.kind === "image");
89+
const audioAssets = Object.entries(assets).filter(([, asset]) => asset.kind === "audio");
90+
const fontAssets = Object.entries(assets).filter(([, asset]) => asset.kind === "font");
91+
```
92+
93+
## Asteroids Requirements
94+
- `image.asteroids.bezel.path` must be `/games/Asteroids/assets/images/bezel.png`.
95+
- Do not use `bezel1.png`.
96+
- `image.asteroids.background.path` must be `/games/Asteroids/assets/images/deluxe.png`.
97+
- `font.asteroids.vector-battle` must exist and point to `/games/Asteroids/assets/fonts/vector_battle.ttf`.
98+
- Existing Asteroids audio files must be listed as flat `audio.asteroids.*` entries if they are currently nested under media.
99+
100+
## Tool Requirements
101+
- SVG Asset Studio must list visible assets from the flat map.
102+
- Asset Browser must list visible assets from the flat map.
103+
- Workspace Manager tile counts must count flat assets by kind/id pattern.
104+
- Runtime game loading must load image/font/audio assets from the flat map.
105+
106+
## Validation
107+
Run targeted checks only.
108+
109+
Required checks:
110+
111+
```powershell
112+
Select-String -Path .\* -Recurse -Pattern "assets\.media"
113+
Select-String -Path .\* -Recurse -Pattern "asset-browser.*media"
114+
Select-String -Path .\* -Recurse -Pattern "bezel1.png"
115+
Select-String -Path .\* -Recurse -Pattern "image\.asteroids\.bezel"
116+
Select-String -Path .\* -Recurse -Pattern "font\.asteroids\.vector-battle"
117+
```
118+
119+
Expected:
120+
- No remaining runtime/tool dependency on nested `media`.
121+
- No `bezel1.png` references.
122+
- Asteroids launches with no 404s for bezel/background/font/audio assets declared in manifest.
123+
- SVG Asset Studio shows manifest assets instead of only saying assets exist.
124+
- Background and bezel still load only from manifest.
125+
126+
## Full Samples Test
127+
Do not run the full samples suite by default. This PR modifies manifest loading code and selected game/tool consumers; use targeted checks for Asteroids, Workspace Manager, Asset Browser, and SVG Asset Studio.
128+
129+
Run full samples only if Codex modifies shared sample loader/framework code broadly enough that targeted validation cannot establish correctness.
130+
131+
## Acceptance
132+
- One flat `asset-browser.assets` contract exists for all asset kinds.
133+
- Runtime loads audio/images/fonts from the flat contract.
134+
- Tools display/list assets from the flat contract.
135+
- `media` is removed as a manifest asset grouping contract.
136+
- Asteroids assets load correctly.
137+
- No hidden fallback or guessed paths remain.

games/AITargetDummy/game.manifest.json

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@
1414
"tools": {
1515
"asset-browser": {
1616
"assets": {
17-
"media": {
18-
"image.ai-target-dummy.preview": {
19-
"path": "games/AITargetDummy/assets/images/preview.svg",
20-
"kind": "image",
21-
"source": "workspace-manager"
22-
}
17+
"image.ai-target-dummy.preview": {
18+
"path": "games/AITargetDummy/assets/images/preview.svg",
19+
"kind": "image",
20+
"source": "workspace-manager"
2321
}
2422
},
2523
"schema": "html-js-gaming.tool.asset-browser",

games/GravityWell/game.manifest.json

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@
1414
"tools": {
1515
"asset-browser": {
1616
"assets": {
17-
"media": {
18-
"image.gravitywell.preview": {
19-
"path": "games/GravityWell/assets/images/preview.svg",
20-
"kind": "image",
21-
"source": "workspace-manager"
22-
}
17+
"image.gravitywell.preview": {
18+
"path": "games/GravityWell/assets/images/preview.svg",
19+
"kind": "image",
20+
"source": "workspace-manager"
2321
}
2422
},
2523
"schema": "html-js-gaming.tool.asset-browser",

games/Pacman/game.manifest.json

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,15 @@
1414
"tools": {
1515
"asset-browser": {
1616
"assets": {
17-
"media": {
18-
"image.pacman.preview-svg": {
19-
"path": "games/Pacman/assets/images/preview.svg",
20-
"kind": "image",
21-
"source": "workspace-manager"
22-
},
23-
"image.pacman.preview-png": {
24-
"path": "games/Pacman/assets/images/preview.png",
25-
"kind": "image",
26-
"source": "workspace-manager"
27-
}
17+
"image.pacman.preview-svg": {
18+
"path": "games/Pacman/assets/images/preview.svg",
19+
"kind": "image",
20+
"source": "workspace-manager"
21+
},
22+
"image.pacman.preview-png": {
23+
"path": "games/Pacman/assets/images/preview.png",
24+
"kind": "image",
25+
"source": "workspace-manager"
2826
}
2927
},
3028
"schema": "html-js-gaming.tool.asset-browser",

games/SpaceDuel/game.manifest.json

Lines changed: 39 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -21,47 +21,45 @@
2121
},
2222
"asset-browser": {
2323
"assets": {
24-
"media": {
25-
"audio.space-duel.thrust": {
26-
"path": "games/SpaceDuel/assets/audio/effects/thrust.wav",
27-
"kind": "audio",
28-
"source": "workspace-manager"
29-
},
30-
"audio.space-duel.fire": {
31-
"path": "games/SpaceDuel/assets/audio/effects/fire.wav",
32-
"kind": "audio",
33-
"source": "workspace-manager"
34-
},
35-
"audio.space-duel.explosion": {
36-
"path": "games/SpaceDuel/assets/audio/effects/explosion.wav",
37-
"kind": "audio",
38-
"source": "workspace-manager"
39-
},
40-
"audio.space-duel.player-death": {
41-
"path": "games/SpaceDuel/assets/audio/effects/player_death.wav",
42-
"kind": "audio",
43-
"source": "workspace-manager"
44-
},
45-
"audio.space-duel.enemy-split": {
46-
"path": "games/SpaceDuel/assets/audio/effects/enemy_split.wav",
47-
"kind": "audio",
48-
"source": "workspace-manager"
49-
},
50-
"audio.space-duel.bonus": {
51-
"path": "games/SpaceDuel/assets/audio/effects/bonus.wav",
52-
"kind": "audio",
53-
"source": "workspace-manager"
54-
},
55-
"audio.space-duel.start": {
56-
"path": "games/SpaceDuel/assets/audio/effects/start.wav",
57-
"kind": "audio",
58-
"source": "workspace-manager"
59-
},
60-
"audio.space-duel.game-over": {
61-
"path": "games/SpaceDuel/assets/audio/effects/game_over.wav",
62-
"kind": "audio",
63-
"source": "workspace-manager"
64-
}
24+
"audio.space-duel.thrust": {
25+
"path": "games/SpaceDuel/assets/audio/effects/thrust.wav",
26+
"kind": "audio",
27+
"source": "workspace-manager"
28+
},
29+
"audio.space-duel.fire": {
30+
"path": "games/SpaceDuel/assets/audio/effects/fire.wav",
31+
"kind": "audio",
32+
"source": "workspace-manager"
33+
},
34+
"audio.space-duel.explosion": {
35+
"path": "games/SpaceDuel/assets/audio/effects/explosion.wav",
36+
"kind": "audio",
37+
"source": "workspace-manager"
38+
},
39+
"audio.space-duel.player-death": {
40+
"path": "games/SpaceDuel/assets/audio/effects/player_death.wav",
41+
"kind": "audio",
42+
"source": "workspace-manager"
43+
},
44+
"audio.space-duel.enemy-split": {
45+
"path": "games/SpaceDuel/assets/audio/effects/enemy_split.wav",
46+
"kind": "audio",
47+
"source": "workspace-manager"
48+
},
49+
"audio.space-duel.bonus": {
50+
"path": "games/SpaceDuel/assets/audio/effects/bonus.wav",
51+
"kind": "audio",
52+
"source": "workspace-manager"
53+
},
54+
"audio.space-duel.start": {
55+
"path": "games/SpaceDuel/assets/audio/effects/start.wav",
56+
"kind": "audio",
57+
"source": "workspace-manager"
58+
},
59+
"audio.space-duel.game-over": {
60+
"path": "games/SpaceDuel/assets/audio/effects/game_over.wav",
61+
"kind": "audio",
62+
"source": "workspace-manager"
6563
}
6664
},
6765
"schema": "html-js-gaming.tool.asset-browser",

0 commit comments

Comments
 (0)